Keep the logout effect active until KWin is killed or the user cancels
the logout by using new information provided by KSMServer; Allow effects to read and detect root window property notify events. svn path=/trunk/KDE/kdebase/workspace/; revision=1083335
This commit is contained in:
parent
b674835c6c
commit
51168e97a4
11 changed files with 128 additions and 51 deletions
97
effects.cpp
97
effects.cpp
|
@ -46,6 +46,52 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
namespace KWin
|
||||
{
|
||||
|
||||
//---------------------
|
||||
// Static
|
||||
|
||||
static QByteArray readWindowProperty( Window win, long atom, long type, int format )
|
||||
{
|
||||
int len = 32768;
|
||||
for(;;)
|
||||
{
|
||||
unsigned char* data;
|
||||
Atom rtype;
|
||||
int rformat;
|
||||
unsigned long nitems, after;
|
||||
if( XGetWindowProperty( QX11Info::display(), win,
|
||||
atom, 0, len, False, AnyPropertyType,
|
||||
&rtype, &rformat, &nitems, &after, &data ) == Success )
|
||||
{
|
||||
if( after > 0 )
|
||||
{
|
||||
XFree( data );
|
||||
len *= 2;
|
||||
continue;
|
||||
}
|
||||
if( long( rtype ) == type && rformat == format )
|
||||
{
|
||||
int bytelen = format == 8 ? nitems : format == 16 ? nitems * sizeof( short ) : nitems * sizeof( long );
|
||||
QByteArray ret( reinterpret_cast< const char* >( data ), bytelen );
|
||||
XFree( data );
|
||||
return ret;
|
||||
}
|
||||
else // wrong format, type or something
|
||||
{
|
||||
XFree( data );
|
||||
return QByteArray();
|
||||
}
|
||||
}
|
||||
else // XGetWindowProperty() failed
|
||||
return QByteArray();
|
||||
}
|
||||
}
|
||||
|
||||
static void deleteWindowProperty( Window win, long int atom )
|
||||
{
|
||||
XDeleteProperty( QX11Info::display(), win, atom );
|
||||
}
|
||||
|
||||
//---------------------
|
||||
|
||||
EffectsHandlerImpl::EffectsHandlerImpl(CompositingType type)
|
||||
: EffectsHandler(type)
|
||||
|
@ -428,6 +474,16 @@ void EffectsHandlerImpl::registerPropertyType( long atom, bool reg )
|
|||
}
|
||||
}
|
||||
|
||||
QByteArray EffectsHandlerImpl::readRootProperty( long atom, long type, int format ) const
|
||||
{
|
||||
return readWindowProperty( rootWindow(), atom, type, format );
|
||||
}
|
||||
|
||||
void EffectsHandlerImpl::deleteRootProperty( long atom ) const
|
||||
{
|
||||
deleteWindowProperty( rootWindow(), atom );
|
||||
}
|
||||
|
||||
void EffectsHandlerImpl::activateWindow( EffectWindow* c )
|
||||
{
|
||||
if( Client* cl = dynamic_cast< Client* >( static_cast<EffectWindowImpl*>(c)->window()))
|
||||
|
@ -1281,46 +1337,13 @@ QRect EffectWindowImpl::contentsRect() const
|
|||
|
||||
QByteArray EffectWindowImpl::readProperty( long atom, long type, int format ) const
|
||||
{
|
||||
int len = 32768;
|
||||
for(;;)
|
||||
{
|
||||
unsigned char* data;
|
||||
Atom rtype;
|
||||
int rformat;
|
||||
unsigned long nitems, after;
|
||||
if( XGetWindowProperty( QX11Info::display(), window()->window(),
|
||||
atom, 0, len, False, AnyPropertyType,
|
||||
&rtype, &rformat, &nitems, &after, &data ) == Success )
|
||||
{
|
||||
if( after > 0 )
|
||||
{
|
||||
XFree( data );
|
||||
len *= 2;
|
||||
continue;
|
||||
}
|
||||
if( long( rtype ) == type && rformat == format )
|
||||
{
|
||||
int bytelen = format == 8 ? nitems : format == 16 ? nitems * sizeof( short ) : nitems * sizeof( long );
|
||||
QByteArray ret( reinterpret_cast< const char* >( data ), bytelen );
|
||||
XFree( data );
|
||||
return ret;
|
||||
}
|
||||
else // wrong format, type or something
|
||||
{
|
||||
XFree( data );
|
||||
return QByteArray();
|
||||
}
|
||||
}
|
||||
else // XGetWindowProperty() failed
|
||||
return QByteArray();
|
||||
}
|
||||
return readWindowProperty( window()->window(), atom, type, format );
|
||||
}
|
||||
|
||||
void EffectWindowImpl::deleteProperty(long int atom) const
|
||||
{
|
||||
XDeleteProperty( QX11Info::display(), window()->window(), atom );
|
||||
}
|
||||
|
||||
{
|
||||
deleteWindowProperty( window()->window(), atom );
|
||||
}
|
||||
|
||||
bool EffectWindowImpl::isMovable() const
|
||||
{
|
||||
|
|
|
@ -134,6 +134,8 @@ class EffectsHandlerImpl : public EffectsHandler
|
|||
virtual unsigned long xrenderBufferPicture();
|
||||
virtual void reconfigure();
|
||||
virtual void registerPropertyType( long atom, bool reg );
|
||||
virtual QByteArray readRootProperty( long atom, long type, int format ) const;
|
||||
virtual void deleteRootProperty( long atom ) const;
|
||||
|
||||
virtual bool hasDecorationShadows() const;
|
||||
|
||||
|
|
|
@ -129,7 +129,7 @@ void HighlightWindowEffect::windowDeleted( EffectWindow* w )
|
|||
|
||||
void HighlightWindowEffect::propertyNotify( EffectWindow* w, long a )
|
||||
{
|
||||
if( a != m_atom )
|
||||
if( !w || a != m_atom )
|
||||
return; // Not our atom
|
||||
|
||||
QByteArray byteData = w->readProperty( m_atom, m_atom, 32 );
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
Copyright (C) 2007 Lubos Lunak <l.lunak@kde.org>
|
||||
Copyright (C) 2009 Martin Gräßlin <kde@martin-graesslin.com>
|
||||
Copyright (C) 2009 Lucas Murray <lmurray@undefinedfire.com>
|
||||
Copyright (C) 2009, 2010 Lucas Murray <lmurray@undefinedfire.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -35,10 +35,18 @@ KWIN_EFFECT( logout, LogoutEffect )
|
|||
|
||||
LogoutEffect::LogoutEffect()
|
||||
: progress( 0.0 )
|
||||
, displayEffect( false )
|
||||
, logoutWindow( NULL )
|
||||
, logoutWindowClosed( true )
|
||||
, logoutWindowPassed( false )
|
||||
, canDoPersistent( false )
|
||||
, ignoredWindows()
|
||||
{
|
||||
// Persistent effect
|
||||
logoutAtom = XInternAtom( display(), "_KDE_LOGGING_OUT", False );
|
||||
effects->registerPropertyType( logoutAtom, true );
|
||||
|
||||
// Block KSMServer's effect
|
||||
char net_wm_cm_name[ 100 ];
|
||||
sprintf( net_wm_cm_name, "_NET_WM_CM_S%d", DefaultScreen( display()));
|
||||
Atom net_wm_cm = XInternAtom( display(), net_wm_cm_name, False );
|
||||
|
@ -46,6 +54,7 @@ LogoutEffect::LogoutEffect()
|
|||
Atom hack = XInternAtom( display(), "_KWIN_LOGOUT_EFFECT", False );
|
||||
XChangeProperty( display(), sel, hack, hack, 8, PropModeReplace, (unsigned char*)&hack, 1 );
|
||||
// the atom is not removed when effect is destroyed, this is temporary anyway
|
||||
|
||||
#ifdef KWIN_HAVE_OPENGL_COMPOSITING
|
||||
blurTexture = NULL;
|
||||
blurTarget = NULL;
|
||||
|
@ -78,7 +87,7 @@ void LogoutEffect::reconfigure( ReconfigureFlags )
|
|||
void LogoutEffect::prePaintScreen( ScreenPrePaintData& data, int time )
|
||||
{
|
||||
#ifdef KWIN_HAVE_OPENGL_COMPOSITING
|
||||
if( !logoutWindow && progress == 0.0 )
|
||||
if( !displayEffect && progress == 0.0 )
|
||||
{
|
||||
if( blurTexture )
|
||||
{
|
||||
|
@ -117,7 +126,7 @@ void LogoutEffect::prePaintScreen( ScreenPrePaintData& data, int time )
|
|||
else
|
||||
#endif
|
||||
{
|
||||
if( logoutWindow != NULL && !logoutWindowClosed )
|
||||
if( displayEffect )
|
||||
progress = qMin( 1.0, progress + time / animationTime( 2000.0 ));
|
||||
else if( progress > 0.0 )
|
||||
progress = qMax( 0.0, progress - time / animationTime( 500.0 ));
|
||||
|
@ -150,7 +159,7 @@ void LogoutEffect::paintWindow( EffectWindow* w, int mask, QRegion region, Windo
|
|||
}
|
||||
else
|
||||
{
|
||||
if( logoutWindowPassed )
|
||||
if( logoutWindowPassed || ignoredWindows.contains( w ))
|
||||
{ // Window is rendered after the FBO
|
||||
windows.append( w );
|
||||
windowsOpacities[ w ] = data.opacity;
|
||||
|
@ -165,7 +174,7 @@ void LogoutEffect::paintWindow( EffectWindow* w, int mask, QRegion region, Windo
|
|||
if( w == logoutWindow )
|
||||
// This is the logout window don't alter it but render our vignetting now
|
||||
renderVignetting();
|
||||
else if( !logoutWindowPassed )
|
||||
else if( !logoutWindowPassed && !ignoredWindows.contains( w ))
|
||||
// Window is in the background, desaturate
|
||||
data.saturation *= ( 1.0 - progress * 0.2 );
|
||||
// All other windows are unaltered
|
||||
|
@ -174,13 +183,15 @@ void LogoutEffect::paintWindow( EffectWindow* w, int mask, QRegion region, Windo
|
|||
#endif
|
||||
if( effects->compositingType() == KWin::XRenderCompositing )
|
||||
{ // Since we can't do vignetting in XRender just do a stronger desaturation and darken
|
||||
if( w != logoutWindow && !logoutWindowPassed )
|
||||
if( w != logoutWindow && !logoutWindowPassed && !ignoredWindows.contains( w ))
|
||||
{
|
||||
data.saturation *= ( 1.0 - progress * 0.8 );
|
||||
data.brightness *= ( 1.0 - progress * 0.3 );
|
||||
}
|
||||
}
|
||||
if( w == logoutWindow )
|
||||
if( w == logoutWindow ||
|
||||
ignoredWindows.contains( w )) // HACK: All windows past the first ignored one should not be
|
||||
// blurred as it affects the stacking order.
|
||||
// All following windows are on top of the logout window and should not be altered either
|
||||
logoutWindowPassed = true;
|
||||
}
|
||||
|
@ -305,8 +316,13 @@ void LogoutEffect::windowAdded( EffectWindow* w )
|
|||
logoutWindow = w;
|
||||
logoutWindowClosed = false; // So we don't blur the window on close
|
||||
progress = 0.0;
|
||||
displayEffect = true;
|
||||
ignoredWindows.clear();
|
||||
effects->addRepaintFull();
|
||||
}
|
||||
else if( canDoPersistent )
|
||||
// TODO: Add parent
|
||||
ignoredWindows.append( w );
|
||||
}
|
||||
|
||||
void LogoutEffect::windowClosed( EffectWindow* w )
|
||||
|
@ -314,12 +330,15 @@ void LogoutEffect::windowClosed( EffectWindow* w )
|
|||
if( w == logoutWindow )
|
||||
{
|
||||
logoutWindowClosed = true;
|
||||
if( !canDoPersistent )
|
||||
displayEffect = false; // Fade back to normal
|
||||
effects->addRepaintFull();
|
||||
}
|
||||
}
|
||||
|
||||
void LogoutEffect::windowDeleted( EffectWindow* w )
|
||||
{
|
||||
ignoredWindows.removeAll( w );
|
||||
if( w == logoutWindow )
|
||||
logoutWindow = NULL;
|
||||
}
|
||||
|
@ -364,4 +383,21 @@ void LogoutEffect::renderVignetting()
|
|||
}
|
||||
#endif
|
||||
|
||||
void LogoutEffect::propertyNotify( EffectWindow* w, long a )
|
||||
{
|
||||
if( w || a != logoutAtom )
|
||||
return; // Not our atom
|
||||
|
||||
QByteArray byteData = effects->readRootProperty( logoutAtom, logoutAtom, 8 );
|
||||
if( byteData.length() < 1 )
|
||||
{ // Property was deleted
|
||||
displayEffect = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// We are using a compatible KSMServer therefore only terminate the effect when the
|
||||
// atom is deleted, not when the dialog is closed.
|
||||
canDoPersistent = true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
Copyright (C) 2007 Lubos Lunak <l.lunak@kde.org>
|
||||
Copyright (C) 2009 Martin Gräßlin <kde@martin-graesslin.com>
|
||||
Copyright (C) 2009 Lucas Murray <lmurray@undefinedfire.com>
|
||||
Copyright (C) 2009, 2010 Lucas Murray <lmurray@undefinedfire.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -46,13 +46,20 @@ class LogoutEffect
|
|||
virtual void windowAdded( EffectWindow* w );
|
||||
virtual void windowClosed( EffectWindow* w );
|
||||
virtual void windowDeleted( EffectWindow* w );
|
||||
virtual void propertyNotify( EffectWindow* w, long a );
|
||||
private:
|
||||
bool isLogoutDialog( EffectWindow* w );
|
||||
double progress; // 0-1
|
||||
bool displayEffect;
|
||||
EffectWindow* logoutWindow;
|
||||
bool logoutWindowClosed;
|
||||
bool logoutWindowPassed;
|
||||
|
||||
// Persistent effect
|
||||
long logoutAtom;
|
||||
bool canDoPersistent;
|
||||
EffectWindowList ignoredWindows;
|
||||
|
||||
#ifdef KWIN_HAVE_OPENGL_COMPOSITING
|
||||
void renderVignetting();
|
||||
int frameDelay;
|
||||
|
|
|
@ -732,7 +732,7 @@ void PresentWindowsEffect::tabBoxKeyEvent( QKeyEvent* event )
|
|||
// Atom handling
|
||||
void PresentWindowsEffect::propertyNotify( EffectWindow* w, long a )
|
||||
{
|
||||
if( a != m_atomDesktop && a != m_atomWindows )
|
||||
if( !w || ( a != m_atomDesktop && a != m_atomWindows ))
|
||||
return; // Not our atom
|
||||
|
||||
if( a == m_atomDesktop )
|
||||
|
|
|
@ -373,7 +373,7 @@ QRect ShadowEffect::transformWindowDamage( EffectWindow* w, const QRect& r )
|
|||
|
||||
void ShadowEffect::propertyNotify( EffectWindow* w, long atom )
|
||||
{
|
||||
if ( atom != shadowOverride )
|
||||
if( !w || atom != shadowOverride )
|
||||
return;
|
||||
const QByteArray value = w->readProperty( atom, atom, 32 );
|
||||
w->setData( ShadowOverrideRole, !value.isNull() );
|
||||
|
|
|
@ -184,7 +184,7 @@ void SlidingPopupsEffect::windowDeleted( EffectWindow* w )
|
|||
|
||||
void SlidingPopupsEffect::propertyNotify( EffectWindow* w, long a )
|
||||
{
|
||||
if( a != mAtom )
|
||||
if( !w || a != mAtom )
|
||||
return;
|
||||
|
||||
QByteArray data = w->readProperty( mAtom, mAtom, 32 );
|
||||
|
|
|
@ -131,7 +131,7 @@ void TaskbarThumbnailEffect::windowDeleted( EffectWindow* w )
|
|||
|
||||
void TaskbarThumbnailEffect::propertyNotify( EffectWindow* w, long a )
|
||||
{
|
||||
if( a != atom )
|
||||
if( !w || a != atom )
|
||||
return;
|
||||
thumbnails.remove( w );
|
||||
QByteArray data = w->readProperty( atom, atom, 32 );
|
||||
|
|
|
@ -321,6 +321,13 @@ bool Workspace::workspaceEvent( XEvent * e )
|
|||
if( c->windowEvent( e ))
|
||||
return true;
|
||||
}
|
||||
|
||||
// We want to pass root window property events to effects
|
||||
if( e->type == PropertyNotify && e->xany.window == rootWindow() && effects )
|
||||
{
|
||||
XPropertyEvent* re = &e->xproperty;
|
||||
static_cast< EffectsHandlerImpl* >( effects )->propertyNotify( NULL, re->atom );
|
||||
}
|
||||
}
|
||||
if( movingClient != NULL && movingClient->moveResizeGrabWindow() == e->xany.window
|
||||
&& ( e->type == MotionNotify || e->type == ButtonPress || e->type == ButtonRelease ))
|
||||
|
|
|
@ -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 112
|
||||
#define KWIN_EFFECT_API_VERSION_MINOR 113
|
||||
#define KWIN_EFFECT_API_VERSION KWIN_EFFECT_API_MAKE_VERSION( \
|
||||
KWIN_EFFECT_API_VERSION_MAJOR, KWIN_EFFECT_API_VERSION_MINOR )
|
||||
|
||||
|
@ -722,6 +722,8 @@ class KWIN_EXPORT EffectsHandler
|
|||
Note that even events that haven't been registered for can be received.
|
||||
*/
|
||||
virtual void registerPropertyType( long atom, bool reg ) = 0;
|
||||
virtual QByteArray readRootProperty( long atom, long type, int format ) const = 0;
|
||||
virtual void deleteRootProperty( long atom ) const = 0;
|
||||
|
||||
/**
|
||||
* Returns @a true if the active window decoration has shadow API hooks.
|
||||
|
|
Loading…
Reference in a new issue