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 KDEOneStepThroughWindows( true );
00743 }
00744 }
00745
00746 void Workspace::slotWalkBackThroughWindows()
00747 {
00748 if ( root != qt_xrootwin() )
00749 return;
00750 if( tab_grab || control_grab )
00751 return;
00752 if ( options->altTabStyle == Options::CDE || !options->focusPolicyIsReasonable() )
00753 {
00754
00755 CDEWalkThroughWindows( false );
00756 }
00757 else
00758 {
00759 if ( areModKeysDepressed( cutWalkThroughWindowsReverse ) )
00760 {
00761 if ( startKDEWalkThroughWindows() )
00762 KDEWalkThroughWindows( false );
00763 }
00764 else
00765 {
00766 KDEOneStepThroughWindows( false );
00767 }
00768 }
00769 }
00770
00771 void Workspace::slotWalkThroughDesktops()
00772 {
00773 if ( root != qt_xrootwin() )
00774 return;
00775 if( tab_grab || control_grab )
00776 return;
00777 if ( areModKeysDepressed( cutWalkThroughDesktops ) )
00778 {
00779 if ( startWalkThroughDesktops() )
00780 walkThroughDesktops( true );
00781 }
00782 else
00783 {
00784 oneStepThroughDesktops( true );
00785 }
00786 }
00787
00788 void Workspace::slotWalkBackThroughDesktops()
00789 {
00790 if ( root != qt_xrootwin() )
00791 return;
00792 if( tab_grab || control_grab )
00793 return;
00794 if ( areModKeysDepressed( cutWalkThroughDesktopsReverse ) )
00795 {
00796 if ( startWalkThroughDesktops() )
00797 walkThroughDesktops( false );
00798 }
00799 else
00800 {
00801 oneStepThroughDesktops( false );
00802 }
00803 }
00804
00805 void Workspace::slotWalkThroughDesktopList()
00806 {
00807 if ( root != qt_xrootwin() )
00808 return;
00809 if( tab_grab || control_grab )
00810 return;
00811 if ( areModKeysDepressed( cutWalkThroughDesktopList ) )
00812 {
00813 if ( startWalkThroughDesktopList() )
00814 walkThroughDesktops( true );
00815 }
00816 else
00817 {
00818 oneStepThroughDesktopList( true );
00819 }
00820 }
00821
00822 void Workspace::slotWalkBackThroughDesktopList()
00823 {
00824 if ( root != qt_xrootwin() )
00825 return;
00826 if( tab_grab || control_grab )
00827 return;
00828 if ( areModKeysDepressed( cutWalkThroughDesktopListReverse ) )
00829 {
00830 if ( startWalkThroughDesktopList() )
00831 walkThroughDesktops( false );
00832 }
00833 else
00834 {
00835 oneStepThroughDesktopList( false );
00836 }
00837 }
00838
00839 bool Workspace::startKDEWalkThroughWindows()
00840 {
00841 if( !establishTabBoxGrab())
00842 return false;
00843 tab_grab = TRUE;
00844 keys->setEnabled( false );
00845 client_keys->setEnabled( false );
00846 tab_box->setMode( TabBox::WindowsMode );
00847 tab_box->reset();
00848 return TRUE;
00849 }
00850
00851 bool Workspace::startWalkThroughDesktops( int mode )
00852 {
00853 if( !establishTabBoxGrab())
00854 return false;
00855 control_grab = TRUE;
00856 keys->setEnabled( false );
00857 client_keys->setEnabled( false );
00858 tab_box->setMode( (TabBox::Mode) mode );
00859 tab_box->reset();
00860 return TRUE;
00861 }
00862
00863 bool Workspace::startWalkThroughDesktops()
00864 {
00865 return startWalkThroughDesktops( TabBox::DesktopMode );
00866 }
00867
00868 bool Workspace::startWalkThroughDesktopList()
00869 {
00870 return startWalkThroughDesktops( TabBox::DesktopListMode );
00871 }
00872
00873 void Workspace::KDEWalkThroughWindows( bool forward )
00874 {
00875 tab_box->nextPrev( forward );
00876 tab_box->delayedShow();
00877 }
00878
00879 void Workspace::walkThroughDesktops( bool forward )
00880 {
00881 tab_box->nextPrev( forward );
00882 tab_box->delayedShow();
00883 }
00884
00885 void Workspace::CDEWalkThroughWindows( bool forward )
00886 {
00887 Client* c = activeClient();
00888 Client* nc = c;
00889 bool options_traverse_all;
00890 {
00891 KConfigGroupSaver saver( KGlobal::config(), "TabBox" );
00892 options_traverse_all = KGlobal::config()->readNumEntry("TraverseAll", false );
00893 }
00894
00895 if ( !forward )
00896 {
00897 do
00898 {
00899 nc = previousStaticClient(nc);
00900 } while (nc && nc != c &&
00901 (( !options_traverse_all && !nc->isOnDesktop(currentDesktop())) ||
00902 nc->isMinimized() || !nc->wantsTabFocus() ) );
00903 }
00904 else
00905 {
00906 do
00907 {
00908 nc = nextStaticClient(nc);
00909 } while (nc && nc != c &&
00910 (( !options_traverse_all && !nc->isOnDesktop(currentDesktop())) ||
00911 nc->isMinimized() || !nc->wantsTabFocus() ) );
00912 }
00913 if (c && c != nc)
00914 lowerClient( c );
00915 if (nc)
00916 {
00917 if ( options->focusPolicyIsReasonable() )
00918 {
00919 activateClient( nc );
00920 if( nc->isShade())
00921 nc->setShade( ShadeActivated );
00922 }
00923 else
00924 {
00925 if( !nc->isOnDesktop( currentDesktop()))
00926 setCurrentDesktop( nc->desktop());
00927 raiseClient( nc );
00928 }
00929 }
00930 }
00931
00932 void Workspace::KDEOneStepThroughWindows( bool forward )
00933 {
00934 tab_box->setMode( TabBox::WindowsMode );
00935 tab_box->reset();
00936 tab_box->nextPrev( forward );
00937 if( Client* c = tab_box->currentClient() )
00938 {
00939 activateClient( c );
00940 if( c->isShade())
00941 c->setShade( ShadeActivated );
00942 }
00943 }
00944
00945 void Workspace::oneStepThroughDesktops( bool forward, int mode )
00946 {
00947 tab_box->setMode( (TabBox::Mode) mode );
00948 tab_box->reset();
00949 tab_box->nextPrev( forward );
00950 if ( tab_box->currentDesktop() != -1 )
00951 setCurrentDesktop( tab_box->currentDesktop() );
00952 }
00953
00954 void Workspace::oneStepThroughDesktops( bool forward )
00955 {
00956 oneStepThroughDesktops( forward, TabBox::DesktopMode );
00957 }
00958
00959 void Workspace::oneStepThroughDesktopList( bool forward )
00960 {
00961 oneStepThroughDesktops( forward, TabBox::DesktopListMode );
00962 }
00963
00967 void Workspace::tabBoxKeyPress( const KKeyNative& keyX )
00968 {
00969 bool forward = false;
00970 bool backward = false;
00971
00972 if (tab_grab)
00973 {
00974 forward = cutWalkThroughWindows.contains( keyX );
00975 backward = cutWalkThroughWindowsReverse.contains( keyX );
00976 if (forward || backward)
00977 {
00978 kdDebug(125) << "== " << cutWalkThroughWindows.toStringInternal()
00979 << " or " << cutWalkThroughWindowsReverse.toStringInternal() << endl;
00980 KDEWalkThroughWindows( forward );
00981 }
00982 }
00983 else if (control_grab)
00984 {
00985 forward = cutWalkThroughDesktops.contains( keyX ) ||
00986 cutWalkThroughDesktopList.contains( keyX );
00987 backward = cutWalkThroughDesktopsReverse.contains( keyX ) ||
00988 cutWalkThroughDesktopListReverse.contains( keyX );
00989 if (forward || backward)
00990 walkThroughDesktops(forward);
00991 }
00992
00993 if (control_grab || tab_grab)
00994 {
00995 uint keyQt = keyX.keyCodeQt();
00996 if ( ((keyQt & 0xffff) == Qt::Key_Escape)
00997 && !(forward || backward) )
00998 {
00999 closeTabBox();
01000 }
01001 }
01002 }
01003
01004 void Workspace::closeTabBox()
01005 {
01006 removeTabBoxGrab();
01007 tab_box->hide();
01008 keys->setEnabled( true );
01009 client_keys->setEnabled( true );
01010 tab_grab = FALSE;
01011 control_grab = FALSE;
01012 }
01013
01017 void Workspace::tabBoxKeyRelease( const XKeyEvent& ev )
01018 {
01019 unsigned int mk = ev.state &
01020 (KKeyNative::modX(KKey::SHIFT) |
01021 KKeyNative::modX(KKey::CTRL) |
01022 KKeyNative::modX(KKey::ALT) |
01023 KKeyNative::modX(KKey::WIN));
01024
01025
01026
01027
01028 int mod_index = -1;
01029 for( int i = ShiftMapIndex;
01030 i <= Mod5MapIndex;
01031 ++i )
01032 if(( mk & ( 1 << i )) != 0 )
01033 {
01034 if( mod_index >= 0 )
01035 return;
01036 mod_index = i;
01037 }
01038 bool release = false;
01039 if( mod_index == -1 )
01040 release = true;
01041 else
01042 {
01043 XModifierKeymap* xmk = XGetModifierMapping(qt_xdisplay());
01044 for (int i=0; i<xmk->max_keypermod; i++)
01045 if (xmk->modifiermap[xmk->max_keypermod * mod_index + i]
01046 == ev.keycode)
01047 release = true;
01048 XFreeModifiermap(xmk);
01049 }
01050 if( !release )
01051 return;
01052 if (tab_grab)
01053 {
01054 removeTabBoxGrab();
01055 tab_box->hide();
01056 keys->setEnabled( true );
01057 client_keys->setEnabled( true );
01058 tab_grab = false;
01059 if( Client* c = tab_box->currentClient())
01060 {
01061 activateClient( c );
01062 if( c->isShade())
01063 c->setShade( ShadeActivated );
01064 }
01065 }
01066 if (control_grab)
01067 {
01068 removeTabBoxGrab();
01069 tab_box->hide();
01070 keys->setEnabled( true );
01071 client_keys->setEnabled( true );
01072 control_grab = False;
01073 if ( tab_box->currentDesktop() != -1 )
01074 {
01075 setCurrentDesktop( tab_box->currentDesktop() );
01076
01077 }
01078 }
01079 }
01080
01081
01082 int Workspace::nextDesktopFocusChain( int iDesktop ) const
01083 {
01084 int i = desktop_focus_chain.find( iDesktop );
01085 if( i >= 0 && i+1 < (int)desktop_focus_chain.size() )
01086 return desktop_focus_chain[i+1];
01087 else if( desktop_focus_chain.size() > 0 )
01088 return desktop_focus_chain[ 0 ];
01089 else
01090 return 1;
01091 }
01092
01093 int Workspace::previousDesktopFocusChain( int iDesktop ) const
01094 {
01095 int i = desktop_focus_chain.find( iDesktop );
01096 if( i-1 >= 0 )
01097 return desktop_focus_chain[i-1];
01098 else if( desktop_focus_chain.size() > 0 )
01099 return desktop_focus_chain[desktop_focus_chain.size()-1];
01100 else
01101 return numberOfDesktops();
01102 }
01103
01108 Client* Workspace::nextFocusChainClient( Client* c ) const
01109 {
01110 if ( focus_chain.isEmpty() )
01111 return 0;
01112 ClientList::ConstIterator it = focus_chain.find( c );
01113 if ( it == focus_chain.end() )
01114 return focus_chain.last();
01115 if ( it == focus_chain.begin() )
01116 return focus_chain.last();
01117 --it;
01118 return *it;
01119 }
01120
01125 Client* Workspace::previousFocusChainClient( Client* c ) const
01126 {
01127 if ( focus_chain.isEmpty() )
01128 return 0;
01129 ClientList::ConstIterator it = focus_chain.find( c );
01130 if ( it == focus_chain.end() )
01131 return focus_chain.first();
01132 ++it;
01133 if ( it == focus_chain.end() )
01134 return focus_chain.first();
01135 return *it;
01136 }
01137
01142 Client* Workspace::nextStaticClient( Client* c ) const
01143 {
01144 if ( !c || clients.isEmpty() )
01145 return 0;
01146 ClientList::ConstIterator it = clients.find( c );
01147 if ( it == clients.end() )
01148 return clients.first();
01149 ++it;
01150 if ( it == clients.end() )
01151 return clients.first();
01152 return *it;
01153 }
01158 Client* Workspace::previousStaticClient( Client* c ) const
01159 {
01160 if ( !c || clients.isEmpty() )
01161 return 0;
01162 ClientList::ConstIterator it = clients.find( c );
01163 if ( it == clients.end() )
01164 return clients.last();
01165 if ( it == clients.begin() )
01166 return clients.last();
01167 --it;
01168 return *it;
01169 }
01170
01171 bool Workspace::establishTabBoxGrab()
01172 {
01173 if( XGrabKeyboard( qt_xdisplay(), root, FALSE,
01174 GrabModeAsync, GrabModeAsync, qt_x_time) != GrabSuccess )
01175 return false;
01176
01177
01178
01179
01180
01181 assert( !forced_global_mouse_grab );
01182 forced_global_mouse_grab = true;
01183 if( active_client != NULL )
01184 active_client->updateMouseGrab();
01185 return true;
01186 }
01187
01188 void Workspace::removeTabBoxGrab()
01189 {
01190 XUngrabKeyboard(qt_xdisplay(), qt_x_time);
01191 assert( forced_global_mouse_grab );
01192 forced_global_mouse_grab = false;
01193 if( active_client != NULL )
01194 active_client->updateMouseGrab();
01195 }
01196
01197 }
01198
01199 #include "tabbox.moc"