diff --git a/client.cpp b/client.cpp index 368a742f8f..d5e7b5413a 100644 --- a/client.cpp +++ b/client.cpp @@ -246,9 +246,9 @@ void Client::updateDecoration( bool check_workspace_pos, bool force, bool delay_ int save_workarea_diff_y = workarea_diff_y; move( calculateGravitation( false )); if( !isShade()) - resize( sizeForClientSize( clientSize()), IgnoreGravity, ForceGeometrySet ); + plainResize( sizeForClientSize( clientSize()), ForceGeometrySet ); else - resize( sizeForClientSize( QSize( clientSize().width(), 0 ), true ), IgnoreGravity, ForceGeometrySet ); + plainResize( sizeForClientSize( QSize( clientSize().width(), 0 ), true ), ForceGeometrySet ); workarea_diff_x = save_workarea_diff_x; workarea_diff_y = save_workarea_diff_y; do_show = true; @@ -284,9 +284,9 @@ void Client::destroyDecoration( bool delay_delete ) int save_workarea_diff_y = workarea_diff_y; move( grav ); if( !isShade()) - resize( clientSize(), IgnoreGravity, ForceGeometrySet ); + plainResize( clientSize(), ForceGeometrySet ); else - resize( QSize( clientSize().width(), 0 ), IgnoreGravity, ForceGeometrySet ); + plainResize( QSize( clientSize().width(), 0 ), ForceGeometrySet ); workarea_diff_x = save_workarea_diff_x; workarea_diff_y = save_workarea_diff_y; } @@ -308,7 +308,7 @@ void Client::checkBorderSizes() border_top = new_top; border_bottom = new_bottom; move( calculateGravitation( false )); - resize( sizeForClientSize( clientSize()), IgnoreGravity, ForceGeometrySet ); + plainResize( sizeForClientSize( clientSize()), ForceGeometrySet ); checkWorkspacePosition(); --block_geometry; setGeometry( geometry(), ForceGeometrySet ); @@ -735,7 +735,7 @@ void Client::setShade( ShadeMode mode ) // if ( !wasStaticContents ) // clearWFlags( WStaticContents ); shade_geometry_change = false; - resize( s, IgnoreGravity ); + plainResize( s ); if( isActive()) workspace()->focusToNull(); } @@ -760,7 +760,7 @@ void Client::setShade( ShadeMode mode ) // if ( !wasStaticContents ) // clearWFlags( WStaticContents ); shade_geometry_change = false; - resize( s, IgnoreGravity ); + plainResize( s ); if( shade_mode == ShadeHover || shade_mode == ShadeActivated ) setActive( TRUE ); XMapWindow( qt_xdisplay(), wrapperId()); diff --git a/client.h b/client.h index a29f260294..429c4f7f02 100644 --- a/client.h +++ b/client.h @@ -192,8 +192,9 @@ class Client : public QObject, public KDecorationDefines void setGeometry( const QRect& r, ForceGeometry_t force = NormalGeometrySet ); void move( int x, int y, ForceGeometry_t force = NormalGeometrySet ); void move( const QPoint & p, ForceGeometry_t force = NormalGeometrySet ); - void resize( int w, int h, UseGravity_t use_gravity, ForceGeometry_t force = NormalGeometrySet ); - void resize( const QSize& s, UseGravity_t use_gravity, ForceGeometry_t force = NormalGeometrySet ); + // plainResize() simply resizes + void plainResize( int w, int h, ForceGeometry_t force = NormalGeometrySet ); + void plainResize( const QSize& s, ForceGeometry_t force = NormalGeometrySet ); void growHorizontal(); void shrinkHorizontal(); @@ -326,7 +327,9 @@ class Client : public QObject, public KDecorationDefines void checkDirection( int new_diff, int old_diff, QRect& rect, const QRect& area ); static int computeWorkareaDiff( int left, int right, int a_left, int a_right ); void configureRequest( int value_mask, int rx, int ry, int rw, int rh, int gravity = 0 ); - void resizeWithGravity( int w, int h, ForceGeometry_t force ); + // resizeWithChecks() resizes according to gravity, and checks workarea position + void resizeWithChecks( int w, int h, ForceGeometry_t force = NormalGeometrySet ); + void resizeWithChecks( const QSize& s, ForceGeometry_t force = NormalGeometrySet ); bool startMoveResize(); void finishMoveResize( bool cancel ); @@ -774,9 +777,14 @@ inline void Client::move( const QPoint & p, ForceGeometry_t force ) move( p.x(), p.y(), force ); } -inline void Client::resize( const QSize& s, UseGravity_t use_gravity, ForceGeometry_t force ) +inline void Client::plainResize( const QSize& s, ForceGeometry_t force ) { - resize( s.width(), s.height(), use_gravity, force ); + plainResize( s.width(), s.height(), force ); + } + +inline void Client::resizeWithChecks( const QSize& s, ForceGeometry_t force ) + { + resizeWithChecks( s.width(), s.height(), force ); } inline bool Client::hasUserTimeSupport() const diff --git a/geometry.cpp b/geometry.cpp index c3879419b4..2c7d73471c 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -747,7 +747,7 @@ void Client::getWmNormalHints() { // update to match restrictions QSize new_size = adjustedSize( size()); if( new_size != size()) - resize( new_size, UseGravity ); + resizeWithChecks( new_size ); } updateAllowedActions(); // affects isResizeable() } @@ -885,7 +885,7 @@ void Client::configureRequest( int value_mask, int rx, int ry, int rw, int rh, i resetMaximize(); ++block_geometry; move( new_pos ); - resize( ns, IgnoreGravity ); // TODO must(?) resize before gravitating? + plainResize( ns ); // TODO must(?) resize before gravitating? --block_geometry; setGeometry( QRect( calculateGravitation( false, gravity ), size()), ForceGeometrySet ); } @@ -907,7 +907,7 @@ void Client::configureRequest( int value_mask, int rx, int ry, int rw, int rh, i resetMaximize(); int save_gravity = xSizeHint.win_gravity; xSizeHint.win_gravity = gravity; - resize( ns, UseGravity ); + resizeWithChecks( ns ); xSizeHint.win_gravity = save_gravity; } } @@ -916,10 +916,19 @@ void Client::configureRequest( int value_mask, int rx, int ry, int rw, int rh, i // Handling of the real ConfigureRequest event forces sending it, as there it's necessary. } -void Client::resizeWithGravity( int w, int h, ForceGeometry_t force ) +void Client::resizeWithChecks( int w, int h, ForceGeometry_t force ) { int newx = x(); int newy = y(); + QRect area = workspace()->clientArea( geometry().center(), desktop()); + // don't allow growing larger than workarea + if( w > area.width()) + w = area.width(); + if( h > area.height()) + h = area.height(); + QSize tmp = adjustedSize( QSize( w, h )); // checks size constraints, including min/max size + w = tmp.width(); + h = tmp.height(); switch( xSizeHint.win_gravity ) { case NorthWestGravity: // top left corner doesn't move @@ -957,6 +966,24 @@ void Client::resizeWithGravity( int w, int h, ForceGeometry_t force ) newy = newy + height() - h; break; } + // if it would be moved outside of workarea, keep it inside, + // see also Client::computeWorkareaDiff() + if( workarea_diff_x != INT_MIN ) // was inside + { + if( newx < area.left()) + newx = area.left(); + if( newx + w > area.right() + 1 ) + newx = area.right() + 1 - w; + assert( newx >= area.left() && newx + w <= area.right() + 1 ); // width was checked above + } + if( workarea_diff_y != INT_MIN ) // was inside + { + if( newy < area.top()) + newy = area.top(); + if( newy + h > area.bottom() + 1 ) + newy = area.bottom() + 1 - h; + assert( newy >= area.top() && newy + h <= area.bottom() + 1 ); // height was checked above + } setGeometry( newx, newy, w, h, force ); } @@ -1047,15 +1074,10 @@ void Client::setGeometry( int x, int y, int w, int h, ForceGeometry_t force ) } } -void Client::resize( int w, int h, UseGravity_t use_gravity, ForceGeometry_t force ) +void Client::plainResize( int w, int h, ForceGeometry_t force ) { // TODO make this deffered with isResize() ? old kwin did if( force == NormalGeometrySet && frame_geometry.size() == QSize( w, h )) return; - if( use_gravity == UseGravity ) - { - resizeWithGravity( w, h, force ); - return; - } frame_geometry.setSize( QSize( w, h )); if( !isShade()) client_size = QSize( w - border_left - border_right, h - border_top - border_bottom ); @@ -1189,7 +1211,7 @@ void Client::changeMaximize( bool vertical, bool horizontal, bool adjust ) { if( geom_restore.width() == 0 ) { // needs placement - resize( adjustedSize(QSize(width(), clientArea.height())), IgnoreGravity ); + plainResize( adjustedSize(QSize(width(), clientArea.height()))); workspace()->placeSmart( this ); } else @@ -1209,7 +1231,7 @@ void Client::changeMaximize( bool vertical, bool horizontal, bool adjust ) { if( geom_restore.height() == 0 ) { // needs placement - resize( adjustedSize(QSize(clientArea.width(), height())), IgnoreGravity ); + plainResize( adjustedSize(QSize(clientArea.width(), height()))); workspace()->placeSmart( this ); } else @@ -1233,7 +1255,7 @@ void Client::changeMaximize( bool vertical, bool horizontal, bool adjust ) s.setWidth( geom_restore.width()); if( geom_restore.height() > 0 ) s.setHeight( geom_restore.height()); - resize( adjustedSize( s ), IgnoreGravity ); + plainResize( adjustedSize( s )); workspace()->placeSmart( this ); restore = geometry(); if( geom_restore.width() > 0 ) diff --git a/manage.cpp b/manage.cpp index 44d12f6926..b804de80e1 100644 --- a/manage.cpp +++ b/manage.cpp @@ -279,7 +279,7 @@ bool Client::manage( Window w, bool isMapped ) updateDecoration( false ); // also gravitates // TODO is CentralGravity right here, when resizing is done after gravitating? - resize( sizeForClientSize( geom.size() ), IgnoreGravity ); + plainResize( sizeForClientSize( geom.size())); if( !placementDone ) { // placement needs to be after setting size diff --git a/utils.h b/utils.h index 00216fdb60..f8f423622d 100644 --- a/utils.h +++ b/utils.h @@ -73,7 +73,6 @@ inline void operator++( Layer& lay ) enum allowed_t { Allowed }; // some enums to have more readable code, instead of using bools -enum UseGravity_t { IgnoreGravity, UseGravity }; enum ForceGeometry_t { NormalGeometrySet, ForceGeometrySet }; class Shape