From 20f80af287c0c9d9c052bc05e72aa0869a7da244 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Lu=C5=88=C3=A1k?= Date: Tue, 7 Jun 2005 15:31:15 +0000 Subject: [PATCH] Make it possible to use the window-specific settings dialog to also set some things only temporarily. E.g. in order to set skiptaskbar flag on a window, it's just Alt+F3/Advanced/Special Window Settings/Preferences -> Apply Now for Skip taskbar, and turn on the checkbox. svn path=/trunk/KDE/kdebase/kwin/; revision=423112 --- client.cpp | 2 + client.h | 11 +- kcmkwin/kwinrules/ruleswidget.cpp | 27 +++- kcmkwin/kwinrules/ruleswidgetbase.ui | 200 +++++++++++++++++++++++++++ manage.cpp | 2 + rules.cpp | 156 ++++++++++++++------- rules.h | 27 +++- workspace.cpp | 10 +- workspace.h | 1 + 9 files changed, 377 insertions(+), 59 deletions(-) diff --git a/client.cpp b/client.cpp index fa82c59aee..02c6e6b58c 100644 --- a/client.cpp +++ b/client.cpp @@ -181,6 +181,7 @@ void Client::releaseWindow( bool on_shutdown ) { assert( !deleting ); deleting = true; + workspace()->discardUsedWindowRules( this, true ); // remove ForceTemporarily rules StackingUpdatesBlocker blocker( workspace()); if (!custom_opacity) setOpacity(FALSE); if (moveResizeMode) @@ -235,6 +236,7 @@ void Client::destroyClient() { assert( !deleting ); deleting = true; + workspace()->discardUsedWindowRules( this, true ); // remove ForceTemporarily rules StackingUpdatesBlocker blocker( workspace()); if (moveResizeMode) leaveMoveResize(); diff --git a/client.h b/client.h index a4a3ae0c43..ab8be0185b 100644 --- a/client.h +++ b/client.h @@ -70,6 +70,9 @@ class Client : public QObject, public KDecorationDefines // prefer isXXX() instead NET::WindowType windowType( bool direct = false, int supported_types = SUPPORTED_WINDOW_TYPES_MASK ) const; const WindowRules* rules() const; + void removeRule( Rules* r ); + void setupWindowRules( bool ignore_temporary ); + void applyWindowRules(); QRect geometry() const; QSize size() const; @@ -366,7 +369,6 @@ class Client : public QObject, public KDecorationDefines QString readName() const; void setCaption( const QString& s, bool force = false ); bool hasTransientInternal( const Client* c, bool indirect, ConstClientList& set ) const; - void setupWindowRules( bool ignore_temporary ); void updateWindowRules(); void finishWindowRules(); void setShortcutInternal( const KShortcut& cut ); @@ -890,7 +892,12 @@ inline void Client::setBMP(bool b) { isBMP_ = b; } - + +inline void Client::removeRule( Rules* rule ) + { + client_rules.remove( rule ); + } + #ifdef NDEBUG inline kndbgstream& operator<<( kndbgstream& stream, const Client* ) { return stream; } diff --git a/kcmkwin/kwinrules/ruleswidget.cpp b/kcmkwin/kwinrules/ruleswidget.cpp index be2219be34..42f140c45b 100644 --- a/kcmkwin/kwinrules/ruleswidget.cpp +++ b/kcmkwin/kwinrules/ruleswidget.cpp @@ -61,13 +61,21 @@ RulesWidget::RulesWidget( QWidget* parent, const char* name ) " after the window is created. No further changes will be affected." "
  • Remember: The value of the window property will be remembered and every time" " time the window is created, the last remembered value will be applied.
  • " - "
  • Force: The window property will be always forced to the given value.
  • " ); + "
  • Force: The window property will be always forced to the given value.
  • " + "
  • Apply Now: The window property will be set to the given value immediatelly" + "and will not be affected later (this action will be deleted afterwards).
  • " + "
  • Force temporarily: The window property will be forced to the given value" + "until it is hidden (this action will be deleted after the window is hidden).
  • " + "" ); QString forceRuleDesc = i18n( "Specify how the window property should be affected:" ); + "
  • Force: The window property will be always forced to the given value.
  • " + "
  • Force temporarily: The window property will be forced to the given value" + "until it is hidden (this action will be deleted after the window is hidden).
  • " + "" ); // window tabs have enable signals done in designer // geometry tab SETUP( position, set ); @@ -159,6 +167,8 @@ static const int set_rule_to_combo[] = 3, // Force 1, // Apply 2, // Remember + 4, // ApplyNow + 5 // ForceTemporarily }; static const Rules::SetRule combo_to_set_rule[] = @@ -166,20 +176,27 @@ static const Rules::SetRule combo_to_set_rule[] = ( Rules::SetRule )Rules::DontAffect, ( Rules::SetRule )Rules::Apply, ( Rules::SetRule )Rules::Remember, - ( Rules::SetRule )Rules::Force + ( Rules::SetRule )Rules::Force, + ( Rules::SetRule )Rules::ApplyNow, + ( Rules::SetRule )Rules::ForceTemporarily }; static const int force_rule_to_combo[] = { 0, // Unused 0, // Don't Affect - 1 // Force + 1, // Force + 0, // Apply + 0, // Remember + 0, // ApplyNow + 2 // ForceTemporarily }; static const Rules::ForceRule combo_to_force_rule[] = { ( Rules::ForceRule )Rules::DontAffect, - ( Rules::ForceRule )Rules::Force + ( Rules::ForceRule )Rules::Force, + ( Rules::ForceRule )Rules::ForceTemporarily }; static QString positionToStr( const QPoint& p ) diff --git a/kcmkwin/kwinrules/ruleswidgetbase.ui b/kcmkwin/kwinrules/ruleswidgetbase.ui index 78938d5626..58126c1ce7 100644 --- a/kcmkwin/kwinrules/ruleswidgetbase.ui +++ b/kcmkwin/kwinrules/ruleswidgetbase.ui @@ -688,6 +688,16 @@ Force + + + Apply Now + + + + + Force Temporarily + + rule_size @@ -754,6 +764,16 @@ Force + + + Apply Now + + + + + Force Temporarily + + rule_position @@ -793,6 +813,16 @@ Force + + + Apply Now + + + + + Force Temporarily + + rule_maximizehoriz @@ -851,6 +881,16 @@ Force + + + Apply Now + + + + + Force Temporarily + + rule_fullscreen @@ -887,6 +927,16 @@ Force + + + Apply Now + + + + + Force Temporarily + + rule_maximizevert @@ -923,6 +973,16 @@ Force + + + Apply Now + + + + + Force Temporarily + + rule_desktop @@ -986,6 +1046,16 @@ Force + + + Apply Now + + + + + Force Temporarily + + rule_minimize @@ -1023,6 +1093,11 @@ Force + + + Force Temporarily + + rule_placement @@ -1129,6 +1204,16 @@ Force + + + Apply Now + + + + + Force Temporarily + + rule_shade @@ -1224,6 +1309,11 @@ Force + + + Force Temporarily + + rule_opacityactive @@ -1466,6 +1556,11 @@ Force + + + Force Temporarily + + rule_closeable @@ -1484,6 +1579,11 @@ Force + + + Force Temporarily + + rule_acceptfocus @@ -1512,6 +1612,16 @@ Force + + + Apply Now + + + + + Force Temporarily + + rule_skippager @@ -1540,6 +1650,16 @@ Force + + + Apply Now + + + + + Force Temporarily + + rule_skiptaskbar @@ -1568,6 +1688,16 @@ Force + + + Apply Now + + + + + Force Temporarily + + rule_noborder @@ -1596,6 +1726,16 @@ Force + + + Apply Now + + + + + Force Temporarily + + rule_below @@ -1624,6 +1764,16 @@ Force + + + Apply Now + + + + + Force Temporarily + + rule_above @@ -1659,6 +1809,11 @@ Force + + + Force Temporarily + + rule_opacityinactive @@ -1734,6 +1889,16 @@ Force + + + Apply Now + + + + + Force Temporarily + + rule_shortcut @@ -1789,6 +1954,11 @@ Force + + + Force Temporarily + + rule_type @@ -1899,6 +2069,11 @@ Force + + + Force Temporarily + + rule_fsplevel @@ -1917,6 +2092,11 @@ Force + + + Force Temporarily + + rule_moveresizemode @@ -1987,6 +2167,11 @@ Force + + + Force Temporarily + + rule_minsize @@ -2024,6 +2209,11 @@ Force + + + Force Temporarily + + rule_maxsize @@ -2050,6 +2240,11 @@ Force + + + Force Temporarily + + rule_ignoreposition @@ -2107,6 +2302,11 @@ Force + + + Force Temporarily + + rule_strictgeometry diff --git a/manage.cpp b/manage.cpp index 08d36d3baf..bd7836d771 100644 --- a/manage.cpp +++ b/manage.cpp @@ -495,6 +495,8 @@ bool Client::manage( Window w, bool isMapped ) ungrabXServer(); client_rules.discardTemporary(); + applyWindowRules(); // just in case + workspace()->discardUsedWindowRules( this, false ); // remove ApplyNow rules updateWindowRules(); // was blocked while !isManaged() // TODO there's a small problem here - isManaged() depends on the mapping state, diff --git a/rules.cpp b/rules.cpp index 35f6f83f24..da344fdc3e 100644 --- a/rules.cpp +++ b/rules.cpp @@ -290,7 +290,7 @@ bool Rules::isEmpty() const Rules::SetRule Rules::readSetRule( KConfig& cfg, const QString& key ) { int v = cfg.readNumEntry( key ); - if( v >= DontAffect && v <= Remember ) + if( v >= DontAffect && v <= ForceTemporarily ) return static_cast< SetRule >( v ); return UnusedSetRule; } @@ -298,7 +298,7 @@ Rules::SetRule Rules::readSetRule( KConfig& cfg, const QString& key ) Rules::ForceRule Rules::readForceRule( KConfig& cfg, const QString& key ) { int v = cfg.readNumEntry( key ); - if( v == DontAffect || v == Force ) + if( v == DontAffect || v == Force || v == ForceTemporarily ) return static_cast< ForceRule >( v ); return UnusedForceRule; } @@ -623,6 +623,50 @@ bool Rules::discardTemporary( bool force ) } return false; } + +#define DISCARD_USED_SET_RULE( var ) \ + do { \ + if( var##rule == ( SetRule ) ApplyNow || ( withdrawn && var##rule == ( SetRule ) ForceTemporarily )) \ + var##rule = UnusedSetRule; \ + } while( false ) +#define DISCARD_USED_FORCE_RULE( var ) \ + do { \ + if( withdrawn && var##rule == ( ForceRule ) ForceTemporarily ) \ + var##rule = UnusedForceRule; \ + } while( false ) + +void Rules::discardUsed( bool withdrawn ) + { + DISCARD_USED_FORCE_RULE( placement ); + DISCARD_USED_SET_RULE( position ); + DISCARD_USED_SET_RULE( size ); + DISCARD_USED_FORCE_RULE( minsize ); + DISCARD_USED_FORCE_RULE( maxsize ); + DISCARD_USED_FORCE_RULE( opacityactive ); + DISCARD_USED_FORCE_RULE( opacityinactive ); + DISCARD_USED_FORCE_RULE( ignoreposition ); + DISCARD_USED_SET_RULE( desktop ); + DISCARD_USED_FORCE_RULE( type ); + DISCARD_USED_SET_RULE( maximizevert ); + DISCARD_USED_SET_RULE( maximizehoriz ); + DISCARD_USED_SET_RULE( minimize ); + DISCARD_USED_SET_RULE( shade ); + DISCARD_USED_SET_RULE( skiptaskbar ); + DISCARD_USED_SET_RULE( skippager ); + DISCARD_USED_SET_RULE( above ); + DISCARD_USED_SET_RULE( below ); + DISCARD_USED_SET_RULE( fullscreen ); + DISCARD_USED_SET_RULE( noborder ); + DISCARD_USED_FORCE_RULE( fsplevel ); + DISCARD_USED_FORCE_RULE( acceptfocus ); + DISCARD_USED_FORCE_RULE( moveresizemode ); + DISCARD_USED_FORCE_RULE( closeable ); + DISCARD_USED_FORCE_RULE( strictgeometry ); + DISCARD_USED_SET_RULE( shortcut ); + } +#undef DISCARD_USED_SET_RULE +#undef DISCARD_USED_FORCE_RULE + #endif #ifndef NDEBUG @@ -740,59 +784,54 @@ CHECK_RULE( Shortcut, QString ) // Client -#define FORCE_RULE( rule, type, getf, setf ) \ - { \ - type val = client_rules.check##rule( getf()); \ - if( val != getf()) \ - setf( val ); \ - } - void Client::setupWindowRules( bool ignore_temporary ) { client_rules = workspace()->findWindowRules( this, ignore_temporary ); // check only after getting the rules, because there may be a rule forcing window type if( isTopMenu()) // TODO cannot have restrictions client_rules = WindowRules(); - checkAndSetInitialRuledOpacity(); - if( isManaged()) - { // apply force rules - // Placement - does need explicit update, just like some others below - // Geometry : setGeometry() doesn't check rules - QRect geom = client_rules.checkGeometry( geometry()); - if( geom != geometry()) - setGeometry( geom ); - // MinSize, MaxSize handled by Geometry - // IgnorePosition - setDesktop( desktop()); - // Type - maximize( maximizeMode()); - // Minimize : functions don't check, and there are two functions - if( client_rules.checkMinimize( isMinimized())) - minimize(); - else - unminimize(); - setShade( shadeMode()); - setSkipTaskbar( skipTaskbar(), true ); - setSkipPager( skipPager()); - setKeepAbove( keepAbove()); - setKeepBelow( keepBelow()); - setFullScreen( isFullScreen(), true ); - setUserNoBorder( isUserNoBorder()); - // FSP - // AcceptFocus : - if( workspace()->mostRecentlyActivatedClient() == this - && !client_rules.checkAcceptFocus( true )) - workspace()->activateNextClient( this ); - // MoveResizeMode - // Closeable - QSize s = adjustedSize( size()); - if( s != size()) - resizeWithChecks( s ); - setShortcut( rules()->checkShortcut( shortcut().toString())); - } } -#undef FORCE_RULE +// Applies Force, ForceTemporarily and ApplyNow rules +// Used e.g. after the rules have been modified using the kcm. +void Client::applyWindowRules() + { + checkAndSetInitialRuledOpacity(); + // apply force rules + // Placement - does need explicit update, just like some others below + // Geometry : setGeometry() doesn't check rules + QRect geom = client_rules.checkGeometry( geometry()); + if( geom != geometry()) + setGeometry( geom ); + // MinSize, MaxSize handled by Geometry + // IgnorePosition + setDesktop( desktop()); + // Type + maximize( maximizeMode()); + // Minimize : functions don't check, and there are two functions + if( client_rules.checkMinimize( isMinimized())) + minimize(); + else + unminimize(); + setShade( shadeMode()); + setSkipTaskbar( skipTaskbar(), true ); + setSkipPager( skipPager()); + setKeepAbove( keepAbove()); + setKeepBelow( keepBelow()); + setFullScreen( isFullScreen(), true ); + setUserNoBorder( isUserNoBorder()); + // FSP + // AcceptFocus : + if( workspace()->mostRecentlyActivatedClient() == this + && !client_rules.checkAcceptFocus( true )) + workspace()->activateNextClient( this ); + // MoveResizeMode + // Closeable + QSize s = adjustedSize( size()); + if( s != size()) + resizeWithChecks( s ); + setShortcut( rules()->checkShortcut( shortcut().toString())); + } void Client::updateWindowRules() { @@ -953,6 +992,29 @@ void Workspace::cleanupTemporaryRules() QTimer::singleShot( 60000, this, SLOT( cleanupTemporaryRules())); } +void Workspace::discardUsedWindowRules( Client* c, bool withdrawn ) + { + for( QValueList< Rules* >::Iterator it = rules.begin(); + it != rules.end(); + ) + { + if( c->rules()->contains( *it )) + { + (*it)->discardUsed( withdrawn ); + if( (*it)->isEmpty()) + { + c->removeRule( *it ); + Rules* r = *it; + it = rules.remove( it ); + delete r; + continue; + } + } + ++it; + } + rulesUpdated(); + } + void Workspace::rulesUpdated() { rulesUpdatedTimer.start( 1000, true ); diff --git a/rules.h b/rules.h index de4a960a98..666009e364 100644 --- a/rules.h +++ b/rules.h @@ -40,6 +40,8 @@ class WindowRules WindowRules(); void update( Client* ); void discardTemporary(); + bool contains( const Rules* rule ) const; + void remove( Rules* rule ); Placement::Policy checkPlacement( Placement::Policy placement ) const; QRect checkGeometry( QRect rect, bool init = false ) const; // use 'invalidPoint' with checkPosition, unlike QSize() and QRect(), QPoint() is a valid point @@ -84,6 +86,7 @@ class Rules void write( KConfig& ) const; bool isEmpty() const; #ifndef KCMRULES + void discardUsed( bool withdrawn ); bool match( const Client* c ) const; bool update( Client* ); bool isTemporary() const; @@ -130,7 +133,9 @@ class Rules DontAffect, // use the default value Force, // force the given value Apply, // apply only after initial mapping - Remember // like apply, and remember the value when the window is withdrawn + Remember, // like apply, and remember the value when the window is withdrawn + ApplyNow, // apply immediatelly, then forget the setting + ForceTemporarily // apply and force until the window is withdrawn }; enum SetRule { @@ -236,7 +241,8 @@ bool Rules::checkSetRule( SetRule rule, bool init ) { if( rule > ( SetRule )DontAffect) // Unused or DontAffect { - if( rule == ( SetRule )Force || init ) + if( rule == ( SetRule )Force || rule == ( SetRule ) ApplyNow + || rule == ( SetRule ) ForceTemporarily || init ) return true; } return false; @@ -245,7 +251,7 @@ bool Rules::checkSetRule( SetRule rule, bool init ) inline bool Rules::checkForceRule( ForceRule rule ) { - return rule == ( ForceRule )Force; + return rule == ( ForceRule )Force || rule == ( ForceRule ) ForceTemporarily; } inline @@ -270,6 +276,21 @@ inline WindowRules::WindowRules() { } + +inline +bool WindowRules::contains( const Rules* rule ) const + { + return qFind( rules.begin(), rules.end(), rule ) != rules.end(); + } + +inline +void WindowRules::remove( Rules* rule ) + { + QValueVector< Rules* >::Iterator pos = qFind( rules.begin(), rules.end(), rule ); + if( pos != rules.end()) + rules.erase( pos ); + } + #endif #ifdef NDEBUG diff --git a/workspace.cpp b/workspace.cpp index 5e5e524090..b680dfb4af 100644 --- a/workspace.cpp +++ b/workspace.cpp @@ -815,7 +815,6 @@ void Workspace::slotSettingsChanged(int category) Reread settings */ KWIN_PROCEDURE( CheckBorderSizesProcedure, cl->checkBorderSizes() ); -KWIN_PROCEDURE( ResetupRulesProcedure, cl->setupWindowRules( true ) ); void Workspace::slotReconfigure() { @@ -873,7 +872,14 @@ void Workspace::slotReconfigure() } loadWindowRules(); - forEachClient( ResetupRulesProcedure()); + for( ClientList::Iterator it = clients.begin(); + it != clients.end(); + ++it ) + { + (*it)->setupWindowRules( true ); + (*it)->applyWindowRules(); + discardUsedWindowRules( *it, false ); + } if (options->resetKompmgr) // need restart { diff --git a/workspace.h b/workspace.h index 31cb936ec2..2a4bf42798 100644 --- a/workspace.h +++ b/workspace.h @@ -211,6 +211,7 @@ class Workspace : public QObject, public KWinInterface, public KDecorationDefine SessionInfo* takeSessionInfo( Client* ); WindowRules findWindowRules( const Client*, bool ); void rulesUpdated(); + void discardUsedWindowRules( Client* c, bool withdraw ); // dcop interface void cascadeDesktop();