From fcbd01779a72b585c3b6d497bf62850102a00243 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Sat, 27 Jun 2009 10:21:49 +0000 Subject: [PATCH] Add support for activating present windows via XAtoms. Present windows can be activated for all windows of a desktop by setting the atom _KDE_PRESENT_WINDOWS_DESKTOP to the number of desktop or -1 for all desktops. Another atom _KDE_PRESENT_WINDOWS_GROUP can be used to activate present windows on a group of windows (e.g. tasks applet). When present windows is deactivated the property on the manager window will be deleted. svn path=/trunk/KDE/kdebase/workspace/; revision=988110 --- effects.cpp | 6 + effects.h | 1 + effects/presentwindows/presentwindows.cpp | 128 +++++++++++++++++++++- effects/presentwindows/presentwindows.h | 26 ++++- lib/kwineffects.h | 3 +- 5 files changed, 155 insertions(+), 9 deletions(-) diff --git a/effects.cpp b/effects.cpp index 2dd801f061..9b11607f3a 100644 --- a/effects.cpp +++ b/effects.cpp @@ -1266,6 +1266,12 @@ QByteArray EffectWindowImpl::readProperty( long atom, long type, int format ) co } } +void EffectWindowImpl::deleteProperty(long int atom) const +{ + XDeleteProperty( QX11Info::display(), window()->window(), atom ); +} + + bool EffectWindowImpl::isMovable() const { if( Client* c = dynamic_cast< Client* >( toplevel )) diff --git a/effects.h b/effects.h index 4023ef7548..ad566e169e 100644 --- a/effects.h +++ b/effects.h @@ -229,6 +229,7 @@ class EffectWindowImpl : public EffectWindow virtual QRect iconGeometry() const; virtual QRect contentsRect() const; virtual QByteArray readProperty( long atom, long type, int format ) const; + virtual void deleteProperty( long atom ) const; virtual bool isDesktop() const; virtual bool isDock() const; diff --git a/effects/presentwindows/presentwindows.cpp b/effects/presentwindows/presentwindows.cpp index 9c37ff469e..69ed54880f 100644 --- a/effects/presentwindows/presentwindows.cpp +++ b/effects/presentwindows/presentwindows.cpp @@ -47,14 +47,25 @@ KWIN_EFFECT( presentwindows, PresentWindowsEffect ) PresentWindowsEffect::PresentWindowsEffect() : m_proxy( this ) , m_activated( false ) - , m_allDesktops( false ) , m_ignoreMinimized( false ) , m_decalOpacity( 0.0 ) , m_hasKeyboardGrab( false ) , m_tabBoxEnabled( false ) + , m_mode( ModeCurrentDesktop ) + , m_managerWindow( NULL ) , m_highlightedWindow( NULL ) , m_filterFrame( EffectFrame::Styled, false ) { + m_atomDesktop = XInternAtom( display(), "_KDE_PRESENT_WINDOWS_DESKTOP", False ); + m_atomWindows = XInternAtom( display(), "_KDE_PRESENT_WINDOWS_GROUP", False ); + effects->registerPropertyType( m_atomDesktop, true ); + effects->registerPropertyType( m_atomWindows, true ); + + // Announce support by creating a dummy version on the root window + unsigned char dummy = 0; + XChangeProperty( display(), rootWindow(), m_atomDesktop, m_atomDesktop, 8, PropModeReplace, &dummy, 1 ); + XChangeProperty( display(), rootWindow(), m_atomWindows, m_atomWindows, 8, PropModeReplace, &dummy, 1 ); + QFont font; font.setPointSize( font.pointSize() * 2 ); font.setBold( true ); @@ -78,6 +89,10 @@ PresentWindowsEffect::PresentWindowsEffect() PresentWindowsEffect::~PresentWindowsEffect() { + XDeleteProperty( display(), rootWindow(), m_atomDesktop ); + effects->registerPropertyType( m_atomDesktop, false ); + XDeleteProperty( display(), rootWindow(), m_atomWindows ); + effects->registerPropertyType( m_atomWindows, false ); foreach( ElectricBorder border, m_borderActivate ) { effects->unreserveElectricBorder( border ); @@ -322,6 +337,8 @@ void PresentWindowsEffect::windowClosed( EffectWindow *w ) { if( m_highlightedWindow == w ) setHighlightedWindow( findFirstWindow() ); + if( m_managerWindow == w ) + m_managerWindow = NULL; if( !m_windowData.contains( w )) return; m_windowData[w].visible = false; // TODO: Fix this so they do actually fade out @@ -389,12 +406,12 @@ void PresentWindowsEffect::grabbedKeyboardEvent( QKeyEvent *e ) { // check for global shortcuts // HACK: keyboard grab disables the global shortcuts so we have to check for global shortcut (bug 156155) - if( !m_allDesktops && shortcut.contains( e->key() + e->modifiers() ) ) + if( m_mode == ModeCurrentDesktop && shortcut.contains( e->key() + e->modifiers() ) ) { toggleActive(); return; } - if( m_allDesktops && shortcutAll.contains( e->key() + e->modifiers() ) ) + if( m_mode == ModeAllDesktops && shortcutAll.contains( e->key() + e->modifiers() ) ) { toggleActiveAllDesktops(); return; @@ -504,6 +521,87 @@ void PresentWindowsEffect::tabBoxUpdated() setHighlightedWindow( effects->currentTabBoxWindow() ); } +//----------------------------------------------------------------------------- +// Atom handling +void PresentWindowsEffect::propertyNotify( EffectWindow* w, long a ) + { + if( a != m_atomDesktop && a != m_atomWindows ) + return; // Not our atom + + if( a == m_atomDesktop ) + { + QByteArray byteData = w->readProperty( m_atomDesktop, m_atomDesktop, 32 ); + if( byteData.length() < 1 ) + { + // Property was removed, end present windows + setActive( false ); + return; + } + long* data = reinterpret_cast( byteData.data() ); + + if( !data[0] ) + { + // Purposely ending present windows by issuing a NULL target + setActive( false ); + return; + } + // present windows is active so don't do anything + if( m_activated ) + return; + + int desktop = data[0]; + if( desktop > effects->numberOfDesktops() ) + return; + if( desktop == -1 ) + toggleActiveAllDesktops(); + else + { + m_mode = ModeSelectedDesktop; + m_desktop = desktop; + m_managerWindow = w; + setActive( true ); + } + } + else if( a == m_atomWindows ) + { + QByteArray byteData = w->readProperty( m_atomWindows, m_atomWindows, 32 ); + if( byteData.length() < 1 ) + { + // Property was removed, end present windows + setActive( false ); + return; + } + long* data = reinterpret_cast( byteData.data() ); + + if( !data[0] ) + { + // Purposely ending present windows by issuing a NULL target + setActive( false ); + return; + } + // present windows is active so don't do anything + if( m_activated ) + return; + + // for security clear selected windows + m_selectedWindows.clear(); + int length = byteData.length() / sizeof( data[0] ); + for( int i=0; ifindWindow( data[i] ); + if( !foundWin ) + { + kDebug(1212) << "Invalid window targetted for present windows. Requested:" << data[i]; + continue; + } + m_selectedWindows.append( foundWin ); + } + m_mode = ModeWindowGroup; + m_managerWindow = w; + setActive( true ); + } + } + //----------------------------------------------------------------------------- // Window rearranging @@ -1301,11 +1399,22 @@ void PresentWindowsEffect::setActive( bool active, bool closingTab ) m_motionManager.moveWindow( w, w->geometry() ); m_filterFrame.free(); m_windowFilter.clear(); + m_selectedWindows.clear(); effects->destroyInputWindow( m_input ); if( m_hasKeyboardGrab ) effects->ungrabKeyboard(); m_hasKeyboardGrab = false; + + // destroy atom on manager window + if( m_managerWindow ) + { + if( m_mode == ModeSelectedDesktop ) + m_managerWindow->deleteProperty( m_atomDesktop ); + else if( m_mode == ModeWindowGroup ) + m_managerWindow->deleteProperty( m_atomWindows ); + m_managerWindow = NULL; + } } effects->addRepaintFull(); // Trigger the first repaint } @@ -1331,8 +1440,17 @@ bool PresentWindowsEffect::isSelectableWindow( EffectWindow *w ) return false; if( !w->acceptsFocus() ) return false; - if( !m_allDesktops && !w->isOnCurrentDesktop() ) - return false; + switch( m_mode ) + { + case ModeAllDesktops: + break; + case ModeCurrentDesktop: + return w->isOnCurrentDesktop(); + case ModeSelectedDesktop: + return w->isOnDesktop( m_desktop ); + case ModeWindowGroup: + return m_selectedWindows.contains( w ); + } if( !m_tabBoxEnabled && m_ignoreMinimized && w->isMinimized() ) return false; return true; diff --git a/effects/presentwindows/presentwindows.h b/effects/presentwindows/presentwindows.h index f9e69cddc6..27ad514806 100644 --- a/effects/presentwindows/presentwindows.h +++ b/effects/presentwindows/presentwindows.h @@ -86,12 +86,22 @@ class PresentWindowsEffect virtual void tabBoxClosed(); virtual void tabBoxUpdated(); + // atoms + virtual void propertyNotify( EffectWindow* w, long atom ); + enum { LayoutNatural, LayoutRegularGrid, LayoutFlexibleGrid }; // Layout modes + enum PresentWindowsMode + { + ModeAllDesktops, // Shows windows of all desktops + ModeCurrentDesktop, // Shows windows on current desktop + ModeSelectedDesktop, // Shows windows of selected desktop via property (m_desktop) + ModeWindowGroup // Shows windows selected via property + }; public slots: void setActive( bool active, bool closingTab = false ); // HACK: closingTab shouldn't be needed - void toggleActive() { m_allDesktops = false; setActive( !m_activated ); } - void toggleActiveAllDesktops() { m_allDesktops = true; setActive( !m_activated ); } + void toggleActive() { m_mode = ModeCurrentDesktop; setActive( !m_activated ); } + void toggleActiveAllDesktops() { m_mode = ModeAllDesktops; setActive( !m_activated ); } // slots for global shortcut changed // needed to toggle the effect @@ -144,12 +154,15 @@ class PresentWindowsEffect // Activation bool m_activated; - bool m_allDesktops; bool m_ignoreMinimized; double m_decalOpacity; Window m_input; bool m_hasKeyboardGrab; bool m_tabBoxEnabled; + PresentWindowsMode m_mode; + int m_desktop; + EffectWindowList m_selectedWindows; + EffectWindow *m_managerWindow; // Window data WindowMotionManager m_motionManager; @@ -166,6 +179,13 @@ class PresentWindowsEffect // Shortcut - needed to toggle the effect KShortcut shortcut; KShortcut shortcutAll; + + // Atoms + // Present windows for all windows of given desktop + // -1 for all desktops + long m_atomDesktop; + // Present windows for group of window ids + long m_atomWindows; }; } // namespace diff --git a/lib/kwineffects.h b/lib/kwineffects.h index a7784739e9..2770e98476 100644 --- a/lib/kwineffects.h +++ b/lib/kwineffects.h @@ -170,7 +170,7 @@ X-KDE-Library=kwin4_effect_cooleffect #define KWIN_EFFECT_API_MAKE_VERSION( major, minor ) (( major ) << 8 | ( minor )) #define KWIN_EFFECT_API_VERSION_MAJOR 0 -#define KWIN_EFFECT_API_VERSION_MINOR 83 +#define KWIN_EFFECT_API_VERSION_MINOR 84 #define KWIN_EFFECT_API_VERSION KWIN_EFFECT_API_MAKE_VERSION( \ KWIN_EFFECT_API_VERSION_MAJOR, KWIN_EFFECT_API_VERSION_MINOR ) @@ -834,6 +834,7 @@ class KWIN_EXPORT EffectWindow virtual QRect contentsRect() const = 0; bool hasDecoration() const; virtual QByteArray readProperty( long atom, long type, int format ) const = 0; + virtual void deleteProperty( long atom ) const = 0; virtual QString caption() const = 0; virtual QPixmap icon() const = 0;