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

View File

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

View File

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

View File

@ -4001,6 +4001,8 @@ meta_window_move_resize_internal (MetaWindow *window,
gboolean did_placement;
MetaRectangle unconstrained_rect;
MetaRectangle constrained_rect;
int rel_x = 0;
int rel_y = 0;
MetaMoveResizeResultFlags result = 0;
gboolean moved_or_resized = FALSE;
MetaWindowUpdateMonitorFlags update_monitor_flags;
@ -4066,7 +4068,14 @@ meta_window_move_resize_internal (MetaWindow *window,
flags,
gravity,
&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
@ -4080,7 +4089,13 @@ meta_window_move_resize_internal (MetaWindow *window,
}
/* 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)
{

View File

@ -220,6 +220,8 @@ meta_window_wayland_move_resize_internal (MetaWindow *window,
int gravity,
MetaRectangle unconstrained_rect,
MetaRectangle constrained_rect,
int rel_x,
int rel_y,
MetaMoveResizeFlags flags,
MetaMoveResizeResultFlags *result)
{
@ -326,11 +328,6 @@ meta_window_wayland_move_resize_internal (MetaWindow *window,
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 =
meta_wayland_window_configuration_new_relative (rel_x,
rel_y,

View File

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