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