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();