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