KWin rules - position and size.

Forcing position doesn't work yet, and forcing size needs more testing.

svn path=/trunk/kdebase/kwin/; revision=316414
This commit is contained in:
Luboš Luňák 2004-05-31 14:25:25 +00:00
parent a114e9acc3
commit 7eadd6463f
7 changed files with 108 additions and 27 deletions

View file

@ -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 );

View file

@ -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 );

View file

@ -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();
}
}

View file

@ -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 );

View file

@ -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

View file

@ -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;

View file

@ -35,6 +35,8 @@ const long ClientWinMask = KeyPressMask | KeyReleaseMask |
StructureNotifyMask |
SubstructureRedirectMask;
const QPoint invalidPoint( INT_MIN, INT_MIN );
class Client;
class Group;
class Options;