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
This commit is contained in:
Luboš Luňák 2003-10-01 12:10:22 +00:00
parent 6b3d8e134a
commit bd4789e32b
6 changed files with 144 additions and 89 deletions

View file

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

View file

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

View file

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

View file

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

View file

@ -1,7 +1,5 @@
// tests for window gravity
#define INITIAL_POSITION_TEST
#include <iostream>
#include <stdlib.h>
#include <X11/Xlib.h>
@ -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 );
}

View file

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