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
This commit is contained in:
parent
d4647a3fbc
commit
fcbd01779a
5 changed files with 155 additions and 9 deletions
|
@ -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 ))
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<long*>( 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<long*>( 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; i<length; i++ )
|
||||
{
|
||||
EffectWindow* foundWin = effects->findWindow( 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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue