constraints: Pass constrained relative coordinates to window impl

A placement rule placed window positions itself relative to its parent,
thus converting between relative coordinates to absolute coordinates,
then back to relative coordinates implies unwanted restrictions for
example when the absolute coordinate should not be calculated againts
the current parent window position.

Deal with this by keeping track of the relative position all the way
from the constraining engine to the move-resize window implementation.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/705
This commit is contained in:
Jonas Ådahl 2020-02-14 08:52:48 +01:00 committed by Carlos Garnacho
parent 05e9d6ab9e
commit ff381d1d52
6 changed files with 86 additions and 23 deletions

View File

@ -123,6 +123,8 @@ typedef struct
{ {
MetaRectangle orig; MetaRectangle orig;
MetaRectangle current; MetaRectangle current;
int rel_x;
int rel_y;
ActionType action_type; ActionType action_type;
gboolean is_user_action; gboolean is_user_action;
@ -281,7 +283,9 @@ meta_window_constrain (MetaWindow *window,
MetaMoveResizeFlags flags, MetaMoveResizeFlags flags,
int resize_gravity, int resize_gravity,
const MetaRectangle *orig, const MetaRectangle *orig,
MetaRectangle *new) MetaRectangle *new,
int *rel_x,
int *rel_y)
{ {
ConstraintInfo info; ConstraintInfo info;
ConstraintPriority priority = PRIORITY_MINIMUM; ConstraintPriority priority = PRIORITY_MINIMUM;
@ -318,6 +322,8 @@ meta_window_constrain (MetaWindow *window,
/* Make sure we use the constrained position */ /* Make sure we use the constrained position */
*new = info.current; *new = info.current;
*rel_x = info.rel_x;
*rel_y = info.rel_y;
/* We may need to update window->require_fully_onscreen, /* We may need to update window->require_fully_onscreen,
* window->require_on_single_monitor, and perhaps other quantities * window->require_on_single_monitor, and perhaps other quantities
@ -342,6 +348,8 @@ setup_constraint_info (ConstraintInfo *info,
info->orig = *orig; info->orig = *orig;
info->current = *new; info->current = *new;
info->rel_x = 0;
info->rel_y = 0;
if (info->current.width < 1) if (info->current.width < 1)
info->current.width = 1; info->current.width = 1;
@ -494,15 +502,14 @@ place_window_if_needed(MetaWindow *window,
{ {
MetaWindow *parent = meta_window_get_transient_for (window); MetaWindow *parent = meta_window_get_transient_for (window);
MetaRectangle parent_rect; MetaRectangle parent_rect;
int rel_x, rel_y;
meta_window_process_placement (window, meta_window_process_placement (window,
window->placement.rule, window->placement.rule,
&rel_x, &rel_y); &info->rel_x, &info->rel_y);
meta_window_get_frame_rect (parent, &parent_rect); meta_window_get_frame_rect (parent, &parent_rect);
placed_rect.x = parent_rect.x + rel_x; placed_rect.x = parent_rect.x + info->rel_x;
placed_rect.y = parent_rect.y + rel_y; placed_rect.y = parent_rect.y + info->rel_y;
} }
else else
{ {
@ -745,6 +752,8 @@ try_flip_window_position (MetaWindow *window,
int parent_x, int parent_x,
int parent_y, int parent_y,
MetaRectangle *rect, MetaRectangle *rect,
int *rel_x,
int *rel_y,
MetaRectangle *intersection) MetaRectangle *intersection)
{ {
MetaPlacementRule flipped_rule = *placement_rule;; MetaPlacementRule flipped_rule = *placement_rule;;
@ -781,6 +790,8 @@ try_flip_window_position (MetaWindow *window,
{ {
*placement_rule = flipped_rule; *placement_rule = flipped_rule;
*rect = flipped_rect; *rect = flipped_rect;
*rel_x = flipped_rel_x;
*rel_y = flipped_rel_y;
*intersection = flipped_intersection; *intersection = flipped_intersection;
} }
} }
@ -815,6 +826,8 @@ constrain_custom_rule (MetaWindow *window,
MetaRectangle intersection; MetaRectangle intersection;
gboolean constraint_satisfied; gboolean constraint_satisfied;
MetaRectangle adjusted_unconstrained; MetaRectangle adjusted_unconstrained;
int adjusted_rel_x;
int adjusted_rel_y;
MetaPlacementRule current_rule; MetaPlacementRule current_rule;
MetaWindow *parent; MetaWindow *parent;
MetaRectangle parent_rect; MetaRectangle parent_rect;
@ -834,12 +847,16 @@ constrain_custom_rule (MetaWindow *window,
switch (window->placement.state) switch (window->placement.state)
{ {
case META_PLACEMENT_STATE_UNCONSTRAINED: case META_PLACEMENT_STATE_UNCONSTRAINED:
adjusted_rel_x = window->rect.x - parent->rect.x;
adjusted_rel_y = window->rect.y - parent->rect.y;
break; break;
case META_PLACEMENT_STATE_CONSTRAINED: case META_PLACEMENT_STATE_CONSTRAINED:
adjusted_unconstrained.x = adjusted_unconstrained.x =
parent->rect.x + window->placement.current.rel_x; parent->rect.x + window->placement.current.rel_x;
adjusted_unconstrained.y = adjusted_unconstrained.y =
parent->rect.y + window->placement.current.rel_y; parent->rect.y + window->placement.current.rel_y;
adjusted_rel_x = window->placement.current.rel_x;
adjusted_rel_y = window->placement.current.rel_y;
break; break;
} }
@ -861,6 +878,8 @@ constrain_custom_rule (MetaWindow *window,
{ {
case META_PLACEMENT_STATE_CONSTRAINED: case META_PLACEMENT_STATE_CONSTRAINED:
info->current = adjusted_unconstrained; info->current = adjusted_unconstrained;
info->rel_x = adjusted_rel_x;
info->rel_y = adjusted_rel_y;
goto done; goto done;
case META_PLACEMENT_STATE_UNCONSTRAINED: case META_PLACEMENT_STATE_UNCONSTRAINED:
break; break;
@ -878,6 +897,8 @@ constrain_custom_rule (MetaWindow *window,
parent_rect.x, parent_rect.x,
parent_rect.y, parent_rect.y,
&info->current, &info->current,
&info->rel_x,
&info->rel_y,
&intersection); &intersection);
} }
if (info->current.height != intersection.height && if (info->current.height != intersection.height &&
@ -889,6 +910,8 @@ constrain_custom_rule (MetaWindow *window,
parent_rect.x, parent_rect.x,
parent_rect.y, parent_rect.y,
&info->current, &info->current,
&info->rel_x,
&info->rel_y,
&intersection); &intersection);
} }
@ -906,6 +929,7 @@ constrain_custom_rule (MetaWindow *window,
{ {
int current_x2; int current_x2;
int work_area_monitor_x2; int work_area_monitor_x2;
int new_x;
current_x2 = info->current.x + info->current.width; current_x2 = info->current.x + info->current.width;
work_area_monitor_x2 = (info->work_area_monitor.x + work_area_monitor_x2 = (info->work_area_monitor.x +
@ -913,19 +937,27 @@ constrain_custom_rule (MetaWindow *window,
if (current_x2 > work_area_monitor_x2) if (current_x2 > work_area_monitor_x2)
{ {
info->current.x = MAX (info->work_area_monitor.x, new_x = MAX (info->work_area_monitor.x,
work_area_monitor_x2 - info->current.width); work_area_monitor_x2 - info->current.width);
} }
else if (info->current.x < info->work_area_monitor.x) else if (info->current.x < info->work_area_monitor.x)
{ {
info->current.x = info->work_area_monitor.x; new_x = info->work_area_monitor.x;
} }
else
{
new_x = info->current.x;
}
info->rel_x += new_x - info->current.x;
info->current.x = new_x;
} }
if (current_rule.constraint_adjustment & if (current_rule.constraint_adjustment &
META_PLACEMENT_CONSTRAINT_ADJUSTMENT_SLIDE_Y) META_PLACEMENT_CONSTRAINT_ADJUSTMENT_SLIDE_Y)
{ {
int current_y2; int current_y2;
int work_area_monitor_y2; int work_area_monitor_y2;
int new_y;
current_y2 = info->current.y + info->current.height; current_y2 = info->current.y + info->current.height;
work_area_monitor_y2 = (info->work_area_monitor.y + work_area_monitor_y2 = (info->work_area_monitor.y +
@ -933,13 +965,20 @@ constrain_custom_rule (MetaWindow *window,
if (current_y2 > work_area_monitor_y2) if (current_y2 > work_area_monitor_y2)
{ {
info->current.y = MAX (info->work_area_monitor.y, new_y = MAX (info->work_area_monitor.y,
work_area_monitor_y2 - info->current.height); work_area_monitor_y2 - info->current.height);
} }
else if (info->current.y < info->work_area_monitor.y) else if (info->current.y < info->work_area_monitor.y)
{ {
info->current.y = info->work_area_monitor.y; new_y = info->work_area_monitor.y;
} }
else
{
new_y = info->current.y;
}
info->rel_y += new_y - info->current.y;
info->current.y = new_y;
} }
meta_rectangle_intersect (&info->current, &info->work_area_monitor, meta_rectangle_intersect (&info->current, &info->work_area_monitor,
@ -954,21 +993,27 @@ constrain_custom_rule (MetaWindow *window,
if (current_rule.constraint_adjustment & if (current_rule.constraint_adjustment &
META_PLACEMENT_CONSTRAINT_ADJUSTMENT_RESIZE_X) META_PLACEMENT_CONSTRAINT_ADJUSTMENT_RESIZE_X)
{ {
info->current.x = intersection.x; int new_x;
new_x = intersection.x;
info->current.width = intersection.width; info->current.width = intersection.width;
info->rel_x += new_x - info->current.x;
info->current.x = new_x;
} }
if (current_rule.constraint_adjustment & if (current_rule.constraint_adjustment &
META_PLACEMENT_CONSTRAINT_ADJUSTMENT_RESIZE_Y) META_PLACEMENT_CONSTRAINT_ADJUSTMENT_RESIZE_Y)
{ {
info->current.y = intersection.y; int new_y;
new_y = intersection.y;
info->current.height = intersection.height; info->current.height = intersection.height;
info->rel_y += new_y - info->current.y;
info->current.y = new_y;
} }
done: done:
window->placement.state = META_PLACEMENT_STATE_CONSTRAINED; window->placement.state = META_PLACEMENT_STATE_CONSTRAINED;
window->placement.current.rel_x = info->current.x - parent_rect.x; window->placement.current.rel_x = info->rel_x;
window->placement.current.rel_y = info->current.y - parent_rect.y; window->placement.current.rel_y = info->rel_y;
return TRUE; return TRUE;
} }

View File

@ -31,6 +31,8 @@ void meta_window_constrain (MetaWindow *window,
MetaMoveResizeFlags flags, MetaMoveResizeFlags flags,
int resize_gravity, int resize_gravity,
const MetaRectangle *orig, const MetaRectangle *orig,
MetaRectangle *new); MetaRectangle *new,
int *rel_x,
int *rel_y);
#endif /* META_CONSTRAINTS_H */ #endif /* META_CONSTRAINTS_H */

View File

@ -569,6 +569,8 @@ struct _MetaWindowClass
int gravity, int gravity,
MetaRectangle unconstrained_rect, MetaRectangle unconstrained_rect,
MetaRectangle constrained_rect, MetaRectangle constrained_rect,
int rel_x,
int rel_y,
MetaMoveResizeFlags flags, MetaMoveResizeFlags flags,
MetaMoveResizeResultFlags *result); MetaMoveResizeResultFlags *result);
gboolean (*update_struts) (MetaWindow *window); gboolean (*update_struts) (MetaWindow *window);

View File

@ -4001,6 +4001,8 @@ meta_window_move_resize_internal (MetaWindow *window,
gboolean did_placement; gboolean did_placement;
MetaRectangle unconstrained_rect; MetaRectangle unconstrained_rect;
MetaRectangle constrained_rect; MetaRectangle constrained_rect;
int rel_x = 0;
int rel_y = 0;
MetaMoveResizeResultFlags result = 0; MetaMoveResizeResultFlags result = 0;
gboolean moved_or_resized = FALSE; gboolean moved_or_resized = FALSE;
MetaWindowUpdateMonitorFlags update_monitor_flags; MetaWindowUpdateMonitorFlags update_monitor_flags;
@ -4066,7 +4068,14 @@ meta_window_move_resize_internal (MetaWindow *window,
flags, flags,
gravity, gravity,
&old_rect, &old_rect,
&constrained_rect); &constrained_rect,
&rel_x,
&rel_y);
}
else if (window->placement.rule)
{
rel_x = window->placement.current.rel_x;
rel_y = window->placement.current.rel_y;
} }
/* If we did placement, then we need to save the position that the window /* If we did placement, then we need to save the position that the window
@ -4080,7 +4089,13 @@ meta_window_move_resize_internal (MetaWindow *window,
} }
/* Do the protocol-specific move/resize logic */ /* Do the protocol-specific move/resize logic */
META_WINDOW_GET_CLASS (window)->move_resize_internal (window, gravity, unconstrained_rect, constrained_rect, flags, &result); META_WINDOW_GET_CLASS (window)->move_resize_internal (window,
gravity,
unconstrained_rect,
constrained_rect,
rel_x,
rel_y,
flags, &result);
if (result & META_MOVE_RESIZE_RESULT_MOVED) if (result & META_MOVE_RESIZE_RESULT_MOVED)
{ {

View File

@ -220,6 +220,8 @@ meta_window_wayland_move_resize_internal (MetaWindow *window,
int gravity, int gravity,
MetaRectangle unconstrained_rect, MetaRectangle unconstrained_rect,
MetaRectangle constrained_rect, MetaRectangle constrained_rect,
int rel_x,
int rel_y,
MetaMoveResizeFlags flags, MetaMoveResizeFlags flags,
MetaMoveResizeResultFlags *result) MetaMoveResizeResultFlags *result)
{ {
@ -326,11 +328,6 @@ meta_window_wayland_move_resize_internal (MetaWindow *window,
if (window->placement.rule) if (window->placement.rule)
{ {
MetaWindow *parent = meta_window_get_transient_for (window);
int rel_x, rel_y;
rel_x = configured_x - parent->rect.x;
rel_y = configured_y - parent->rect.y;
configuration = configuration =
meta_wayland_window_configuration_new_relative (rel_x, meta_wayland_window_configuration_new_relative (rel_x,
rel_y, rel_y,

View File

@ -1308,6 +1308,8 @@ meta_window_x11_move_resize_internal (MetaWindow *window,
int gravity, int gravity,
MetaRectangle unconstrained_rect, MetaRectangle unconstrained_rect,
MetaRectangle constrained_rect, MetaRectangle constrained_rect,
int rel_x,
int rel_y,
MetaMoveResizeFlags flags, MetaMoveResizeFlags flags,
MetaMoveResizeResultFlags *result) MetaMoveResizeResultFlags *result)
{ {