From d2dbc773237ae7183342412a2a3c408acb51281a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Lu=C5=88=C3=A1k?= Date: Tue, 10 Apr 2007 14:48:55 +0000 Subject: [PATCH] Add support for dimming of inactive windows (accessibility). FEATURE: 46226 svn path=/branches/work/kwin_composite/; revision=652255 --- COMPOSITE_TODO | 4 + effects.cpp | 35 +++++ effects.h | 20 +++ effects/CMakeLists.txt | 4 +- effects/diminactive.cpp | 76 +++++++++ effects/diminactive.desktop | 4 + effects/diminactive.h | 36 +++++ group.cpp | 298 ++++++------------------------------ group.h | 12 +- lib/kwineffects.cpp | 9 ++ lib/kwineffects.h | 11 ++ 11 files changed, 255 insertions(+), 254 deletions(-) create mode 100644 effects/diminactive.cpp create mode 100644 effects/diminactive.desktop create mode 100644 effects/diminactive.h diff --git a/COMPOSITE_TODO b/COMPOSITE_TODO index d630110a13..a4c17fe9ca 100644 --- a/COMPOSITE_TODO +++ b/COMPOSITE_TODO @@ -71,6 +71,8 @@ General TODO * cursorPos() does not work reliably now (not from e.g. timers, it needs events), so it's disabled +* window grouping is not implemented for unmanaged windows (used e.g. by DimInactive) + OpenGL TODO ================================= @@ -237,3 +239,5 @@ Effects TODO + - something that presents all virtual desktops as being in grid (as in pager) and zooms out of the old one and into the new one - or whatever + +* DimInactive flickers when switching between windows (temporarily no window becomes active) diff --git a/effects.cpp b/effects.cpp index 1b33473e61..697db4afa7 100644 --- a/effects.cpp +++ b/effects.cpp @@ -12,6 +12,7 @@ License. See the file "COPYING" for the exact licensing terms. #include "deleted.h" #include "client.h" +#include "group.h" #include "workspace.h" #include "kdebug.h" @@ -286,6 +287,21 @@ void EffectWindowImpl::disablePainting( int reason ) sceneWindow()->disablePainting( reason ); } +void EffectWindowImpl::addRepaint( const QRect& r ) + { + toplevel->addRepaint( r ); + } + +void EffectWindowImpl::addRepaint( int x, int y, int w, int h ) + { + toplevel->addRepaint( x, y, w, h ); + } + +void EffectWindowImpl::addRepaintFull() + { + toplevel->addRepaintFull(); + } + int EffectWindowImpl::desktop() const { return toplevel->desktop(); @@ -304,6 +320,13 @@ QString EffectWindowImpl::caption() const return ""; } +const EffectWindowGroup* EffectWindowImpl::group() const + { + if( Client* c = dynamic_cast< Client* >( toplevel )) + return c->group()->effectGroup(); + return NULL; // TODO + } + bool EffectWindowImpl::isMinimized() const { if( Client* c = dynamic_cast( toplevel )) @@ -479,5 +502,17 @@ EffectWindow* effectWindow( Scene::Window* w ) return ret; } +//**************************************** +// EffectWindowGroupImpl +//**************************************** + + +EffectWindowList EffectWindowGroupImpl::members() const + { + EffectWindowList ret; + foreach( Toplevel* c, group->members()) + ret.append( c->effectWindow()); + return ret; + } } // namespace diff --git a/effects.h b/effects.h index 784a926376..1ac7a3227e 100644 --- a/effects.h +++ b/effects.h @@ -64,6 +64,9 @@ class EffectWindowImpl : public EffectWindow virtual void enablePainting( int reason ); virtual void disablePainting( int reason ); + virtual void addRepaint( const QRect& r ); + virtual void addRepaint( int x, int y, int w, int h ); + virtual void addRepaintFull(); virtual bool isDeleted() const; @@ -71,6 +74,7 @@ class EffectWindowImpl : public EffectWindow virtual int desktop() const; // prefer isOnXXX() virtual bool isMinimized() const; virtual QString caption() const; + virtual const EffectWindowGroup* group() const; virtual int x() const; virtual int y() const; @@ -109,6 +113,22 @@ class EffectWindowImpl : public EffectWindow Scene::Window* sw; // This one is used only during paint pass. }; +class EffectWindowGroupImpl + : public EffectWindowGroup + { + public: + EffectWindowGroupImpl( Group* g ); + virtual EffectWindowList members() const; + private: + Group* group; + }; + +inline +EffectWindowGroupImpl::EffectWindowGroupImpl( Group* g ) + : group( g ) + { + } + EffectWindow* effectWindow( Toplevel* w ); EffectWindow* effectWindow( Scene::Window* w ); diff --git a/effects/CMakeLists.txt b/effects/CMakeLists.txt index f444ff413c..99c4cc6303 100644 --- a/effects/CMakeLists.txt +++ b/effects/CMakeLists.txt @@ -11,7 +11,7 @@ include_directories( ${CMAKE_SOURCE_DIR}/workspace/kwin/lib ) -KWIN4_ADD_EFFECT(builtins presentwindows.cpp shadow.cpp) +KWIN4_ADD_EFFECT(builtins presentwindows.cpp shadow.cpp diminactive.cpp) -install( FILES presentwindows.desktop shadow.desktop +install( FILES presentwindows.desktop shadow.desktop diminactive.desktop DESTINATION ${DATA_INSTALL_DIR}/kwin/effects ) diff --git a/effects/diminactive.cpp b/effects/diminactive.cpp new file mode 100644 index 0000000000..17c0a17c83 --- /dev/null +++ b/effects/diminactive.cpp @@ -0,0 +1,76 @@ +/***************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2007 Lubos Lunak + +You can Freely distribute this program under the GNU General Public +License. See the file "COPYING" for the exact licensing terms. +******************************************************************/ + + +#include "diminactive.h" + +namespace KWin +{ + +KWIN_EFFECT( DimInactive, DimInactiveEffect ) + +DimInactiveEffect::DimInactiveEffect() + : active( NULL ) + { + dim_panels = true; // TODO config option + dim_by_group = true; // TODO config option + } + +void DimInactiveEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ) + { + bool dim = false; + if( active == NULL ) + dim = true; + else if( dim_by_group && active->group() == w->group()) + dim = false; + else if( !dim_by_group && active == w ) + dim = false; + else if( w->isDock()) + dim = dim_panels; + else + dim = true; + if( dim ) + { + data.brightness *= 0.75; + data.saturation *= 0.75; + } + effects->paintWindow( w, mask, region, data ); + } + +void DimInactiveEffect::windowActivated( EffectWindow* w ) + { + if( active != NULL ) + { + if( dim_by_group ) + { + if(( w == NULL || w->group() != active->group()) && active->group() != NULL ) + { // repaint windows that are not longer in active group + foreach( EffectWindow* tmp, active->group()->members()) + tmp->addRepaintFull(); + } + } + else + active->addRepaintFull(); + } + active = w; + if( active != NULL ) + if( dim_by_group ) + { + if( active->group() != NULL ) + { // repaint newly active windows + foreach( EffectWindow* tmp, active->group()->members()) + tmp->addRepaintFull(); + } + } + else + active->addRepaintFull(); + } + +} // namespace diff --git a/effects/diminactive.desktop b/effects/diminactive.desktop new file mode 100644 index 0000000000..ea4a923b38 --- /dev/null +++ b/effects/diminactive.desktop @@ -0,0 +1,4 @@ +[Desktop Entry] +Encoding=UTF-8 +Name=DimInactive +X-KDE-Library=kwin4_effect_builtins diff --git a/effects/diminactive.h b/effects/diminactive.h new file mode 100644 index 0000000000..cca9355433 --- /dev/null +++ b/effects/diminactive.h @@ -0,0 +1,36 @@ +/***************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2007 Lubos Lunak + +You can Freely distribute this program under the GNU General Public +License. See the file "COPYING" for the exact licensing terms. +******************************************************************/ + +#ifndef KWIN_DIMINACTIVE_H +#define KWIN_DIMINACTIVE_H + +// Include with base class for effects. +#include + + +namespace KWin +{ + +class DimInactiveEffect + : public Effect + { + public: + DimInactiveEffect(); + virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ); + virtual void windowActivated( EffectWindow* c ); + private: + EffectWindow* active; + bool dim_panels; // do/don't dim also all panels + bool dim_by_group; // keep visible all windows from the active window's group or only the active window + }; + +} // namespace + +#endif diff --git a/group.cpp b/group.cpp index 481700e8d2..0413539944 100644 --- a/group.cpp +++ b/group.cpp @@ -21,6 +21,7 @@ License. See the file "COPYING" for the exact licensing terms. #include "workspace.h" #include "client.h" +#include "effects.h" #include #include @@ -36,164 +37,6 @@ License. See the file "COPYING" for the exact licensing terms. namespace KWin { -/* - Consistency checks for window relations. Since transients are determinated - using Client::transiency_list and main windows are determined using Client::transientFor() - or the group for group transients, these have to match both ways. -*/ -//#define ENABLE_TRANSIENCY_CHECK - -#ifdef NDEBUG -#undef ENABLE_TRANSIENCY_CHECK -#endif - -#ifdef ENABLE_TRANSIENCY_CHECK -static bool transiencyCheckNonExistent = false; - -bool performTransiencyCheck() - { - bool ret = true; - ClientList clients = Workspace::self()->clients; - for( ClientList::ConstIterator it1 = clients.begin(); - it1 != clients.end(); - ++it1 ) - { - if( (*it1)->deleting ) - continue; - if( (*it1)->in_group == NULL ) - { - kdDebug() << "TC: " << *it1 << " in not in a group" << endl; - ret = false; - } - else if( !(*it1)->in_group->members().contains( *it1 )) - { - kdDebug() << "TC: " << *it1 << " has a group " << (*it1)->in_group << " but group does not contain it" << endl; - ret = false; - } - if( !(*it1)->isTransient()) - { - if( !(*it1)->mainClients().isEmpty()) - { - kdDebug() << "TC: " << *it1 << " is not transient, has main clients:" << (*it1)->mainClients() << endl; - ret = false; - } - } - else - { - ClientList mains = (*it1)->mainClients(); - for( ClientList::ConstIterator it2 = mains.begin(); - it2 != mains.end(); - ++it2 ) - { - if( transiencyCheckNonExistent - && !Workspace::self()->clients.contains( *it2 ) - && !Workspace::self()->desktops.contains( *it2 )) - { - kDebug() << "TC:" << *it1 << " has non-existent main client " << endl; - kDebug() << "TC2:" << *it2 << endl; // this may crash - ret = false; - continue; - } - if( !(*it2)->transients_list.contains( *it1 )) - { - kdDebug() << "TC:" << *it1 << " has main client " << *it2 << " but main client does not have it as a transient" << endl; - ret = false; - } - } - } - ClientList trans = (*it1)->transients_list; - for( ClientList::ConstIterator it2 = trans.begin(); - it2 != trans.end(); - ++it2 ) - { - if( transiencyCheckNonExistent - && !Workspace::self()->clients.contains( *it2 ) - && !Workspace::self()->desktops.contains( *it2 )) - { - kDebug() << "TC:" << *it1 << " has non-existent transient " << endl; - kDebug() << "TC2:" << *it2 << endl; // this may crash - ret = false; - continue; - } - if( !(*it2)->mainClients().contains( *it1 )) - { - kdDebug() << "TC:" << *it1 << " has transient " << *it2 << " but transient does not have it as a main client" << endl; - ret = false; - } - } - } - GroupList groups = Workspace::self()->groups; - for( GroupList::ConstIterator it1 = groups.begin(); - it1 != groups.end(); - ++it1 ) - { - ClientList members = (*it1)->members(); - for( ClientList::ConstIterator it2 = members.begin(); - it2 != members.end(); - ++it2 ) - { - if( (*it2)->in_group != *it1 ) - { - kdDebug() << "TC: Group " << *it1 << " contains client " << *it2 << " but client is not in that group" << endl; - ret = false; - } - } - } - return ret; - } - -static QString transiencyCheckStartBt; -static const Client* transiencyCheckClient; -static int transiencyCheck = 0; - -static void startTransiencyCheck( const QString& bt, const Client* c, bool ne ) - { - if( ++transiencyCheck == 1 ) - { - transiencyCheckStartBt = bt; - transiencyCheckClient = c; - } - if( ne ) - transiencyCheckNonExistent = true; - } -static void checkTransiency() - { - if( --transiencyCheck == 0 ) - { - if( !performTransiencyCheck()) - { - kdDebug() << "BT:" << transiencyCheckStartBt << endl; - kdDebug() << "CLIENT:" << transiencyCheckClient << endl; - assert( false ); - } - transiencyCheckNonExistent = false; - } - } -class TransiencyChecker - { - public: - TransiencyChecker( const QString& bt, const Client*c ) { startTransiencyCheck( bt, c, false ); } - ~TransiencyChecker() { checkTransiency(); } - }; - -void checkNonExistentClients() - { - startTransiencyCheck( kdBacktrace(), NULL, true ); - checkTransiency(); - } - -#define TRANSIENCY_CHECK( c ) TransiencyChecker transiency_checker( kdBacktrace(), c ) - -#else - -#define TRANSIENCY_CHECK( c ) - -void checkNonExistentClients() - { - } - -#endif - //******************************************** // Group //******************************************** @@ -203,8 +46,7 @@ Group::Group( Window leader_P, Workspace* workspace_P ) leader_wid( leader_P ), _workspace( workspace_P ), leader_info( NULL ), - user_time( -1U ), - refcount( 0 ) + user_time( -1U ) { if( leader_P != None ) { @@ -213,12 +55,14 @@ Group::Group( Window leader_P, Workspace* workspace_P ) leader_info = new NETWinInfo( display(), leader_P, workspace()->rootWin(), properties, 2 ); } + effect_group = new EffectWindowGroupImpl( this ); workspace()->addGroup( this, Allowed ); } Group::~Group() { delete leader_info; + delete effect_group; } QPixmap Group::icon() const @@ -249,7 +93,6 @@ QPixmap Group::miniIcon() const void Group::addMember( Client* member_P ) { - TRANSIENCY_CHECK( member_P ); _members.append( member_P ); // kDebug() << "GROUPADD:" << this << ":" << member_P << endl; // kDebug() << kBacktrace() << endl; @@ -257,30 +100,11 @@ void Group::addMember( Client* member_P ) void Group::removeMember( Client* member_P ) { - TRANSIENCY_CHECK( member_P ); // kDebug() << "GROUPREMOVE:" << this << ":" << member_P << endl; // kDebug() << kBacktrace() << endl; Q_ASSERT( _members.contains( member_P )); _members.removeAll( member_P ); -// there are cases when automatic deleting of groups must be delayed, -// e.g. when removing a member and doing some operation on the possibly -// other members of the group (which would be however deleted already -// if there were no other members) - if( refcount == 0 && _members.isEmpty()) - { - workspace()->removeGroup( this, Allowed ); - delete this; - } - } - -void Group::ref() - { - ++refcount; - } - -void Group::deref() - { - if( --refcount == 0 && _members.isEmpty()) + if( _members.isEmpty()) { workspace()->removeGroup( this, Allowed ); delete this; @@ -328,7 +152,6 @@ Group* Workspace::findGroup( Window leader ) const // group with windows with the same client leader. Group* Workspace::findClientLeaderGroup( const Client* c ) const { - TRANSIENCY_CHECK( c ); Group* ret = NULL; for( ClientList::ConstIterator it = clients.begin(); it != clients.end(); @@ -346,15 +169,14 @@ Group* Workspace::findClientLeaderGroup( const Client* c ) const // This most probably means the app uses group transients without // setting group for its windows. Merging the two groups is a bad // hack, but there's no really good solution for this case. - ClientList old_group = (*it)->group()->members(); + Group* old_group = (*it)->group(); // old_group autodeletes when being empty - for( int pos = 0; - pos < old_group.count(); - ++pos ) + for( int cnt = old_group->members().count(); + cnt > 0; + --cnt ) { - Client* tmp = old_group[ pos ]; - if( tmp != c ) - tmp->changeClientLeaderGroup( ret ); + Client* tmp = old_group->members().first(); + tmp->checkGroup( ret ); // change group } } } @@ -413,7 +235,6 @@ void Workspace::updateOnAllDesktopsOfTransients( Client* c ) // A new window has been mapped. Check if it's not a mainwindow for some already existing transient window. void Workspace::checkTransients( Window w ) { - TRANSIENCY_CHECK( NULL ); for( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it ) @@ -421,14 +242,13 @@ void Workspace::checkTransients( Window w ) } - //**************************************** -// Client +// Toplevel //**************************************** // hacks for broken apps here // all resource classes are forced to be lowercase -bool Client::resourceMatch( const Client* c1, const Client* c2 ) +bool Toplevel::resourceMatch( const Toplevel* c1, const Toplevel* c2 ) { // xv has "xv" as resource name, and different strings starting with "XV" as resource class if( qstrncmp( c1->resourceClass(), "xv", 2 ) == 0 && c1->resourceName() == "xv" ) @@ -439,25 +259,20 @@ bool Client::resourceMatch( const Client* c1, const Client* c2 ) return c1->resourceClass() == c2->resourceClass(); } + +//**************************************** +// Client +//**************************************** + bool Client::belongToSameApplication( const Client* c1, const Client* c2, bool active_hack ) { bool same_app = false; - - // tests that definitely mean they belong together if( c1 == c2 ) same_app = true; else if( c1->isTransient() && c2->hasTransient( c1, true )) same_app = true; // c1 has c2 as mainwindow else if( c2->isTransient() && c1->hasTransient( c2, true )) same_app = true; // c2 has c1 as mainwindow - else if( c1->group() == c2->group()) - same_app = true; // same group - else if( c1->wmClientLeader() == c2->wmClientLeader() - && c1->wmClientLeader() != c1->window() // if WM_CLIENT_LEADER is not set, it returns window(), - && c2->wmClientLeader() != c2->window()) // don't use in this test then - same_app = true; // same client leader - - // tests that mean they most probably don't belong together else if( c1->pid() != c2->pid() || c1->wmClientMachine( false ) != c2->wmClientMachine( false )) ; // different processes @@ -469,12 +284,17 @@ bool Client::belongToSameApplication( const Client* c1, const Client* c2, bool a ; // different apps else if( !sameAppWindowRoleMatch( c1, c2, active_hack )) ; // "different" apps + else if( c1->wmClientLeader() == c2->wmClientLeader() + && c1->wmClientLeader() != c1->window() // if WM_CLIENT_LEADER is not set, it returns window(), + && c2->wmClientLeader() != c2->window()) // don't use in this test then + same_app = true; // same client leader + else if( c1->group() == c2->group()) + same_app = true; // same group else if( c1->pid() == 0 || c2->pid() == 0 ) ; // old apps that don't have _NET_WM_PID, consider them different // if they weren't found to match above else same_app = true; // looks like it's the same app - return same_app; } @@ -579,7 +399,6 @@ bool Client::sameAppWindowRoleMatch( const Client* c1, const Client* c2, bool ac void Client::readTransient() { - TRANSIENCY_CHECK( this ); Window new_transient_for_id; if( XGetTransientForHint( display(), window(), &new_transient_for_id )) { @@ -596,7 +415,6 @@ void Client::readTransient() void Client::setTransient( Window new_transient_for_id ) { - TRANSIENCY_CHECK( this ); if( new_transient_for_id != transient_for_id ) { removeFromMainClients(); @@ -617,7 +435,6 @@ void Client::setTransient( Window new_transient_for_id ) void Client::removeFromMainClients() { - TRANSIENCY_CHECK( this ); if( transientFor() != NULL ) transientFor()->removeTransient( this ); if( groupTransient()) @@ -635,7 +452,6 @@ void Client::removeFromMainClients() // related lists. void Client::cleanGrouping() { - TRANSIENCY_CHECK( this ); // kDebug() << "CLEANGROUPING:" << this << endl; // for( ClientList::ConstIterator it = group()->members().begin(); // it != group()->members().end(); @@ -705,7 +521,6 @@ void Client::cleanGrouping() // Non-group transients not causing loops are checked in verifyTransientFor(). void Client::checkGroupTransients() { - TRANSIENCY_CHECK( this ); for( ClientList::ConstIterator it1 = group()->members().begin(); it1 != group()->members().end(); ++it1 ) @@ -835,7 +650,6 @@ Window Client::verifyTransientFor( Window new_transient_for, bool defined ) void Client::addTransient( Client* cl ) { - TRANSIENCY_CHECK( this ); assert( !transients_list.contains( cl )); // assert( !cl->hasTransient( this, true )); will be fixed in checkGroupTransients() assert( cl != this ); @@ -852,7 +666,6 @@ void Client::addTransient( Client* cl ) void Client::removeTransient( Client* cl ) { - TRANSIENCY_CHECK( this ); // kDebug() << "REMOVETRANS:" << this << ":" << cl << endl; // kDebug() << kBacktrace() << endl; transients_list.removeAll( cl ); @@ -870,7 +683,6 @@ void Client::removeTransient( Client* cl ) // A new window has been mapped. Check if it's not a mainwindow for this already existing window. void Client::checkTransient( Window w ) { - TRANSIENCY_CHECK( this ); if( original_transient_for_id != w ) return; w = verifyTransientFor( w, true ); @@ -951,10 +763,7 @@ Client* Client::findModal() // Argument is only when some specific group needs to be set. void Client::checkGroup( Group* set_group, bool force ) { - TRANSIENCY_CHECK( this ); Group* old_group = in_group; - if( old_group != NULL ) - old_group->ref(); // turn off automatic deleting if( set_group != NULL ) { if( set_group != in_group ) @@ -1011,21 +820,16 @@ void Client::checkGroup( Group* set_group, bool force ) in_group->addMember( this ); } } - else // Not transient without a group, put it in its client leader group. - { // This might be stupid if grouping was used for e.g. taskbar grouping - // or minimizing together the whole group, but as long as its used - // only for dialogs it's better to keep windows from one app in one group. - Group* new_group = workspace()->findClientLeaderGroup( this ); - if( in_group != NULL && in_group != new_group ) + else // not transient without a group, put it in its own group + { + if( in_group != NULL && in_group->leader() != window()) { in_group->removeMember( this ); in_group = NULL; } - if( new_group == NULL ) - new_group = new Group( None, workspace() ); - if( in_group != new_group ) + if( in_group == NULL ) { - in_group = new_group; + in_group = new Group( None, workspace()); in_group->addMember( this ); } } @@ -1042,16 +846,7 @@ void Client::checkGroup( Group* set_group, bool force ) ++it; } if( groupTransient()) - { - // no longer transient for ones in the old group - if( old_group != NULL ) - { - for( ClientList::ConstIterator it = old_group->members().begin(); - it != old_group->members().end(); - ++it ) - (*it)->removeTransient( this ); - } - // and make transient for all in the new group + { // and make transient for all in the group for( ClientList::ConstIterator it = group()->members().begin(); it != group()->members().end(); ++it ) @@ -1061,6 +856,25 @@ void Client::checkGroup( Group* set_group, bool force ) (*it)->addTransient( this ); } } +#if 0 // TODO + if( groupTransient()) + { + if( workspace()->findGroup( old_group )) // if it still exists + { // it's no longer transient for windows in the old group + for( ClientList::ConstIterator it = old_group->members().begin(); + it != old_group->members().end(); + ++it ) + (*it)->removeTransient( this ); + } + // and it's transiet for all windows in the new group (this one is the most recent + // in the group, so it is transient only for all previous windows) + // loops are checked in checkGroupTransients() + for( ClientList::ConstIterator it = group()->members().begin(); + it != group()->members().end(); + ++it ) + (*it)->addTransient( this ); + } +#endif // group transient splashscreens should be transient even for windows // in group mapped later for( ClientList::ConstIterator it = group()->members().begin(); @@ -1076,25 +890,11 @@ void Client::checkGroup( Group* set_group, bool force ) addTransient( *it ); } } - if( old_group != NULL ) - old_group->deref(); // can be now deleted if empty checkGroupTransients(); checkActiveModal(); workspace()->updateClientLayer( this ); } -// used by Workspace::findClientLeaderGroup() -void Client::changeClientLeaderGroup( Group* gr ) - { - // transientFor() != NULL are in the group of their mainwindow, so keep them there - if( transientFor() != NULL ) - return; - // also don't change the group for window which have group set - if( window_group ) - return; - checkGroup( gr ); // change group - } - bool Client::check_active_modal = false; void Client::checkActiveModal() diff --git a/group.h b/group.h index 0ad6fa0eb9..7a29eab0d8 100644 --- a/group.h +++ b/group.h @@ -21,6 +21,7 @@ namespace KWin class Client; class Workspace; +class EffectWindowGroupImpl; class Group { @@ -41,8 +42,7 @@ class Group bool groupEvent( XEvent* e ); void updateUserTime( Time time = CurrentTime ); Time userTime() const; - void ref(); - void deref(); + EffectWindowGroupImpl* effectGroup(); private: void getIcons(); void startupIdChanged(); @@ -52,7 +52,7 @@ class Group Workspace* _workspace; NETWinInfo* leader_info; Time user_time; - int refcount; + EffectWindowGroupImpl* effect_group; }; inline Window Group::leader() const @@ -85,6 +85,12 @@ inline Time Group::userTime() const return user_time; } +inline +EffectWindowGroupImpl* Group::effectGroup() + { + return effect_group; + } + } // namespace #endif diff --git a/lib/kwineffects.cpp b/lib/kwineffects.cpp index ec4e38a773..a6a31fdac5 100644 --- a/lib/kwineffects.cpp +++ b/lib/kwineffects.cpp @@ -469,4 +469,13 @@ bool EffectWindow::isOnDesktop( int d ) const } +//**************************************** +// EffectWindowGroup +//**************************************** + +EffectWindowGroup::~EffectWindowGroup() + { + } + + } // namespace diff --git a/lib/kwineffects.h b/lib/kwineffects.h index d5b56bf466..c9a15d6402 100644 --- a/lib/kwineffects.h +++ b/lib/kwineffects.h @@ -32,6 +32,7 @@ namespace KWin class EffectWindow; +class EffectWindowGroup; class Effect; typedef QPair< QString, Effect* > EffectPair; @@ -251,6 +252,9 @@ class KWIN_EXPORT EffectWindow virtual void enablePainting( int reason ) = 0; virtual void disablePainting( int reason ) = 0; + virtual void addRepaint( const QRect& r ) = 0; + virtual void addRepaint( int x, int y, int w, int h ) = 0; + virtual void addRepaintFull() = 0; virtual bool isDeleted() const = 0; virtual bool isMinimized() const = 0; @@ -270,6 +274,7 @@ class KWIN_EXPORT EffectWindow virtual QRect rect() const = 0; virtual QString caption() const = 0; + virtual const EffectWindowGroup* group() const = 0; virtual bool isDesktop() const = 0; virtual bool isDock() const = 0; @@ -290,6 +295,12 @@ class KWIN_EXPORT EffectWindow }; +class KWIN_EXPORT EffectWindowGroup + { + public: + virtual ~EffectWindowGroup(); + virtual EffectWindowList members() const = 0; + }; extern KWIN_EXPORT EffectsHandler* effects;