00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "tabbox.h"
00014 #include "workspace.h"
00015 #include "client.h"
00016 #include <qpainter.h>
00017 #include <qlabel.h>
00018 #include <qdrawutil.h>
00019 #include <qstyle.h>
00020 #include <kglobal.h>
00021 #include <fixx11h.h>
00022 #include <kconfig.h>
00023 #include <klocale.h>
00024 #include <qapplication.h>
00025 #include <qdesktopwidget.h>
00026 #include <qcursor.h>
00027 #include <kstringhandler.h>
00028 #include <stdarg.h>
00029 #include <kdebug.h>
00030 #include <kglobalaccel.h>
00031 #include <kkeynative.h>
00032 #include <kglobalsettings.h>
00033 #include <kiconeffect.h>
00034 #include <X11/keysym.h>
00035 #include <X11/keysymdef.h>
00036
00037
00038
00039 extern Time qt_x_time;
00040
00041 namespace KWinInternal
00042 {
00043
00044 extern QPixmap* kwin_get_menu_pix_hack();
00045
00046 TabBox::TabBox( Workspace *ws, const char *name )
00047 : QFrame( 0, name, Qt::WNoAutoErase ), client(0), wspace(ws)
00048 {
00049 setFrameStyle(QFrame::StyledPanel | QFrame::Plain);
00050 setLineWidth(2);
00051 setMargin(2);
00052
00053 showMiniIcon = false;
00054
00055 no_tasks = i18n("*** No Windows ***");
00056 m = DesktopMode;
00057 reconfigure();
00058 reset();
00059 connect(&delayedShowTimer, SIGNAL(timeout()), this, SLOT(show()));
00060 }
00061
00062 TabBox::~TabBox()
00063 {
00064 }
00065
00066
00072 void TabBox::setMode( Mode mode )
00073 {
00074 m = mode;
00075 }
00076
00077
00081 void TabBox::createClientList(ClientList &list, int desktop , Client *c, bool chain)
00082 {
00083 ClientList::size_type idx = 0;
00084
00085 list.clear();
00086
00087 Client* start = c;
00088
00089 if ( chain )
00090 c = workspace()->nextFocusChainClient(c);
00091 else
00092 c = workspace()->stackingOrder().first();
00093
00094 Client* stop = c;
00095
00096 while ( c )
00097 {
00098 if ( ((desktop == -1) || c->isOnDesktop(desktop))
00099 && c->wantsTabFocus() )
00100 {
00101 if ( start == c )
00102 {
00103 list.remove( c );
00104 list.prepend( c );
00105 }
00106 else
00107 {
00108 Client* modal = c->findModal();
00109 if( modal == NULL || modal == c )
00110 list += c;
00111 else if( !list.contains( modal ))
00112 list += modal;
00113 else
00114 ;
00115 }
00116 }
00117
00118 if ( chain )
00119 c = workspace()->nextFocusChainClient( c );
00120 else
00121 {
00122 if ( idx >= (workspace()->stackingOrder().size()-1) )
00123 c = 0;
00124 else
00125 c = workspace()->stackingOrder()[++idx];
00126 }
00127
00128 if ( c == stop )
00129 break;
00130 }
00131 }
00132
00133
00138 void TabBox::reset()
00139 {
00140 int w, h, cw = 0, wmax = 0;
00141
00142 QRect r = KGlobalSettings::desktopGeometry(QCursor::pos());
00143
00144
00145
00146 lineHeight = QMAX(fontMetrics().height() + 2, 32 + 4);
00147
00148 if ( mode() == WindowsMode )
00149 {
00150 client = workspace()->activeClient();
00151
00152
00153 createClientList(clients, options_traverse_all ? -1 : workspace()->currentDesktop(), client, true);
00154
00155
00156 cw = fontMetrics().width(no_tasks)+20;
00157 for (ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it)
00158 {
00159 cw = fontMetrics().width( (*it)->caption() );
00160 if ( cw > wmax ) wmax = cw;
00161 }
00162
00163
00164 if ( clients.count() == 0 )
00165 {
00166 QFont f = font();
00167 f.setBold( TRUE );
00168 f.setPointSize( 14 );
00169
00170 h = QFontMetrics(f).height()*4;
00171 }
00172 else
00173 {
00174 showMiniIcon = false;
00175 h = clients.count() * lineHeight;
00176
00177 if ( h > (r.height()-(2*frameWidth())) )
00178 {
00179 showMiniIcon = true;
00180
00181 lineHeight = QMAX(fontMetrics().height() + 2, 16 + 2);
00182
00183 h = clients.count() * lineHeight;
00184
00185 if ( h > (r.height()-(2*frameWidth())) )
00186 {
00187
00188 int howMany = (h - (r.height()-(2*frameWidth())))/lineHeight;
00189 for (; howMany; howMany--)
00190 clients.remove(clients.last());
00191
00192 h = clients.count() * lineHeight;
00193 }
00194 }
00195 }
00196 }
00197 else
00198 {
00199 showMiniIcon = false;
00200 desk = workspace()->currentDesktop();
00201
00202 for ( int i = 1; i <= workspace()->numberOfDesktops(); i++ )
00203 {
00204 cw = fontMetrics().width( workspace()->desktopName(i) );
00205 if ( cw > wmax ) wmax = cw;
00206 }
00207
00208
00209 h = workspace()->numberOfDesktops() * lineHeight;
00210 }
00211
00212
00213 h += 2 * frameWidth();
00214 w = 2*frameWidth() + 5*2 + ( showMiniIcon ? 16 : 32 ) + 8 + wmax;
00215 w = kClamp( w, r.width()/3 , r.width() * 4 / 5 );
00216
00217 setGeometry( (r.width()-w)/2 + r.x(),
00218 (r.height()-h)/2+ r.y(),
00219 w, h );
00220 }
00221
00222
00226 void TabBox::nextPrev( bool next)
00227 {
00228 if ( mode() == WindowsMode )
00229 {
00230 Client* firstClient = 0;
00231 do
00232 {
00233 if ( next )
00234 client = workspace()->nextFocusChainClient(client);
00235 else
00236 client = workspace()->previousFocusChainClient(client);
00237 if (!firstClient)
00238 {
00239
00240
00241 firstClient = client;
00242 }
00243 else if (client == firstClient)
00244 {
00245
00246 client = 0;
00247 break;
00248 }
00249 } while ( client && !clients.contains( client ));
00250 }
00251 else if( mode() == DesktopMode )
00252 {
00253 if ( next )
00254 desk = workspace()->nextDesktopFocusChain( desk );
00255 else
00256 desk = workspace()->previousDesktopFocusChain( desk );
00257 }
00258 else
00259 {
00260 if ( next )
00261 {
00262 desk++;
00263 if ( desk > workspace()->numberOfDesktops() )
00264 desk = 1;
00265 }
00266 else
00267 {
00268 desk--;
00269 if ( desk < 1 )
00270 desk = workspace()->numberOfDesktops();
00271 }
00272 }
00273
00274 update();
00275 }
00276
00277
00278
00283 Client* TabBox::currentClient()
00284 {
00285 if ( mode() != WindowsMode )
00286 return 0;
00287 if (!workspace()->hasClient( client ))
00288 return 0;
00289 return client;
00290 }
00291
00297 int TabBox::currentDesktop()
00298 {
00299 if ( mode() == DesktopListMode || mode() == DesktopMode )
00300 return desk;
00301 else
00302 return -1;
00303 }
00304
00305
00309 void TabBox::showEvent( QShowEvent* )
00310 {
00311 raise();
00312 }
00313
00314
00318 void TabBox::hideEvent( QHideEvent* )
00319 {
00320 }
00321
00325 void TabBox::drawContents( QPainter * )
00326 {
00327 QRect r(contentsRect());
00328 QPixmap pix(r.size());
00329 pix.fill(this, 0, 0);
00330
00331 QPainter p;
00332 p.begin(&pix, this);
00333
00334 QPixmap* menu_pix = kwin_get_menu_pix_hack();
00335
00336 int iconWidth = showMiniIcon ? 16 : 32;
00337 int x = 0;
00338 int y = 0;
00339
00340 if ( mode () == WindowsMode )
00341 {
00342 if ( !currentClient() )
00343 {
00344 QFont f = font();
00345 f.setBold( TRUE );
00346 f.setPointSize( 14 );
00347
00348 p.setFont(f);
00349 p.drawText( r, AlignCenter, no_tasks);
00350 }
00351 else
00352 {
00353 for (ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it)
00354 {
00355 if ( workspace()->hasClient( *it ) )
00356 {
00357
00358 if ( (*it) == currentClient() )
00359 p.fillRect(x, y, r.width(), lineHeight, colorGroup().highlight());
00360
00361
00362 QPixmap icon;
00363 if ( showMiniIcon )
00364 {
00365 if ( !(*it)->miniIcon().isNull() )
00366 icon = (*it)->miniIcon();
00367 }
00368 else
00369 if ( !(*it)->icon().isNull() )
00370 icon = (*it)->icon();
00371 else if ( menu_pix )
00372 icon = *menu_pix;
00373
00374 if( !icon.isNull())
00375 {
00376 if( (*it)->isMinimized())
00377 KIconEffect::semiTransparent( icon );
00378 p.drawPixmap( x+5, y + (lineHeight - iconWidth)/2, icon );
00379 }
00380
00381
00382 QString s;
00383
00384 if ( !(*it)->isOnDesktop(workspace()->currentDesktop()) )
00385 s = workspace()->desktopName((*it)->desktop()) + ": ";
00386
00387 if ( (*it)->isMinimized() )
00388 s += QString("(") + (*it)->caption() + ")";
00389 else
00390 s += (*it)->caption();
00391
00392 s = KStringHandler::cPixelSqueeze(s, fontMetrics(), r.width() - 5 - iconWidth - 8);
00393
00394
00395 if ( (*it) == currentClient() )
00396 p.setPen(colorGroup().highlightedText());
00397 else if( (*it)->isMinimized())
00398 {
00399 QColor c1 = colorGroup().text();
00400 QColor c2 = colorGroup().background();
00401
00402 int r1, g1, b1;
00403 int r2, g2, b2;
00404
00405 c1.rgb( &r1, &g1, &b1 );
00406 c2.rgb( &r2, &g2, &b2 );
00407
00408 r1 += (int) ( .5 * ( r2 - r1 ) );
00409 g1 += (int) ( .5 * ( g2 - g1 ) );
00410 b1 += (int) ( .5 * ( b2 - b1 ) );
00411
00412 p.setPen(QColor( r1, g1, b1 ));
00413 }
00414 else
00415 p.setPen(colorGroup().text());
00416
00417 p.drawText(x+5 + iconWidth + 8, y, r.width() - 5 - iconWidth - 8, lineHeight,
00418 Qt::AlignLeft | Qt::AlignVCenter | Qt::SingleLine, s);
00419
00420 y += lineHeight;
00421 }
00422 if ( y >= r.height() ) break;
00423 }
00424 }
00425 }
00426 else
00427 {
00428 int iconHeight = iconWidth;
00429
00430
00431 QFont f(font());
00432 f.setBold(true);
00433 f.setPixelSize(iconHeight - 4);
00434 QFontMetrics fm(f);
00435
00436 int wmax = 0;
00437 for ( int i = 1; i <= workspace()->numberOfDesktops(); i++ )
00438 {
00439 wmax = QMAX(wmax, fontMetrics().width(workspace()->desktopName(i)));
00440
00441
00442 QString num = QString::number(i);
00443 iconWidth = QMAX(iconWidth - 4, fm.boundingRect(num).width()) + 4;
00444 }
00445
00446
00447
00448 int iDesktop = (mode() == DesktopMode) ? workspace()->currentDesktop() : 1;
00449 for ( int i = 1; i <= workspace()->numberOfDesktops(); i++ )
00450 {
00451
00452 if ( iDesktop == desk )
00453 p.fillRect(x, y, r.width(), lineHeight, colorGroup().highlight());
00454
00455 p.save();
00456
00457
00458 p.fillRect(x+5, y+2, iconWidth, iconHeight, colorGroup().base());
00459 p.setPen(colorGroup().text());
00460 p.drawRect(x+5, y+2, iconWidth, iconHeight);
00461
00462
00463 p.setFont(f);
00464 QString num = QString::number(iDesktop);
00465 p.drawText(x+5, y+2, iconWidth, iconHeight, Qt::AlignCenter, num);
00466
00467 p.restore();
00468
00469
00470 if ( iDesktop == desk )
00471 p.setPen(colorGroup().highlightedText());
00472 else
00473 p.setPen(colorGroup().text());
00474
00475 p.drawText(x+5 + iconWidth + 8, y, r.width() - 5 - iconWidth - 8, lineHeight,
00476 Qt::AlignLeft | Qt::AlignVCenter | Qt::SingleLine,
00477 workspace()->desktopName(iDesktop));
00478
00479
00480 int x1 = x + 5 + iconWidth + 8 + wmax + 5;
00481
00482 ClientList list;
00483 createClientList(list, iDesktop, 0, false);
00484
00485 for (ClientList::ConstIterator it = list.fromLast(); it != list.end(); --it)
00486 {
00487 if ( !(*it)->miniIcon().isNull() )
00488 {
00489 if ( x1+18 >= x+r.width() )
00490 break;
00491
00492 p.drawPixmap( x1, y + (lineHeight - 16)/2, (*it)->miniIcon() );
00493 x1 += 18;
00494 }
00495 }
00496
00497
00498 y += lineHeight;
00499 if ( y >= r.height() ) break;
00500
00501 if( mode() == DesktopMode )
00502 iDesktop = workspace()->nextDesktopFocusChain( iDesktop );
00503 else
00504 iDesktop++;
00505 }
00506 }
00507 p.end();
00508 bitBlt(this, r.x(), r.y(), &pix);
00509 }
00510
00511 void TabBox::hide()
00512 {
00513 delayedShowTimer.stop();
00514 QWidget::hide();
00515 QApplication::syncX();
00516 XEvent otherEvent;
00517 while (XCheckTypedEvent (qt_xdisplay(), EnterNotify, &otherEvent ) )
00518 ;
00519 }
00520
00521
00522 void TabBox::reconfigure()
00523 {
00524 KConfig * c(KGlobal::config());
00525 c->setGroup("TabBox");
00526 options_traverse_all = c->readNumEntry("TraverseAll", false );
00527 }
00528
00547 void TabBox::delayedShow()
00548 {
00549 KConfig * c(KGlobal::config());
00550 c->setGroup("TabBox");
00551 bool delay = c->readNumEntry("ShowDelay", true);
00552
00553 if (!delay)
00554 {
00555 show();
00556 return;
00557 }
00558
00559 int delayTime = c->readNumEntry("DelayTime", 90);
00560 delayedShowTimer.start(delayTime, true);
00561 }
00562
00563
00564 void TabBox::handleMouseEvent( XEvent* e )
00565 {
00566 XAllowEvents( qt_xdisplay(), AsyncPointer, qt_x_time );
00567 if( e->type != ButtonPress )
00568 return;
00569 QPoint pos( e->xbutton.x_root, e->xbutton.y_root );
00570 if( !geometry().contains( pos ))
00571 {
00572 workspace()->closeTabBox();
00573 return;
00574 }
00575 pos.rx() -= x();
00576 pos.ry() -= y();
00577 int num = (pos.y()-frameWidth()) / lineHeight;
00578
00579 if( mode() == WindowsMode )
00580 {
00581 for( ClientList::ConstIterator it = clients.begin();
00582 it != clients.end();
00583 ++it)
00584 {
00585 if( workspace()->hasClient( *it ) && (num == 0) )
00586 {
00587 client = *it;
00588 break;
00589 }
00590 num--;
00591 }
00592 }
00593 else
00594 {
00595 int iDesktop = (mode() == DesktopMode) ? workspace()->currentDesktop() : 1;
00596 for( int i = 1;
00597 i <= workspace()->numberOfDesktops();
00598 ++i )
00599 {
00600 if( num == 0 )
00601 {
00602 desk = iDesktop;
00603 break;
00604 }
00605 num--;
00606 if( mode() == DesktopMode )
00607 iDesktop = workspace()->nextDesktopFocusChain( iDesktop );
00608 else
00609 iDesktop++;
00610 }
00611 }
00612 update();
00613 }
00614
00615
00616
00617
00618
00619
00624 static
00625 bool areKeySymXsDepressed( bool bAll, int nKeySyms, ... )
00626 {
00627 va_list args;
00628 char keymap[32];
00629
00630 kdDebug(125) << "areKeySymXsDepressed: " << (bAll ? "all of " : "any of ") << nKeySyms << endl;
00631
00632 va_start( args, nKeySyms );
00633 XQueryKeymap( qt_xdisplay(), keymap );
00634
00635 for( int iKeySym = 0; iKeySym < nKeySyms; iKeySym++ )
00636 {
00637 uint keySymX = va_arg( args, uint );
00638 uchar keyCodeX = XKeysymToKeycode( qt_xdisplay(), keySymX );
00639 int i = keyCodeX / 8;
00640 char mask = 1 << (keyCodeX - (i * 8));
00641
00642 kdDebug(125) << iKeySym << ": keySymX=0x" << QString::number( keySymX, 16 )
00643 << " i=" << i << " mask=0x" << QString::number( mask, 16 )
00644 << " keymap[i]=0x" << QString::number( keymap[i], 16 ) << endl;
00645
00646
00647 if( i < 0 || i >= 32 )
00648 return false;
00649
00650
00651 if( bAll )
00652 {
00653 if( (keymap[i] & mask) == 0 )
00654 return false;
00655 }
00656 else
00657 {
00658
00659 if( keymap[i] & mask )
00660 return true;
00661 }
00662 }
00663
00664
00665
00666 return bAll;
00667 }
00668
00669 static bool areModKeysDepressed( const KKeySequence& seq )
00670 {
00671 uint rgKeySyms[10];
00672 int nKeySyms = 0;
00673 if( seq.isNull())
00674 return false;
00675 int mod = seq.key(seq.count()-1).modFlags();
00676
00677 if ( mod & KKey::SHIFT )
00678 {
00679 rgKeySyms[nKeySyms++] = XK_Shift_L;
00680 rgKeySyms[nKeySyms++] = XK_Shift_R;
00681 }
00682 if ( mod & KKey::CTRL )
00683 {
00684 rgKeySyms[nKeySyms++] = XK_Control_L;
00685 rgKeySyms[nKeySyms++] = XK_Control_R;
00686 }
00687 if( mod & KKey::ALT )
00688 {
00689 rgKeySyms[nKeySyms++] = XK_Alt_L;
00690 rgKeySyms[nKeySyms++] = XK_Alt_R;
00691 }
00692 if( mod & KKey::WIN )
00693 {
00694
00695
00696 rgKeySyms[nKeySyms++] = XK_Super_L;
00697 rgKeySyms[nKeySyms++] = XK_Super_R;
00698 rgKeySyms[nKeySyms++] = XK_Meta_L;
00699 rgKeySyms[nKeySyms++] = XK_Meta_R;
00700 }
00701
00702
00703 return areKeySymXsDepressed( false, nKeySyms,
00704 rgKeySyms[0], rgKeySyms[1], rgKeySyms[2], rgKeySyms[3],
00705 rgKeySyms[4], rgKeySyms[5], rgKeySyms[6], rgKeySyms[7] );
00706 }
00707
00708 static bool areModKeysDepressed( const KShortcut& cut )
00709 {
00710 for( unsigned int i = 0;
00711 i < cut.count();
00712 ++i )
00713 {
00714 if( areModKeysDepressed( cut.seq( i )))
00715 return true;
00716 }
00717 return false;
00718 }
00719
00720 void Workspace::slotWalkThroughWindows()
00721 {
00722 if ( root != qt_xrootwin() )
00723 return;
00724 if ( tab_grab || control_grab )
00725 return;
00726 if ( options->altTabStyle == Options::CDE || !options->focusPolicyIsReasonable() )
00727 {
00728
00729
00730 CDEWalkThroughWindows( true );
00731 }
00732 else
00733 {
00734 if ( areModKeysDepressed( cutWalkThroughWindows ) )
00735 {
00736 if ( startKDEWalkThroughWindows() )
00737 KDEWalkThroughWindows( true );
00738 }
00739 else
00740
00741
00742
00743
00744 CDEWalkThroughWindows( true );
00745 }
00746 }
00747
00748 void Workspace::slotWalkBackThroughWindows()
00749 {
00750 if ( root != qt_xrootwin() )
00751 return;
00752 if( tab_grab || control_grab )
00753 return;
00754 if ( options->altTabStyle == Options::CDE || !options->focusPolicyIsReasonable() )
00755 {
00756
00757 CDEWalkThroughWindows( false );
00758 }
00759 else
00760 {
00761 if ( areModKeysDepressed( cutWalkThroughWindowsReverse ) )
00762 {
00763 if ( startKDEWalkThroughWindows() )
00764 KDEWalkThroughWindows( false );
00765 }
00766 else
00767 {
00768 CDEWalkThroughWindows( false );
00769 }
00770 }
00771 }
00772
00773 void Workspace::slotWalkThroughDesktops()
00774 {
00775 if ( root != qt_xrootwin() )
00776 return;
00777 if( tab_grab || control_grab )
00778 return;
00779 if ( areModKeysDepressed( cutWalkThroughDesktops ) )
00780 {
00781 if ( startWalkThroughDesktops() )
00782 walkThroughDesktops( true );
00783 }
00784 else
00785 {
00786 oneStepThroughDesktops( true );
00787 }
00788 }
00789
00790 void Workspace::slotWalkBackThroughDesktops()
00791 {
00792 if ( root != qt_xrootwin() )
00793 return;
00794 if( tab_grab || control_grab )
00795 return;
00796 if ( areModKeysDepressed( cutWalkThroughDesktopsReverse ) )
00797 {
00798 if ( startWalkThroughDesktops() )
00799 walkThroughDesktops( false );
00800 }
00801 else
00802 {
00803 oneStepThroughDesktops( false );
00804 }
00805 }
00806
00807 void Workspace::slotWalkThroughDesktopList()
00808 {
00809 if ( root != qt_xrootwin() )
00810 return;
00811 if( tab_grab || control_grab )
00812 return;
00813 if ( areModKeysDepressed( cutWalkThroughDesktopList ) )
00814 {
00815 if ( startWalkThroughDesktopList() )
00816 walkThroughDesktops( true );
00817 }
00818 else
00819 {
00820 oneStepThroughDesktopList( true );
00821 }
00822 }
00823
00824 void Workspace::slotWalkBackThroughDesktopList()
00825 {
00826 if ( root != qt_xrootwin() )
00827 return;
00828 if( tab_grab || control_grab )
00829 return;
00830 if ( areModKeysDepressed( cutWalkThroughDesktopListReverse ) )
00831 {
00832 if ( startWalkThroughDesktopList() )
00833 walkThroughDesktops( false );
00834 }
00835 else
00836 {
00837 oneStepThroughDesktopList( false );
00838 }
00839 }
00840
00841 bool Workspace::startKDEWalkThroughWindows()
00842 {
00843 if( !establishTabBoxGrab())
00844 return false;
00845 tab_grab = TRUE;
00846 keys->setEnabled( false );
00847 client_keys->setEnabled( false );
00848 tab_box->setMode( TabBox::WindowsMode );
00849 tab_box->reset();
00850 return TRUE;
00851 }
00852
00853 bool Workspace::startWalkThroughDesktops( int mode )
00854 {
00855 if( !establishTabBoxGrab())
00856 return false;
00857 control_grab = TRUE;
00858 keys->setEnabled( false );
00859 client_keys->setEnabled( false );
00860 tab_box->setMode( (TabBox::Mode) mode );
00861 tab_box->reset();
00862 return TRUE;
00863 }
00864
00865 bool Workspace::startWalkThroughDesktops()
00866 {
00867 return startWalkThroughDesktops( TabBox::DesktopMode );
00868 }
00869
00870 bool Workspace::startWalkThroughDesktopList()
00871 {
00872 return startWalkThroughDesktops( TabBox::DesktopListMode );
00873 }
00874
00875 void Workspace::KDEWalkThroughWindows( bool forward )
00876 {
00877 tab_box->nextPrev( forward );
00878 tab_box->delayedShow();
00879 }
00880
00881 void Workspace::walkThroughDesktops( bool forward )
00882 {
00883 tab_box->nextPrev( forward );
00884 tab_box->delayedShow();
00885 }
00886
00887 void Workspace::CDEWalkThroughWindows( bool forward )
00888 {
00889 Client* c = topClientOnDesktop( currentDesktop());
00890 Client* nc = c;
00891 bool options_traverse_all;
00892 {
00893 KConfigGroupSaver saver( KGlobal::config(), "TabBox" );
00894 options_traverse_all = KGlobal::config()->readNumEntry("TraverseAll", false );
00895 }
00896
00897 if ( !forward )
00898 {
00899 do
00900 {
00901 nc = previousStaticClient(nc);
00902 } while (nc && nc != c &&
00903 (( !options_traverse_all && !nc->isOnDesktop(currentDesktop())) ||
00904 nc->isMinimized() || !nc->wantsTabFocus() ) );
00905 }
00906 else
00907 {
00908 do
00909 {
00910 nc = nextStaticClient(nc);
00911 } while (nc && nc != c &&
00912 (( !options_traverse_all && !nc->isOnDesktop(currentDesktop())) ||
00913 nc->isMinimized() || !nc->wantsTabFocus() ) );
00914 }
00915 if (c && c != nc)
00916 lowerClient( c );
00917 if (nc)
00918 {
00919 if ( options->focusPolicyIsReasonable() )
00920 {
00921 activateClient( nc );
00922 if( nc->isShade())
00923 nc->setShade( ShadeActivated );
00924 }
00925 else
00926 {
00927 if( !nc->isOnDesktop( currentDesktop()))
00928 setCurrentDesktop( nc->desktop());
00929 raiseClient( nc );
00930 }
00931 }
00932 }
00933
00934 void Workspace::KDEOneStepThroughWindows( bool forward )
00935 {
00936 tab_box->setMode( TabBox::WindowsMode );
00937 tab_box->reset();
00938 tab_box->nextPrev( forward );
00939 if( Client* c = tab_box->currentClient() )
00940 {
00941 activateClient( c );
00942 if( c->isShade())
00943 c->setShade( ShadeActivated );
00944 }
00945 }
00946
00947 void Workspace::oneStepThroughDesktops( bool forward, int mode )
00948 {
00949 tab_box->setMode( (TabBox::Mode) mode );
00950 tab_box->reset();
00951 tab_box->nextPrev( forward );
00952 if ( tab_box->currentDesktop() != -1 )
00953 setCurrentDesktop( tab_box->currentDesktop() );
00954 }
00955
00956 void Workspace::oneStepThroughDesktops( bool forward )
00957 {
00958 oneStepThroughDesktops( forward, TabBox::DesktopMode );
00959 }
00960
00961 void Workspace::oneStepThroughDesktopList( bool forward )
00962 {
00963 oneStepThroughDesktops( forward, TabBox::DesktopListMode );
00964 }
00965
00969 void Workspace::tabBoxKeyPress( const KKeyNative& keyX )
00970 {
00971 bool forward = false;
00972 bool backward = false;
00973
00974 if (tab_grab)
00975 {
00976 forward = cutWalkThroughWindows.contains( keyX );
00977 backward = cutWalkThroughWindowsReverse.contains( keyX );
00978 if (forward || backward)
00979 {
00980 kdDebug(125) << "== " << cutWalkThroughWindows.toStringInternal()
00981 << " or " << cutWalkThroughWindowsReverse.toStringInternal() << endl;
00982 KDEWalkThroughWindows( forward );
00983 }
00984 }
00985 else if (control_grab)
00986 {
00987 forward = cutWalkThroughDesktops.contains( keyX ) ||
00988 cutWalkThroughDesktopList.contains( keyX );
00989 backward = cutWalkThroughDesktopsReverse.contains( keyX ) ||
00990 cutWalkThroughDesktopListReverse.contains( keyX );
00991 if (forward || backward)
00992 walkThroughDesktops(forward);
00993 }
00994
00995 if (control_grab || tab_grab)
00996 {
00997 uint keyQt = keyX.keyCodeQt();
00998 if ( ((keyQt & 0xffff) == Qt::Key_Escape)
00999 && !(forward || backward) )
01000 {
01001 closeTabBox();
01002 }
01003 }
01004 }
01005
01006 void Workspace::closeTabBox()
01007 {
01008 removeTabBoxGrab();
01009 tab_box->hide();
01010 keys->setEnabled( true );
01011 client_keys->setEnabled( true );
01012 tab_grab = FALSE;
01013 control_grab = FALSE;
01014 }
01015
01019 void Workspace::tabBoxKeyRelease( const XKeyEvent& ev )
01020 {
01021 unsigned int mk = ev.state &
01022 (KKeyNative::modX(KKey::SHIFT) |
01023 KKeyNative::modX(KKey::CTRL) |
01024 KKeyNative::modX(KKey::ALT) |
01025 KKeyNative::modX(KKey::WIN));
01026
01027
01028
01029
01030 int mod_index = -1;
01031 for( int i = ShiftMapIndex;
01032 i <= Mod5MapIndex;
01033 ++i )
01034 if(( mk & ( 1 << i )) != 0 )
01035 {
01036 if( mod_index >= 0 )
01037 return;
01038 mod_index = i;
01039 }
01040 bool release = false;
01041 if( mod_index == -1 )
01042 release = true;
01043 else
01044 {
01045 XModifierKeymap* xmk = XGetModifierMapping(qt_xdisplay());
01046 for (int i=0; i<xmk->max_keypermod; i++)
01047 if (xmk->modifiermap[xmk->max_keypermod * mod_index + i]
01048 == ev.keycode)
01049 release = true;
01050 XFreeModifiermap(xmk);
01051 }
01052 if( !release )
01053 return;
01054 if (tab_grab)
01055 {
01056 removeTabBoxGrab();
01057 tab_box->hide();
01058 keys->setEnabled( true );
01059 client_keys->setEnabled( true );
01060 tab_grab = false;
01061 if( Client* c = tab_box->currentClient())
01062 {
01063 activateClient( c );
01064 if( c->isShade())
01065 c->setShade( ShadeActivated );
01066 }
01067 }
01068 if (control_grab)
01069 {
01070 removeTabBoxGrab();
01071 tab_box->hide();
01072 keys->setEnabled( true );
01073 client_keys->setEnabled( true );
01074 control_grab = False;
01075 if ( tab_box->currentDesktop() != -1 )
01076 {
01077 setCurrentDesktop( tab_box->currentDesktop() );
01078
01079 }
01080 }
01081 }
01082
01083
01084 int Workspace::nextDesktopFocusChain( int iDesktop ) const
01085 {
01086 int i = desktop_focus_chain.find( iDesktop );
01087 if( i >= 0 && i+1 < (int)desktop_focus_chain.size() )
01088 return desktop_focus_chain[i+1];
01089 else if( desktop_focus_chain.size() > 0 )
01090 return desktop_focus_chain[ 0 ];
01091 else
01092 return 1;
01093 }
01094
01095 int Workspace::previousDesktopFocusChain( int iDesktop ) const
01096 {
01097 int i = desktop_focus_chain.find( iDesktop );
01098 if( i-1 >= 0 )
01099 return desktop_focus_chain[i-1];
01100 else if( desktop_focus_chain.size() > 0 )
01101 return desktop_focus_chain[desktop_focus_chain.size()-1];
01102 else
01103 return numberOfDesktops();
01104 }
01105
01110 Client* Workspace::nextFocusChainClient( Client* c ) const
01111 {
01112 if ( focus_chain.isEmpty() )
01113 return 0;
01114 ClientList::ConstIterator it = focus_chain.find( c );
01115 if ( it == focus_chain.end() )
01116 return focus_chain.last();
01117 if ( it == focus_chain.begin() )
01118 return focus_chain.last();
01119 --it;
01120 return *it;
01121 }
01122
01127 Client* Workspace::previousFocusChainClient( Client* c ) const
01128 {
01129 if ( focus_chain.isEmpty() )
01130 return 0;
01131 ClientList::ConstIterator it = focus_chain.find( c );
01132 if ( it == focus_chain.end() )
01133 return focus_chain.first();
01134 ++it;
01135 if ( it == focus_chain.end() )
01136 return focus_chain.first();
01137 return *it;
01138 }
01139
01144 Client* Workspace::nextStaticClient( Client* c ) const
01145 {
01146 if ( !c || clients.isEmpty() )
01147 return 0;
01148 ClientList::ConstIterator it = clients.find( c );
01149 if ( it == clients.end() )
01150 return clients.first();
01151 ++it;
01152 if ( it == clients.end() )
01153 return clients.first();
01154 return *it;
01155 }
01160 Client* Workspace::previousStaticClient( Client* c ) const
01161 {
01162 if ( !c || clients.isEmpty() )
01163 return 0;
01164 ClientList::ConstIterator it = clients.find( c );
01165 if ( it == clients.end() )
01166 return clients.last();
01167 if ( it == clients.begin() )
01168 return clients.last();
01169 --it;
01170 return *it;
01171 }
01172
01173 bool Workspace::establishTabBoxGrab()
01174 {
01175 if( XGrabKeyboard( qt_xdisplay(), root, FALSE,
01176 GrabModeAsync, GrabModeAsync, qt_x_time) != GrabSuccess )
01177 return false;
01178
01179
01180
01181
01182
01183 assert( !forced_global_mouse_grab );
01184 forced_global_mouse_grab = true;
01185 if( active_client != NULL )
01186 active_client->updateMouseGrab();
01187 return true;
01188 }
01189
01190 void Workspace::removeTabBoxGrab()
01191 {
01192 XUngrabKeyboard(qt_xdisplay(), qt_x_time);
01193 assert( forced_global_mouse_grab );
01194 forced_global_mouse_grab = false;
01195 if( active_client != NULL )
01196 active_client->updateMouseGrab();
01197 }
01198
01199 }
01200
01201 #include "tabbox.moc"