00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "tabbox.h"
00024 #include <QTextStream>
00025 #include "workspace.h"
00026 #include "effects.h"
00027 #include "client.h"
00028 #include <QPainter>
00029 #include <QLabel>
00030 #include <qdrawutil.h>
00031 #include <QStyle>
00032 #include <kglobal.h>
00033 #include <fixx11h.h>
00034 #include <kconfig.h>
00035 #include <klocale.h>
00036 #include <QApplication>
00037 #include <QDesktopWidget>
00038 #include <QAction>
00039 #include <stdarg.h>
00040 #include <kdebug.h>
00041 #include <kglobalsettings.h>
00042 #include <kiconeffect.h>
00043 #include <X11/keysym.h>
00044 #include <X11/keysymdef.h>
00045 #include <QX11Info>
00046 #include <kactioncollection.h>
00047 #include <kkeyserver.h>
00048 #include <kconfiggroup.h>
00049
00050
00051
00052 namespace KWin
00053 {
00054
00055 extern QPixmap* kwin_get_menu_pix_hack();
00056
00057 TabBox::TabBox( Workspace *ws )
00058 : QFrame( 0, Qt::X11BypassWindowManagerHint )
00059 , wspace(ws)
00060 , client(0)
00061 , display_refcount( 0 )
00062 {
00063 setFrameStyle(QFrame::StyledPanel);
00064 setFrameShadow(QFrame::Raised);
00065 setBackgroundRole(QPalette::Base);
00066 setLineWidth(3);
00067 setMidLineWidth(3);
00068 setContentsMargins( 3, 3, 3, 3 );
00069
00070 showMiniIcon = false;
00071
00072 no_tasks = i18n("*** No Windows ***");
00073 m = TabBoxDesktopMode;
00074 reconfigure();
00075 reset();
00076 connect(&delayedShowTimer, SIGNAL(timeout()), this, SLOT(show()));
00077 }
00078
00079 TabBox::~TabBox()
00080 {
00081 }
00082
00083
00089 void TabBox::setMode( TabBoxMode mode )
00090 {
00091 m = mode;
00092 }
00093
00094
00098 void TabBox::createClientList(ClientList &list, int desktop , Client *c, bool chain)
00099 {
00100 ClientList::size_type idx = 0;
00101
00102 list.clear();
00103
00104 Client* start = c;
00105
00106 if ( chain )
00107 c = workspace()->nextClientFocusChain(c);
00108 else
00109 c = workspace()->stackingOrder().first();
00110
00111 Client* stop = c;
00112
00113 while ( c )
00114 {
00115 Client* add = NULL;
00116 if ( ((desktop == -1) || c->isOnDesktop(desktop))
00117 && c->wantsTabFocus() )
00118 {
00119 Client* modal = c->findModal();
00120 if( modal == NULL || modal == c )
00121 add = c;
00122 else if( !list.contains( modal ))
00123 add = modal;
00124 else
00125 {
00126
00127 }
00128 }
00129 if( options->separateScreenFocus && options->xineramaEnabled )
00130 {
00131 if( c->screen() != workspace()->activeScreen())
00132 add = NULL;
00133 }
00134 if( add != NULL )
00135 {
00136 if ( start == add )
00137 {
00138 list.removeAll( add );
00139 list.prepend( add );
00140 }
00141 else
00142 list += add;
00143 }
00144 if ( chain )
00145 c = workspace()->nextClientFocusChain( c );
00146 else
00147 {
00148 if ( idx >= (workspace()->stackingOrder().size()-1) )
00149 c = 0;
00150 else
00151 c = workspace()->stackingOrder()[++idx];
00152 }
00153
00154 if ( c == stop )
00155 break;
00156 }
00157 }
00158
00159
00163 void TabBox::createDesktopList(QList< int > &list, int start, SortOrder order)
00164 {
00165 list.clear();
00166
00167 int iDesktop = start;
00168
00169 for( int i = 1; i <= workspace()->numberOfDesktops(); i++ )
00170 {
00171 list.append( iDesktop );
00172 if ( order == StaticOrder )
00173 {
00174 iDesktop = workspace()->nextDesktopStatic( iDesktop );
00175 }
00176 else
00177 {
00178 iDesktop = workspace()->nextDesktopFocusChain( iDesktop );
00179 }
00180 }
00181 }
00182
00183
00188 void TabBox::reset( bool partial_reset )
00189 {
00190 int w, h, cw = 0, wmax = 0;
00191
00192 QRect r = workspace()->screenGeometry( workspace()->activeScreen());
00193
00194
00195
00196 lineHeight = qMax(fontMetrics().height() + 2, 32 + 4);
00197
00198 if ( mode() == TabBoxWindowsMode )
00199 {
00200 Client* starting_client = 0;
00201 if( partial_reset && clients.count() != 0 )
00202 starting_client = clients.first();
00203 else
00204 client = starting_client = workspace()->activeClient();
00205
00206
00207 createClientList(clients, options_traverse_all ? -1 : workspace()->currentDesktop(), starting_client, true);
00208
00209
00210 cw = fontMetrics().width(no_tasks)+20;
00211 for (ClientList::ConstIterator it = clients.constBegin(); it != clients.constEnd(); ++it)
00212 {
00213 cw = fontMetrics().width( (*it)->caption() );
00214 if ( cw > wmax ) wmax = cw;
00215 }
00216
00217
00218 if ( clients.count() == 0 )
00219 {
00220 QFont f = font();
00221 f.setBold( true );
00222 f.setPointSize( 14 );
00223
00224 h = QFontMetrics(f).height()*4;
00225 }
00226 else
00227 {
00228 showMiniIcon = false;
00229 h = clients.count() * lineHeight;
00230
00231 if ( h > (r.height()-(2*frameWidth())) )
00232 {
00233 showMiniIcon = true;
00234
00235 lineHeight = qMax(fontMetrics().height() + 2, 16 + 2);
00236
00237 h = clients.count() * lineHeight;
00238
00239 if ( h > (r.height()-(2*frameWidth())) )
00240 {
00241
00242 int howMany = (h - (r.height()-(2*frameWidth())))/lineHeight;
00243 for (; howMany; howMany--)
00244 clients.removeAll(clients.last());
00245
00246 h = clients.count() * lineHeight;
00247 }
00248 }
00249 }
00250 }
00251 else
00252 {
00253 int starting_desktop;
00254 if( mode() == TabBoxDesktopListMode )
00255 {
00256 starting_desktop = 1;
00257 createDesktopList(desktops, starting_desktop, StaticOrder );
00258 }
00259 else
00260 {
00261 starting_desktop = workspace()->currentDesktop();
00262 createDesktopList(desktops, starting_desktop, MostRecentlyUsedOrder );
00263 }
00264
00265 if( !partial_reset )
00266 desk = workspace()->currentDesktop();
00267
00268 showMiniIcon = false;
00269
00270 foreach (int it, desktops)
00271 {
00272 cw = fontMetrics().width( workspace()->desktopName(it) );
00273 if ( cw > wmax ) wmax = cw;
00274 }
00275
00276
00277 h = desktops.count() * lineHeight;
00278 }
00279
00280
00281 h += 2 * frameWidth();
00282 w = 2*frameWidth() + 5*2 + ( showMiniIcon ? 16 : 32 ) + 8 + wmax;
00283 w = qBound( r.width()/3 , w, r.width() * 4 / 5 );
00284
00285 setGeometry( (r.width()-w)/2 + r.x(),
00286 (r.height()-h)/2+ r.y(),
00287 w, h );
00288
00289 if( effects )
00290 static_cast<EffectsHandlerImpl*>(effects)->tabBoxUpdated();
00291 }
00292
00293
00297 void TabBox::nextPrev( bool next)
00298 {
00299 if ( mode() == TabBoxWindowsMode )
00300 {
00301 Client* firstClient = 0;
00302 Client* newClient = client;
00303 do
00304 {
00305 if ( next )
00306 newClient = workspace()->nextClientFocusChain(newClient);
00307 else
00308 newClient = workspace()->previousClientFocusChain(newClient);
00309 if (!firstClient)
00310 {
00311
00312
00313 firstClient = newClient;
00314 }
00315 else if (newClient == firstClient)
00316 {
00317
00318 newClient = 0;
00319 break;
00320 }
00321 } while ( newClient && !clients.contains( newClient ));
00322 setCurrentClient( newClient );
00323 }
00324 else if( mode() == TabBoxDesktopMode )
00325 {
00326 setCurrentDesktop ( next ? workspace()->nextDesktopFocusChain( desk )
00327 : workspace()->previousDesktopFocusChain( desk ) );
00328 }
00329 else
00330 {
00331 setCurrentDesktop ( next ? workspace()->nextDesktopStatic( desk )
00332 : workspace()->previousDesktopStatic( desk )) ;
00333 }
00334
00335 if( effects )
00336 static_cast<EffectsHandlerImpl*>(effects)->tabBoxUpdated();
00337 update();
00338 }
00339
00340
00341
00346 Client* TabBox::currentClient()
00347 {
00348 if ( mode() != TabBoxWindowsMode )
00349 return 0;
00350 if (!workspace()->hasClient( client ))
00351 return 0;
00352 return client;
00353 }
00354
00360 ClientList TabBox::currentClientList()
00361 {
00362 if( mode() != TabBoxWindowsMode )
00363 return ClientList();
00364 return clients;
00365 }
00366
00367
00373 int TabBox::currentDesktop()
00374 {
00375 if ( mode() == TabBoxDesktopListMode || mode() == TabBoxDesktopMode )
00376 return desk;
00377 return -1;
00378 }
00379
00380
00386 QList< int > TabBox::currentDesktopList()
00387 {
00388 if ( mode() == TabBoxDesktopListMode || mode() == TabBoxDesktopMode )
00389 return desktops;
00390 return QList< int >();
00391 }
00392
00393
00399 void TabBox::setCurrentClient( Client* newClient )
00400 {
00401 client = newClient;
00402 if( effects )
00403 static_cast<EffectsHandlerImpl*>(effects)->tabBoxUpdated();
00404 }
00405
00411 void TabBox::setCurrentDesktop( int newDesktop )
00412 {
00413 desk = newDesktop;
00414 if( effects )
00415 static_cast<EffectsHandlerImpl*>(effects)->tabBoxUpdated();
00416 }
00417
00421 void TabBox::showEvent( QShowEvent* )
00422 {
00423 raise();
00424 }
00425
00426
00430 void TabBox::hideEvent( QHideEvent* )
00431 {
00432 }
00433
00437 void TabBox::paintEvent( QPaintEvent* e )
00438 {
00439 QFrame::paintEvent( e );
00440
00441 QPainter p( this );
00442 QRect r( contentsRect());
00443
00444 QPixmap* menu_pix = kwin_get_menu_pix_hack();
00445
00446 int iconWidth = showMiniIcon ? 16 : 32;
00447 int x = r.x();
00448 int y = r.y();
00449
00450 if ( mode () == TabBoxWindowsMode )
00451 {
00452 if ( !currentClient() )
00453 {
00454 QFont f = font();
00455 f.setBold( true );
00456 f.setPointSize( 14 );
00457
00458 p.setFont(f);
00459 p.drawText( r, Qt::AlignCenter, no_tasks);
00460 }
00461 else
00462 {
00463 for (ClientList::ConstIterator it = clients.constBegin(); it != clients.constEnd(); ++it)
00464 {
00465 if ( workspace()->hasClient( *it ) )
00466 {
00467
00468 if ( (*it) == currentClient() )
00469 p.fillRect(x, y, r.width(), lineHeight, palette().brush( QPalette::Active, QPalette::Highlight ));
00470
00471
00472 QPixmap icon;
00473 if ( showMiniIcon )
00474 {
00475 if ( !(*it)->miniIcon().isNull() )
00476 icon = (*it)->miniIcon();
00477 }
00478 else
00479 if ( !(*it)->icon().isNull() )
00480 icon = (*it)->icon();
00481 else if ( menu_pix )
00482 icon = *menu_pix;
00483
00484 if( !icon.isNull())
00485 {
00486 if( (*it)->isMinimized())
00487 KIconEffect::semiTransparent( icon );
00488 p.drawPixmap( x+5, y + (lineHeight - iconWidth)/2, icon );
00489 }
00490
00491
00492 QString s;
00493
00494 if ( !(*it)->isOnDesktop(workspace()->currentDesktop()) )
00495 s = workspace()->desktopName((*it)->desktop()) + ": ";
00496
00497 if ( (*it)->isMinimized() )
00498 s += '(' + (*it)->caption() + ')';
00499 else
00500 s += (*it)->caption();
00501
00502 s = fontMetrics().elidedText( s, Qt::ElideMiddle, r.width() - 5 - iconWidth - 8 );
00503
00504
00505 if ( (*it) == currentClient() )
00506 p.setPen(palette().color( QPalette::Active, QPalette::HighlightedText ));
00507 else if( (*it)->isMinimized())
00508 {
00509 QColor c1 = palette().color( QPalette::Active, QPalette::Text );
00510 QColor c2 = palette().color( QPalette::Active, QPalette::Background );
00511
00512 int r1, g1, b1;
00513 int r2, g2, b2;
00514
00515 c1.getRgb( &r1, &g1, &b1 );
00516 c2.getRgb( &r2, &g2, &b2 );
00517
00518 r1 += (int) ( .5 * ( r2 - r1 ) );
00519 g1 += (int) ( .5 * ( g2 - g1 ) );
00520 b1 += (int) ( .5 * ( b2 - b1 ) );
00521
00522 p.setPen(QColor( r1, g1, b1 ));
00523 }
00524 else
00525 p.setPen(palette().color( QPalette::Active, QPalette::Text ));
00526
00527 p.drawText(x+5 + iconWidth + 8, y, r.width() - 5 - iconWidth - 8, lineHeight,
00528 Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine, s);
00529
00530 y += lineHeight;
00531 }
00532 if ( y >= r.height() ) break;
00533 }
00534 }
00535 }
00536 else
00537 {
00538 int iconHeight = iconWidth;
00539
00540
00541 QFont f(font());
00542 f.setBold(true);
00543 f.setPixelSize(iconHeight - 4);
00544 QFontMetrics fm(f);
00545
00546 int wmax = 0;
00547 foreach (int it, desktops)
00548 {
00549 wmax = qMax(wmax, fontMetrics().width(workspace()->desktopName(it)));
00550
00551
00552 QString num = QString::number(it);
00553 iconWidth = qMax(iconWidth - 4, fm.boundingRect(num).width()) + 4;
00554 }
00555
00556 foreach (int it, desktops)
00557 {
00558
00559 if ( it == desk )
00560 p.fillRect(x, y, r.width(), lineHeight, palette().brush( QPalette::Active, QPalette::Highlight ));
00561
00562 p.save();
00563
00564
00565 p.fillRect(x+5, y+2, iconWidth, iconHeight, palette().brush( QPalette::Active, QPalette::Base ));
00566 p.setPen(palette().color( QPalette::Active, QPalette::Text ));
00567 p.drawRect(x+5, y+2, iconWidth, iconHeight);
00568
00569
00570 p.setFont(f);
00571 QString num = QString::number(it);
00572 p.drawText(x+5, y+2, iconWidth, iconHeight, Qt::AlignCenter, num);
00573
00574 p.restore();
00575
00576
00577 if ( it == desk )
00578 p.setPen(palette().color( QPalette::Active, QPalette::HighlightedText ));
00579 else
00580 p.setPen(palette().color( QPalette::Active, QPalette::Text ));
00581
00582 p.drawText(x+5 + iconWidth + 8, y, r.width() - 5 - iconWidth - 8, lineHeight,
00583 Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine,
00584 workspace()->desktopName(it));
00585
00586
00587 int x1 = x + 5 + iconWidth + 8 + wmax + 5;
00588
00589 ClientList list;
00590 createClientList(list, it, 0, false);
00591
00592 for ( int i = list.size() - 1; i>=0; i-- )
00593 {
00594 if ( !list.at( i )->miniIcon().isNull() )
00595 {
00596 if ( x1+18 >= x+r.width() )
00597 break;
00598
00599 p.drawPixmap( x1, y + (lineHeight - 16)/2, list.at( i )->miniIcon() );
00600 x1 += 18;
00601 }
00602 }
00603
00604
00605 y += lineHeight;
00606 if ( y >= r.height() ) break;
00607 }
00608 }
00609 }
00610
00611
00616 void TabBox::show()
00617 {
00618 if( effects )
00619 static_cast<EffectsHandlerImpl*>(effects)->tabBoxAdded( mode());
00620 if( isDisplayed())
00621 return;
00622 refDisplay();
00623 QWidget::show();
00624 }
00625
00626
00630 void TabBox::hide()
00631 {
00632 delayedShowTimer.stop();
00633 if( isVisible())
00634 unrefDisplay();
00635 if( effects )
00636 static_cast<EffectsHandlerImpl*>(effects)->tabBoxClosed();
00637 if( isDisplayed())
00638 kDebug( 1212 ) << "Tab box was not properly closed by an effect";
00639 QWidget::hide();
00640 QApplication::syncX();
00641 XEvent otherEvent;
00642 while (XCheckTypedEvent (display(), EnterNotify, &otherEvent ) )
00643 ;
00644 }
00645
00646
00651 void TabBox::unrefDisplay()
00652 {
00653 --display_refcount;
00654 }
00655
00656 void TabBox::reconfigure()
00657 {
00658 KSharedConfigPtr c(KGlobal::config());
00659 options_traverse_all = c->group("TabBox").readEntry("TraverseAll", false );
00660 }
00661
00680 void TabBox::delayedShow()
00681 {
00682 KSharedConfigPtr c(KGlobal::config());
00683 KConfigGroup cg(c, "TabBox");
00684 bool delay = cg.readEntry("ShowDelay", true);
00685
00686 if (!delay)
00687 {
00688 show();
00689 return;
00690 }
00691
00692 int delayTime = cg.readEntry("DelayTime", 90);
00693 delayedShowTimer.setSingleShot(true);
00694 delayedShowTimer.start(delayTime);
00695 }
00696
00697
00698 void TabBox::handleMouseEvent( XEvent* e )
00699 {
00700 XAllowEvents( display(), AsyncPointer, xTime());
00701 if( !isVisible() && isDisplayed())
00702 {
00703 if( effects && static_cast<EffectsHandlerImpl*>(effects)->checkInputWindowEvent( e ))
00704 return;
00705 }
00706 if( e->type != ButtonPress )
00707 return;
00708 QPoint pos( e->xbutton.x_root, e->xbutton.y_root );
00709 QPoint widgetPos = mapFromGlobal( pos );
00710
00711 if(( !isVisible() && isDisplayed())
00712 || !geometry().contains( pos ))
00713 {
00714 workspace()->closeTabBox();
00715 return;
00716 }
00717
00718 int num = (widgetPos.y()-frameWidth()) / lineHeight;
00719
00720 if( mode() == TabBoxWindowsMode )
00721 {
00722 for( ClientList::ConstIterator it = clients.constBegin();
00723 it != clients.constEnd();
00724 ++it)
00725 {
00726 if( workspace()->hasClient( *it ) && (num == 0) )
00727 {
00728 setCurrentClient( *it );
00729 break;
00730 }
00731 num--;
00732 }
00733 }
00734 else
00735 {
00736 foreach( int it, desktops )
00737 {
00738 if( num == 0 )
00739 {
00740 setCurrentDesktop( it );
00741 break;
00742 }
00743 num--;
00744 }
00745 }
00746 update();
00747 }
00748
00749
00750
00751
00752
00753
00758 static
00759 bool areKeySymXsDepressed( bool bAll, const uint keySyms[], int nKeySyms )
00760 {
00761 char keymap[32];
00762
00763 kDebug(125) << "areKeySymXsDepressed: " << (bAll ? "all of " : "any of ") << nKeySyms;
00764
00765 XQueryKeymap( display(), keymap );
00766
00767 for( int iKeySym = 0; iKeySym < nKeySyms; iKeySym++ )
00768 {
00769 uint keySymX = keySyms[ iKeySym ];
00770 uchar keyCodeX = XKeysymToKeycode( display(), keySymX );
00771 int i = keyCodeX / 8;
00772 char mask = 1 << (keyCodeX - (i * 8));
00773
00774
00775 if( i < 0 || i >= 32 )
00776 return false;
00777
00778 kDebug(125) << iKeySym << ": keySymX=0x" << QString::number( keySymX, 16 )
00779 << " i=" << i << " mask=0x" << QString::number( mask, 16 )
00780 << " keymap[i]=0x" << QString::number( keymap[i], 16 ) << endl;
00781
00782
00783 if( bAll )
00784 {
00785 if( (keymap[i] & mask) == 0 )
00786 return false;
00787 }
00788 else
00789 {
00790
00791 if( keymap[i] & mask )
00792 return true;
00793 }
00794 }
00795
00796
00797
00798 return bAll;
00799 }
00800
00801 static bool areModKeysDepressed( const QKeySequence& seq )
00802 {
00803 uint rgKeySyms[10];
00804 int nKeySyms = 0;
00805 if( seq.isEmpty())
00806 return false;
00807 int mod = seq[seq.count()-1] & Qt::KeyboardModifierMask;
00808
00809 if ( mod & Qt::SHIFT )
00810 {
00811 rgKeySyms[nKeySyms++] = XK_Shift_L;
00812 rgKeySyms[nKeySyms++] = XK_Shift_R;
00813 }
00814 if ( mod & Qt::CTRL )
00815 {
00816 rgKeySyms[nKeySyms++] = XK_Control_L;
00817 rgKeySyms[nKeySyms++] = XK_Control_R;
00818 }
00819 if( mod & Qt::ALT )
00820 {
00821 rgKeySyms[nKeySyms++] = XK_Alt_L;
00822 rgKeySyms[nKeySyms++] = XK_Alt_R;
00823 }
00824 if( mod & Qt::META )
00825 {
00826
00827
00828
00829 rgKeySyms[nKeySyms++] = XK_Super_L;
00830 rgKeySyms[nKeySyms++] = XK_Super_R;
00831 rgKeySyms[nKeySyms++] = XK_Meta_L;
00832 rgKeySyms[nKeySyms++] = XK_Meta_R;
00833 }
00834
00835 return areKeySymXsDepressed( false, rgKeySyms, nKeySyms );
00836 }
00837
00838 static bool areModKeysDepressed( const KShortcut& cut )
00839 {
00840 if( areModKeysDepressed( cut.primary()) || areModKeysDepressed( cut.alternate()) )
00841 return true;
00842
00843 return false;
00844 }
00845
00846 void Workspace::slotWalkThroughWindows()
00847 {
00848 if ( tab_grab || control_grab )
00849 return;
00850 if ( options->altTabStyle == Options::CDE || !options->focusPolicyIsReasonable())
00851 {
00852
00853
00854 CDEWalkThroughWindows( true );
00855 }
00856 else
00857 {
00858 if ( areModKeysDepressed( cutWalkThroughWindows ) )
00859 {
00860 if ( startKDEWalkThroughWindows() )
00861 KDEWalkThroughWindows( true );
00862 }
00863 else
00864
00865
00866 KDEOneStepThroughWindows( true );
00867 }
00868 }
00869
00870 void Workspace::slotWalkBackThroughWindows()
00871 {
00872 if( tab_grab || control_grab )
00873 return;
00874 if ( options->altTabStyle == Options::CDE || !options->focusPolicyIsReasonable())
00875 {
00876
00877 CDEWalkThroughWindows( false );
00878 }
00879 else
00880 {
00881 if ( areModKeysDepressed( cutWalkThroughWindowsReverse ) )
00882 {
00883 if ( startKDEWalkThroughWindows() )
00884 KDEWalkThroughWindows( false );
00885 }
00886 else
00887 {
00888 KDEOneStepThroughWindows( false );
00889 }
00890 }
00891 }
00892
00893 void Workspace::slotWalkThroughDesktops()
00894 {
00895 if( tab_grab || control_grab )
00896 return;
00897 if ( areModKeysDepressed( cutWalkThroughDesktops ) )
00898 {
00899 if ( startWalkThroughDesktops() )
00900 walkThroughDesktops( true );
00901 }
00902 else
00903 {
00904 oneStepThroughDesktops( true );
00905 }
00906 }
00907
00908 void Workspace::slotWalkBackThroughDesktops()
00909 {
00910 if( tab_grab || control_grab )
00911 return;
00912 if ( areModKeysDepressed( cutWalkThroughDesktopsReverse ) )
00913 {
00914 if ( startWalkThroughDesktops() )
00915 walkThroughDesktops( false );
00916 }
00917 else
00918 {
00919 oneStepThroughDesktops( false );
00920 }
00921 }
00922
00923 void Workspace::slotWalkThroughDesktopList()
00924 {
00925 if( tab_grab || control_grab )
00926 return;
00927 if ( areModKeysDepressed( cutWalkThroughDesktopList ) )
00928 {
00929 if ( startWalkThroughDesktopList() )
00930 walkThroughDesktops( true );
00931 }
00932 else
00933 {
00934 oneStepThroughDesktopList( true );
00935 }
00936 }
00937
00938 void Workspace::slotWalkBackThroughDesktopList()
00939 {
00940 if( tab_grab || control_grab )
00941 return;
00942 if ( areModKeysDepressed( cutWalkThroughDesktopListReverse ) )
00943 {
00944 if ( startWalkThroughDesktopList() )
00945 walkThroughDesktops( false );
00946 }
00947 else
00948 {
00949 oneStepThroughDesktopList( false );
00950 }
00951 }
00952
00953 void Workspace::modalActionsSwitch( bool enabled )
00954 {
00955 QList<KActionCollection*> collections;
00956 collections.append( keys );
00957 collections.append( disable_shortcuts_keys );
00958 collections.append( client_keys );
00959 foreach (KActionCollection* collection, collections)
00960 foreach (QAction *action, collection->actions())
00961 action->setEnabled(enabled);
00962 }
00963
00964 bool Workspace::startKDEWalkThroughWindows()
00965 {
00966 if( !establishTabBoxGrab())
00967 return false;
00968 tab_grab = true;
00969 modalActionsSwitch( false );
00970 tab_box->setMode( TabBoxWindowsMode );
00971 tab_box->reset();
00972 return true;
00973 }
00974
00975 bool Workspace::startWalkThroughDesktops( TabBoxMode mode )
00976 {
00977 if( !establishTabBoxGrab())
00978 return false;
00979 control_grab = true;
00980 modalActionsSwitch( false );
00981 tab_box->setMode( mode );
00982 tab_box->reset();
00983 return true;
00984 }
00985
00986 bool Workspace::startWalkThroughDesktops()
00987 {
00988 return startWalkThroughDesktops( TabBoxDesktopMode );
00989 }
00990
00991 bool Workspace::startWalkThroughDesktopList()
00992 {
00993 return startWalkThroughDesktops( TabBoxDesktopListMode );
00994 }
00995
00996 void Workspace::KDEWalkThroughWindows( bool forward )
00997 {
00998 tab_box->nextPrev( forward );
00999 tab_box->delayedShow();
01000 }
01001
01002 void Workspace::walkThroughDesktops( bool forward )
01003 {
01004 tab_box->nextPrev( forward );
01005 tab_box->delayedShow();
01006 }
01007
01008 void Workspace::CDEWalkThroughWindows( bool forward )
01009 {
01010 Client* c = NULL;
01011
01012
01013
01014 Q_ASSERT( block_stacking_updates == 0 );
01015 for( int i = stacking_order.size() - 1;
01016 i >= 0 ;
01017 --i )
01018 {
01019 Client* it = stacking_order.at( i );
01020 if ( it->isOnCurrentDesktop() && !it->isSpecialWindow()
01021 && it->isShown( false ) && it->wantsTabFocus()
01022 && !it->keepAbove() && !it->keepBelow())
01023 {
01024 c = it;
01025 break;
01026 }
01027 }
01028 Client* nc = c;
01029 bool options_traverse_all;
01030 {
01031 KConfigGroup group( KGlobal::config(), "TabBox" );
01032 options_traverse_all = group.readEntry("TraverseAll", false );
01033 }
01034
01035 Client* firstClient = 0;
01036 do
01037 {
01038 nc = forward ? nextClientStatic(nc) : previousClientStatic(nc);
01039 if (!firstClient)
01040 {
01041
01042
01043 firstClient = nc;
01044 }
01045 else if (nc == firstClient)
01046 {
01047
01048 nc = 0;
01049 break;
01050 }
01051 } while (nc && nc != c &&
01052 (( !options_traverse_all && !nc->isOnDesktop(currentDesktop())) ||
01053 nc->isMinimized() || !nc->wantsTabFocus() || nc->keepAbove() || nc->keepBelow() ) );
01054 if (nc)
01055 {
01056 if (c && c != nc)
01057 lowerClient( c );
01058 if ( options->focusPolicyIsReasonable() )
01059 {
01060 activateClient( nc );
01061 if( nc->isShade() && options->shadeHover )
01062 nc->setShade( ShadeActivated );
01063 }
01064 else
01065 {
01066 if( !nc->isOnDesktop( currentDesktop()))
01067 setCurrentDesktop( nc->desktop());
01068 raiseClient( nc );
01069 }
01070 }
01071 }
01072
01073 void Workspace::KDEOneStepThroughWindows( bool forward )
01074 {
01075 tab_box->setMode( TabBoxWindowsMode );
01076 tab_box->reset();
01077 tab_box->nextPrev( forward );
01078 if( Client* c = tab_box->currentClient() )
01079 {
01080 activateClient( c );
01081 if( c->isShade() && options->shadeHover )
01082 c->setShade( ShadeActivated );
01083 }
01084 }
01085
01086 void Workspace::oneStepThroughDesktops( bool forward, TabBoxMode mode )
01087 {
01088 tab_box->setMode( mode );
01089 tab_box->reset();
01090 tab_box->nextPrev( forward );
01091 if ( tab_box->currentDesktop() != -1 )
01092 setCurrentDesktop( tab_box->currentDesktop() );
01093 }
01094
01095 void Workspace::oneStepThroughDesktops( bool forward )
01096 {
01097 oneStepThroughDesktops( forward, TabBoxDesktopMode );
01098 }
01099
01100 void Workspace::oneStepThroughDesktopList( bool forward )
01101 {
01102 oneStepThroughDesktops( forward, TabBoxDesktopListMode );
01103 }
01104
01108 void Workspace::tabBoxKeyPress( int keyQt )
01109 {
01110 bool forward = false;
01111 bool backward = false;
01112
01113 if (tab_grab)
01114 {
01115 forward = cutWalkThroughWindows.contains( keyQt );
01116 backward = cutWalkThroughWindowsReverse.contains( keyQt );
01117 if (forward || backward)
01118 {
01119 kDebug(125) << "== " << cutWalkThroughWindows.toString()
01120 << " or " << cutWalkThroughWindowsReverse.toString() << endl;
01121 KDEWalkThroughWindows( forward );
01122 }
01123 }
01124 else if (control_grab)
01125 {
01126 forward = cutWalkThroughDesktops.contains( keyQt ) ||
01127 cutWalkThroughDesktopList.contains( keyQt );
01128 backward = cutWalkThroughDesktopsReverse.contains( keyQt ) ||
01129 cutWalkThroughDesktopListReverse.contains( keyQt );
01130 if (forward || backward)
01131 walkThroughDesktops(forward);
01132 }
01133
01134 if (control_grab || tab_grab)
01135 {
01136 if ( ((keyQt & ~Qt::KeyboardModifierMask) == Qt::Key_Escape)
01137 && !(forward || backward) )
01138 {
01139 closeTabBox();
01140 }
01141 }
01142 }
01143
01144 void Workspace::refTabBox()
01145 {
01146 if( tab_box )
01147 tab_box->refDisplay();
01148 }
01149
01150 void Workspace::unrefTabBox()
01151 {
01152 if( tab_box )
01153 tab_box->unrefDisplay();
01154 }
01155
01156 void Workspace::closeTabBox()
01157 {
01158 removeTabBoxGrab();
01159 tab_box->hide();
01160 modalActionsSwitch( true );
01161 tab_grab = false;
01162 control_grab = false;
01163 }
01164
01168 void Workspace::tabBoxKeyRelease( const XKeyEvent& ev )
01169 {
01170 unsigned int mk = ev.state &
01171 (KKeyServer::modXShift() |
01172 KKeyServer::modXCtrl() |
01173 KKeyServer::modXAlt() |
01174 KKeyServer::modXMeta() );
01175
01176
01177
01178
01179 int mod_index = -1;
01180 for( int i = ShiftMapIndex;
01181 i <= Mod5MapIndex;
01182 ++i )
01183 if(( mk & ( 1 << i )) != 0 )
01184 {
01185 if( mod_index >= 0 )
01186 return;
01187 mod_index = i;
01188 }
01189 bool release = false;
01190 if( mod_index == -1 )
01191 release = true;
01192 else
01193 {
01194 XModifierKeymap* xmk = XGetModifierMapping(display());
01195 for (int i=0; i<xmk->max_keypermod; i++)
01196 if (xmk->modifiermap[xmk->max_keypermod * mod_index + i]
01197 == ev.keycode)
01198 release = true;
01199 XFreeModifiermap(xmk);
01200 }
01201 if( !release )
01202 return;
01203 if (tab_grab)
01204 {
01205 bool old_control_grab = control_grab;
01206 closeTabBox();
01207 control_grab = old_control_grab;
01208 if( Client* c = tab_box->currentClient())
01209 {
01210 activateClient( c );
01211 if( c->isShade() && options->shadeHover )
01212 c->setShade( ShadeActivated );
01213 }
01214 }
01215 if (control_grab)
01216 {
01217 bool old_tab_grab = tab_grab;
01218 closeTabBox();
01219 tab_grab = old_tab_grab;
01220 if ( tab_box->currentDesktop() != -1 )
01221 {
01222 setCurrentDesktop( tab_box->currentDesktop() );
01223 }
01224 }
01225 }
01226
01227
01228 int Workspace::nextDesktopFocusChain( int iDesktop ) const
01229 {
01230 int i = desktop_focus_chain.indexOf( iDesktop );
01231 if( i >= 0 && i+1 < (int)desktop_focus_chain.size() )
01232 return desktop_focus_chain[i+1];
01233 else if( desktop_focus_chain.size() > 0 )
01234 return desktop_focus_chain[ 0 ];
01235 else
01236 return 1;
01237 }
01238
01239 int Workspace::previousDesktopFocusChain( int iDesktop ) const
01240 {
01241 int i = desktop_focus_chain.indexOf( iDesktop );
01242 if( i-1 >= 0 )
01243 return desktop_focus_chain[i-1];
01244 else if( desktop_focus_chain.size() > 0 )
01245 return desktop_focus_chain[desktop_focus_chain.size()-1];
01246 else
01247 return numberOfDesktops();
01248 }
01249
01250 int Workspace::nextDesktopStatic( int iDesktop ) const
01251 {
01252 int i = ++iDesktop;
01253 if( i > numberOfDesktops())
01254 i = 1;
01255 return i;
01256 }
01257
01258 int Workspace::previousDesktopStatic( int iDesktop ) const
01259 {
01260 int i = --iDesktop;
01261 if( i < 1 )
01262 i = numberOfDesktops();
01263 return i;
01264 }
01265
01270 Client* Workspace::nextClientFocusChain( Client* c ) const
01271 {
01272 if ( global_focus_chain.isEmpty() )
01273 return 0;
01274 int pos = global_focus_chain.indexOf( c );
01275 if ( pos == -1 )
01276 return global_focus_chain.last();
01277 if ( pos == 0 )
01278 return global_focus_chain.last();
01279 pos--;
01280 return global_focus_chain[ pos ];
01281 }
01282
01287 Client* Workspace::previousClientFocusChain( Client* c ) const
01288 {
01289 if ( global_focus_chain.isEmpty() )
01290 return 0;
01291 int pos = global_focus_chain.indexOf( c );
01292 if ( pos == -1 )
01293 return global_focus_chain.first();
01294 pos++;
01295 if ( pos == global_focus_chain.count() )
01296 return global_focus_chain.first();
01297 return global_focus_chain[ pos ];
01298 }
01299
01304 Client* Workspace::nextClientStatic( Client* c ) const
01305 {
01306 if ( !c || clients.isEmpty() )
01307 return 0;
01308 int pos = clients.indexOf( c );
01309 if ( pos == -1 )
01310 return clients.first();
01311 ++pos;
01312 if ( pos == clients.count() )
01313 return clients.first();
01314 return clients[ pos ];
01315 }
01320 Client* Workspace::previousClientStatic( Client* c ) const
01321 {
01322 if ( !c || clients.isEmpty() )
01323 return 0;
01324 int pos = clients.indexOf( c );
01325 if ( pos == -1 )
01326 return clients.last();
01327 if ( pos == 0 )
01328 return clients.last();
01329 --pos;
01330 return clients[ pos ];
01331 }
01332
01333 Client* Workspace::currentTabBoxClient() const
01334 {
01335 if( !tab_box )
01336 return 0;
01337 return tab_box->currentClient();
01338 }
01339
01340 ClientList Workspace::currentTabBoxClientList() const
01341 {
01342 if( !tab_box )
01343 return ClientList();
01344 return tab_box->currentClientList();
01345 }
01346
01347 int Workspace::currentTabBoxDesktop() const
01348 {
01349 if( !tab_box )
01350 return -1;
01351 return tab_box->currentDesktop();
01352 }
01353
01354 QList< int > Workspace::currentTabBoxDesktopList() const
01355 {
01356 if( !tab_box )
01357 return QList< int >();
01358 return tab_box->currentDesktopList();
01359 }
01360
01361 void Workspace::setTabBoxClient( Client* c )
01362 {
01363 if( tab_box )
01364 tab_box->setCurrentClient( c );
01365 }
01366
01367 void Workspace::setTabBoxDesktop( int iDesktop )
01368 {
01369 if( tab_box )
01370 tab_box->setCurrentDesktop( iDesktop );
01371 }
01372
01373 bool Workspace::establishTabBoxGrab()
01374 {
01375 if( !grabXKeyboard())
01376 return false;
01377
01378
01379
01380
01381
01382 assert( !forced_global_mouse_grab );
01383 forced_global_mouse_grab = true;
01384 if( active_client != NULL )
01385 active_client->updateMouseGrab();
01386 return true;
01387 }
01388
01389 void Workspace::removeTabBoxGrab()
01390 {
01391 ungrabXKeyboard();
01392 assert( forced_global_mouse_grab );
01393 forced_global_mouse_grab = false;
01394 if( active_client != NULL )
01395 active_client->updateMouseGrab();
01396 }
01397
01398 }
01399
01400 #include "tabbox.moc"