window: Move adjust_for_gravity to window-x11

This removes the weirdness about which edge cases are where in the
move_resize_internal API, and we now always pass in client top-left
coordinates.
This commit is contained in:
Jasper St. Pierre 2014-05-01 17:39:25 -04:00
parent 4c21a46452
commit acb3dc6754
3 changed files with 169 additions and 203 deletions

View File

@ -74,11 +74,10 @@ typedef enum {
typedef enum
{
META_IS_CONFIGURE_REQUEST = 1 << 0,
META_DO_GRAVITY_ADJUST = 1 << 1,
META_IS_USER_ACTION = 1 << 2,
META_IS_MOVE_ACTION = 1 << 3,
META_IS_RESIZE_ACTION = 1 << 4,
META_IS_WAYLAND_RESIZE = 1 << 5
META_IS_USER_ACTION = 1 << 1,
META_IS_MOVE_ACTION = 1 << 2,
META_IS_RESIZE_ACTION = 1 << 3,
META_IS_WAYLAND_RESIZE = 1 << 4,
} MetaMoveResizeFlags;
typedef enum

View File

@ -3625,121 +3625,6 @@ meta_window_activate_with_workspace (MetaWindow *window,
meta_window_activate_full (window, timestamp, META_CLIENT_TYPE_APPLICATION, workspace);
}
/* Manually fix all the weirdness explained in the big comment at the
* beginning of meta_window_move_resize_internal() giving positions
* expected by meta_window_constrain (i.e. positions & sizes of the
* internal or client window).
*/
static void
adjust_for_gravity (MetaWindow *window,
gboolean coords_assume_border,
int gravity,
MetaRectangle *rect)
{
int ref_x, ref_y;
int bw;
int child_x, child_y;
int frame_width, frame_height;
MetaFrameBorders borders;
if (coords_assume_border)
bw = window->border_width;
else
bw = 0;
meta_frame_calc_borders (window->frame, &borders);
child_x = borders.visible.left;
child_y = borders.visible.top;
frame_width = child_x + rect->width + borders.visible.right;
frame_height = child_y + rect->height + borders.visible.bottom;
/* We're computing position to pass to window_move, which is
* the position of the client window (StaticGravity basically)
*
* (see WM spec description of gravity computation, but note that
* their formulas assume we're honoring the border width, rather
* than compensating for having turned it off)
*/
/* Calculate the the reference point, which is the corner of the
* outer window specified by the gravity. So, NorthEastGravity
* would have the reference point as the top-right corner of the
* outer window. */
ref_x = rect->x;
ref_y = rect->y;
switch (gravity)
{
case NorthGravity:
case CenterGravity:
case SouthGravity:
ref_x += rect->width / 2 + bw;
break;
case NorthEastGravity:
case EastGravity:
case SouthEastGravity:
ref_x += rect->width + bw * 2;
break;
default:
break;
}
switch (gravity)
{
case WestGravity:
case CenterGravity:
case EastGravity:
ref_y += rect->height / 2 + bw;
break;
case SouthWestGravity:
case SouthGravity:
case SouthEastGravity:
ref_y += rect->height + bw * 2;
break;
default:
break;
}
/* Find the top-left corner of the outer window from
* the reference point. */
rect->x = ref_x;
rect->y = ref_y;
switch (gravity)
{
case NorthGravity:
case CenterGravity:
case SouthGravity:
rect->x -= frame_width / 2;
break;
case NorthEastGravity:
case EastGravity:
case SouthEastGravity:
rect->x -= frame_width;
break;
}
switch (gravity)
{
case WestGravity:
case CenterGravity:
case EastGravity:
rect->y -= frame_height / 2;
break;
case SouthWestGravity:
case SouthGravity:
case SouthEastGravity:
rect->y -= frame_height;
break;
}
/* Adjust to get the top-left corner of the inner window. */
rect->x += child_x;
rect->y += child_y;
}
/**
* meta_window_updates_are_frozen:
* @window: a #MetaWindow
@ -3889,46 +3774,14 @@ meta_window_move_resize_internal (MetaWindow *window,
int w,
int h)
{
/* meta_window_move_resize_internal gets called with very different
* meanings for root_x_nw and root_y_nw. w & h are always the area
* of the inner or client window (i.e. excluding the frame) and
* gravity is the relevant gravity associated with the request (note
* that gravity is ignored for move-only operations unless its
* e.g. a configure request). The location is different for
* different cases because of how this function gets called; note
* that in all cases what we want to find out is the upper left
* corner of the position of the inner window:
/* The rectangle here that's passed in is always the root position
* of the client window. For undecorated or client-decorated windows,
* this is the root position of the X11 window. For server-decorated
* windows, this is the root position of the client area of the window.
*
* Case | Called from (flags; gravity)
* -----+-----------------------------------------------
* 1 | A resize only ConfigureRequest
* 1 | meta_window_resize
* 1 | meta_window_resize_with_gravity
* 2 | New window
* 2 | Session restore
* 2 | A not-resize-only ConfigureRequest/net_moveresize_window request
* 3 | meta_window_move
* 3 | meta_window_move_resize
* 4 | meta_window_move_resize_wayland
*
* For each of the cases, root_x_nw and root_y_nw must be treated as follows:
*
* (1) They should be entirely ignored; instead the previous position
* and size of the window should be resized according to the given
* gravity in order to determine the new position of the window.
* (2) Needs to be fixed up by adjust_for_gravity() as these
* coordinates are relative to some corner or side of the outer
* window (except for the case of StaticGravity) and we want to
* know the location of the upper left corner of the inner window.
* (3) These values are already the desired position of the NW corner
* of the inner window
* (4) These values are already the desired position of the NW corner
* of the inner window (which is also the outer window, because
* we don't decorate wayland clients), and the client has acknowledged
* the window size change.
* Similarly, the width and height passed in are in client window
* coordinates as well.
*/
gboolean is_configure_request;
gboolean do_gravity_adjust;
gboolean is_user_action;
gboolean did_placement;
/* used for the configure request, but may not be final
@ -3941,8 +3794,6 @@ meta_window_move_resize_internal (MetaWindow *window,
g_return_if_fail (!window->override_redirect);
is_configure_request = (flags & META_IS_CONFIGURE_REQUEST) != 0;
do_gravity_adjust = (flags & META_DO_GRAVITY_ADJUST) != 0;
is_user_action = (flags & META_IS_USER_ACTION) != 0;
/* The action has to be a move, a resize or the wayland client
@ -3956,9 +3807,8 @@ meta_window_move_resize_internal (MetaWindow *window,
meta_window_get_client_root_coords (window, &old_rect);
meta_topic (META_DEBUG_GEOMETRY,
"Move/resize %s to %d,%d %dx%d%s%s from %d,%d %dx%d\n",
"Move/resize %s to %d,%d %dx%d%s from %d,%d %dx%d\n",
window->desc, root_x_nw, root_y_nw, w, h,
is_configure_request ? " (configure request)" : "",
is_user_action ? " (user move/resize)" : "",
old_rect.x, old_rect.y, old_rect.width, old_rect.height);
@ -3986,21 +3836,6 @@ meta_window_move_resize_internal (MetaWindow *window,
"Compensated for gravity in resize action; new pos %d,%d\n",
new_rect.x, new_rect.y);
}
else if (is_configure_request || do_gravity_adjust)
{
adjust_for_gravity (window,
/* configure request coords assume
* the border width existed
*/
is_configure_request,
gravity,
&new_rect);
meta_topic (META_DEBUG_GEOMETRY,
"Compensated for configure_request/do_gravity_adjust needing "
"weird positioning; new pos %d,%d\n",
new_rect.x, new_rect.y);
}
did_placement = !window->placed && window->calc_placement;

View File

@ -250,6 +250,116 @@ send_configure_notify (MetaWindow *window)
meta_error_trap_pop (window->display);
}
static void
adjust_for_gravity (MetaWindow *window,
gboolean coords_assume_border,
int gravity,
MetaRectangle *rect)
{
int ref_x, ref_y;
int bw;
int child_x, child_y;
int frame_width, frame_height;
MetaFrameBorders borders;
if (coords_assume_border)
bw = window->border_width;
else
bw = 0;
meta_frame_calc_borders (window->frame, &borders);
child_x = borders.visible.left;
child_y = borders.visible.top;
frame_width = child_x + rect->width + borders.visible.right;
frame_height = child_y + rect->height + borders.visible.bottom;
/* We're computing position to pass to window_move, which is
* the position of the client window (StaticGravity basically)
*
* (see WM spec description of gravity computation, but note that
* their formulas assume we're honoring the border width, rather
* than compensating for having turned it off)
*/
/* Calculate the the reference point, which is the corner of the
* outer window specified by the gravity. So, NorthEastGravity
* would have the reference point as the top-right corner of the
* outer window. */
ref_x = rect->x;
ref_y = rect->y;
switch (gravity)
{
case NorthGravity:
case CenterGravity:
case SouthGravity:
ref_x += rect->width / 2 + bw;
break;
case NorthEastGravity:
case EastGravity:
case SouthEastGravity:
ref_x += rect->width + bw * 2;
break;
default:
break;
}
switch (gravity)
{
case WestGravity:
case CenterGravity:
case EastGravity:
ref_y += rect->height / 2 + bw;
break;
case SouthWestGravity:
case SouthGravity:
case SouthEastGravity:
ref_y += rect->height + bw * 2;
break;
default:
break;
}
/* Find the top-left corner of the outer window from
* the reference point. */
rect->x = ref_x;
rect->y = ref_y;
switch (gravity)
{
case NorthGravity:
case CenterGravity:
case SouthGravity:
rect->x -= frame_width / 2;
break;
case NorthEastGravity:
case EastGravity:
case SouthEastGravity:
rect->x -= frame_width;
break;
}
switch (gravity)
{
case WestGravity:
case CenterGravity:
case EastGravity:
rect->y -= frame_height / 2;
break;
case SouthWestGravity:
case SouthGravity:
case SouthEastGravity:
rect->y -= frame_height;
break;
}
/* Adjust to get the top-left corner of the inner window. */
rect->x += child_x;
rect->y += child_y;
}
static void
meta_window_apply_session_info (MetaWindow *window,
const MetaWindowSessionInfo *info)
@ -359,31 +469,31 @@ meta_window_apply_session_info (MetaWindow *window,
if (info->geometry_set)
{
int x, y, w, h;
MetaRectangle rect;
MetaMoveResizeFlags flags;
window->placed = TRUE; /* don't do placement algorithms later */
x = info->rect.x;
y = info->rect.y;
rect.x = info->rect.x;
rect.y = info->rect.y;
w = window->size_hints.base_width +
info->rect.width * window->size_hints.width_inc;
h = window->size_hints.base_height +
info->rect.height * window->size_hints.height_inc;
rect.width = window->size_hints.base_width + info->rect.width * window->size_hints.width_inc;
rect.height = window->size_hints.base_height + info->rect.height * window->size_hints.height_inc;
/* Force old gravity, ignoring anything now set */
window->size_hints.win_gravity = info->gravity;
meta_topic (META_DEBUG_SM,
"Restoring pos %d,%d size %d x %d for %s\n",
x, y, w, h, window->desc);
flags = META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION;
adjust_for_gravity (window,
FALSE,
window->size_hints.win_gravity,
&rect);
flags = META_DO_GRAVITY_ADJUST | META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION;
meta_window_move_resize_internal (window,
flags,
window->size_hints.win_gravity,
x, y, w, h);
rect.x, rect.y, rect.width, rect.height);
}
}
@ -428,13 +538,24 @@ meta_window_x11_manage (MetaWindow *window)
*/
flags = META_IS_CONFIGURE_REQUEST | META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION;
if (!window->override_redirect)
{
MetaRectangle rect;
rect.x = window->size_hints.x;
rect.y = window->size_hints.y;
rect.width = window->size_hints.width;
rect.height = window->size_hints.height;
adjust_for_gravity (window,
TRUE,
window->size_hints.win_gravity,
&rect);
meta_window_move_resize_internal (window,
flags,
window->size_hints.win_gravity,
window->size_hints.x,
window->size_hints.y,
window->size_hints.width,
window->size_hints.height);
rect.x, rect.y, rect.width, rect.height);
}
}
static void
@ -1958,13 +2079,24 @@ meta_window_move_resize_request (MetaWindow *window,
flags |= META_IS_RESIZE_ACTION;
if (flags & (META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION))
{
MetaRectangle rect;
rect.x = x;
rect.y = y;
rect.width = width;
rect.height = height;
adjust_for_gravity (window,
TRUE,
window->size_hints.win_gravity,
&rect);
meta_window_move_resize_internal (window,
flags,
gravity,
x,
y,
width,
height);
rect.x, rect.y, rect.width, rect.height);
}
/* window->user_rect exists to allow "snapping-back" the window if a
* new strut is set (causing the window to move) and then the strut