diff --git a/options.cpp b/options.cpp index f16ccd7781..12c483166d 100644 --- a/options.cpp +++ b/options.cpp @@ -92,12 +92,7 @@ unsigned long Options::updateSettings() } delete gc; - val = config->readEntry("Placement","Smart"); - if (val == "Random") placement = Random; - else if (val == "Cascade") placement = Cascade; - else if (val == "Centered") placement = Centered; - else if (val == "ZeroCornered") placement = ZeroCornered; - else placement = Smart; + placement = Placement::policyFromString( config->readEntry("Placement"), true ); animateShade = config->readBoolEntry("AnimateShade", TRUE ); diff --git a/options.h b/options.h index 5b3bd2484c..abb135d439 100644 --- a/options.h +++ b/options.h @@ -18,6 +18,8 @@ License. See the file "COPYING" for the exact licensing terms. #include #include +#include "placement.h" + namespace KWinInternal { @@ -140,14 +142,7 @@ class Options : public KDecorationOptions MoveResizeMode resizeMode; MoveResizeMode moveMode; - /** - * Placement policies. How workspace decides the way windows get positioned - * on the screen. The better the policy, the heavier the resource use. - * Normally you don't have to worry. What the WM adds to the startup time - * is nil compared to the creation of the window itself in the memory - */ - enum PlacementPolicy { Random, Smart, Cascade, Centered, ZeroCornered }; - PlacementPolicy placement; + Placement::Policy placement; bool focusPolicyIsReasonable() { diff --git a/placement.cpp b/placement.cpp index 7a491421c4..348989dcd6 100644 --- a/placement.cpp +++ b/placement.cpp @@ -10,13 +10,13 @@ You can Freely distribute this program under the GNU General Public License. See the file "COPYING" for the exact licensing terms. ******************************************************************/ +#include + #include "workspace.h" #include "client.h" #include "options.h" #include "placement.h" - -#include - +#include "rules.h" namespace KWinInternal { @@ -42,6 +42,10 @@ Placement::Placement(Workspace* w) */ void Placement::place(Client* c, QRect& area ) { + Policy policy = c->rules()->checkPlacement( Default ); + if( policy != Default ) + return place( c, policy, area ); + if( c->isUtility()) placeUtility(c, area); else if( c->isDialog()) @@ -49,16 +53,29 @@ void Placement::place(Client* c, QRect& area ) else if( c->isSplash()) placeOnMainWindow( c, area ); // on mainwindow, if any, otherwise centered else - placeInternal(c, area); + place(c, options->placement, area); } -void Placement::placeInternal(Client* c, const QRect& area ) +void Placement::place(Client* c, Policy policy, QRect& area ) { - if (options->placement == Options::Random) placeAtRandom(c, area); - else if (options->placement == Options::Cascade) placeCascaded(c, area); - else if (options->placement == Options::Centered) placeCentered(c, area); - else if (options->placement == Options::ZeroCornered) placeZeroCornered(c, area); - else placeSmart(c, area); + if( policy == Default ) + policy = options->placement; + if( policy == NoPlacement ) + return; + else if (policy == Random) + placeAtRandom(c, area); + else if (policy == Cascade) + placeCascaded(c, area); + else if (policy == Centered) + placeCentered(c, area); + else if (policy == ZeroCornered) + placeZeroCornered(c, area); + else if (policy == UnderMouse) + placeUnderMouse(c, area); + else if (policy == OnMainWindow) + placeOnMainWindow(c, area); + else + placeSmart(c, area); } /*! @@ -395,7 +412,7 @@ void Placement::placeUtility(Client* c, QRect& area ) // if there's not enough place outside the mainwindow, it should prefer // top-right corner // use the default placement for now - placeInternal( c, area ); + place( c, Default, area ); } @@ -467,6 +484,38 @@ QRect Placement::checkArea( const Client* c, const QRect& area ) return area; } +Placement::Policy Placement::policyFromString( const QString& policy, bool no_special ) + { + if( policy == "NoPlacement" ) + return NoPlacement; + else if( policy == "Default" && !no_special ) + return Default; + else if( policy == "Random" ) + return Random; + else if( policy == "Cascade" ) + return Cascade; + else if( policy == "Centered" ) + return Centered; + else if( policy == "ZeroCornered" ) + return ZeroCornered; + else if( policy == "UnderMouse" && !no_special) + return UnderMouse; + else if( policy == "OnMainWindow" && !no_special) + return OnMainWindow; + else + return Smart; + } + +const char* Placement::policyToString( Policy policy ) + { + const char* const policies[] = + { "NoPlacement", "Default", "Random", "Smart", "Cascade", "Centered", + "ZeroCornered", "UnderMouse", "OnMainWindow" }; + assert( policy < int( sizeof( policies ) / sizeof( policies[ 0 ] ))); + return policies[ policy ]; + } + + // ******************** // Workspace // ******************** diff --git a/placement.h b/placement.h index c92cbe53e5..842f790ccc 100644 --- a/placement.h +++ b/placement.h @@ -38,9 +38,31 @@ class Placement void placeDialog (Client* c, QRect& area ); void placeUtility (Client* c, QRect& area ); + /** + * Placement policies. How workspace decides the way windows get positioned + * on the screen. The better the policy, the heavier the resource use. + * Normally you don't have to worry. What the WM adds to the startup time + * is nil compared to the creation of the window itself in the memory + */ + enum Policy + { + NoPlacement, // not really a placement + Default, // special, means to use the global default + Random, + Smart, + Cascade, + Centered, + ZeroCornered, + UnderMouse, // special + OnMainWindow // special + }; + + static Policy policyFromString( const QString& policy, bool no_special ); + static const char* policyToString( Policy policy ); + private: - void placeInternal(Client* c, const QRect& area ); + void place(Client* c, Policy policy, QRect& area); void placeUnderMouse(Client* c, QRect& area ); void placeOnMainWindow(Client* c, QRect& area ); QRect checkArea( const Client*c, const QRect& area ); diff --git a/rules.cpp b/rules.cpp index 6fe0501009..0ad9a53533 100644 --- a/rules.cpp +++ b/rules.cpp @@ -29,6 +29,7 @@ WindowRules::WindowRules() , extraroleregexp( false ) , clientmachineregexp( false ) , types( NET::AllTypesMask ) + , placementrule( DontCareRule ) , desktoprule( DontCareRule ) , typerule( DontCareRule ) , aboverule( DontCareRule ) @@ -50,6 +51,8 @@ WindowRules::WindowRules( KConfig& cfg ) clientmachine = cfg.readEntry( "clientmachine" ).lower().latin1(); clientmachineregexp = cfg.readBoolEntry( "clientmachineregexp" ); types = cfg.readUnsignedLongNumEntry( "types", NET::AllTypesMask ); + placement = Placement::policyFromString( cfg.readEntry( "placement" ), false ); + placementrule = readRule( cfg, "placementrule" ); desktop = cfg.readNumEntry( "desktop" ); desktoprule = readRule( cfg, "desktoprule" ); type = readType( cfg, "type" ); @@ -73,10 +76,10 @@ WindowRules::WindowRules( KConfig& cfg ) cfg.deleteEntry( #var "regexp" ); \ } -#define WRITE_SET_RULE( var ) \ +#define WRITE_SET_RULE( var, func ) \ if( var##rule != DontCareRule ) \ { \ - cfg.writeEntry( #var, var ); \ + cfg.writeEntry( #var, func ( var )); \ cfg.writeEntry( #var "rule", var##rule ); \ } \ else \ @@ -103,10 +106,11 @@ void WindowRules::write( KConfig& cfg ) const WRITE_MATCH_STRING( extrarole, (const char*) ); WRITE_MATCH_STRING( clientmachine, (const char*) ); WRITE_WITH_DEFAULT( types, NET::AllTypesMask ); - WRITE_SET_RULE( desktop ); - WRITE_SET_RULE( type ); - WRITE_SET_RULE( above ); - WRITE_SET_RULE( below ); + WRITE_SET_RULE( placement, Placement::policyToString ); + WRITE_SET_RULE( desktop, ); + WRITE_SET_RULE( type, ); + WRITE_SET_RULE( above, ); + WRITE_SET_RULE( below, ); } #undef WRITE_MATCH_STRING @@ -194,25 +198,30 @@ void WindowRules::update( Client* c ) below = c->keepBelow(); } +Placement::Policy WindowRules::checkPlacement( Placement::Policy placement ) const + { + return checkForceRule( placementrule ) ? this->placement : placement; + } + int WindowRules::checkDesktop( int req_desktop, bool init ) const { // TODO chaining? - return checkRule( desktoprule, init ) ? desktop : req_desktop; + return checkRule( desktoprule, init ) ? this->desktop : req_desktop; } bool WindowRules::checkKeepAbove( bool req_above, bool init ) const { - return checkRule( aboverule, init ) ? above : req_above; + return checkRule( aboverule, init ) ? this->above : req_above; } bool WindowRules::checkKeepBelow( bool req_below, bool init ) const { - return checkRule( belowrule, init ) ? below : req_below; + return checkRule( belowrule, init ) ? this->below : req_below; } NET::WindowType WindowRules::checkType( NET::WindowType req_type ) const { - return checkForceRule( typerule ) ? type : req_type; + return checkForceRule( typerule ) ? this->type : req_type; } // Client diff --git a/rules.h b/rules.h index b2d38dc259..a873e0dd00 100644 --- a/rules.h +++ b/rules.h @@ -14,6 +14,8 @@ License. See the file "COPYING" for the exact licensing terms. #include #include +#include "placement.h" + class KConfig; namespace KWinInternal @@ -38,10 +40,11 @@ class WindowRules void write( KConfig& ) const; void update( Client* ); bool match( const Client* c ) const; + Placement::Policy checkPlacement( Placement::Policy placement ) const; int checkDesktop( int desktop, bool init = false ) const; + NET::WindowType checkType( NET::WindowType type ) const; bool checkKeepAbove( bool above, bool init = false ) const; bool checkKeepBelow( bool above, bool init = false ) const; - NET::WindowType checkType( NET::WindowType type ) const; private: static SettingRule readRule( KConfig&, const QString& key ); static SettingRule readForceRule( KConfig&, const QString& key ); @@ -60,6 +63,8 @@ class WindowRules QCString clientmachine; bool clientmachineregexp; unsigned long types; // types for matching + Placement::Policy placement; + SettingRule placementrule; int desktop; SettingRule desktoprule; NET::WindowType type; // type for setting