diff --git a/COMPOSITE_TODO b/COMPOSITE_TODO index a4c17fe9ca..78e506af4d 100644 --- a/COMPOSITE_TODO +++ b/COMPOSITE_TODO @@ -175,6 +175,8 @@ Effects framework TODO + EffectWindow should be completely opaque when kept as the only API for effects - no inlines, etc. ++ API for tabbox for effects should be cleaned up + Effects TODO =============================== diff --git a/effects.cpp b/effects.cpp index 6fc1979e67..fed174cc70 100644 --- a/effects.cpp +++ b/effects.cpp @@ -247,6 +247,11 @@ int EffectsHandlerImpl::numberOfDesktops() const return Workspace::self()->numberOfDesktops(); } +QString EffectsHandlerImpl::desktopName( int desktop ) const + { + return Workspace::self()->desktopName( desktop ); + } + void EffectsHandlerImpl::calcDesktopLayout(int* x, int* y, Qt::Orientation* orientation) const { Workspace::self()->calcDesktopLayout( x, y, orientation ); @@ -281,6 +286,58 @@ EffectWindowList EffectsHandlerImpl::stackingOrder() const return ret; } +void EffectsHandlerImpl::setTabBoxWindow(EffectWindow* w) + { + if( Client* c = dynamic_cast< Client* >( static_cast< EffectWindowImpl* >( w )->window())) + Workspace::self()->setTabBoxClient( c ); + } + +void EffectsHandlerImpl::setTabBoxDesktop(int desktop) + { + Workspace::self()->setTabBoxDesktop( desktop ); + } + +EffectWindowList EffectsHandlerImpl::currentTabBoxWindowList() const + { + EffectWindowList ret; + ClientList clients = Workspace::self()->currentTabBoxClientList(); + foreach( Client* c, clients ) + ret.append( c->effectWindow()); + return ret; + } + +void EffectsHandlerImpl::refTabBox() + { + Workspace::self()->refTabBox(); + } + +void EffectsHandlerImpl::unrefTabBox() + { + Workspace::self()->unrefTabBox(); + } + +void EffectsHandlerImpl::closeTabBox() + { + Workspace::self()->closeTabBox(); + } + +QList< int > EffectsHandlerImpl::currentTabBoxDesktopList() const + { + return Workspace::self()->currentTabBoxDesktopList(); + } + +int EffectsHandlerImpl::currentTabBoxDesktop() const + { + return Workspace::self()->currentTabBoxDesktop(); + } + +EffectWindow* EffectsHandlerImpl::currentTabBoxWindow() const + { + if( Client* c = Workspace::self()->currentTabBoxClient()) + return c->effectWindow(); + return NULL; + } + void EffectsHandlerImpl::addRepaintFull() { Workspace::self()->addRepaintFull(); @@ -565,6 +622,13 @@ QString EffectWindowImpl::caption() const return ""; } +QPixmap EffectWindowImpl::icon() const + { + if( Client* c = dynamic_cast( toplevel )) + return c->icon(); + return QPixmap(); // TODO + } + const EffectWindowGroup* EffectWindowImpl::group() const { if( Client* c = dynamic_cast< Client* >( toplevel )) diff --git a/effects.h b/effects.h index 7e034589ff..65271f753e 100644 --- a/effects.h +++ b/effects.h @@ -38,10 +38,22 @@ class EffectsHandlerImpl : public EffectsHandler virtual int currentDesktop() const; virtual int numberOfDesktops() const; + virtual QString desktopName( int desktop ) const; virtual int displayWidth() const; virtual int displayHeight() const; virtual QPoint cursorPos() const; virtual EffectWindowList stackingOrder() const; + + virtual void setTabBoxWindow(EffectWindow*); + virtual void setTabBoxDesktop(int); + virtual EffectWindowList currentTabBoxWindowList() const; + virtual void refTabBox(); + virtual void unrefTabBox(); + virtual void closeTabBox(); + virtual QList< int > currentTabBoxDesktopList() const; + virtual int currentTabBoxDesktop() const; + virtual EffectWindow* currentTabBoxWindow() const; + virtual void addRepaintFull(); virtual void addRepaint( const QRect& r ); virtual void addRepaint( int x, int y, int w, int h ); @@ -107,6 +119,7 @@ class EffectWindowImpl : public EffectWindow virtual bool isMinimized() const; virtual double opacity() const; virtual QString caption() const; + virtual QPixmap icon() const; virtual const EffectWindowGroup* group() const; virtual int x() const; diff --git a/effects/boxswitch.cpp b/effects/boxswitch.cpp index 02aeb40644..0cfccb0191 100644 --- a/effects/boxswitch.cpp +++ b/effects/boxswitch.cpp @@ -12,14 +12,16 @@ License. See the file "COPYING" for the exact licensing terms. #include "boxswitch.h" +#include +#include #include +#include + #ifdef HAVE_OPENGL #include #endif -#if 0 -// TODO namespace KWin { @@ -50,12 +52,12 @@ void BoxSwitchEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint { if( mActivated ) { - if( mMode == TabBox::WindowsMode ) + if( mMode == TabBoxWindowsMode ) { if( windows.contains( w ) && w != selected_window ) { - *mask |= Scene::PAINT_WINDOW_TRANSLUCENT; - *mask &= ~Scene::PAINT_WINDOW_OPAQUE; + *mask |= PAINT_WINDOW_TRANSLUCENT; + *mask &= ~PAINT_WINDOW_OPAQUE; } } else @@ -63,9 +65,9 @@ void BoxSwitchEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint if( painting_desktop ) { if( w->isOnDesktop( painting_desktop )) - w->enablePainting( Scene::Window::PAINT_DISABLED_BY_DESKTOP ); + w->enablePainting( EffectWindow::PAINT_DISABLED_BY_DESKTOP ); else - w->disablePainting( Scene::Window::PAINT_DISABLED_BY_DESKTOP ); + w->disablePainting( EffectWindow::PAINT_DISABLED_BY_DESKTOP ); } } } @@ -77,7 +79,7 @@ void BoxSwitchEffect::paintScreen( int mask, QRegion region, ScreenPaintData& da effects->paintScreen( mask, region, data ); if( mActivated ) { - if( mMode == TabBox::WindowsMode ) + if( mMode == TabBoxWindowsMode ) { paintFrame(); @@ -85,8 +87,7 @@ void BoxSwitchEffect::paintScreen( int mask, QRegion region, ScreenPaintData& da { if( w == selected_window ) { - paintHighlight( windows[ w ]->area, - static_cast< Client* >( w->window())->caption()); + paintHighlight( windows[ w ]->area, w->caption()); } paintWindowThumbnail( w ); paintWindowIcon( w ); @@ -103,7 +104,7 @@ void BoxSwitchEffect::paintScreen( int mask, QRegion region, ScreenPaintData& da if( painting_desktop == selected_desktop ) { paintHighlight( desktops[ painting_desktop ]->area, - Workspace::self()->desktopName( painting_desktop )); + effects->desktopName( painting_desktop )); } paintDesktopThumbnail( painting_desktop ); @@ -118,7 +119,7 @@ void BoxSwitchEffect::paintWindow( EffectWindow* w, int mask, QRegion region, Wi { if( mActivated ) { - if( mMode == TabBox::WindowsMode ) + if( mMode == TabBoxWindowsMode ) { if( windows.contains( w ) && w != selected_window ) { @@ -138,13 +139,13 @@ void BoxSwitchEffect::windowInputMouseEvent( Window w, QEvent* e ) pos += frame_area.topLeft(); // determine which item was clicked - if( mMode == TabBox::WindowsMode ) + if( mMode == TabBoxWindowsMode ) { foreach( EffectWindow* w, windows.keys()) { if( windows[ w ]->clickable.contains( pos )) { - Workspace::self()->setTabBoxClient( static_cast< Client* >( w->window())); + effects->setTabBoxWindow( w ); } } } @@ -154,7 +155,7 @@ void BoxSwitchEffect::windowInputMouseEvent( Window w, QEvent* e ) { if( desktops[ i ]->clickable.contains( pos )) { - Workspace::self()->setTabBoxDesktop( i ); + effects->setTabBoxDesktop( i ); } } } @@ -164,11 +165,11 @@ void BoxSwitchEffect::windowDamaged( EffectWindow* w, const QRect& damage ) { if( mActivated ) { - if( mMode == TabBox::WindowsMode ) + if( mMode == TabBoxWindowsMode ) { if( windows.contains( w )) { - workspace()->addRepaint( windows[ w ]->area ); + effects->addRepaint( windows[ w ]->area ); } } else @@ -176,11 +177,11 @@ void BoxSwitchEffect::windowDamaged( EffectWindow* w, const QRect& damage ) if( w->isOnAllDesktops()) { foreach( ItemInfo* info, desktops ) - workspace()->addRepaint( info->area ); + effects->addRepaint( info->area ); } else { - workspace()->addRepaint( desktops[ w->desktop() ]->area ); + effects->addRepaint( desktops[ w->desktop() ]->area ); } } } @@ -190,11 +191,11 @@ void BoxSwitchEffect::windowGeometryShapeChanged( EffectWindow* w, const QRect& { if( mActivated ) { - if( mMode == TabBox::WindowsMode ) + if( mMode == TabBoxWindowsMode ) { if( windows.contains( w ) && w->size() != old.size()) { - workspace()->addRepaint( windows[ w ]->area ); + effects->addRepaint( windows[ w ]->area ); } } else @@ -202,11 +203,11 @@ void BoxSwitchEffect::windowGeometryShapeChanged( EffectWindow* w, const QRect& if( w->isOnAllDesktops()) { foreach( ItemInfo* info, desktops ) - workspace()->addRepaint( info->area ); + effects->addRepaint( info->area ); } else { - workspace()->addRepaint( desktops[ w->desktop() ]->area ); + effects->addRepaint( desktops[ w->desktop() ]->area ); } } } @@ -216,22 +217,22 @@ void BoxSwitchEffect::tabBoxAdded( int mode ) { if( !mActivated ) { - if( mode == TabBox::WindowsMode ) + if( mode == TabBoxWindowsMode ) { - if( Workspace::self()->currentTabBoxClientList().count() > 0 ) + if( effects->currentTabBoxWindowList().count() > 0 ) { mMode = mode; - Workspace::self()->refTabBox(); + effects->refTabBox(); setActive(); } } else { // DesktopMode - if( Workspace::self()->currentTabBoxDesktopList().count() > 0 ) + if( effects->currentTabBoxDesktopList().count() > 0 ) { mMode = mode; painting_desktop = 0; - Workspace::self()->refTabBox(); + effects->refTabBox(); setActive(); } } @@ -248,65 +249,65 @@ void BoxSwitchEffect::tabBoxUpdated() { if( mActivated ) { - if( mMode == TabBox::WindowsMode ) + if( mMode == TabBoxWindowsMode ) { if( selected_window != NULL ) { if( windows.contains( selected_window )) - workspace()->addRepaint( windows.value( selected_window )->area ); - selected_window->window()->addRepaintFull(); + effects->addRepaint( windows.value( selected_window )->area ); + selected_window->addRepaintFull(); } - selected_window = Workspace::self()->currentTabBoxClient()->effectWindow(); + selected_window = effects->currentTabBoxWindow(); if( windows.contains( selected_window )) - workspace()->addRepaint( windows.value( selected_window )->area ); - selected_window->window()->addRepaintFull(); - if( Workspace::self()->currentTabBoxClientList() == original_windows ) + effects->addRepaint( windows.value( selected_window )->area ); + selected_window->addRepaintFull(); + if( effects->currentTabBoxWindowList() == original_windows ) return; - original_windows = Workspace::self()->currentTabBoxClientList(); + original_windows = effects->currentTabBoxWindowList(); } else { // DesktopMode if( desktops.contains( selected_desktop )) - workspace()->addRepaint( desktops.value( selected_desktop )->area ); - selected_desktop = Workspace::self()->currentTabBoxDesktop(); + effects->addRepaint( desktops.value( selected_desktop )->area ); + selected_desktop = effects->currentTabBoxDesktop(); if( desktops.contains( selected_desktop )) - workspace()->addRepaint( desktops.value( selected_desktop )->area ); - if( Workspace::self()->currentTabBoxDesktopList() == original_desktops ) + effects->addRepaint( desktops.value( selected_desktop )->area ); + if( effects->currentTabBoxDesktopList() == original_desktops ) return; - original_desktops = Workspace::self()->currentTabBoxDesktopList(); + original_desktops = effects->currentTabBoxDesktopList(); } - workspace()->addRepaint( frame_area ); + effects->addRepaint( frame_area ); calculateFrameSize(); calculateItemSizes(); moveResizeInputWindow( frame_area.x(), frame_area.y(), frame_area.width(), frame_area.height()); - workspace()->addRepaint( frame_area ); + effects->addRepaint( frame_area ); } } void BoxSwitchEffect::setActive() { mActivated = true; - if( mMode == TabBox::WindowsMode ) + if( mMode == TabBoxWindowsMode ) { - original_windows = Workspace::self()->currentTabBoxClientList(); - selected_window = Workspace::self()->currentTabBoxClient()->effectWindow(); + original_windows = effects->currentTabBoxWindowList(); + selected_window = effects->currentTabBoxWindow(); } else { - original_desktops = Workspace::self()->currentTabBoxDesktopList(); - selected_desktop = Workspace::self()->currentTabBoxDesktop(); + original_desktops = effects->currentTabBoxDesktopList(); + selected_desktop = effects->currentTabBoxDesktop(); } calculateFrameSize(); calculateItemSizes(); mInput = effects->createInputWindow( this, frame_area.x(), frame_area.y(), frame_area.width(), frame_area.height(), Qt::ArrowCursor ); - workspace()->addRepaint( frame_area ); - if( mMode == TabBox::WindowsMode ) + effects->addRepaint( frame_area ); + if( mMode == TabBoxWindowsMode ) { foreach( EffectWindow* w, windows.keys()) { if( w != selected_window ) - w->window()->addRepaintFull(); + w->addRepaintFull(); } } } @@ -314,23 +315,23 @@ void BoxSwitchEffect::setActive() void BoxSwitchEffect::setInactive() { mActivated = false; - Workspace::self()->unrefTabBox(); + effects->unrefTabBox(); if( mInput != None ) { effects->destroyInputWindow( mInput ); mInput = None; } - if( mMode == TabBox::WindowsMode ) + if( mMode == TabBoxWindowsMode ) { foreach( EffectWindow* w, windows.keys()) { if( w != selected_window ) - w->window()->addRepaintFull(); + w->addRepaintFull(); } foreach( ItemInfo* i, windows ) { #ifdef HAVE_XRENDER - if( dynamic_cast< SceneXrender* >( scene )) + if( effects->compositingType() == XRenderCompositing ) { if( i->iconPicture != None ) XRenderFreePicture( display(), i->iconPicture ); @@ -347,7 +348,7 @@ void BoxSwitchEffect::setInactive() delete i; desktops.clear(); } - workspace()->addRepaint( frame_area ); + effects->addRepaint( frame_area ); frame_area = QRect(); } @@ -361,7 +362,7 @@ void BoxSwitchEffect::calculateFrameSize() { int itemcount; - if( mMode == TabBox::WindowsMode ) + if( mMode == TabBoxWindowsMode ) { itemcount = original_windows.count(); item_max_size.setWidth( 200 ); @@ -386,12 +387,12 @@ void BoxSwitchEffect::calculateFrameSize() void BoxSwitchEffect::calculateItemSizes() { - if( mMode == TabBox::WindowsMode ) + if( mMode == TabBoxWindowsMode ) { windows.clear(); for( int i = 0; i < original_windows.count(); i++ ) { - EffectWindow* w = original_windows.at( i )->effectWindow(); + EffectWindow* w = original_windows.at( i ); windows[ w ] = new ItemInfo(); windows[ w ]->area = QRect( frame_area.x() + frame_margin @@ -422,7 +423,7 @@ void BoxSwitchEffect::paintFrame() { double alpha = 0.75; #ifdef HAVE_OPENGL - if( dynamic_cast< SceneOpenGL* >( scene )) + if( effects->compositingType() == OpenGLCompositing ) { glPushAttrib( GL_CURRENT_BIT | GL_ENABLE_BIT ); glEnable( GL_BLEND ); @@ -441,10 +442,10 @@ void BoxSwitchEffect::paintFrame() glDisableClientState( GL_VERTEX_ARRAY ); glPopAttrib(); } - else #endif - { #ifdef HAVE_XRENDER + if( effects->compositingType() == XRenderCompositing ) + { Pixmap pixmap = XCreatePixmap( display(), rootWindow(), frame_area.width(), frame_area.height(), 32 ); Picture pic = XRenderCreatePicture( display(), pixmap, alphaFormat, 0, NULL ); @@ -457,18 +458,18 @@ void BoxSwitchEffect::paintFrame() XRenderFillRectangle( display(), PictOpSrc, pic, &col, 0, 0, frame_area.width(), frame_area.height()); XRenderComposite( display(), alpha != 1.0 ? PictOpOver : PictOpSrc, - pic, None, static_cast< SceneXrender* >( scene )->bufferPicture(), + pic, None, effects->xrenderBufferPicture(), 0, 0, 0, 0, frame_area.x(), frame_area.y(), frame_area.width(), frame_area.height()); XRenderFreePicture( display(), pic ); -#endif } +#endif } void BoxSwitchEffect::paintHighlight( QRect area, QString text ) { double alpha = 0.75; #ifdef HAVE_OPENGL - if( dynamic_cast< SceneOpenGL* >( scene )) + if( effects->compositingType() == OpenGLCompositing ) { glPushAttrib( GL_CURRENT_BIT | GL_ENABLE_BIT ); glEnable( GL_BLEND ); @@ -487,10 +488,10 @@ void BoxSwitchEffect::paintHighlight( QRect area, QString text ) glDisableClientState( GL_VERTEX_ARRAY ); glPopAttrib(); } - else #endif - { #ifdef HAVE_XRENDER + if( effects->compositingType() == XRenderCompositing ) + { Pixmap pixmap = XCreatePixmap( display(), rootWindow(), area.width(), area.height(), 32 ); Picture pic = XRenderCreatePicture( display(), pixmap, alphaFormat, 0, NULL ); @@ -503,11 +504,11 @@ void BoxSwitchEffect::paintHighlight( QRect area, QString text ) XRenderFillRectangle( display(), PictOpSrc, pic, &col, 0, 0, area.width(), area.height()); XRenderComposite( display(), alpha != 1.0 ? PictOpOver : PictOpSrc, - pic, None, static_cast< SceneXrender* >( scene )->bufferPicture(), + pic, None, effects->xrenderBufferPicture(), 0, 0, 0, 0, area.x(), area.y(), area.width(), area.height()); XRenderFreePicture( display(), pic ); -#endif } +#endif // kDebug() << text << endl; // TODO draw this nicely on screen } @@ -523,7 +524,7 @@ void BoxSwitchEffect::paintWindowThumbnail( EffectWindow* w ) Qt::KeepAspectRatio ); effects->drawWindow( w, - Scene::PAINT_WINDOW_OPAQUE | Scene::PAINT_WINDOW_TRANSFORMED, + PAINT_WINDOW_OPAQUE | PAINT_WINDOW_TRANSFORMED, windows[ w ]->thumbnail, data ); } @@ -549,7 +550,7 @@ void BoxSwitchEffect::paintDesktopThumbnail( int iDesktop ) data.xTranslate = x; data.yTranslate = y; - effects->paintScreen( Scene::PAINT_SCREEN_TRANSFORMED | Scene::PAINT_SCREEN_BACKGROUND_FIRST, + effects->paintScreen( PAINT_SCREEN_TRANSFORMED | PAINT_SCREEN_BACKGROUND_FIRST, region, data ); } @@ -557,33 +558,32 @@ void BoxSwitchEffect::paintWindowIcon( EffectWindow* w ) { if( !windows.contains( w )) return; - if( windows[ w ]->icon.serialNumber() - != static_cast< Client* >( w->window())->icon().serialNumber()) + if( windows[ w ]->icon.serialNumber() != w->icon().serialNumber()) { // make sure windows[ w ]->icon is the right QPixmap, and rebind - windows[ w ]->icon = static_cast< Client* >( w->window())->icon(); + windows[ w ]->icon = w->icon(); #ifdef HAVE_OPENGL - if( dynamic_cast< SceneOpenGL* >( scene )) + if( effects->compositingType() == OpenGLCompositing ) { windows[ w ]->iconTexture.load( windows[ w ]->icon ); windows[ w ]->iconTexture.setFilter( GL_LINEAR ); } - else #endif - { #ifdef HAVE_XRENDER + if( effects->compositingType() == XRenderCompositing ) + { if( windows[ w ]->iconPicture != None ) XRenderFreePicture( display(), windows[ w ]->iconPicture ); windows[ w ]->iconPicture = XRenderCreatePicture( display(), windows[ w ]->icon.handle(), alphaFormat, 0, NULL ); -#endif } +#endif } int width = windows[ w ]->icon.width(); int height = windows[ w ]->icon.height(); int x = windows[ w ]->area.x() + windows[ w ]->area.width() - width - highlight_margin; int y = windows[ w ]->area.y() + windows[ w ]->area.height() - height - highlight_margin; #ifdef HAVE_OPENGL - if( dynamic_cast< SceneOpenGL* >( scene )) + if( effects->compositingType() == OpenGLCompositing ) { glPushAttrib( GL_CURRENT_BIT | GL_ENABLE_BIT ); glEnable( GL_BLEND ); @@ -613,18 +613,17 @@ void BoxSwitchEffect::paintWindowIcon( EffectWindow* w ) windows[ w ]->iconTexture.unbind(); glPopAttrib(); } - else #endif - { #ifdef HAVE_XRENDER + if( effects->compositingType() == XRenderCompositing ) + { XRenderComposite( display(), windows[ w ]->icon.depth() == 32 ? PictOpOver : PictOpSrc, windows[ w ]->iconPicture, None, - static_cast< SceneXrender* >( scene )->bufferPicture(), + effects->xrenderBufferPicture(), 0, 0, 0, 0, x, y, width, height ); -#endif } +#endif } } // namespace -#endif diff --git a/effects/boxswitch.h b/effects/boxswitch.h index 66a788d8d3..921e3743be 100644 --- a/effects/boxswitch.h +++ b/effects/boxswitch.h @@ -11,9 +11,6 @@ License. See the file "COPYING" for the exact licensing terms. #ifndef KWIN_BOXSWITCH_H #define KWIN_BOXSWITCH_H -#if 0 -// TODO - #include #include @@ -104,4 +101,3 @@ class BoxSwitchEffect::ItemInfo } // namespace #endif -#endif diff --git a/lib/kwineffects.h b/lib/kwineffects.h index c3a5342b8b..f276a7cf47 100644 --- a/lib/kwineffects.h +++ b/lib/kwineffects.h @@ -181,12 +181,23 @@ class KWIN_EXPORT EffectsHandler // virtual int currentDesktop() const = 0; virtual int numberOfDesktops() const = 0; + virtual QString desktopName( int desktop ) const = 0; virtual QRect clientArea( clientAreaOption, const QPoint& p, int desktop ) const = 0; virtual void calcDesktopLayout(int* x, int* y, Qt::Orientation* orientation) const = 0; virtual bool optionRollOverDesktops() const = 0; virtual EffectWindowList stackingOrder() const = 0; + virtual void setTabBoxWindow(EffectWindow*) = 0; + virtual void setTabBoxDesktop(int) = 0; + virtual EffectWindowList currentTabBoxWindowList() const = 0; + virtual void refTabBox() = 0; + virtual void unrefTabBox() = 0; + virtual void closeTabBox() = 0; + virtual QList< int > currentTabBoxDesktopList() const = 0; + virtual int currentTabBoxDesktop() const = 0; + virtual EffectWindow* currentTabBoxWindow() const = 0; + // Repaints the entire workspace virtual void addRepaintFull() = 0; virtual void addRepaint( const QRect& r ) = 0; @@ -262,6 +273,7 @@ class KWIN_EXPORT EffectWindow virtual QRect iconGeometry() const = 0; virtual QString caption() const = 0; + virtual QPixmap icon() const = 0; virtual const EffectWindowGroup* group() const = 0; virtual bool isDesktop() const = 0; diff --git a/lib/kwinglobals.h b/lib/kwinglobals.h index 9f87bcbe1f..a7ab3bc467 100644 --- a/lib/kwinglobals.h +++ b/lib/kwinglobals.h @@ -59,6 +59,10 @@ enum ElectricBorder ElectricNone }; +// DesktopMode and WindowsMode are based on the order in which the desktop +// or window were viewed. +// DesktopListMode lists them in the order created. +enum TabBoxMode { TabBoxDesktopMode, TabBoxDesktopListMode, TabBoxWindowsMode }; class KWIN_EXPORT WindowPaintData { diff --git a/tabbox.cpp b/tabbox.cpp index a75b7fd87e..1d7d3682b6 100644 --- a/tabbox.cpp +++ b/tabbox.cpp @@ -12,19 +12,19 @@ License. See the file "COPYING" for the exact licensing terms. //#define QT_CLEAN_NAMESPACE #include "tabbox.h" #include "workspace.h" +#include "effects.h" #include "client.h" #include #include -#include +#include #include #include #include #include #include #include -#include +#include #include -#include #include #include #include @@ -43,48 +43,39 @@ namespace KWin extern QPixmap* kwin_get_menu_pix_hack(); -TabBox::TabBox( Workspace *ws, const char *name ) - : Q3Frame( 0, name, Qt::WNoAutoErase ), current_client( NULL ), wspace(ws) +TabBox::TabBox( Workspace *ws ) + : QFrame( 0, Qt::X11BypassWindowManagerHint ) + , wspace(ws) + , client(0) + , display_refcount( 0 ) { - setFrameStyle(QFrame::StyledPanel | QFrame::Plain); + setFrameStyle(QFrame::StyledPanel); + setFrameShadow(QFrame::Plain); + setBackgroundRole(QPalette::Base); setLineWidth(2); - setMargin(2); + setContentsMargins( 2, 2, 2, 2 ); showMiniIcon = false; no_tasks = i18n("*** No Windows ***"); - m = DesktopMode; // init variables + m = TabBoxDesktopMode; // init variables + updateKeyMapping(); reconfigure(); reset(); connect(&delayedShowTimer, SIGNAL(timeout()), this, SLOT(show())); - - XSetWindowAttributes attr; - attr.override_redirect = 1; - outline_left = XCreateWindow( display(), rootWindow(), 0, 0, 1, 1, 0, - CopyFromParent, CopyFromParent, CopyFromParent, CWOverrideRedirect, &attr ); - outline_right = XCreateWindow( display(), rootWindow(), 0, 0, 1, 1, 0, - CopyFromParent, CopyFromParent, CopyFromParent, CWOverrideRedirect, &attr ); - outline_top = XCreateWindow( display(), rootWindow(), 0, 0, 1, 1, 0, - CopyFromParent, CopyFromParent, CopyFromParent, CWOverrideRedirect, &attr ); - outline_bottom = XCreateWindow( display(), rootWindow(), 0, 0, 1, 1, 0, - CopyFromParent, CopyFromParent, CopyFromParent, CWOverrideRedirect, &attr ); } TabBox::~TabBox() { - XDestroyWindow( display(), outline_left ); - XDestroyWindow( display(), outline_right ); - XDestroyWindow( display(), outline_top ); - XDestroyWindow( display(), outline_bottom ); } /*! - Sets the current mode to \a mode, either DesktopListMode or WindowsMode + Sets the current mode to \a mode, either TabBoxDesktopListMode or TabBoxWindowsMode \sa mode() */ -void TabBox::setMode( Mode mode ) +void TabBox::setMode( TabBoxMode mode ) { m = mode; } @@ -102,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(); @@ -125,15 +116,11 @@ void TabBox::createClientList(ClientList &list, int desktop /*-1 = all*/, Client list += c; else if( !list.contains( modal )) list += modal; - else - { - // nothing - } } } if ( chain ) - c = workspace()->nextFocusChainClient( c ); + c = workspace()->nextClientFocusChain( c ); else { if ( idx >= (workspace()->stackingOrder().size()-1) ) @@ -149,25 +136,53 @@ void TabBox::createClientList(ClientList &list, int desktop /*-1 = all*/, Client /*! - Resets the tab box to display the active client in WindowsMode, or the - current desktop in DesktopListMode + 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 TabBoxWindowsMode, or the + current desktop in TabBoxDesktopListMode */ -void TabBox::reset() +void TabBox::reset( bool partial_reset ) { int w, h, cw = 0, wmax = 0; - QRect r = KGlobalSettings::desktopGeometry(QCursor::pos()); + QRect r = KGlobalSettings::desktopGeometry(cursorPos()); // calculate height of 1 line // fontheight + 1 pixel above + 1 pixel below, or 32x32 icon + 2 pixel above + below lineHeight = qMax(fontMetrics().height() + 2, 32 + 4); - if ( mode() == WindowsMode ) + if ( mode() == TabBoxWindowsMode ) { - setCurrentClient( workspace()->activeClient()); + Client* starting_client = 0; + if( partial_reset && clients.count() != 0 ) + starting_client = clients.first(); + else + client = starting_client = workspace()->activeClient(); // get all clients to show - createClientList(clients, options_traverse_all ? -1 : workspace()->currentDesktop(), current_client, true); + createClientList(clients, options_traverse_all ? -1 : workspace()->currentDesktop(), starting_client, true); // calculate maximum caption width cw = fontMetrics().width(no_tasks)+20; @@ -212,18 +227,32 @@ void TabBox::reset() } } else - { // DesktopListMode - showMiniIcon = false; - desk = workspace()->currentDesktop(); + { + int starting_desktop; + if( mode() == TabBoxDesktopListMode ) + { + starting_desktop = 1; + createDesktopList(desktops, starting_desktop, StaticOrder ); + } + else + { // TabBoxDesktopMode + 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 @@ -234,6 +263,9 @@ void TabBox::reset() setGeometry( (r.width()-w)/2 + r.x(), (r.height()-h)/2+ r.y(), w, h ); + + if( effects ) + static_cast(effects)->tabBoxUpdated(); } @@ -242,105 +274,130 @@ void TabBox::reset() */ void TabBox::nextPrev( bool next) { - if ( mode() == WindowsMode ) + if ( mode() == TabBoxWindowsMode ) { - Client* firstClient = NULL; - Client* client = current_client; + 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 )); - setCurrentClient( client ); + } while ( newClient && !clients.contains( newClient )); + setCurrentClient( newClient ); } - else if( mode() == DesktopMode ) + else if( mode() == TabBoxDesktopMode ) { - 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(); - } + { // TabBoxDesktopListMode + setCurrentDesktop ( next ? workspace()->nextDesktopStatic( desk ) + : workspace()->previousDesktopStatic( desk )) ; } + if( effects ) + static_cast(effects)->tabBoxUpdated(); update(); } /*! - Returns the currently displayed client ( only works in WindowsMode ). + Returns the currently displayed client ( only works in TabBoxWindowsMode ). Returns 0 if no client is displayed. */ Client* TabBox::currentClient() { - if ( mode() != WindowsMode ) + if ( mode() != TabBoxWindowsMode ) return 0; - if (!workspace()->hasClient( current_client )) + if (!workspace()->hasClient( client )) return 0; - return current_client; - } - -void TabBox::setCurrentClient( Client* c ) - { - if( current_client != c ) - { - current_client = c; - updateOutline(); - } + return client; } +/*! + Returns the list of clients potentially displayed ( only works in + TabBoxWindowsMode ). + Returns an empty list if no clients are available. + */ +ClientList TabBox::currentClientList() + { + if( mode() != TabBoxWindowsMode ) + return ClientList(); + return clients; + } + + /*! Returns the currently displayed virtual desktop ( only works in - DesktopListMode ) + TabBoxDesktopListMode ) Returns -1 if no desktop is displayed. */ int TabBox::currentDesktop() { - if ( mode() == DesktopListMode || mode() == DesktopMode ) + if ( mode() == TabBoxDesktopListMode || mode() == TabBoxDesktopMode ) return desk; - else - return -1; + return -1; } +/*! + Returns the list of desktops potentially displayed ( only works in + TabBoxDesktopListMode ) + Returns an empty list if no desktops are available. + */ +QList< int > TabBox::currentDesktopList() + { + if ( mode() == TabBoxDesktopListMode || mode() == TabBoxDesktopMode ) + 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 ) + static_cast(effects)->tabBoxUpdated(); + } + +/*! + Change the currently selected desktop, and notify the effects. + + \sa setCurrentClient() + */ +void TabBox::setCurrentDesktop( int newDesktop ) + { + desk = newDesktop; + if( effects ) + static_cast(effects)->tabBoxUpdated(); + } + /*! Reimplemented to raise the tab box as well */ void TabBox::showEvent( QShowEvent* ) { - updateOutline(); - XRaiseWindow( display(), outline_left ); - XRaiseWindow( display(), outline_right ); - XRaiseWindow( display(), outline_top ); - XRaiseWindow( display(), outline_bottom ); raise(); } @@ -350,31 +407,25 @@ void TabBox::showEvent( QShowEvent* ) */ void TabBox::hideEvent( QHideEvent* ) { - XUnmapWindow( display(), outline_left ); - XUnmapWindow( display(), outline_right ); - XUnmapWindow( display(), outline_top ); - XUnmapWindow( display(), outline_bottom ); } /*! Paints the tab box */ -void TabBox::drawContents( QPainter * ) +void TabBox::paintEvent( QPaintEvent* e ) { - QRect r(contentsRect()); - QPixmap pix(r.size()); // do double buffering to avoid flickers - pix.fill(this, 0, 0); + QFrame::paintEvent( e ); - QPainter p; - p.begin(&pix); + QPainter p( this ); + QRect r( contentsRect()); QPixmap* menu_pix = kwin_get_menu_pix_hack(); int iconWidth = showMiniIcon ? 16 : 32; - int x = 0; - int y = 0; + int x = r.x(); + int y = r.y(); - if ( mode () == WindowsMode ) + if ( mode () == TabBoxWindowsMode ) { if ( !currentClient() ) { @@ -392,7 +443,7 @@ void TabBox::drawContents( QPainter * ) if ( workspace()->hasClient( *it ) ) // safety { // draw highlight background - if ( (*it) == current_client ) + if ( (*it) == currentClient() ) p.fillRect(x, y, r.width(), lineHeight, palette().brush( QPalette::Highlight )); // draw icon @@ -426,10 +477,10 @@ void TabBox::drawContents( QPainter * ) else s += (*it)->caption(); - s = fontMetrics().elidedText(s, Qt::ElideMiddle, r.width() - 5 - iconWidth - 8); + s = fontMetrics().elidedText( s, Qt::ElideMiddle, r.width() - 5 - iconWidth - 8 ); // draw text - if ( (*it) == current_client ) + if ( (*it) == currentClient() ) p.setPen(palette().color( QPalette::HighlightedText )); else if( (*it)->isMinimized()) { @@ -461,7 +512,7 @@ void TabBox::drawContents( QPainter * ) } } else - { // DesktopMode || DesktopListMode + { // TabBoxDesktopMode || TabBoxDesktopListMode int iconHeight = iconWidth; // get widest desktop name/number @@ -471,22 +522,19 @@ void TabBox::drawContents( QPainter * ) 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(); @@ -498,28 +546,28 @@ void TabBox::drawContents( QPainter * ) // 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() ) { @@ -534,107 +582,38 @@ void TabBox::drawContents( QPainter * ) // next desktop y += lineHeight; if ( y >= r.height() ) break; - - if( mode() == DesktopMode ) - iDesktop = workspace()->nextDesktopFocusChain( iDesktop ); - else - iDesktop++; } } - p.end(); - - QPainter localPainter( this ); - localPainter.drawImage( QPoint( r.x(), r.y() ), pix.toImage() ); } -void TabBox::updateOutline() + +/*! + 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() { - Client* c = currentClient(); - if( c == NULL || this->isHidden() || !c->isShown( true ) || !c->isOnCurrentDesktop()) - { - XUnmapWindow( display(), outline_left ); - XUnmapWindow( display(), outline_right ); - XUnmapWindow( display(), outline_top ); - XUnmapWindow( display(), outline_bottom ); + if( effects ) + static_cast(effects)->tabBoxAdded( mode()); + if( isDisplayed()) return; - } - // left/right parts are between top/bottom, they don't reach as far as the corners - XMoveResizeWindow( display(), outline_left, c->x(), c->y() + 5, 5, c->height() - 10 ); - XMoveResizeWindow( display(), outline_right, c->x() + c->width() - 5, c->y() + 5, 5, c->height() - 10 ); - XMoveResizeWindow( display(), outline_top, c->x(), c->y(), c->width(), 5 ); - XMoveResizeWindow( display(), outline_bottom, c->x(), c->y() + c->height() - 5, c->width(), 5 ); - { - QPixmap pix( 5, c->height() - 10 ); - QPainter p( &pix ); - p.setPen( Qt::white ); - p.drawLine( 0, 0, 0, pix.height() - 1 ); - p.drawLine( 4, 0, 4, pix.height() - 1 ); - p.setPen( Qt::gray ); - p.drawLine( 1, 0, 1, pix.height() - 1 ); - p.drawLine( 3, 0, 3, pix.height() - 1 ); - p.setPen( Qt::black ); - p.drawLine( 2, 0, 2, pix.height() - 1 ); - p.end(); - XSetWindowBackgroundPixmap( display(), outline_left, pix.handle()); - XSetWindowBackgroundPixmap( display(), outline_right, pix.handle()); - } - { - QPixmap pix( c->width(), 5 ); - QPainter p( &pix ); - p.setPen( Qt::white ); - p.drawLine( 0, 0, pix.width() - 1 - 0, 0 ); - p.drawLine( 4, 4, pix.width() - 1 - 4, 4 ); - p.drawLine( 0, 0, 0, 4 ); - p.drawLine( pix.width() - 1 - 0, 0, pix.width() - 1 - 0, 4 ); - p.setPen( Qt::gray ); - p.drawLine( 1, 1, pix.width() - 1 - 1, 1 ); - p.drawLine( 3, 3, pix.width() - 1 - 3, 3 ); - p.drawLine( 1, 1, 1, 4 ); - p.drawLine( 3, 3, 3, 4 ); - p.drawLine( pix.width() - 1 - 1, 1, pix.width() - 1 - 1, 4 ); - p.drawLine( pix.width() - 1 - 3, 3, pix.width() - 1 - 3, 4 ); - p.setPen( Qt::black ); - p.drawLine( 2, 2, pix.width() - 1 - 2, 2 ); - p.drawLine( 2, 2, 2, 4 ); - p.drawLine( pix.width() - 1 - 2, 2, pix.width() - 1 - 2, 4 ); - p.end(); - XSetWindowBackgroundPixmap( display(), outline_top, pix.handle()); - } - { - QPixmap pix( c->width(), 5 ); - QPainter p( &pix ); - p.setPen( Qt::white ); - p.drawLine( 4, 0, pix.width() - 1 - 4, 0 ); - p.drawLine( 0, 4, pix.width() - 1 - 0, 4 ); - p.drawLine( 0, 4, 0, 0 ); - p.drawLine( pix.width() - 1 - 0, 4, pix.width() - 1 - 0, 0 ); - p.setPen( Qt::gray ); - p.drawLine( 3, 1, pix.width() - 1 - 3, 1 ); - p.drawLine( 1, 3, pix.width() - 1 - 1, 3 ); - p.drawLine( 3, 1, 3, 0 ); - p.drawLine( 1, 3, 1, 0 ); - p.drawLine( pix.width() - 1 - 3, 1, pix.width() - 1 - 3, 0 ); - p.drawLine( pix.width() - 1 - 1, 3, pix.width() - 1 - 1, 0 ); - p.setPen( Qt::black ); - p.drawLine( 2, 2, pix.width() - 1 - 2, 2 ); - p.drawLine( 2, 0, 2, 2 ); - p.drawLine( pix.width() - 1 - 2, 0, pix.width() - 1 - 2 , 2 ); - p.end(); - XSetWindowBackgroundPixmap( display(), outline_bottom, pix.handle()); - } - XClearWindow( display(), outline_left ); - XClearWindow( display(), outline_right ); - XClearWindow( display(), outline_top ); - XClearWindow( display(), outline_bottom ); - XMapWindow( display(), outline_left ); - XMapWindow( display(), outline_right ); - XMapWindow( display(), outline_top ); - XMapWindow( display(), outline_bottom ); + refDisplay(); + QWidget::show(); } + +/*! + Notify effects that the tab box is being hidden. +*/ void TabBox::hide() { delayedShowTimer.stop(); + if( isVisible()) + unrefDisplay(); + if( effects ) + static_cast(effects)->tabBoxClosed(); + if( isDisplayed()) + kDebug( 1212 ) << "Tab box was not properly closed by an effect" << endl; QWidget::hide(); QApplication::syncX(); XEvent otherEvent; @@ -643,6 +622,15 @@ void TabBox::hide() } +/*! + Decrease the reference count. Only when the reference count is 0 will + the default tab box be shown. + */ +void TabBox::unrefDisplay() + { + --display_refcount; + } + void TabBox::reconfigure() { KSharedConfigPtr c(KGlobal::config()); @@ -688,19 +676,26 @@ void TabBox::delayedShow() void TabBox::handleMouseEvent( XEvent* e ) { XAllowEvents( display(), AsyncPointer, xTime() ); + if( !isVisible() && isDisplayed()) + { // tabbox has been replaced, check effects + if( effects && static_cast(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 )) { workspace()->closeTabBox(); // click outside closes tab return; } - pos.rx() -= x(); // pos is now inside tabbox - pos.ry() -= y(); - int num = (pos.y()-frameWidth()) / lineHeight; - if( mode() == WindowsMode ) + int num = (widgetPos.y()-frameWidth()) / lineHeight; + + if( mode() == TabBoxWindowsMode ) { for( ClientList::ConstIterator it = clients.begin(); it != clients.end(); @@ -716,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(); @@ -788,12 +776,16 @@ bool areKeySymXsDepressed( bool bAll, const uint keySyms[], int nKeySyms ) return bAll; } +static const int MAX_KEYSYMS = 4; +static uint alt_keysyms[ MAX_KEYSYMS ]; +static uint win_keysyms[ MAX_KEYSYMS ]; + 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 ) @@ -808,18 +800,17 @@ static bool areModKeysDepressed( const QKeySequence& seq ) } if( mod & Qt::ALT ) { - rgKeySyms[nKeySyms++] = XK_Alt_L; - rgKeySyms[nKeySyms++] = XK_Alt_R; + for( int i = 0; + i < MAX_KEYSYMS && alt_keysyms[ i ] != NoSymbol; + ++i ) + rgKeySyms[nKeySyms++] = alt_keysyms[ i ]; } if( mod & Qt::META ) { - // It would take some code to determine whether the Win key - // is associated with Super or Meta, so check for both. - // See bug #140023 for details. - rgKeySyms[nKeySyms++] = XK_Super_L; - rgKeySyms[nKeySyms++] = XK_Super_R; - rgKeySyms[nKeySyms++] = XK_Meta_L; - rgKeySyms[nKeySyms++] = XK_Meta_R; + for( int i = 0; + i < MAX_KEYSYMS && win_keysyms[ i ] != NoSymbol; + ++i ) + rgKeySyms[nKeySyms++] = win_keysyms[ i ]; } return areKeySymXsDepressed( false, rgKeySyms, nKeySyms ); @@ -833,6 +824,44 @@ static bool areModKeysDepressed( const KShortcut& cut ) return false; } +void TabBox::updateKeyMapping() + { + const int size = 6; + uint keysyms[ size ] = { XK_Alt_L, XK_Alt_R, XK_Super_L, XK_Super_R, XK_Meta_L, XK_Meta_R }; + XModifierKeymap* map = XGetModifierMapping( display() ); + int altpos = 0; + int winpos = 0; + int winmodpos = -1; + int winmod = KKeyServer::modXMeta(); + while( winmod > 0 ) // get position of the set bit in winmod + { + winmod >>= 1; + ++winmodpos; + } + for( int i = 0; + i < MAX_KEYSYMS; + ++i ) + alt_keysyms[ i ] = win_keysyms[ i ] = NoSymbol; + for( int i = 0; + i < size; + ++i ) + { + KeyCode keycode = XKeysymToKeycode( display(), keysyms[ i ] ); + for( int j = 0; + j < map->max_keypermod; + ++j ) + { + if( map->modifiermap[ 3 * map->max_keypermod + j ] == keycode ) // Alt + if( altpos < MAX_KEYSYMS ) + alt_keysyms[ altpos++ ] = keysyms[ i ]; + if( winmodpos >= 0 && map->modifiermap[ winmodpos * map->max_keypermod + j ] == keycode ) + if( winpos < MAX_KEYSYMS ) + win_keysyms[ winpos++ ] = keysyms[ i ]; + } + } + XFreeModifiermap( map ); + } + void Workspace::slotWalkThroughWindows() { if ( root != rootWindow() ) @@ -956,16 +985,16 @@ 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 ); - tab_box->setMode( TabBox::WindowsMode ); + tab_box->setMode( TabBoxWindowsMode ); tab_box->reset(); return true; } -bool Workspace::startWalkThroughDesktops( int mode ) +bool Workspace::startWalkThroughDesktops( TabBoxMode mode ) { if( !establishTabBoxGrab()) return false; @@ -973,19 +1002,19 @@ bool Workspace::startWalkThroughDesktops( int mode ) keys->setEnabled( false ); disable_shortcuts_keys->setEnabled( false ); client_keys->setEnabled( false ); - tab_box->setMode( (TabBox::Mode) mode ); + tab_box->setMode( mode ); tab_box->reset(); return true; } bool Workspace::startWalkThroughDesktops() { - return startWalkThroughDesktops( TabBox::DesktopMode ); + return startWalkThroughDesktops( TabBoxDesktopMode ); } bool Workspace::startWalkThroughDesktopList() { - return startWalkThroughDesktops( TabBox::DesktopListMode ); + return startWalkThroughDesktops( TabBoxDesktopListMode ); } void Workspace::KDEWalkThroughWindows( bool forward ) @@ -1030,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, @@ -1067,7 +1096,7 @@ void Workspace::CDEWalkThroughWindows( bool forward ) void Workspace::KDEOneStepThroughWindows( bool forward ) { - tab_box->setMode( TabBox::WindowsMode ); + tab_box->setMode( TabBoxWindowsMode ); tab_box->reset(); tab_box->nextPrev( forward ); if( Client* c = tab_box->currentClient() ) @@ -1078,9 +1107,9 @@ void Workspace::KDEOneStepThroughWindows( bool forward ) } } -void Workspace::oneStepThroughDesktops( bool forward, int mode ) +void Workspace::oneStepThroughDesktops( bool forward, TabBoxMode mode ) { - tab_box->setMode( (TabBox::Mode) mode ); + tab_box->setMode( mode ); tab_box->reset(); tab_box->nextPrev( forward ); if ( tab_box->currentDesktop() != -1 ) @@ -1089,12 +1118,12 @@ void Workspace::oneStepThroughDesktops( bool forward, int mode ) void Workspace::oneStepThroughDesktops( bool forward ) { - oneStepThroughDesktops( forward, TabBox::DesktopMode ); + oneStepThroughDesktops( forward, TabBoxDesktopMode ); } void Workspace::oneStepThroughDesktopList( bool forward ) { - oneStepThroughDesktops( forward, TabBox::DesktopListMode ); + oneStepThroughDesktops( forward, TabBoxDesktopListMode ); } /*! @@ -1136,6 +1165,18 @@ void Workspace::tabBoxKeyPress( int keyQt ) } } +void Workspace::refTabBox() + { + if( tab_box ) + tab_box->refDisplay(); + } + +void Workspace::unrefTabBox() + { + if( tab_box ) + tab_box->unrefDisplay(); + } + void Workspace::closeTabBox() { removeTabBoxGrab(); @@ -1187,12 +1228,9 @@ void Workspace::tabBoxKeyRelease( const XKeyEvent& ev ) return; if (tab_grab) { - removeTabBoxGrab(); - tab_box->hide(); - keys->setEnabled( true ); - disable_shortcuts_keys->setEnabled( true ); - client_keys->setEnabled( true ); - tab_grab = false; + bool old_control_grab = control_grab; + closeTabBox(); + control_grab = old_control_grab; if( Client* c = tab_box->currentClient()) { activateClient( c ); @@ -1202,12 +1240,9 @@ void Workspace::tabBoxKeyRelease( const XKeyEvent& ev ) } if (control_grab) { - removeTabBoxGrab(); - tab_box->hide(); - keys->setEnabled( true ); - disable_shortcuts_keys->setEnabled( true ); - client_keys->setEnabled( true ); - control_grab = False; + bool old_tab_grab = tab_grab; + closeTabBox(); + tab_grab = old_tab_grab; if ( tab_box->currentDesktop() != -1 ) { setCurrentDesktop( tab_box->currentDesktop() ); @@ -1238,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; @@ -1259,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; @@ -1276,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; @@ -1292,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; @@ -1305,6 +1356,46 @@ Client* Workspace::previousStaticClient( Client* c ) const return clients[ pos ]; } +Client* Workspace::currentTabBoxClient() const + { + if( !tab_box ) + return 0; + return tab_box->currentClient(); + } + +ClientList Workspace::currentTabBoxClientList() const + { + if( !tab_box ) + return ClientList(); + return tab_box->currentClientList(); + } + +int Workspace::currentTabBoxDesktop() const + { + if( !tab_box ) + return -1; + 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 d037cef39b..cb70adaa7a 100644 --- a/tabbox.h +++ b/tabbox.h @@ -12,7 +12,7 @@ License. See the file "COPYING" for the exact licensing terms. #ifndef KWIN_TABBOX_H #define KWIN_TABBOX_H -#include +#include #include #include "utils.h" @@ -24,57 +24,68 @@ namespace KWin class Workspace; class Client; -class TabBox : public Q3Frame +class TabBox : public QFrame { Q_OBJECT public: - TabBox( Workspace *ws, const char *name=0 ); + TabBox( Workspace *ws ); ~TabBox(); Client* currentClient(); - void setCurrentClient( Client* c ); + ClientList currentClientList(); int currentDesktop(); + QList< int > currentDesktopList(); - // 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 }; - void setMode( Mode mode ); - Mode mode() const; + void setCurrentClient( Client* newClient ); + void setCurrentDesktop( int newDesktop ); - void reset(); + enum SortOrder { StaticOrder, MostRecentlyUsedOrder }; + void setMode( TabBoxMode mode ); + TabBoxMode mode() const; + + void reset( bool partial_reset = false ); void nextPrev( bool next = true); void delayedShow(); void hide(); + void refDisplay(); + void unrefDisplay(); + bool isDisplayed() const; + void handleMouseEvent( XEvent* ); Workspace* workspace() const; void reconfigure(); + void updateKeyMapping(); + + public slots: + void show(); protected: void showEvent( QShowEvent* ); void hideEvent( QHideEvent* ); - void drawContents( QPainter * ); + void paintEvent( QPaintEvent* ); private: void createClientList(ClientList &list, int desktop /*-1 = all*/, Client *start, bool chain); - void updateOutline(); + void createDesktopList(QList< int > &list, int start, SortOrder order); private: - Client* current_client; - Mode m; Workspace* wspace; + TabBoxMode 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; - Window outline_left, outline_right, outline_top, outline_bottom; }; @@ -87,15 +98,36 @@ inline Workspace* TabBox::workspace() const } /*! - Returns the current mode, either DesktopListMode or WindowsMode + Returns the current mode, either TabBoxDesktopListMode or TabBoxWindowsMode \sa setMode() */ -inline TabBox::Mode TabBox::mode() const +inline TabBoxMode TabBox::mode() const { return m; } +/*! + Increase the reference count, preventing the default tabbox from showing. + + \sa unrefDisplay(), isDisplayed() + */ +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 6146eb2ecf..d5f3149201 100644 --- a/workspace.h +++ b/workspace.h @@ -462,14 +462,14 @@ class Workspace : public QObject, public KDecorationDefines void setupWindowShortcut( Client* c ); bool startKDEWalkThroughWindows(); - bool startWalkThroughDesktops( int mode ); // TabBox::Mode::DesktopMode | DesktopListMode + bool startWalkThroughDesktops( TabBoxMode mode ); // TabBoxDesktopMode | TabBoxDesktopListMode bool startWalkThroughDesktops(); bool startWalkThroughDesktopList(); void KDEWalkThroughWindows( bool forward ); void CDEWalkThroughWindows( bool forward ); void walkThroughDesktops( bool forward ); void KDEOneStepThroughWindows( bool forward ); - void oneStepThroughDesktops( bool forward, int mode ); // TabBox::Mode::DesktopMode | DesktopListMode + void oneStepThroughDesktops( bool forward, TabBoxMode mode ); // TabBoxDesktopMode | TabBoxDesktopListMode void oneStepThroughDesktops( bool forward ); void oneStepThroughDesktopList( bool forward ); bool establishTabBoxGrab();