From 7eadd6463fb551032da15bf2094d0696f661e401 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Lu=C5=88=C3=A1k?= Date: Mon, 31 May 2004 14:25:25 +0000 Subject: [PATCH] KWin rules - position and size. Forcing position doesn't work yet, and forcing size needs more testing. svn path=/trunk/kdebase/kwin/; revision=316414 --- client.cpp | 21 +++++---------------- client.h | 3 ++- geometry.cpp | 46 ++++++++++++++++++++++++++++++++++++++++------ manage.cpp | 12 +++++++++--- rules.cpp | 43 ++++++++++++++++++++++++++++++++++++++++++- rules.h | 8 ++++++++ utils.h | 2 ++ 7 files changed, 108 insertions(+), 27 deletions(-) diff --git a/client.cpp b/client.cpp index 3a79650819..79e325e783 100644 --- a/client.cpp +++ b/client.cpp @@ -175,7 +175,7 @@ void Client::releaseWindow( bool on_shutdown ) { if (moveResizeMode) leaveMoveResize(); - updateWindowRules(); + finishWindowRules(); setModal( false ); // otherwise its mainwindow wouldn't get focus hidden = true; // so that it's not considered visible anymore (can't use hideClient(), it would set flags) if( !on_shutdown ) @@ -223,7 +223,7 @@ void Client::destroyClient() { if (moveResizeMode) leaveMoveResize(); - updateWindowRules(); + finishWindowRules(); ++block_geometry; setModal( false ); hidden = true; // so that it's not considered visible anymore @@ -292,9 +292,9 @@ void Client::destroyDecoration() int save_workarea_diff_x = workarea_diff_x; int save_workarea_diff_y = workarea_diff_y; if( !isShade()) - plainResize( clientSize(), ForceGeometrySet ); + plainResize( sizeForClientSize( clientSize()), ForceGeometrySet ); else - plainResize( QSize( clientSize().width(), 0 ), ForceGeometrySet ); + plainResize( sizeForClientSize( QSize( clientSize().width(), 0 ), SizemodeShaded ), ForceGeometrySet ); move( grav ); workarea_diff_x = save_workarea_diff_x; workarea_diff_y = save_workarea_diff_y; @@ -1499,17 +1499,6 @@ bool Client::wantsInput() const return input || Ptakefocus; } -/*! - Returns whether the window is moveable or has a fixed - position. !isMovable implies !isResizable. - */ -bool Client::isMovable() const - { - return motif_may_move && !isFullScreen() && - ( !isSpecialWindow() || isOverride() || isSplash() || isToolbar()) && // allow moving of splashscreens :) - ( maximizeMode() != MaximizeFull || options->moveResizeMaximizedWindows() ); - } - bool Client::isDesktop() const { return windowType() == NET::Desktop; @@ -1628,7 +1617,7 @@ void Client::setCursor( Position m ) setCursor( sizeHorCursor ); break; default: - if( buttonDown ) + if( buttonDown && isMovable()) setCursor( sizeAllCursor ); else setCursor( arrowCursor ); diff --git a/client.h b/client.h index 0e30000baf..b18b62e357 100644 --- a/client.h +++ b/client.h @@ -344,8 +344,9 @@ private slots: QString readName() const; void setCaption( const QString& s, bool force = false ); bool hasTransientInternal( const Client* c, bool indirect, ConstClientList& set ) const; - void initWindowRules(); + void setupWindowRules(); void updateWindowRules(); + void finishWindowRules(); void updateWorkareaDiffs(); void checkDirection( int new_diff, int old_diff, QRect& rect, const QRect& area ); diff --git a/geometry.cpp b/geometry.cpp index e7d9ac9cd3..7c9d9bc658 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -959,9 +959,12 @@ QSize Client::sizeForClientSize( const QSize& wsize, Sizemode mode ) const h += xSizeHint.base_height; } + w += border_left + border_right; + h += border_top + border_bottom; + QSize ret = rules()->checkSize( QSize( w, h )); if ( mode == SizemodeShaded && wsize.height() == 0 ) - h = 0; - return QSize( w + border_left + border_right, h + border_top + border_bottom ); + ret.setHeight( border_top + border_bottom ); + return ret; } /*! @@ -1290,13 +1293,36 @@ void Client::NETMoveResizeWindow( int flags, int x, int y, int width, int height configureRequest( value_mask, x, y, width, height, gravity ); } +/*! + Returns whether the window is moveable or has a fixed + position. + */ +bool Client::isMovable() const + { + if( !motif_may_move || isFullScreen()) + return false; + if( isSpecialWindow() && !isOverride() && !isSplash() && !isToolbar()) // allow moving of splashscreens :) + return false; + if( maximizeMode() == MaximizeFull && !options->moveResizeMaximizedWindows() ) + return false; + if( rules()->checkPosition( invalidPoint ) != invalidPoint ) // forced position + return false; + return true; + } + /*! Returns whether the window is resizable or has a fixed size. */ bool Client::isResizable() const { - if ( !isMovable() || !motif_may_resize || isSplash()) - return FALSE; + if( !motif_may_resize || isFullScreen()) + return false; + if( isSpecialWindow() || isSplash() || isToolbar()) + return false; + if( maximizeMode() == MaximizeFull && !options->moveResizeMaximizedWindows() ) + return false; + if( rules()->checkSize( QSize()).isValid()) // forced size + return false; QSize min = minSize(); QSize max = maxSize(); @@ -1310,7 +1336,7 @@ bool Client::isMaximizable() const { if ( maximizeMode() != MaximizeRestore ) return TRUE; - if( !isResizable() || isToolbar()) // SELI isToolbar() ? + if( !isMovable() || !isResizable() || isToolbar()) // SELI isToolbar() ? return false; QSize max = maxSize(); if( max.width() < 32767 || max.height() < 32767 ) // sizes are 16bit with X @@ -1357,11 +1383,17 @@ void Client::setGeometry( int x, int y, int w, int h, ForceGeometry_t force ) // SELI TODO won't this be too expensive? updateWorkareaDiffs(); sendSyntheticConfigureNotify(); + updateWindowRules(); } } void Client::plainResize( int w, int h, ForceGeometry_t force ) - { // TODO make this deffered with isResize() ? old kwin did + { + if( QSize( w, h ) != rules()->checkSize( QSize( w, h ))) + { + kdDebug() << "forced size fail:" << QSize( w,h ) << ":" << rules()->checkSize( QSize( w, h )) << endl; + kdDebug() << kdBacktrace() << endl; + } if( force == NormalGeometrySet && frame_geometry.size() == QSize( w, h )) return; frame_geometry.setSize( QSize( w, h )); @@ -1394,6 +1426,7 @@ void Client::plainResize( int w, int h, ForceGeometry_t force ) updateShape(); updateWorkareaDiffs(); sendSyntheticConfigureNotify(); + updateWindowRules(); } } @@ -1410,6 +1443,7 @@ void Client::move( int x, int y, ForceGeometry_t force ) { XMoveWindow( qt_xdisplay(), frameId(), x, y ); sendSyntheticConfigureNotify(); + updateWindowRules(); } } diff --git a/manage.cpp b/manage.cpp index 960bff219f..0405cffff3 100644 --- a/manage.cpp +++ b/manage.cpp @@ -107,11 +107,11 @@ bool Client::manage( Window w, bool isMapped ) ignore_focus_stealing = options->checkIgnoreFocusStealing( this ); // TODO change to rules window_role = getStringProperty( w, qt_window_role ); - // first only read the caption text, so that initWindowRules() can use it for matching, + // first only read the caption text, so that setupWindowRules() can use it for matching, // and only then really set the caption using setCaption(), which checks for duplicates etc. // and also relies on rules already existing cap_normal = readName(); - initWindowRules(); + setupWindowRules(); setCaption( cap_normal, true ); detectNoBorder(); @@ -269,8 +269,14 @@ bool Client::manage( Window w, bool isMapped ) updateDecoration( false ); // also gravitates // TODO is CentralGravity right here, when resizing is done after gravitating? - plainResize( sizeForClientSize( geom.size())); + plainResize( rules()->checkSize( sizeForClientSize( geom.size()), true )); + QPoint forced_pos = rules()->checkPosition( invalidPoint, true ); + if( forced_pos != invalidPoint ) + { + move( forced_pos ); + placementDone = true; + } if( !placementDone ) { // placement needs to be after setting size workspace()->place( this, area ); diff --git a/rules.cpp b/rules.cpp index fd5390ebc6..36c55f4cf1 100644 --- a/rules.cpp +++ b/rules.cpp @@ -30,6 +30,8 @@ WindowRules::WindowRules() , clientmachineregexp( false ) , types( NET::AllTypesMask ) , placementrule( DontCareRule ) + , positionrule( DontCareRule ) + , sizerule( DontCareRule ) , minsizerule( DontCareRule ) , maxsizerule( DontCareRule ) , desktoprule( DontCareRule ) @@ -55,10 +57,20 @@ WindowRules::WindowRules( KConfig& cfg ) types = cfg.readUnsignedLongNumEntry( "types", NET::AllTypesMask ); placement = Placement::policyFromString( cfg.readEntry( "placement" ), false ); placementrule = readRule( cfg, "placementrule" ); + position = cfg.readPointEntry( "position" ); + positionrule = readRule( cfg, "positionrule" ); + size = cfg.readSizeEntry( "size" ); + sizerule = readRule( cfg, "sizerule" ); + if( size.isEmpty()) + sizerule = DontCareRule; minsize = cfg.readSizeEntry( "minsize" ); minsizerule = readRule( cfg, "minsizerule" ); + if( !minsize.isValid()) + minsizerule = DontCareRule; maxsize = cfg.readSizeEntry( "maxsize" ); maxsizerule = readRule( cfg, "maxsizerule" ); + if( maxsize.isEmpty()) + maxsizerule = DontCareRule; desktop = cfg.readNumEntry( "desktop" ); desktoprule = readRule( cfg, "desktoprule" ); type = readType( cfg, "type" ); @@ -113,6 +125,8 @@ void WindowRules::write( KConfig& cfg ) const WRITE_MATCH_STRING( clientmachine, (const char*) ); WRITE_WITH_DEFAULT( types, NET::AllTypesMask ); WRITE_SET_RULE( placement, Placement::policyToString ); + WRITE_SET_RULE( position, ); + WRITE_SET_RULE( size, ); WRITE_SET_RULE( minsize, ); WRITE_SET_RULE( maxsize, ); WRITE_SET_RULE( desktop, ); @@ -198,6 +212,10 @@ bool WindowRules::match( const Client* c ) const void WindowRules::update( Client* c ) { // TODO check this setting is for this client ? + if( positionrule == RememberRule ) + position = c->pos(); + if( sizerule == RememberRule ) + size = c->size(); if( desktoprule == RememberRule ) desktop = c->desktop(); if( aboverule == RememberRule ) @@ -211,6 +229,23 @@ Placement::Policy WindowRules::checkPlacement( Placement::Policy placement ) con return checkForceRule( placementrule ) ? this->placement : placement; } +// TODO at to porad jeste kontroluje min/max size , + udelat override pro min/max? +QRect WindowRules::checkGeometry( const QRect& rect, bool init ) const + { + return QRect( checkRule( positionrule, init ) ? this->position : rect.topLeft(), + checkRule( sizerule, init ) ? this->size : rect.size()); + } + +QPoint WindowRules::checkPosition( const QPoint& pos, bool init ) const + { + return checkRule( positionrule, init ) ? this->position : pos; + } + +QSize WindowRules::checkSize( const QSize& s, bool init ) const + { + return checkRule( sizerule, init ) ? this->size : s; + } + QSize WindowRules::checkMinSize( const QSize& s ) const { return checkForceRule( minsizerule ) ? this->minsize : s; @@ -244,7 +279,7 @@ NET::WindowType WindowRules::checkType( NET::WindowType req_type ) const // Client -void Client::initWindowRules() +void Client::setupWindowRules() { client_rules = workspace()->findWindowRules( this ); // check only after getting the rules, because there may be a rule forcing window type @@ -257,6 +292,12 @@ void Client::updateWindowRules() client_rules->update( this ); } +void Client::finishWindowRules() + { + updateWindowRules(); + client_rules = &dummyRules; + } + // Workspace WindowRules* Workspace::findWindowRules( const Client* c ) const diff --git a/rules.h b/rules.h index a68394b659..206beb8e81 100644 --- a/rules.h +++ b/rules.h @@ -42,6 +42,10 @@ class WindowRules void update( Client* ); bool match( const Client* c ) const; Placement::Policy checkPlacement( Placement::Policy placement ) const; + QRect checkGeometry( const QRect& rect, bool init = false ) const; + // use 'invalidPoint' with checkPosition, unlike QSize() and QRect(), QPoint() is a valid point + QPoint checkPosition( const QPoint& pos, bool init = false ) const; + QSize checkSize( const QSize& s, bool init = false ) const; QSize checkMinSize( const QSize& s ) const; QSize checkMaxSize( const QSize& s ) const; int checkDesktop( int desktop, bool init = false ) const; @@ -68,6 +72,10 @@ class WindowRules unsigned long types; // types for matching Placement::Policy placement; SettingRule placementrule; + QPoint position; + SettingRule positionrule; + QSize size; + SettingRule sizerule; QSize minsize; SettingRule minsizerule; QSize maxsize; diff --git a/utils.h b/utils.h index c26d861ec9..986fec2a6a 100644 --- a/utils.h +++ b/utils.h @@ -35,6 +35,8 @@ const long ClientWinMask = KeyPressMask | KeyReleaseMask | StructureNotifyMask | SubstructureRedirectMask; +const QPoint invalidPoint( INT_MIN, INT_MIN ); + class Client; class Group; class Options;