From ff381d1d52f0869486f97c923ac4cada35910217 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Fri, 14 Feb 2020 08:52:48 +0100 Subject: [PATCH] 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 --- src/core/constraints.c | 75 ++++++++++++++++++++++++------- src/core/constraints.h | 4 +- src/core/window-private.h | 2 + src/core/window.c | 19 +++++++- src/wayland/meta-window-wayland.c | 7 +-- src/x11/window-x11.c | 2 + 6 files changed, 86 insertions(+), 23 deletions(-) diff --git a/src/core/constraints.c b/src/core/constraints.c index fa70ec1bf..8e5009097 100644 --- a/src/core/constraints.c +++ b/src/core/constraints.c @@ -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; } diff --git a/src/core/constraints.h b/src/core/constraints.h index 2ebefbecd..775e95dff 100644 --- a/src/core/constraints.h +++ b/src/core/constraints.h @@ -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 */ diff --git a/src/core/window-private.h b/src/core/window-private.h index f1daa9da6..d88f0eb2d 100644 --- a/src/core/window-private.h +++ b/src/core/window-private.h @@ -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); diff --git a/src/core/window.c b/src/core/window.c index 4a7e2b756..612f75974 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -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) { diff --git a/src/wayland/meta-window-wayland.c b/src/wayland/meta-window-wayland.c index 9b113a6c9..cc7f66a92 100644 --- a/src/wayland/meta-window-wayland.c +++ b/src/wayland/meta-window-wayland.c @@ -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, diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c index aeaebb7c7..a546ed089 100644 --- a/src/x11/window-x11.c +++ b/src/x11/window-x11.c @@ -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) {