• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • twin
 

twin

tabbox.cpp

00001 /*****************************************************************
00002  KWin - the KDE window manager
00003  This file is part of the KDE project.
00004 
00005 Copyright (C) 1999, 2000 Matthias Ettrich <ettrich@kde.org>
00006 Copyright (C) 2003 Lubos Lunak <l.lunak@kde.org>
00007 
00008 You can Freely distribute this program under the GNU General Public
00009 License. See the file "COPYING" for the exact licensing terms.
00010 ******************************************************************/
00011 
00012 //#define QT_CLEAN_NAMESPACE
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 // specify externals before namespace
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; // init variables
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 /*-1 = all*/, 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             { // don't add windows that have modal dialogs
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                 // nothing
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     // calculate height of 1 line
00185     // fontheight + 1 pixel above + 1 pixel below, or 32x32 icon + 2 pixel above + below
00186     lineHeight = TQMAX(fontMetrics().height() + 2, 32 + 4);
00187 
00188     if ( mode() == WindowsMode )
00189         {
00190         setCurrentClient( workspace()->activeClient());
00191 
00192         // get all clients to show
00193         createClientList(clients, options_traverse_all ? -1 : workspace()->currentDesktop(), current_client, true);
00194 
00195         // calculate maximum caption width
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         // calculate height for the popup
00204         if ( clients.count() == 0 )  // height for the "not tasks" text
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())) )  // if too high, use mini icons
00218             {
00219             showMiniIcon = true;
00220             // fontheight + 1 pixel above + 1 pixel below, or 16x16 icon + 1 pixel above + below
00221             lineHeight = TQMAX(fontMetrics().height() + 2, 16 + 2);
00222 
00223             h = clients.count() * lineHeight;
00224 
00225             if ( h > (r.height()-(2*frameWidth())) ) // if still too high, remove some clients
00226               {
00227                 // how many clients to remove
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         { // DesktopListMode
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         // calculate height for the popup (max. 16 desktops always fit in a 800x600 screen)
00249         h = workspace()->numberOfDesktops() * lineHeight;
00250         }
00251 
00252     // height, width for the popup
00253     h += 2 * frameWidth();
00254     w = 2*frameWidth() + 5*2 + ( showMiniIcon ? 16 : 32 ) + 8 + wmax; // 5*2=margins, ()=icon, 8=space between icon+text
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         // When we see our first client for the second time,
00281         // it's time to stop.
00282                 firstClient = client;
00283                 }
00284             else if (client == firstClient)
00285                 {
00286         // No candidates found.
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         { // DesktopListMode
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());  // do double buffering to avoid flickers
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 ) )  // safety
00416                   {
00417                   // draw highlight background
00418                   if ( (*it) == current_client )
00419                     p.fillRect(x, y, r.width(), lineHeight, colorGroup().highlight());
00420 
00421                   // draw icon
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                   // generate text to display
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                   // draw text
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                     // from kicker's TaskContainer::blendColors()
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         { // DesktopMode || DesktopListMode
00488         int iconHeight = iconWidth;
00489 
00490         // get widest desktop name/number
00491         TQFont f(font());
00492         f.setBold(true);
00493         f.setPixelSize(iconHeight - 4);  // pixel, not point because I need to know the pixels
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             // calculate max width of desktop-number text
00502             TQString num = TQString::number(i);
00503             iconWidth = TQMAX(iconWidth - 4, fm.boundingRect(num).width()) + 4;
00504             }
00505 
00506         // In DesktopMode, start at the current desktop
00507         // In DesktopListMode, start at desktop #1
00508         int iDesktop = (mode() == DesktopMode) ? workspace()->currentDesktop() : 1;
00509         for ( int i = 1; i <= workspace()->numberOfDesktops(); i++ )
00510             {
00511             // draw highlight background
00512             if ( iDesktop == desk )  // current desktop
00513               p.fillRect(x, y, r.width(), lineHeight, colorGroup().highlight());
00514 
00515             p.save();
00516 
00517             // draw "icon" (here: number of desktop)
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             // draw desktop-number
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             // draw desktop name text
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             // show mini icons from that desktop aligned to each other
00540             int x1 = x + 5 + iconWidth + 8 + wmax + 5;
00541 
00542             ClientList list;
00543             createClientList(list, iDesktop, 0, false);
00544             // clients are in reversed stacking order
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() )  // only show full icons
00550                   break;
00551 
00552                 p.drawPixmap( x1, y + (lineHeight - 16)/2, (*it)->miniIcon() );
00553                 x1 += 18;
00554                 }
00555               }
00556 
00557             // next desktop
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     // left/right parts are between top/bottom, they don't reach as far as the corners
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();  // click outside closes tab
00719         return;
00720         }
00721     pos.rx() -= x(); // pos is now inside tabbox
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) ) // safety
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 // Workspace
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                 // Abort if bad index value,
00791         if( i < 0 || i >= 32 )
00792                 return false;
00793 
00794                 // If ALL keys passed need to be depressed,
00795         if( bAll )
00796             {
00797             if( (keymap[i] & mask) == 0 )
00798                     return false;
00799             }
00800         else
00801             {
00802                         // If we are looking for ANY key press, and this key is depressed,
00803             if( keymap[i] & mask )
00804                     return true;
00805             }
00806         }
00807 
00808         // If we were looking for ANY key press, then none was found, return false,
00809         // If we were looking for ALL key presses, then all were found, return true.
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         // It would take some code to determine whether the Win key
00839         // is associated with Super or Meta, so check for both.
00840         // See bug #140023 for details.
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         //XUngrabKeyboard(tqt_xdisplay(), GET_QT_X_TIME()); // need that because of accelerator raw mode
00871         // CDE style raise / lower
00872         CDEWalkThroughWindows( true );
00873         }
00874     else
00875         {
00876         if ( areModKeysDepressed( cutWalkThroughWindows ) )
00877             {
00878             if ( startKDEWalkThroughWindows() )
00879                 KDEWalkThroughWindows( true );
00880             }
00881         else
00882             // if the shortcut has no modifiers, don't show the tabbox,
00883             // don't grab, but simply go to the next window
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         // CDE style raise / lower
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 // this function find the first suitable client for unreasonable focus
01045 // policies - the topmost one, with some exceptions (can't be keepabove/below,
01046 // otherwise it gets stuck on them)
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             // When we see our first client for the second time,
01074             // it's time to stop.
01075             firstClient = nc;
01076             }
01077         else if (nc == firstClient)
01078             {
01079             // No candidates found.
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             { // if Escape is part of the shortcut, don't cancel
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     // ev.state is state before the key release, so just checking mk being 0 isn't enough
01214     // using XQueryPointer() also doesn't seem to work well, so the check that all
01215     // modifiers are released: only one modifier is active and the currently released
01216     // key is this modifier - if yes, release the grab
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     // Don't try to establish a global mouse grab using XGrabPointer, as that would prevent
01367     // using Alt+Tab while DND (#44972). However force passive grabs on all windows
01368     // in order to catch MouseRelease events and close the tabbox (#67416).
01369     // All clients already have passive grabs in their wrapper windows, so check only
01370     // the active client, which may not have it.
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 } // namespace
01388 
01389 #include "tabbox.moc"

twin

Skip menu "twin"
  • Main Page
  • Alphabetical List
  • Class List
  • File List
  • Class Members

twin

Skip menu "twin"
  • kate
  • libkonq
  • twin
  •   lib
Generated for twin by doxygen 1.7.1
This website is maintained by Timothy Pearson.