From bd4789e32bf07d5e7b5bbbf9cc2fdb9bfd7cf3b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Lu=C5=88=C3=A1k?= Date: Wed, 1 Oct 2003 12:10:22 +0000 Subject: [PATCH] Looks like I got window gravities working correctly also for configure requests. CCMAIL: 64981-done@bugs.kde.org svn path=/trunk/kdebase/kwin/; revision=255356 --- client.cpp | 22 +++--- client.h | 21 +++--- geometry.cpp | 155 +++++++++++++++++++++++++---------------- manage.cpp | 3 +- tools/test_gravity.cpp | 28 ++++++-- utils.h | 4 ++ 6 files changed, 144 insertions(+), 89 deletions(-) diff --git a/client.cpp b/client.cpp index aa5509cc77..2b143774f9 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()), true ); + resize( sizeForClientSize( clientSize()), IgnoreGravity, ForceGeometrySet ); else - resize( sizeForClientSize( QSize( clientSize().width(), 0 ), true ), true ); + resize( sizeForClientSize( QSize( clientSize().width(), 0 ), true ), IgnoreGravity, ForceGeometrySet ); workarea_diff_x = save_workarea_diff_x; workarea_diff_y = save_workarea_diff_y; do_show = true; @@ -258,7 +258,7 @@ void Client::updateDecoration( bool check_workspace_pos, bool force, bool delay_ if( check_workspace_pos ) checkWorkspacePosition(); --block_geometry; - setGeometry( geometry(), true ); + setGeometry( geometry(), ForceGeometrySet ); if( do_show ) decoration->widget()->show(); updateFrameStrut(); @@ -283,9 +283,9 @@ void Client::destroyDecoration( bool delay_delete ) int save_workarea_diff_y = workarea_diff_y; move( calculateGravitation( true )); if( !isShade()) - resize( clientSize(), true ); + resize( clientSize(), IgnoreGravity, ForceGeometrySet ); else - resize( QSize( clientSize().width(), 0 ), true ); + resize( QSize( clientSize().width(), 0 ), IgnoreGravity, ForceGeometrySet ); workarea_diff_x = save_workarea_diff_x; workarea_diff_y = save_workarea_diff_y; } @@ -307,10 +307,10 @@ void Client::checkBorderSizes() border_top = new_top; border_bottom = new_bottom; move( calculateGravitation( false )); - resize( sizeForClientSize( clientSize()), true ); + resize( sizeForClientSize( clientSize()), IgnoreGravity, ForceGeometrySet ); checkWorkspacePosition(); --block_geometry; - setGeometry( geometry(), true ); + setGeometry( geometry(), ForceGeometrySet ); } void Client::detectNoBorder() @@ -734,7 +734,7 @@ void Client::setShade( ShadeMode mode ) // if ( !wasStaticContents ) // clearWFlags( WStaticContents ); shade_geometry_change = false; - resize( s ); + resize( s, IgnoreGravity ); if( isActive()) workspace()->focusToNull(); } @@ -759,7 +759,7 @@ void Client::setShade( ShadeMode mode ) // if ( !wasStaticContents ) // clearWFlags( WStaticContents ); shade_geometry_change = false; - resize( s ); + resize( s, IgnoreGravity ); if( shade_mode == ShadeHover || shade_mode == ShadeActivated ) setActive( TRUE ); XMapWindow( qt_xdisplay(), wrapperId()); @@ -768,7 +768,7 @@ void Client::setShade( ShadeMode mode ) workspace()->requestFocus( this ); } --block_geometry; - setGeometry( geometry(), true ); + setGeometry( geometry(), ForceGeometrySet ); info->setState( isShade() ? NET::Shaded : 0, NET::Shaded ); info->setState( isShown() ? 0 : NET::Hidden, NET::Hidden ); setMappingState( isShown() && isOnCurrentDesktop() ? NormalState : IconicState ); @@ -837,7 +837,7 @@ void Client::setMappingState(int s) { assert( block_geometry == 1 ); --block_geometry; - setGeometry( frame_geometry, true ); + setGeometry( frame_geometry, ForceGeometrySet ); } } diff --git a/client.h b/client.h index 5f639046f5..3305bdd0fe 100644 --- a/client.h +++ b/client.h @@ -187,12 +187,12 @@ class Client : public QObject, public KDecorationDefines bool shape() const; void updateShape(); - void setGeometry( int x, int y, int w, int h, bool force = false ); - void setGeometry( const QRect& r, bool force = false ); - void move( int x, int y, bool force = false ); - void move( const QPoint & p, bool force = false ); - void resize( int w, int h, bool force = false ); - void resize( const QSize& s, bool force = false ); + void setGeometry( int x, int y, int w, int h, ForceGeometry_t force = NormalGeometrySet ); + 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 ); void growHorizontal(); void shrinkHorizontal(); @@ -325,6 +325,7 @@ 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 ); bool startMoveResize(); void finishMoveResize( bool cancel ); @@ -757,19 +758,19 @@ inline QSize Client::clientSize() const return client_size; } -inline void Client::setGeometry( const QRect& r, bool force ) +inline void Client::setGeometry( const QRect& r, ForceGeometry_t force ) { setGeometry( r.x(), r.y(), r.width(), r.height(), force ); } -inline void Client::move( const QPoint & p, bool force ) +inline void Client::move( const QPoint & p, ForceGeometry_t force ) { move( p.x(), p.y(), force ); } -inline void Client::resize( const QSize& s, bool force ) +inline void Client::resize( const QSize& s, UseGravity_t use_gravity, ForceGeometry_t force ) { - resize( s.width(), s.height(), force ); + resize( s.width(), s.height(), use_gravity, force ); } inline bool Client::hasUserTimeSupport() const diff --git a/geometry.cpp b/geometry.cpp index 00f8eb9269..d75cc8a3fb 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 ); + resize( new_size, UseGravity ); } updateAllowedActions(); // affects isResizeable() } @@ -786,6 +786,7 @@ const QPoint Client::calculateGravitation( bool invert, int gravity ) const switch (gravity) { case NorthWestGravity: // move down right + default: dx = border_left; dy = border_top; break; @@ -849,24 +850,13 @@ void Client::configureRequest( int value_mask, int rx, int ry, int rw, int rh, i if ( isShade()) // SELI SHADE setShade( ShadeNone ); - int ox = 0; - int oy = 0; - // GRAVITATE - if ( gravity == StaticGravity ) - { // only with StaticGravity according to ICCCM 4.1.5 - ox = clientPos().x(); - oy = clientPos().y(); - } - - int nx = x() + ox; - int ny = y() + oy; - + QPoint new_pos = calculateGravitation( true, gravity ); // undo gravitation if ( value_mask & CWX ) - nx = rx; + new_pos.setX( rx ); if ( value_mask & CWY ) - ny = ry; - + new_pos.setY( ry ); +#if 0 /* let's see how well things will work without trying to be clever */ // clever workaround for applications like xv that want to set // the location to the current location but miscalculate the // frame size due to kwin being a double-reparenting window @@ -878,33 +868,31 @@ void Client::configureRequest( int value_mask, int rx, int ry, int rw, int rh, i nx = x(); ny = y(); } - - - QPoint np( nx-ox, ny-oy); -#if 0 - if ( windowType() == NET::Normal && isMovable()) - { - // crap for broken netscape - QRect area = workspace()->clientArea(); - if ( !area.contains( np ) && width() < area.width() && - height() < area.height() ) - { - if ( np.x() < area.x() ) - np.rx() = area.x(); - if ( np.y() < area.y() ) - np.ry() = area.y(); - } - } #endif - if ( maximizeMode() != MaximizeFull ) + int nw = clientSize().width(); + int nh = clientSize().height(); + if ( value_mask & CWWidth ) + nw = rw; + if ( value_mask & CWHeight ) + nh = rh; + QSize ns = sizeForClientSize( QSize( nw, nh ) ); + + // TODO what to do with maximized windows? + if ( maximizeMode() != MaximizeFull + || ns != size()) { resetMaximize(); - move( np ); + ++block_geometry; + move( new_pos ); + resize( ns, IgnoreGravity ); // TODO must(?) resize before gravitating? + --block_geometry; + setGeometry( QRect( calculateGravitation( false, gravity ), size()), ForceGeometrySet ); } } - if ( value_mask & (CWWidth | CWHeight ) ) + if ( value_mask & (CWWidth | CWHeight ) + && ! ( value_mask & ( CWX | CWY )) ) // pure resize { int nw = clientSize().width(); int nh = clientSize().height(); @@ -913,25 +901,65 @@ void Client::configureRequest( int value_mask, int rx, int ry, int rw, int rh, i if ( value_mask & CWHeight ) nh = rh; QSize ns = sizeForClientSize( QSize( nw, nh ) ); - - //QRect area = workspace()->clientArea(); - if ( maximizeMode() != MaximizeRestore ) - { //&& ( ns.width() < area.width() || ns.height() < area.height() ) ) { - if( ns != size()) - { // don't restore if some app sets its own size again - resetMaximize(); - resize( ns ); - } - } - else + + if( ns != size()) // don't restore if some app sets its own size again { - if ( ns == size() ) - return; // broken xemacs stuff (ediff) - resize( ns ); + resetMaximize(); + int save_gravity = xSizeHint.win_gravity; + xSizeHint.win_gravity = gravity; + resize( ns, UseGravity ); + xSizeHint.win_gravity = save_gravity; } } + // No need to send synthetic configure notify event here, either it's sent together + // with geometry change, or there's no need to send it. + // Handling of the real ConfigureRequest event forces sending it, as there it's necessary. } +void Client::resizeWithGravity( int w, int h, ForceGeometry_t force ) + { + int newx = x(); + int newy = y(); + switch( xSizeHint.win_gravity ) + { + case NorthWestGravity: // top left corner doesn't move + default: + break; + case NorthGravity: // middle of top border doesn't move + newx = ( newx + width() / 2 ) - ( w / 2 ); + break; + case NorthEastGravity: // top right corner doesn't move + newx = newx + width() - w; + break; + case WestGravity: // middle of left border doesn't move + newy = ( newy + height() / 2 ) - ( h / 2 ); + break; + case CenterGravity: // middle point doesn't move + newx = ( newx + width() / 2 ) - ( w / 2 ); + newy = ( newy + height() / 2 ) - ( h / 2 ); + break; + case StaticGravity: // top left corner of _client_ window doesn't move + // since decoration doesn't change, equal to NorthWestGravity + break; + case EastGravity: // // middle of right border doesn't move + newx = newx + width() - w; + newy = ( newy + height() / 2 ) - ( h / 2 ); + break; + case SouthWestGravity: // bottom left corner doesn't move + newy = newy + height() - h; + break; + case SouthGravity: // middle of bottom border doesn't move + newx = ( newx + width() / 2 ) - ( w / 2 ); + newy = newy + height() - h; + break; + case SouthEastGravity: // bottom right corner doesn't move + newx = newx + width() - w; + newy = newy + height() - h; + break; + } + setGeometry( newx, newy, w, h, force ); + } + // _NET_MOVERESIZE_WINDOW void Client::NETMoveResizeWindow( int flags, int x, int y, int width, int height ) { @@ -980,9 +1008,9 @@ bool Client::isMaximizable() const /*! Reimplemented to inform the client about the new window position. */ -void Client::setGeometry( int x, int y, int w, int h, bool force ) +void Client::setGeometry( int x, int y, int w, int h, ForceGeometry_t force ) { - if( !force && frame_geometry == QRect( x, y, w, h )) + if( force == NormalGeometrySet && frame_geometry == QRect( x, y, w, h )) return; frame_geometry = QRect( x, y, w, h ); if( !isShade()) @@ -1019,10 +1047,15 @@ void Client::setGeometry( int x, int y, int w, int h, bool force ) } } -void Client::resize( int w, int h, bool force ) +void Client::resize( int w, int h, UseGravity_t use_gravity, ForceGeometry_t force ) { // TODO make this deffered with isResize() ? old kwin did - if( !force && frame_geometry.size() == QSize( w, h )) + 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 ); @@ -1056,9 +1089,9 @@ void Client::resize( int w, int h, bool force ) /*! Reimplemented to inform the client about the new window position. */ -void Client::move( int x, int y, bool force ) +void Client::move( int x, int y, ForceGeometry_t force ) { - if( !force && frame_geometry.topLeft() == QPoint( x, y )) + if( force == NormalGeometrySet && frame_geometry.topLeft() == QPoint( x, y )) return; frame_geometry.moveTopLeft( QPoint( x, y )); updateWorkareaDiffs(); @@ -1148,7 +1181,7 @@ void Client::changeMaximize( bool vertical, bool horizontal, bool adjust ) { if( geom_restore.width() == 0 ) { // needs placement - resize( adjustedSize(QSize(width(), clientArea.height()))); + resize( adjustedSize(QSize(width(), clientArea.height())), IgnoreGravity ); workspace()->placeSmart( this ); } else @@ -1168,7 +1201,7 @@ void Client::changeMaximize( bool vertical, bool horizontal, bool adjust ) { if( geom_restore.height() == 0 ) { // needs placement - resize( adjustedSize(QSize(clientArea.width(), height()))); + resize( adjustedSize(QSize(clientArea.width(), height())), IgnoreGravity ); workspace()->placeSmart( this ); } else @@ -1192,7 +1225,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 )); + resize( adjustedSize( s ), IgnoreGravity ); workspace()->placeSmart( this ); restore = geometry(); if( geom_restore.width() > 0 ) @@ -1229,7 +1262,7 @@ void Client::changeMaximize( bool vertical, bool horizontal, bool adjust ) } --block_geometry; - setGeometry( geometry(), true ); + setGeometry( geometry(), ForceGeometrySet ); updateAllowedActions(); if( decoration != NULL ) @@ -1238,6 +1271,8 @@ void Client::changeMaximize( bool vertical, bool horizontal, bool adjust ) void Client::resetMaximize() { + if( max_mode == MaximizeRestore ) + return; max_mode = MaximizeRestore; Notify::raise( Notify::UnMaximize ); info->setState( 0, NET::Max ); diff --git a/manage.cpp b/manage.cpp index b19b052c70..fb56bcecb3 100644 --- a/manage.cpp +++ b/manage.cpp @@ -280,7 +280,8 @@ bool Client::manage( Window w, bool isMapped ) move( geom.x(), geom.y() ); // before gravitating updateDecoration( false ); // also gravitates - resize ( sizeForClientSize( geom.size() ) ); + // TODO is CentralGravity right here, when resizing is done after gravitating? + resize( sizeForClientSize( geom.size() ), IgnoreGravity ); if( !placementDone ) { // placement needs to be after setting size diff --git a/tools/test_gravity.cpp b/tools/test_gravity.cpp index 573721f1d4..618023b5f7 100644 --- a/tools/test_gravity.cpp +++ b/tools/test_gravity.cpp @@ -1,7 +1,5 @@ // tests for window gravity -#define INITIAL_POSITION_TEST - #include #include #include @@ -41,7 +39,7 @@ int get_gravity( const char* name ) exit( 1 ); } -void initial_position_test( const char* gravity ) +void test( const char* gravity ) { XSetWindowAttributes attrs; XSizeHints hints; @@ -50,7 +48,7 @@ void initial_position_test( const char* gravity ) Window w = XCreateWindow( dpy, DefaultRootWindow( dpy ), 100, 100, 200, 100, 0, CopyFromParent, CopyFromParent, CopyFromParent, 0, &attrs ); XSetWMNormalHints( dpy, w, &hints ); - XSelectInput( dpy, w, StructureNotifyMask ); + XSelectInput( dpy, w, StructureNotifyMask | ButtonPressMask ); XMapWindow( dpy, w ); for(;;) { @@ -67,19 +65,35 @@ void initial_position_test( const char* gravity ) XTranslateCoordinates( dpy, w, root, 0, 0, &x, &y, &child ); cout << "GEOMETRY:" << x << ":" << y << ":" << width << ":" << height << ":(" << x_local << ":" << y_local << ")" << endl; } + else if( ev.type == ButtonPress ) + { + if( ev.xbutton.button == Button1 ) // move + { + cout << "MOVE" << endl; + XMoveWindow( dpy, w, 100, 100 ); + } + else if( ev.xbutton.button == Button2 ) // resize + { + cout << "RESIZE" << endl; + XResizeWindow( dpy, w, 200, 100 ); + } + else if( ev.xbutton.button == Button3 ) // move and resize + { + cout << "MOVERESIZE" << endl; + XMoveResizeWindow( dpy, w, 100, 100, 200, 100 ); + } + } } } int main( int argc, char* argv[] ) { dpy = XOpenDisplay( NULL ); -#ifdef INITIAL_POSITION_TEST if( argc != 2 ) { cerr << "specify gravity" << endl; exit( 1 ); } - initial_position_test( argv[ 1 ] ); -#endif + test( argv[ 1 ] ); XCloseDisplay( dpy ); } diff --git a/utils.h b/utils.h index 2842debc53..00216fdb60 100644 --- a/utils.h +++ b/utils.h @@ -72,6 +72,10 @@ inline void operator++( Layer& lay ) // as an argument to any function, make sure you really know what you're doing. 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 { public: