From 574e562906f18ca8716ca1c7f9ca0feb99671149 Mon Sep 17 00:00:00 2001 From: Philip Falkner Date: Wed, 28 Mar 2007 20:29:45 +0000 Subject: [PATCH] Some updates to the tabbox. Provide a pair of methods, setCurrentClient() and setCurrentDesktop(), to allow effects to select items in the tabbox without activating them. Insulate effects from having to know the order of desktops, with currentDesktopList(). DesktopMode and DesktopListMode should be effectively identical as far as how effects work. Some changes to how the tabbox refcounting is done, should work a little better. Other small cosmetic changes. Update BoxSwitchEffect. svn path=/branches/work/kwin_composite/; revision=647594 --- effects/boxswitch.cpp | 173 ++++++++++++----------- effects/boxswitch.h | 19 ++- tabbox.cpp | 316 +++++++++++++++++++++++++++--------------- tabbox.h | 40 ++++-- workspace.h | 13 +- 5 files changed, 345 insertions(+), 216 deletions(-) diff --git a/effects/boxswitch.cpp b/effects/boxswitch.cpp index 5e88a3d3f5..4d6d1c9428 100644 --- a/effects/boxswitch.cpp +++ b/effects/boxswitch.cpp @@ -10,10 +10,11 @@ License. See the file "COPYING" for the exact licensing terms. #include "boxswitch.h" -#include -#include -#include -#include +#include "tabbox.h" +#include "client.h" +#include "scene_xrender.h" +#include "scene_opengl.h" + #include #ifdef HAVE_OPENGL @@ -96,7 +97,7 @@ void BoxSwitchEffect::paintScreen( int mask, QRegion region, ScreenPaintData& da { paintFrame(); - for( painting_desktop = 1; painting_desktop <= desktops.count(); painting_desktop++ ) + foreach( painting_desktop, desktops.keys()) { if( painting_desktop == selected_desktop ) { @@ -120,7 +121,7 @@ void BoxSwitchEffect::paintWindow( EffectWindow* w, int mask, QRegion region, Wi { if( windows.contains( w ) && w != selected_window ) { - data.opacity *= 0.1; + data.opacity *= 0.2; } } } @@ -142,28 +143,17 @@ void BoxSwitchEffect::windowInputMouseEvent( Window w, QEvent* e ) { if( windows[ w ]->clickable.contains( pos )) { - if( Client* c = static_cast< Client* >( w->window())) - { - Workspace::self()->activateClient( c ); - if( c->isShade() && options->shadeHover ) - c->setShade( ShadeActivated ); - Workspace::self()->unrefTabBox(); - setInactive(); - break; - } + Workspace::self()->setTabBoxClient( static_cast< Client* >( w->window())); } } } else { - for( int i = 1; i <= desktops.count(); i++ ) + foreach( int i, desktops.keys()) { if( desktops[ i ]->clickable.contains( pos )) { - Workspace::self()->setCurrentDesktop( i ); - Workspace::self()->unrefTabBox(); - setInactive(); - break; + Workspace::self()->setTabBoxDesktop( i ); } } } @@ -235,8 +225,8 @@ void BoxSwitchEffect::tabBoxAdded( int mode ) } } else - { // DesktopMode or DesktopListMode - if( Workspace::self()->numberOfDesktops() > 0 ) + { // DesktopMode + if( Workspace::self()->currentTabBoxDesktopList().count() > 0 ) { mMode = mode; painting_desktop = 0; @@ -269,19 +259,20 @@ void BoxSwitchEffect::tabBoxUpdated() if( windows.contains( selected_window )) workspace()->addRepaint( windows.value( selected_window )->area ); selected_window->window()->addRepaintFull(); - if( Workspace::self()->currentTabBoxClientList() == tab_clients ) + if( Workspace::self()->currentTabBoxClientList() == original_windows ) return; - tab_clients = Workspace::self()->currentTabBoxClientList(); + original_windows = Workspace::self()->currentTabBoxClientList(); } else - { + { // DesktopMode if( desktops.contains( selected_desktop )) workspace()->addRepaint( desktops.value( selected_desktop )->area ); selected_desktop = Workspace::self()->currentTabBoxDesktop(); if( desktops.contains( selected_desktop )) workspace()->addRepaint( desktops.value( selected_desktop )->area ); - if( Workspace::self()->numberOfDesktops() == desktops.count()) + if( Workspace::self()->currentTabBoxDesktopList() == original_desktops ) return; + original_desktops = Workspace::self()->currentTabBoxDesktopList(); } workspace()->addRepaint( frame_area ); calculateFrameSize(); @@ -296,11 +287,12 @@ void BoxSwitchEffect::setActive() mActivated = true; if( mMode == TabBox::WindowsMode ) { - tab_clients = Workspace::self()->currentTabBoxClientList(); + original_windows = Workspace::self()->currentTabBoxClientList(); selected_window = Workspace::self()->currentTabBoxClient()->effectWindow(); } else { + original_desktops = Workspace::self()->currentTabBoxDesktopList(); selected_desktop = Workspace::self()->currentTabBoxDesktop(); } calculateFrameSize(); @@ -321,6 +313,7 @@ void BoxSwitchEffect::setActive() void BoxSwitchEffect::setInactive() { mActivated = false; + Workspace::self()->unrefTabBox(); if( mInput != None ) { effects->destroyInputWindow( mInput ); @@ -369,13 +362,13 @@ void BoxSwitchEffect::calculateFrameSize() if( mMode == TabBox::WindowsMode ) { - itemcount = tab_clients.count(); + itemcount = original_windows.count(); item_max_size.setWidth( 200 ); item_max_size.setHeight( 200 ); } else { - itemcount = Workspace::self()->numberOfDesktops(); + itemcount = original_desktops.count(); item_max_size.setWidth( 200 ); item_max_size.setHeight( 200 ); } @@ -395,9 +388,9 @@ void BoxSwitchEffect::calculateItemSizes() if( mMode == TabBox::WindowsMode ) { windows.clear(); - for( int i = 0; i < tab_clients.count(); i++ ) + for( int i = 0; i < original_windows.count(); i++ ) { - EffectWindow* w = tab_clients.at( i )->effectWindow(); + EffectWindow* w = original_windows.at( i )->effectWindow(); windows[ w ] = new ItemInfo(); windows[ w ]->area = QRect( frame_area.x() + frame_margin @@ -410,21 +403,16 @@ void BoxSwitchEffect::calculateItemSizes() else { desktops.clear(); - int iDesktop = ( mMode == TabBox::DesktopMode ) ? Workspace::self()->currentDesktop() : 1; - for( int i = 1; i <= Workspace::self()->numberOfDesktops(); i++ ) + for( int i = 0; i < original_desktops.count(); i++ ) { - desktops[ iDesktop ] = new ItemInfo(); + int it = original_desktops.at( i ); + desktops[ it ] = new ItemInfo(); - desktops[ iDesktop ]->area = QRect( frame_area.x() + frame_margin - + ( i - 1 ) * item_max_size.width(), + desktops[ it ]->area = QRect( frame_area.x() + frame_margin + + i * item_max_size.width(), frame_area.y() + frame_margin, item_max_size.width(), item_max_size.height()); - desktops[ iDesktop ]->clickable = desktops[ iDesktop ]->area; - - if( mMode == TabBox::DesktopMode ) - iDesktop = Workspace::self()->nextDesktopFocusChain( iDesktop ); - else - iDesktop++; + desktops[ it ]->clickable = desktops[ it ]->area; } } } @@ -439,12 +427,17 @@ void BoxSwitchEffect::paintFrame() glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); glColor4f( 0, 0, 0, alpha ); - glBegin( GL_QUADS ); - glVertex2i( frame_area.x(), frame_area.y()); - glVertex2i( frame_area.x() + frame_area.width(), frame_area.y()); - glVertex2i( frame_area.x() + frame_area.width(), frame_area.y() + frame_area.height()); - glVertex2i( frame_area.x(), frame_area.y() + frame_area.height()); - glEnd(); + glEnableClientState( GL_VERTEX_ARRAY ); + int verts[ 4 * 2 ] = + { + frame_area.x(), frame_area.y(), + frame_area.x(), frame_area.y() + frame_area.height(), + frame_area.x() + frame_area.width(), frame_area.y() + frame_area.height(), + frame_area.x() + frame_area.width(), frame_area.y() + }; + glVertexPointer( 2, GL_INT, 0, verts ); + glDrawArrays( GL_QUADS, 0, 4 ); + glDisableClientState( GL_VERTEX_ARRAY ); glPopAttrib(); } else @@ -480,12 +473,17 @@ void BoxSwitchEffect::paintHighlight( QRect area, QString text ) glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); glColor4f( 1, 1, 1, alpha ); - glBegin( GL_QUADS ); - glVertex2i( area.x(), area.y()); - glVertex2i( area.x() + area.width(), area.y()); - glVertex2i( area.x() + area.width(), area.y() + area.height()); - glVertex2i( area.x(), area.y() + area.height()); - glEnd(); + glEnableClientState( GL_VERTEX_ARRAY ); + int verts[ 4 * 2 ] = + { + area.x(), area.y(), + area.x(), area.y() + area.height(), + area.x() + area.width(), area.y() + area.height(), + area.x() + area.width(), area.y() + }; + glVertexPointer( 2, GL_INT, 0, verts ); + glDrawArrays( GL_QUADS, 0, 4 ); + glDisableClientState( GL_VERTEX_ARRAY ); glPopAttrib(); } else @@ -512,6 +510,22 @@ void BoxSwitchEffect::paintHighlight( QRect area, QString text ) // kDebug() << text << endl; // TODO draw this nicely on screen } +void BoxSwitchEffect::paintWindowThumbnail( EffectWindow* w ) + { + if( !windows.contains( w )) + return; + WindowPaintData data; + + setPositionTransformations( data, + windows[ w ]->thumbnail, w, + windows[ w ]->area.adjusted( highlight_margin, highlight_margin, -highlight_margin, -highlight_margin ), + Qt::KeepAspectRatio ); + + effects->drawWindow( w, + Scene::PAINT_WINDOW_OPAQUE | Scene::PAINT_WINDOW_TRANSFORMED, + windows[ w ]->thumbnail, data ); + } + void BoxSwitchEffect::paintDesktopThumbnail( int iDesktop ) { if( !desktops.contains( iDesktop )) @@ -538,22 +552,6 @@ void BoxSwitchEffect::paintDesktopThumbnail( int iDesktop ) region, data ); } -void BoxSwitchEffect::paintWindowThumbnail( EffectWindow* w ) - { - if( !windows.contains( w )) - return; - WindowPaintData data; - - setPositionTransformations( data, - windows[ w ]->thumbnail, w, - windows[ w ]->area.adjusted( highlight_margin, highlight_margin, -highlight_margin, -highlight_margin ), - Qt::KeepAspectRatio ); - - effects->drawWindow( w, - Scene::PAINT_WINDOW_OPAQUE | Scene::PAINT_WINDOW_TRANSFORMED, - windows[ w ]->thumbnail, data ); - } - void BoxSwitchEffect::paintWindowIcon( EffectWindow* w ) { if( !windows.contains( w )) @@ -586,23 +584,32 @@ void BoxSwitchEffect::paintWindowIcon( EffectWindow* w ) #ifdef HAVE_OPENGL if( dynamic_cast< SceneOpenGL* >( scene )) { - glPushMatrix(); - glPushAttrib( GL_ENABLE_BIT ); + glPushAttrib( GL_CURRENT_BIT | GL_ENABLE_BIT ); glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); windows[ w ]->iconTexture.bind(); - glBegin( GL_QUADS ); - glTexCoord2i( 0, 1 ); - glVertex2i( x, y ); - glTexCoord2i( 1, 1 ); - glVertex2i( x + width, y ); - glTexCoord2i( 1, 0 ); - glVertex2i( x + width, y + height ); - glTexCoord2i( 0, 0 ); - glVertex2i( x, y + height ); - glEnd(); + glEnableClientState( GL_VERTEX_ARRAY ); + int verts[ 4 * 2 ] = + { + x, y, + x, y + height, + x + width, y + height, + x + width, y + }; + glVertexPointer( 2, GL_INT, 0, verts ); + glEnableClientState( GL_TEXTURE_COORD_ARRAY ); + int texcoords[ 4 * 2 ] = + { + 0, 1, + 0, 0, + 1, 0, + 1, 1 + }; + glTexCoordPointer( 2, GL_INT, 0, texcoords ); + glDrawArrays( GL_QUADS, 0, 4 ); + glDisableClientState( GL_TEXTURE_COORD_ARRAY ); + glDisableClientState( GL_VERTEX_ARRAY ); windows[ w ]->iconTexture.unbind(); - glPopMatrix(); glPopAttrib(); } else diff --git a/effects/boxswitch.h b/effects/boxswitch.h index 434d375d36..57c3ef2e41 100644 --- a/effects/boxswitch.h +++ b/effects/boxswitch.h @@ -12,8 +12,8 @@ License. See the file "COPYING" for the exact licensing terms. #define KWIN_BOXSWITCH_H #include -#include -#include +#include "scene_xrender.h" +#include "scene_opengl.h" #include #include @@ -52,8 +52,8 @@ class BoxSwitchEffect void paintFrame(); void paintHighlight( QRect area, QString text ); - void paintDesktopThumbnail( int iDesktop ); void paintWindowThumbnail( EffectWindow* w ); + void paintDesktopThumbnail( int iDesktop ); void paintWindowIcon( EffectWindow* w ); bool mActivated; @@ -61,17 +61,16 @@ class BoxSwitchEffect int mMode; QRect frame_area; - int frame_margin; - + int frame_margin; // TODO graphical background + int highlight_margin; // TODO graphical background QSize item_max_size; // maximum item display size (including highlight) - int highlight_margin; // TODO graphical background, highlight - QHash< int, ItemInfo* > desktops; QHash< EffectWindow*, ItemInfo* > windows; - - int selected_desktop; - ClientList tab_clients; + ClientList original_windows; EffectWindow* selected_window; + QHash< int, ItemInfo* > desktops; + QList< int > original_desktops; + int selected_desktop; int painting_desktop; diff --git a/tabbox.cpp b/tabbox.cpp index f9e97d9539..c468f49b52 100644 --- a/tabbox.cpp +++ b/tabbox.cpp @@ -45,11 +45,13 @@ extern QPixmap* kwin_get_menu_pix_hack(); TabBox::TabBox( Workspace *ws ) : QFrame( 0, Qt::X11BypassWindowManagerHint ) - , client(0) , wspace(ws) + , client(0) , display_refcount( 0 ) { - setFrameStyle(QFrame::StyledPanel | QFrame::Plain); + setFrameStyle(QFrame::StyledPanel); + setFrameShadow(QFrame::Plain); + setBackgroundRole(QPalette::Base); setLineWidth(2); setContentsMargins( 2, 2, 2, 2 ); @@ -91,7 +93,7 @@ void TabBox::createClientList(ClientList &list, int desktop /*-1 = all*/, Client Client* start = c; if ( chain ) - c = workspace()->nextFocusChainClient(c); + c = workspace()->nextClientFocusChain(c); else c = workspace()->stackingOrder().first(); @@ -118,7 +120,7 @@ void TabBox::createClientList(ClientList &list, int desktop /*-1 = all*/, Client } if ( chain ) - c = workspace()->nextFocusChainClient( c ); + c = workspace()->nextClientFocusChain( c ); else { if ( idx >= (workspace()->stackingOrder().size()-1) ) @@ -133,6 +135,30 @@ void TabBox::createClientList(ClientList &list, int desktop /*-1 = all*/, Client } +/*! + Create list of desktops, starting with desktop start +*/ +void TabBox::createDesktopList(QList< int > &list, int start, SortOrder order) + { + list.clear(); + + int iDesktop = start; + + for( int i = 1; i <= workspace()->numberOfDesktops(); i++ ) + { + list.append( iDesktop ); + if ( order == StaticOrder ) + { + iDesktop = workspace()->nextDesktopStatic( iDesktop ); + } + else + { // MostRecentlyUsedOrder + iDesktop = workspace()->nextDesktopFocusChain( iDesktop ); + } + } + } + + /*! Resets the tab box to display the active client in WindowsMode, or the current desktop in DesktopListMode @@ -158,18 +184,16 @@ void TabBox::reset( bool partial_reset ) // get all clients to show createClientList(clients, options_traverse_all ? -1 : workspace()->currentDesktop(), starting_client, true); - displayed_clients = clients; - // calculate maximum caption width cw = fontMetrics().width(no_tasks)+20; - for (ClientList::ConstIterator it = displayed_clients.begin(); it != displayed_clients.end(); ++it) + for (ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it) { cw = fontMetrics().width( (*it)->caption() ); if ( cw > wmax ) wmax = cw; } // calculate height for the popup - if ( displayed_clients.count() == 0 ) // height for the "not tasks" text + if ( clients.count() == 0 ) // height for the "not tasks" text { QFont f = font(); f.setBold( true ); @@ -180,7 +204,7 @@ void TabBox::reset( bool partial_reset ) else { showMiniIcon = false; - h = displayed_clients.count() * lineHeight; + h = clients.count() * lineHeight; if ( h > (r.height()-(2*frameWidth())) ) // if too high, use mini icons { @@ -188,33 +212,47 @@ void TabBox::reset( bool partial_reset ) // fontheight + 1 pixel above + 1 pixel below, or 16x16 icon + 1 pixel above + below lineHeight = qMax(fontMetrics().height() + 2, 16 + 2); - h = displayed_clients.count() * lineHeight; + h = clients.count() * lineHeight; if ( h > (r.height()-(2*frameWidth())) ) // if still too high, remove some clients { // how many clients to remove int howMany = (h - (r.height()-(2*frameWidth())))/lineHeight; for (; howMany; howMany--) - displayed_clients.removeAll(displayed_clients.last()); + clients.removeAll(clients.last()); - h = displayed_clients.count() * lineHeight; + h = clients.count() * lineHeight; } } } } else - { // DesktopListMode - showMiniIcon = false; - desk = workspace()->currentDesktop(); + { + int starting_desktop; + if( mode() == DesktopListMode ) + { + starting_desktop = 1; + createDesktopList(desktops, starting_desktop, StaticOrder ); + } + else + { // DesktopMode + starting_desktop = workspace()->currentDesktop(); + createDesktopList(desktops, starting_desktop, MostRecentlyUsedOrder ); + } - for ( int i = 1; i <= workspace()->numberOfDesktops(); i++ ) + if( !partial_reset ) + desk = workspace()->currentDesktop(); + + showMiniIcon = false; + + foreach (int it, desktops) { - cw = fontMetrics().width( workspace()->desktopName(i) ); + cw = fontMetrics().width( workspace()->desktopName(it) ); if ( cw > wmax ) wmax = cw; } // calculate height for the popup (max. 16 desktops always fit in a 800x600 screen) - h = workspace()->numberOfDesktops() * lineHeight; + h = desktops.count() * lineHeight; } // height, width for the popup @@ -239,47 +277,37 @@ void TabBox::nextPrev( bool next) if ( mode() == WindowsMode ) { Client* firstClient = 0; + Client* newClient = client; do { if ( next ) - client = workspace()->nextFocusChainClient(client); + newClient = workspace()->nextClientFocusChain(newClient); else - client = workspace()->previousFocusChainClient(client); + newClient = workspace()->previousClientFocusChain(newClient); if (!firstClient) { - // When we see our first client for the second time, - // it's time to stop. - firstClient = client; + // When we see our first client for the second time, + // it's time to stop. + firstClient = newClient; } - else if (client == firstClient) + else if (newClient == firstClient) { - // No candidates found. - client = 0; + // No candidates found. + newClient = 0; break; } - } while ( client && !clients.contains( client )); + } while ( newClient && !clients.contains( newClient )); + setCurrentClient( newClient ); } else if( mode() == DesktopMode ) { - if ( next ) - desk = workspace()->nextDesktopFocusChain( desk ); - else - desk = workspace()->previousDesktopFocusChain( desk ); + setCurrentDesktop ( next ? workspace()->nextDesktopFocusChain( desk ) + : workspace()->previousDesktopFocusChain( desk ) ); } else { // DesktopListMode - if ( next ) - { - desk++; - if ( desk > workspace()->numberOfDesktops() ) - desk = 1; - } - else - { - desk--; - if ( desk < 1 ) - desk = workspace()->numberOfDesktops(); - } + setCurrentDesktop ( next ? workspace()->nextDesktopStatic( desk ) + : workspace()->previousDesktopStatic( desk )) ; } if( effects ) @@ -324,11 +352,47 @@ int TabBox::currentDesktop() { if ( mode() == DesktopListMode || mode() == DesktopMode ) return desk; - else - return -1; + return -1; } +/*! + Returns the list of desktops potentially displayed ( only works in + DesktopListMode ) + Returns an empty list if no desktops are available. + */ +QList< int > TabBox::currentDesktopList() + { + if ( mode() == DesktopListMode || mode() == DesktopMode ) + return desktops; + return QList< int >(); + } + + +/*! + Change the currently selected client, and notify the effects. + + \sa setCurrentDesktop() + */ +void TabBox::setCurrentClient( Client* newClient ) + { + client = newClient; + if( effects ) + effects->tabBoxUpdated(); + } + +/*! + Change the currently selected desktop, and notify the effects. + + \sa setCurrentClient() + */ +void TabBox::setCurrentDesktop( int newDesktop ) + { + desk = newDesktop; + if( effects ) + effects->tabBoxUpdated(); + } + /*! Reimplemented to raise the tab box as well */ @@ -374,7 +438,7 @@ void TabBox::paintEvent( QPaintEvent* e ) } else { - for (ClientList::ConstIterator it = displayed_clients.begin(); it != displayed_clients.end(); ++it) + for (ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it) { if ( workspace()->hasClient( *it ) ) // safety { @@ -458,22 +522,19 @@ void TabBox::paintEvent( QPaintEvent* e ) QFontMetrics fm(f); int wmax = 0; - for ( int i = 1; i <= workspace()->numberOfDesktops(); i++ ) + foreach (int it, desktops) { - wmax = qMax(wmax, fontMetrics().width(workspace()->desktopName(i))); + wmax = qMax(wmax, fontMetrics().width(workspace()->desktopName(it))); // calculate max width of desktop-number text - QString num = QString::number(i); + QString num = QString::number(it); iconWidth = qMax(iconWidth - 4, fm.boundingRect(num).width()) + 4; } - // In DesktopMode, start at the current desktop - // In DesktopListMode, start at desktop #1 - int iDesktop = (mode() == DesktopMode) ? workspace()->currentDesktop() : 1; - for ( int i = 1; i <= workspace()->numberOfDesktops(); i++ ) + foreach (int it, desktops) { // draw highlight background - if ( iDesktop == desk ) // current desktop + if ( it == desk ) // current desktop p.fillRect(x, y, r.width(), lineHeight, palette().brush( QPalette::Highlight )); p.save(); @@ -485,28 +546,28 @@ void TabBox::paintEvent( QPaintEvent* e ) // draw desktop-number p.setFont(f); - QString num = QString::number(iDesktop); + QString num = QString::number(it); p.drawText(x+5, y+2, iconWidth, iconHeight, Qt::AlignCenter, num); p.restore(); // draw desktop name text - if ( iDesktop == desk ) + if ( it == desk ) p.setPen(palette().color( QPalette::HighlightedText )); else p.setPen(palette().color( QPalette::Text )); p.drawText(x+5 + iconWidth + 8, y, r.width() - 5 - iconWidth - 8, lineHeight, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine, - workspace()->desktopName(iDesktop)); + workspace()->desktopName(it)); // show mini icons from that desktop aligned to each other int x1 = x + 5 + iconWidth + 8 + wmax + 5; ClientList list; - createClientList(list, iDesktop, 0, false); + createClientList(list, it, 0, false); // clients are in reversed stacking order - for ( int i = list.size() - 1; i>=0; i-- ) + for ( int i = list.size() - 1; i>=0; i-- ) { if ( !list.at( i )->miniIcon().isNull() ) { @@ -521,29 +582,38 @@ void TabBox::paintEvent( QPaintEvent* e ) // next desktop y += lineHeight; if ( y >= r.height() ) break; - - if( mode() == DesktopMode ) - iDesktop = workspace()->nextDesktopFocusChain( iDesktop ); - else - iDesktop++; } } } + +/*! + Notify effects that the tab box is being shown, and only display the + default tab box QFrame if no effect has referenced the tab box. +*/ void TabBox::show() { - if( display_refcount > 0 ) - return; - display_refcount = 0; if( effects ) effects->tabBoxAdded( mode()); - if( display_refcount == 0 ) // no effects have claimed TabBox - QWidget::show(); + if( isDisplayed()) + return; + refDisplay(); + QWidget::show(); } + +/*! + Notify effects that the tab box is being hidden. +*/ void TabBox::hide() { delayedShowTimer.stop(); + if( isVisible()) + unrefDisplay(); + if( effects ) + effects->tabBoxClosed(); + if( isDisplayed()) + kDebug( 1212 ) << "Tab box was not properly closed by an effect" << endl; QWidget::hide(); QApplication::syncX(); XEvent otherEvent; @@ -553,13 +623,12 @@ void TabBox::hide() /*! - Reduce the reference count, eventually closing the tabbox. + Decrease the reference count. Only when the reference count is 0 will + the default tab box be shown. */ -void TabBox::unrefTabBox() +void TabBox::unrefDisplay() { - if( --display_refcount > 0 ) - return; - workspace()->closeTabBox(); + --display_refcount; } void TabBox::reconfigure() @@ -607,33 +676,34 @@ void TabBox::delayedShow() void TabBox::handleMouseEvent( XEvent* e ) { XAllowEvents( display(), AsyncPointer, xTime() ); - if( display_refcount > 0 ) // tabbox has been replaced, check effects - { - if( effects && !effects->checkInputWindowEvent( e ) && e->type == ButtonPress ) - unrefTabBox(); - return; + if( !isVisible() && isDisplayed()) + { // tabbox has been replaced, check effects + if( effects && effects->checkInputWindowEvent( e )) + return; } if( e->type != ButtonPress ) return; QPoint pos( e->xbutton.x_root, e->xbutton.y_root ); - if( !geometry().contains( pos )) + QPoint widgetPos = mapFromGlobal( pos ); // inside tabbox + + if(( !isVisible() && isDisplayed()) + || !geometry().contains( pos )) { - unrefTabBox(); // click outside closes tab + workspace()->closeTabBox(); // click outside closes tab return; } - pos.rx() -= x(); // pos is now inside tabbox - pos.ry() -= y(); - int num = (pos.y()-frameWidth()) / lineHeight; + + int num = (widgetPos.y()-frameWidth()) / lineHeight; if( mode() == WindowsMode ) { - for( ClientList::ConstIterator it = displayed_clients.begin(); - it != displayed_clients.end(); + for( ClientList::ConstIterator it = clients.begin(); + it != clients.end(); ++it) { if( workspace()->hasClient( *it ) && (num == 0) ) // safety { - client = *it; + setCurrentClient( *it ); break; } num--; @@ -641,21 +711,14 @@ void TabBox::handleMouseEvent( XEvent* e ) } else { - int iDesktop = (mode() == DesktopMode) ? workspace()->currentDesktop() : 1; - for( int i = 1; - i <= workspace()->numberOfDesktops(); - ++i ) + foreach( int it, desktops ) { if( num == 0 ) { - desk = iDesktop; + setCurrentDesktop( it ); break; } num--; - if( mode() == DesktopMode ) - iDesktop = workspace()->nextDesktopFocusChain( iDesktop ); - else - iDesktop++; } } update(); @@ -722,7 +785,7 @@ static bool areModKeysDepressed( const QKeySequence& seq ) uint rgKeySyms[10]; int nKeySyms = 0; if( seq.isEmpty()) - return false; + return false; int mod = seq[seq.count()-1] & Qt::KeyboardModifierMask; if ( mod & Qt::SHIFT ) @@ -922,7 +985,7 @@ bool Workspace::startKDEWalkThroughWindows() { if( !establishTabBoxGrab()) return false; - tab_grab = true; + tab_grab = true; keys->setEnabled( false ); disable_shortcuts_keys->setEnabled( false ); client_keys->setEnabled( false ); @@ -996,7 +1059,7 @@ void Workspace::CDEWalkThroughWindows( bool forward ) Client* firstClient = 0; do { - nc = forward ? nextStaticClient(nc) : previousStaticClient(nc); + nc = forward ? nextClientStatic(nc) : previousClientStatic(nc); if (!firstClient) { // When we see our first client for the second time, @@ -1097,7 +1160,7 @@ void Workspace::tabBoxKeyPress( int keyQt ) if ( ((keyQt & ~Qt::KeyboardModifierMask) == Qt::Key_Escape) && !(forward || backward) ) { // if Escape is part of the shortcut, don't cancel - unrefTabBox(); + closeTabBox(); } } } @@ -1105,21 +1168,19 @@ void Workspace::tabBoxKeyPress( int keyQt ) void Workspace::refTabBox() { if( tab_box ) - tab_box->refTabBox(); + tab_box->refDisplay(); } void Workspace::unrefTabBox() { if( tab_box ) - tab_box->unrefTabBox(); + tab_box->unrefDisplay(); } void Workspace::closeTabBox() { removeTabBoxGrab(); tab_box->hide(); - if( effects ) - effects->tabBoxClosed(); keys->setEnabled( true ); disable_shortcuts_keys->setEnabled( true ); client_keys->setEnabled( true ); @@ -1168,7 +1229,7 @@ void Workspace::tabBoxKeyRelease( const XKeyEvent& ev ) if (tab_grab) { bool old_control_grab = control_grab; - unrefTabBox(); + closeTabBox(); control_grab = old_control_grab; if( Client* c = tab_box->currentClient()) { @@ -1180,7 +1241,7 @@ void Workspace::tabBoxKeyRelease( const XKeyEvent& ev ) if (control_grab) { bool old_tab_grab = tab_grab; - unrefTabBox(); + closeTabBox(); tab_grab = old_tab_grab; if ( tab_box->currentDesktop() != -1 ) { @@ -1212,11 +1273,27 @@ int Workspace::previousDesktopFocusChain( int iDesktop ) const return numberOfDesktops(); } +int Workspace::nextDesktopStatic( int iDesktop ) const + { + int i = ++iDesktop; + if( i > numberOfDesktops()) + i = 1; + return i; + } + +int Workspace::previousDesktopStatic( int iDesktop ) const + { + int i = --iDesktop; + if( i < 1 ) + i = numberOfDesktops(); + return i; + } + /*! auxiliary functions to travers all clients according the focus order. Useful for kwms Alt-tab feature. */ -Client* Workspace::nextFocusChainClient( Client* c ) const +Client* Workspace::nextClientFocusChain( Client* c ) const { if ( global_focus_chain.isEmpty() ) return 0; @@ -1233,7 +1310,7 @@ Client* Workspace::nextFocusChainClient( Client* c ) const auxiliary functions to travers all clients according the focus order. Useful for kwms Alt-tab feature. */ -Client* Workspace::previousFocusChainClient( Client* c ) const +Client* Workspace::previousClientFocusChain( Client* c ) const { if ( global_focus_chain.isEmpty() ) return 0; @@ -1250,7 +1327,7 @@ Client* Workspace::previousFocusChainClient( Client* c ) const auxiliary functions to travers all clients according the static order. Useful for the CDE-style Alt-tab feature. */ -Client* Workspace::nextStaticClient( Client* c ) const +Client* Workspace::nextClientStatic( Client* c ) const { if ( !c || clients.isEmpty() ) return 0; @@ -1266,7 +1343,7 @@ Client* Workspace::nextStaticClient( Client* c ) const auxiliary functions to travers all clients according the static order. Useful for the CDE-style Alt-tab feature. */ -Client* Workspace::previousStaticClient( Client* c ) const +Client* Workspace::previousClientStatic( Client* c ) const { if ( !c || clients.isEmpty() ) return 0; @@ -1300,6 +1377,25 @@ int Workspace::currentTabBoxDesktop() const return tab_box->currentDesktop(); } +QList< int > Workspace::currentTabBoxDesktopList() const + { + if( !tab_box ) + return QList< int >(); + return tab_box->currentDesktopList(); + } + +void Workspace::setTabBoxClient( Client* c ) + { + if( tab_box ) + tab_box->setCurrentClient( c ); + } + +void Workspace::setTabBoxDesktop( int iDesktop ) + { + if( tab_box ) + tab_box->setCurrentDesktop( iDesktop ); + } + bool Workspace::establishTabBoxGrab() { if( XGrabKeyboard( display(), root, false, diff --git a/tabbox.h b/tabbox.h index 8e78540632..919a7b0fce 100644 --- a/tabbox.h +++ b/tabbox.h @@ -34,11 +34,16 @@ class TabBox : public QFrame Client* currentClient(); ClientList currentClientList(); int currentDesktop(); + QList< int > currentDesktopList(); + + void setCurrentClient( Client* newClient ); + void setCurrentDesktop( int newDesktop ); // DesktopMode and WindowsMode are based on the order in which the desktop // or window were viewed. // DesktopListMode lists them in the order created. enum Mode { DesktopMode, DesktopListMode, WindowsMode }; + enum SortOrder { StaticOrder, MostRecentlyUsedOrder }; void setMode( Mode mode ); Mode mode() const; @@ -48,8 +53,9 @@ class TabBox : public QFrame void delayedShow(); void hide(); - void refTabBox(); - void unrefTabBox(); + void refDisplay(); + void unrefDisplay(); + bool isDisplayed() const; void handleMouseEvent( XEvent* ); @@ -68,19 +74,22 @@ class TabBox : public QFrame private: void createClientList(ClientList &list, int desktop /*-1 = all*/, Client *start, bool chain); + void createDesktopList(QList< int > &list, int start, SortOrder order); private: - Client* client; - Mode m; Workspace* wspace; - ClientList clients, displayed_clients; + Mode m; + ClientList clients; + Client* client; + QList< int > desktops; int desk; + + QTimer delayedShowTimer; + int display_refcount; + QString no_tasks; int lineHeight; bool showMiniIcon; - QTimer delayedShowTimer; - QString no_tasks; bool options_traverse_all; - int display_refcount; }; @@ -104,12 +113,25 @@ inline TabBox::Mode TabBox::mode() const /*! Increase the reference count, preventing the default tabbox from showing. + + \sa unrefDisplay(), isDisplayed() */ -inline void TabBox::refTabBox() +inline void TabBox::refDisplay() { ++display_refcount; } +/*! + Returns whether the tab box is being displayed, either natively or by an + effect. + + \sa refDisplay(), unrefDisplay() + */ +inline bool TabBox::isDisplayed() const + { + return display_refcount > 0; + } + } // namespace #endif diff --git a/workspace.h b/workspace.h index 30ce012a23..ac3acc149b 100644 --- a/workspace.h +++ b/workspace.h @@ -172,12 +172,17 @@ class Workspace : public QObject, public KDecorationDefines Client* currentTabBoxClient() const; ClientList currentTabBoxClientList() const; int currentTabBoxDesktop() const; - Client* nextFocusChainClient(Client*) const; - Client* previousFocusChainClient(Client*) const; - Client* nextStaticClient(Client*) const; - Client* previousStaticClient(Client*) const; + QList< int > currentTabBoxDesktopList() const; + void setTabBoxClient(Client*); + void setTabBoxDesktop(int); + Client* nextClientFocusChain(Client*) const; + Client* previousClientFocusChain(Client*) const; + Client* nextClientStatic(Client*) const; + Client* previousClientStatic(Client*) const; int nextDesktopFocusChain( int iDesktop ) const; int previousDesktopFocusChain( int iDesktop ) const; + int nextDesktopStatic( int iDesktop ) const; + int previousDesktopStatic( int iDesktop ) const; void refTabBox(); void unrefTabBox(); void closeTabBox();