diff --git a/client.cpp b/client.cpp index 02c6e6b58c..e7b17a4d99 100644 --- a/client.cpp +++ b/client.cpp @@ -86,7 +86,8 @@ Client::Client( Workspace *ws ) process_killer( NULL ), user_time( CurrentTime ), // not known yet allowed_actions( 0 ), - block_geometry( 0 ), + postpone_geometry_updates( 0 ), + pending_geometry_update( false ), shade_geometry_change( false ), border_left( 0 ), border_right( 0 ), @@ -162,7 +163,7 @@ Client::~Client() assert( client == None ); assert( frame == None && wrapper == None ); assert( decoration == NULL ); - assert( block_geometry == 0 ); + assert( postpone_geometry_updates == 0 ); assert( !check_active_modal ); delete info; delete bridge; @@ -187,7 +188,7 @@ void Client::releaseWindow( bool on_shutdown ) if (moveResizeMode) leaveMoveResize(); finishWindowRules(); - ++block_geometry; + ++postpone_geometry_updates; setMappingState( WithdrawnState ); 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) @@ -226,7 +227,7 @@ void Client::releaseWindow( bool on_shutdown ) wrapper = None; XDestroyWindow( qt_xdisplay(), frame ); frame = None; - --block_geometry; + --postpone_geometry_updates; // don't use GeometryUpdatesBlocker, it would now set the geometry deleteClient( this, Allowed ); } @@ -241,7 +242,7 @@ void Client::destroyClient() if (moveResizeMode) leaveMoveResize(); finishWindowRules(); - ++block_geometry; + ++postpone_geometry_updates; setModal( false ); hidden = true; // so that it's not considered visible anymore workspace()->clientHidden( this ); @@ -253,7 +254,7 @@ void Client::destroyClient() wrapper = None; XDestroyWindow( qt_xdisplay(), frame ); frame = None; - --block_geometry; + --postpone_geometry_updates; // don't use GeometryUpdatesBlocker, it would now set the geometry deleteClient( this, Allowed ); } @@ -263,7 +264,7 @@ void Client::updateDecoration( bool check_workspace_pos, bool force ) || ( decoration != NULL && !noBorder()))) return; bool do_show = false; - ++block_geometry; + postponeGeometryUpdates( true ); if( force ) destroyDecoration(); if( !noBorder()) @@ -291,8 +292,7 @@ void Client::updateDecoration( bool check_workspace_pos, bool force ) destroyDecoration(); if( check_workspace_pos ) checkWorkspacePosition(); - --block_geometry; - setGeometry( geometry(), ForceGeometrySet ); + postponeGeometryUpdates( false ); if( do_show ) decoration->widget()->show(); updateFrameStrut(); @@ -328,7 +328,7 @@ void Client::checkBorderSizes() if( new_left == border_left && new_right == border_right && new_top == border_top && new_bottom == border_bottom ) return; - ++block_geometry; + GeometryUpdatesPostponer blocker( this ); move( calculateGravitation( true )); border_left = new_left; border_right = new_right; @@ -339,8 +339,6 @@ void Client::checkBorderSizes() move( calculateGravitation( false )); plainResize( sizeForClientSize( clientSize()), ForceGeometrySet ); checkWorkspacePosition(); - --block_geometry; - setGeometry( geometry(), ForceGeometrySet ); } void Client::detectNoBorder() @@ -731,7 +729,7 @@ void Client::setShade( ShadeMode mode ) } assert( decoration != NULL ); // noborder windows can't be shaded - ++block_geometry; + GeometryUpdatesPostponer blocker( this ); // decorations may turn off some borders when shaded decoration->borders( border_left, border_right, border_top, border_bottom ); @@ -809,8 +807,6 @@ void Client::setShade( ShadeMode mode ) workspace()->requestFocus( this ); } checkMaximizeGeometry(); - --block_geometry; - setGeometry( geometry(), ForceGeometrySet ); info->setState( isShade() ? NET::Shaded : 0, NET::Shaded ); info->setState( isShown( false ) ? 0 : NET::Hidden, NET::Hidden ); updateVisibility(); @@ -907,12 +903,8 @@ void Client::setMappingState(int s) XChangeProperty(qt_xdisplay(), window(), qt_wm_state, qt_wm_state, 32, PropModeReplace, (unsigned char *)data, 2); - if( was_unmanaged ) // force setting the geometry, manage() did block_geometry = 1 - { - assert( block_geometry == 1 ); - --block_geometry; - setGeometry( frame_geometry, ForceGeometrySet ); - } + if( was_unmanaged ) // manage() did postpone_geometry_updates = 1, now it's ok to finally set the geometry + postponeGeometryUpdates( false ); } /*! diff --git a/client.h b/client.h index ab8be0185b..f2c2fbe93c 100644 --- a/client.h +++ b/client.h @@ -383,6 +383,7 @@ class Client : public QObject, public KDecorationDefines NETExtendedStrut strut() const; bool hasStrut() const; int checkShadeGeometry( int w, int h ); + void postponeGeometryUpdates( bool postpone ); bool startMoveResize(); void finishMoveResize( bool cancel ); @@ -520,7 +521,8 @@ class Client : public QObject, public KDecorationDefines unsigned long allowed_actions; QRect frame_geometry; QSize client_size; - int block_geometry; // >0 - new geometry is remembered, but not actually set + int postpone_geometry_updates; // >0 - new geometry is remembered, but not actually set + bool pending_geometry_update; bool shade_geometry_change; int border_left, border_right, border_top, border_bottom; QRegion _mask; @@ -529,6 +531,7 @@ class Client : public QObject, public KDecorationDefines friend struct FetchNameInternalPredicate; friend struct CheckIgnoreFocusStealingProcedure; friend struct ResetupRulesProcedure; + friend class GeometryUpdatesPostponer; void show() { assert( false ); } // SELI remove after Client is no longer QWidget void hide() { assert( false ); } uint opacity_; @@ -541,6 +544,19 @@ class Client : public QObject, public KDecorationDefines QTimer* demandAttentionKNotifyTimer; }; +// helper for Client::postponeGeometryUpdates() being called in pairs (true/false) +class GeometryUpdatesPostponer + { + public: + GeometryUpdatesPostponer( Client* c ) + : cl( c ) { cl->postponeGeometryUpdates( true ); } + ~GeometryUpdatesPostponer() + { cl->postponeGeometryUpdates( false ); } + private: + Client* cl; + }; + + // NET WM Protocol handler class class WinInfo : public NETWinInfo { diff --git a/geometry.cpp b/geometry.cpp index 8345c33e87..7cd406c3c8 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -1393,7 +1393,7 @@ void Client::configureRequest( int value_mask, int rx, int ry, int rw, int rh, i || ns != size()) { QRect orig_geometry = geometry(); - ++block_geometry; + GeometryUpdatesPostponer blocker( this ); move( new_pos ); plainResize( ns ); setGeometry( QRect( calculateGravitation( false, gravity ), size())); @@ -1402,8 +1402,6 @@ void Client::configureRequest( int value_mask, int rx, int ry, int rw, int rh, i if( !from_tool && ( !isSpecialWindow() || isToolbar()) && !isFullScreen() && area.contains( orig_geometry )) keepInArea( area ); - --block_geometry; - setGeometry( geometry(), ForceGeometrySet ); // this is part of the kicker-xinerama-hack... it should be // safe to remove when kicker gets proper ExtendedStrut support; @@ -1428,7 +1426,7 @@ void Client::configureRequest( int value_mask, int rx, int ry, int rw, int rh, i if( ns != size()) // don't restore if some app sets its own size again { QRect orig_geometry = geometry(); - ++block_geometry; + GeometryUpdatesPostponer blocker( this ); int save_gravity = xSizeHint.win_gravity; xSizeHint.win_gravity = gravity; resizeWithChecks( ns ); @@ -1438,8 +1436,6 @@ void Client::configureRequest( int value_mask, int rx, int ry, int rw, int rh, i if( !from_tool && ( !isSpecialWindow() || isToolbar()) && !isFullScreen() && area.contains( orig_geometry )) keepInArea( area ); - --block_geometry; - setGeometry( geometry(), ForceGeometrySet ); } } // No need to send synthetic configure notify event here, either it's sent together @@ -1612,27 +1608,28 @@ void Client::setGeometry( int x, int y, int w, int h, ForceGeometry_t force ) else client_size = QSize( w - border_left - border_right, client_size.height()); updateWorkareaDiffs(); - if( block_geometry == 0 ) + if( postpone_geometry_updates != 0 ) { - resizeDecoration( QSize( w, h )); - XMoveResizeWindow( qt_xdisplay(), frameId(), x, y, w, h ); -// resizeDecoration( QSize( w, h )); - if( !isShade()) - { - QSize cs = clientSize(); - XMoveResizeWindow( qt_xdisplay(), wrapperId(), clientPos().x(), clientPos().y(), - cs.width(), cs.height()); - // FRAME tady poradi tak, at neni flicker - XMoveResizeWindow( qt_xdisplay(), window(), 0, 0, cs.width(), cs.height()); - } - if( shape()) - updateShape(); - // SELI TODO won't this be too expensive? - updateWorkareaDiffs(); - sendSyntheticConfigureNotify(); - updateWindowRules(); - checkMaximizeGeometry(); + pending_geometry_update = true; + return; } + resizeDecoration( QSize( w, h )); + XMoveResizeWindow( qt_xdisplay(), frameId(), x, y, w, h ); +// resizeDecoration( QSize( w, h )); + if( !isShade()) + { + QSize cs = clientSize(); + XMoveResizeWindow( qt_xdisplay(), wrapperId(), clientPos().x(), clientPos().y(), + cs.width(), cs.height()); + XMoveResizeWindow( qt_xdisplay(), window(), 0, 0, cs.width(), cs.height()); + } + if( shape()) + updateShape(); + // SELI TODO won't this be too expensive? + updateWorkareaDiffs(); + sendSyntheticConfigureNotify(); + updateWindowRules(); + checkMaximizeGeometry(); } void Client::plainResize( int w, int h, ForceGeometry_t force ) @@ -1651,25 +1648,27 @@ void Client::plainResize( int w, int h, ForceGeometry_t force ) else client_size = QSize( w - border_left - border_right, client_size.height()); updateWorkareaDiffs(); - if( block_geometry == 0 ) + if( postpone_geometry_updates != 0 ) { - resizeDecoration( QSize( w, h )); - XResizeWindow( qt_xdisplay(), frameId(), w, h ); -// resizeDecoration( QSize( w, h )); - if( !isShade()) - { - QSize cs = clientSize(); - XMoveResizeWindow( qt_xdisplay(), wrapperId(), clientPos().x(), clientPos().y(), - cs.width(), cs.height()); - XMoveResizeWindow( qt_xdisplay(), window(), 0, 0, cs.width(), cs.height()); - } - if( shape()) - updateShape(); - updateWorkareaDiffs(); - sendSyntheticConfigureNotify(); - updateWindowRules(); - checkMaximizeGeometry(); + pending_geometry_update = true; + return; } + resizeDecoration( QSize( w, h )); + XResizeWindow( qt_xdisplay(), frameId(), w, h ); +// resizeDecoration( QSize( w, h )); + if( !isShade()) + { + QSize cs = clientSize(); + XMoveResizeWindow( qt_xdisplay(), wrapperId(), clientPos().x(), clientPos().y(), + cs.width(), cs.height()); + XMoveResizeWindow( qt_xdisplay(), window(), 0, 0, cs.width(), cs.height()); + } + if( shape()) + updateShape(); + updateWorkareaDiffs(); + sendSyntheticConfigureNotify(); + updateWindowRules(); + checkMaximizeGeometry(); } // There may be cases when an application requests resizing while shaded, @@ -1699,16 +1698,36 @@ void Client::move( int x, int y, ForceGeometry_t force ) return; frame_geometry.moveTopLeft( QPoint( x, y )); updateWorkareaDiffs(); - if( block_geometry == 0 ) + if( postpone_geometry_updates != 0 ) { - XMoveWindow( qt_xdisplay(), frameId(), x, y ); - sendSyntheticConfigureNotify(); - updateWindowRules(); - checkMaximizeGeometry(); + pending_geometry_update = true; + return; } + XMoveWindow( qt_xdisplay(), frameId(), x, y ); + sendSyntheticConfigureNotify(); + updateWindowRules(); + checkMaximizeGeometry(); } +void Client::postponeGeometryUpdates( bool postpone ) + { + if( postpone ) + { + ++postpone_geometry_updates; + pending_geometry_update = false; + } + else + { + if( --postpone_geometry_updates == 0 ) + { + if( pending_geometry_update ) + setGeometry( geometry(), ForceGeometrySet ); + pending_geometry_update = false; + } + } + } + void Client::maximize( MaximizeMode m ) { setMaximize( m & MaximizeVertical, m & MaximizeHorizontal ); @@ -1744,7 +1763,7 @@ void Client::changeMaximize( bool vertical, bool horizontal, bool adjust ) if( !adjust && max_mode == old_mode ) return; - ++block_geometry; // TODO GeometryBlocker class? + GeometryUpdatesPostponer blocker( this ); // maximing one way and unmaximizing the other way shouldn't happen Q_ASSERT( !( vertical && horizontal ) @@ -1865,9 +1884,6 @@ void Client::changeMaximize( bool vertical, bool horizontal, bool adjust ) break; } - --block_geometry; - setGeometry( geometry(), ForceGeometrySet ); - updateAllowedActions(); if( decoration != NULL ) decoration->maximizeChange(); @@ -1973,8 +1989,8 @@ void Client::setFullScreen( bool set, bool user ) fullscreen_mode = set ? FullScreenNormal : FullScreenNone; if( was_fs == isFullScreen()) return; - StackingUpdatesBlocker blocker( workspace()); - ++block_geometry; + StackingUpdatesBlocker blocker1( workspace()); + GeometryUpdatesPostponer blocker2( this ); workspace()->updateClientLayer( this ); // active fullscreens get different layer info->setState( isFullScreen() ? NET::FullScreen : 0, NET::FullScreen ); updateDecoration( false, false ); @@ -1992,8 +2008,6 @@ void Client::setFullScreen( bool set, bool user ) setGeometry( workspace()->clientArea( MaximizeArea, this )); } } - --block_geometry; - setGeometry( geometry(), ForceGeometrySet ); updateWindowRules(); } diff --git a/manage.cpp b/manage.cpp index bd7836d771..8c6f4a5941 100644 --- a/manage.cpp +++ b/manage.cpp @@ -43,7 +43,7 @@ bool Client::manage( Window w, bool isMapped ) grabXServer(); // from this place on, manage() mustn't return false - block_geometry = 1; + postpone_geometry_updates = 1; embedClient( w, attr );