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