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->readNumEntry("TraverseAll", false );
00530 }
00531
00550 void TabBox::delayedShow()
00551 {
00552 KConfig * c(KGlobal::config());
00553 c->setGroup("TabBox");
00554 bool delay = c->readNumEntry("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 )
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 )
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 = activeClient();
00930 Client* nc = c;
00931 bool options_traverse_all;
00932 {
00933 KConfigGroupSaver saver( KGlobal::config(), "TabBox" );
00934 options_traverse_all = KGlobal::config()->readNumEntry("TraverseAll", false );
00935 }
00936
00937 Client* firstClient = 0;
00938 do
00939 {
00940 nc = forward ? nextStaticClient(nc) : previousStaticClient(nc);
00941 if (!firstClient)
00942 {
00943
00944
00945 firstClient = nc;
00946 }
00947 else if (nc == firstClient)
00948 {
00949
00950 nc = 0;
00951 break;
00952 }
00953 } while (nc && nc != c &&
00954 (( !options_traverse_all && !nc->isOnDesktop(currentDesktop())) ||
00955 nc->isMinimized() || !nc->wantsTabFocus() ) );
00956 if (nc)
00957 {
00958 if (c && c != nc)
00959 lowerClient( c );
00960 if ( options->focusPolicyIsReasonable() )
00961 {
00962 activateClient( nc );
00963 if( nc->isShade())
00964 nc->setShade( ShadeActivated );
00965 }
00966 else
00967 {
00968 if( !nc->isOnDesktop( currentDesktop()))
00969 setCurrentDesktop( nc->desktop());
00970 raiseClient( nc );
00971 }
00972 }
00973 }
00974
00975 void Workspace::KDEOneStepThroughWindows( bool forward )
00976 {
00977 tab_box->setMode( TabBox::WindowsMode );
00978 tab_box->reset();
00979 tab_box->nextPrev( forward );
00980 if( Client* c = tab_box->currentClient() )
00981 {
00982 activateClient( c );
00983 if( c->isShade())
00984 c->setShade( ShadeActivated );
00985 }
00986 }
00987
00988 void Workspace::oneStepThroughDesktops( bool forward, int mode )
00989 {
00990 tab_box->setMode( (TabBox::Mode) mode );
00991 tab_box->reset();
00992 tab_box->nextPrev( forward );
00993 if ( tab_box->currentDesktop() != -1 )
00994 setCurrentDesktop( tab_box->currentDesktop() );
00995 }
00996
00997 void Workspace::oneStepThroughDesktops( bool forward )
00998 {
00999 oneStepThroughDesktops( forward, TabBox::DesktopMode );
01000 }
01001
01002 void Workspace::oneStepThroughDesktopList( bool forward )
01003 {
01004 oneStepThroughDesktops( forward, TabBox::DesktopListMode );
01005 }
01006
01010 void Workspace::tabBoxKeyPress( const KKeyNative& keyX )
01011 {
01012 bool forward = false;
01013 bool backward = false;
01014
01015 if (tab_grab)
01016 {
01017 forward = cutWalkThroughWindows.contains( keyX );
01018 backward = cutWalkThroughWindowsReverse.contains( keyX );
01019 if (forward || backward)
01020 {
01021 kdDebug(125) << "== " << cutWalkThroughWindows.toStringInternal()
01022 << " or " << cutWalkThroughWindowsReverse.toStringInternal() << endl;
01023 KDEWalkThroughWindows( forward );
01024 }
01025 }
01026 else if (control_grab)
01027 {
01028 forward = cutWalkThroughDesktops.contains( keyX ) ||
01029 cutWalkThroughDesktopList.contains( keyX );
01030 backward = cutWalkThroughDesktopsReverse.contains( keyX ) ||
01031 cutWalkThroughDesktopListReverse.contains( keyX );
01032 if (forward || backward)
01033 walkThroughDesktops(forward);
01034 }
01035
01036 if (control_grab || tab_grab)
01037 {
01038 uint keyQt = keyX.keyCodeQt();
01039 if ( ((keyQt & 0xffff) == Qt::Key_Escape)
01040 && !(forward || backward) )
01041 {
01042 closeTabBox();
01043 }
01044 }
01045 }
01046
01047 void Workspace::closeTabBox()
01048 {
01049 removeTabBoxGrab();
01050 tab_box->hide();
01051 keys->setEnabled( true );
01052 disable_shortcuts_keys->setEnabled( true );
01053 client_keys->setEnabled( true );
01054 tab_grab = FALSE;
01055 control_grab = FALSE;
01056 }
01057
01061 void Workspace::tabBoxKeyRelease( const XKeyEvent& ev )
01062 {
01063 unsigned int mk = ev.state &
01064 (KKeyNative::modX(KKey::SHIFT) |
01065 KKeyNative::modX(KKey::CTRL) |
01066 KKeyNative::modX(KKey::ALT) |
01067 KKeyNative::modX(KKey::WIN));
01068
01069
01070
01071
01072 int mod_index = -1;
01073 for( int i = ShiftMapIndex;
01074 i <= Mod5MapIndex;
01075 ++i )
01076 if(( mk & ( 1 << i )) != 0 )
01077 {
01078 if( mod_index >= 0 )
01079 return;
01080 mod_index = i;
01081 }
01082 bool release = false;
01083 if( mod_index == -1 )
01084 release = true;
01085 else
01086 {
01087 XModifierKeymap* xmk = XGetModifierMapping(qt_xdisplay());
01088 for (int i=0; i<xmk->max_keypermod; i++)
01089 if (xmk->modifiermap[xmk->max_keypermod * mod_index + i]
01090 == ev.keycode)
01091 release = true;
01092 XFreeModifiermap(xmk);
01093 }
01094 if( !release )
01095 return;
01096 if (tab_grab)
01097 {
01098 removeTabBoxGrab();
01099 tab_box->hide();
01100 keys->setEnabled( true );
01101 disable_shortcuts_keys->setEnabled( true );
01102 client_keys->setEnabled( true );
01103 tab_grab = false;
01104 if( Client* c = tab_box->currentClient())
01105 {
01106 activateClient( c );
01107 if( c->isShade())
01108 c->setShade( ShadeActivated );
01109 }
01110 }
01111 if (control_grab)
01112 {
01113 removeTabBoxGrab();
01114 tab_box->hide();
01115 keys->setEnabled( true );
01116 disable_shortcuts_keys->setEnabled( true );
01117 client_keys->setEnabled( true );
01118 control_grab = False;
01119 if ( tab_box->currentDesktop() != -1 )
01120 {
01121 setCurrentDesktop( tab_box->currentDesktop() );
01122 }
01123 }
01124 }
01125
01126
01127 int Workspace::nextDesktopFocusChain( int iDesktop ) const
01128 {
01129 int i = desktop_focus_chain.find( iDesktop );
01130 if( i >= 0 && i+1 < (int)desktop_focus_chain.size() )
01131 return desktop_focus_chain[i+1];
01132 else if( desktop_focus_chain.size() > 0 )
01133 return desktop_focus_chain[ 0 ];
01134 else
01135 return 1;
01136 }
01137
01138 int Workspace::previousDesktopFocusChain( int iDesktop ) const
01139 {
01140 int i = desktop_focus_chain.find( iDesktop );
01141 if( i-1 >= 0 )
01142 return desktop_focus_chain[i-1];
01143 else if( desktop_focus_chain.size() > 0 )
01144 return desktop_focus_chain[desktop_focus_chain.size()-1];
01145 else
01146 return numberOfDesktops();
01147 }
01148
01153 Client* Workspace::nextFocusChainClient( Client* c ) const
01154 {
01155 if ( focus_chain.isEmpty() )
01156 return 0;
01157 ClientList::ConstIterator it = focus_chain.find( c );
01158 if ( it == focus_chain.end() )
01159 return focus_chain.last();
01160 if ( it == focus_chain.begin() )
01161 return focus_chain.last();
01162 --it;
01163 return *it;
01164 }
01165
01170 Client* Workspace::previousFocusChainClient( Client* c ) const
01171 {
01172 if ( focus_chain.isEmpty() )
01173 return 0;
01174 ClientList::ConstIterator it = focus_chain.find( c );
01175 if ( it == focus_chain.end() )
01176 return focus_chain.first();
01177 ++it;
01178 if ( it == focus_chain.end() )
01179 return focus_chain.first();
01180 return *it;
01181 }
01182
01187 Client* Workspace::nextStaticClient( Client* c ) const
01188 {
01189 if ( !c || clients.isEmpty() )
01190 return 0;
01191 ClientList::ConstIterator it = clients.find( c );
01192 if ( it == clients.end() )
01193 return clients.first();
01194 ++it;
01195 if ( it == clients.end() )
01196 return clients.first();
01197 return *it;
01198 }
01203 Client* Workspace::previousStaticClient( 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.last();
01210 if ( it == clients.begin() )
01211 return clients.last();
01212 --it;
01213 return *it;
01214 }
01215
01216 bool Workspace::establishTabBoxGrab()
01217 {
01218 if( XGrabKeyboard( qt_xdisplay(), root, FALSE,
01219 GrabModeAsync, GrabModeAsync, qt_x_time) != GrabSuccess )
01220 return false;
01221
01222
01223
01224
01225
01226 assert( !forced_global_mouse_grab );
01227 forced_global_mouse_grab = true;
01228 if( active_client != NULL )
01229 active_client->updateMouseGrab();
01230 return true;
01231 }
01232
01233 void Workspace::removeTabBoxGrab()
01234 {
01235 XUngrabKeyboard(qt_xdisplay(), qt_x_time);
01236 assert( forced_global_mouse_grab );
01237 forced_global_mouse_grab = false;
01238 if( active_client != NULL )
01239 active_client->updateMouseGrab();
01240 }
01241
01242 }
01243
01244 #include "tabbox.moc"