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:
parent
6b3d8e134a
commit
bd4789e32b
6 changed files with 144 additions and 89 deletions
22
client.cpp
22
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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
21
client.h
21
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
|
||||
|
|
155
geometry.cpp
155
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 );
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
4
utils.h
4
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:
|
||||
|
|
Loading…
Reference in a new issue