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