From 70775ba624b17be7804f8de3716f347c1071d421 Mon Sep 17 00:00:00 2001 From: Sebastian Keller Date: Tue, 19 Jan 2021 19:46:55 +0100 Subject: [PATCH 1/3] wayland/surface: Add function to transform coordinates to buffer This function transforms surface relative coordinates to buffer coordinates. This will become useful when determining which server side decoration control element of a viewport scaled xwayland window an event was on. --- src/wayland/meta-wayland-surface.c | 43 ++++++++++++++++++++++++++++++ src/wayland/meta-wayland-surface.h | 4 +++ 2 files changed, 47 insertions(+) diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c index 0f0c55b1c74..562bfb4c2d9 100644 --- a/src/wayland/meta-wayland-surface.c +++ b/src/wayland/meta-wayland-surface.c @@ -1590,6 +1590,49 @@ meta_wayland_surface_get_absolute_coordinates (MetaWaylandSurface *surface, *y = v.y; } +void +meta_wayland_surface_transform_relative_coordinates_to_buffer (MetaWaylandSurface *surface, + float *x, + float *y) +{ + graphene_rect_t src_rect; + + if (!surface->viewport.has_src_rect && !surface->viewport.has_dst_size) + return; + + if (surface->viewport.has_src_rect) + { + src_rect = (graphene_rect_t) { + .origin.x = surface->viewport.src_rect.origin.x, + .origin.y = surface->viewport.src_rect.origin.y, + .size.width = surface->viewport.src_rect.size.width, + .size.height = surface->viewport.src_rect.size.height, + }; + } + else + { + if (meta_monitor_transform_is_rotated (surface->buffer_transform)) + { + src_rect = (graphene_rect_t) { + .size.width = get_buffer_height (surface) / surface->scale, + .size.height = get_buffer_width (surface) / surface->scale, + }; + } + else + { + src_rect = (graphene_rect_t) { + .size.width = get_buffer_width (surface) / surface->scale, + .size.height = get_buffer_height (surface) / surface->scale, + }; + } + } + + *x = *x * src_rect.size.width / meta_wayland_surface_get_width (surface) + + src_rect.origin.x; + *y = *y * src_rect.size.height / meta_wayland_surface_get_height (surface) + + src_rect.origin.y; +} + static void meta_wayland_surface_init (MetaWaylandSurface *surface) { diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h index 0c7298886d8..e9ffb55cf0f 100644 --- a/src/wayland/meta-wayland-surface.h +++ b/src/wayland/meta-wayland-surface.h @@ -303,6 +303,10 @@ void meta_wayland_surface_get_absolute_coordinates (MetaWaylandSu float *x, float *y); +void meta_wayland_surface_transform_relative_coordinates_to_buffer (MetaWaylandSurface *surface, + float *x, + float *y); + MetaWaylandSurface * meta_wayland_surface_role_get_surface (MetaWaylandSurfaceRole *role); cairo_region_t * meta_wayland_surface_calculate_input_region (MetaWaylandSurface *surface); -- GitLab From a0b3ab8e42dfdca61fbd79a983b64bc86cb30d75 Mon Sep 17 00:00:00 2001 From: Sebastian Keller Date: Tue, 19 Jan 2021 19:51:42 +0100 Subject: [PATCH 2/3] window: Add function to transform coordinates to buffer coordinates This uses the previously added function to transform surface coordinates to buffer coordinates. --- src/core/window-private.h | 4 ++++ src/core/window.c | 10 ++++++++++ 2 files changed, 14 insertions(+) diff --git a/src/core/window-private.h b/src/core/window-private.h index 39fd38d1250..1a557fe36f2 100644 --- a/src/core/window-private.h +++ b/src/core/window-private.h @@ -838,6 +838,10 @@ void meta_window_get_client_area_rect (const MetaWindow *window, void meta_window_get_titlebar_rect (MetaWindow *window, MetaRectangle *titlebar_rect); +void meta_window_transform_coordinates_to_buffer (const MetaWindow *window, + float *x, + float *y); + void meta_window_activate_full (MetaWindow *window, guint32 timestamp, MetaClientType source_indication, diff --git a/src/core/window.c b/src/core/window.c index 07eb0cda2e4..fd279e9d15b 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -4711,6 +4711,16 @@ meta_window_get_titlebar_rect (MetaWindow *window, } } +void meta_window_transform_coordinates_to_buffer (const MetaWindow *window, + float *x, + float *y) +{ +#ifdef HAVE_WAYLAND + if (meta_is_wayland_compositor ()) + meta_wayland_surface_transform_relative_coordinates_to_buffer (window->surface, x, y); +#endif +} + const char* meta_window_get_startup_id (MetaWindow *window) { -- GitLab From ce5150704ebfe02371f4c892a8121b709cb792d4 Mon Sep 17 00:00:00 2001 From: Sebastian Keller Date: Tue, 19 Jan 2021 19:53:32 +0100 Subject: [PATCH 3/3] frames: Use viewport aware coordinate transform to determine control The old code was using event coordinates when determining the frame control under the cursor for each event. These coordinates were in the display coordinate space and unaware of any transformation applied to the window surface/buffer. This was working on X11, but in xwayland due to it using viewports for fullscreen support, this assumption breaks. As a result a cursor position that was on the (viewport scaled) client area could be considered outside of the client area if it was outside of the (unscaled) buffer area. This meant that it was possible to accidentally open window frame context in these regions. Fixes https://gitlab.gnome.org/GNOME/mutter/-/issues/1592 --- src/ui/frames.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/ui/frames.c b/src/ui/frames.c index 542cc54e095..254d529ad70 100644 --- a/src/ui/frames.c +++ b/src/ui/frames.c @@ -66,8 +66,8 @@ static void meta_frames_button_layout_changed (MetaFrames *frames); static GdkRectangle* control_rect (MetaFrameControl control, MetaFrameGeometry *fgeom); static MetaFrameControl get_control (MetaUIFrame *frame, - int x, - int y); + float x, + float y); G_DEFINE_TYPE (MetaFrames, meta_frames, GTK_TYPE_WINDOW); @@ -1729,7 +1729,7 @@ control_rect (MetaFrameControl control, #define TOP_RESIZE_HEIGHT 4 #define CORNER_SIZE_MULT 2 static MetaFrameControl -get_control (MetaUIFrame *frame, int root_x, int root_y) +get_control (MetaUIFrame *frame, float root_x, float root_y) { MetaFrameGeometry fgeom; MetaFrameFlags flags; @@ -1737,12 +1737,13 @@ get_control (MetaUIFrame *frame, int root_x, int root_y) gboolean has_vert, has_horiz; gboolean has_north_resize; cairo_rectangle_int_t client; - int x, y; + float x, y; int win_x, win_y; gdk_window_get_position (frame->window, &win_x, &win_y); x = root_x - win_x; y = root_y - win_y; + meta_window_transform_coordinates_to_buffer (frame->meta_window, &x, &y); meta_window_get_client_area_rect (frame->meta_window, &client); if (META_POINT_IN_RECT (x, y, client)) -- GitLab