From 1a482cbbea109406e48962669a89465f3f8bb98d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Tue, 12 Dec 2023 22:41:20 +0100 Subject: [PATCH 1/5] x11-display: Expose UI scaling factor via D-Bus This replaces the `legacy-ui-scaling-factor` entry in `org.gnome.Mutter.DisplayConfig`, with the motivation being to no longer expose X11 specific state via the monitor configuration API. Signed-off-by: Mingi Sung --- .../org.gnome.Mutter.DisplayConfig.xml | 4 -- data/dbus-interfaces/org.gnome.Mutter.X11.xml | 8 +++ src/backends/meta-monitor-manager.c | 7 -- src/meson.build | 5 ++ src/x11/meta-x11-display.c | 64 ++++++++++++++++++- 5 files changed, 76 insertions(+), 12 deletions(-) create mode 100644 data/dbus-interfaces/org.gnome.Mutter.X11.xml diff --git a/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml b/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml index b05337d74f..7294c57a84 100644 --- a/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml +++ b/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml @@ -426,10 +426,6 @@ always use the same scale. Absence of this means logical monitor scales can differ. - * "legacy-ui-scaling-factor" (i): The legacy scaling factor traditionally - used to scale X11 clients (commonly - communicated via the - Gdk/WindowScalingFactor XSetting entry). --> diff --git a/data/dbus-interfaces/org.gnome.Mutter.X11.xml b/data/dbus-interfaces/org.gnome.Mutter.X11.xml new file mode 100644 index 0000000000..3d3c8a42f8 --- /dev/null +++ b/data/dbus-interfaces/org.gnome.Mutter.X11.xml @@ -0,0 +1,8 @@ + + + + + + diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c index 77743bc722..7f98c2d983 100644 --- a/src/backends/meta-monitor-manager.c +++ b/src/backends/meta-monitor-manager.c @@ -2051,14 +2051,12 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton, GDBusMethodInvocation *invocation, MetaMonitorManager *manager) { - MetaSettings *settings = meta_backend_get_settings (manager->backend); GVariantBuilder monitors_builder; GVariantBuilder logical_monitors_builder; GVariantBuilder properties_builder; GList *l; int i; MetaMonitorManagerCapability capabilities; - int ui_scaling_factor; int max_screen_width, max_screen_height; g_variant_builder_init (&monitors_builder, @@ -2261,11 +2259,6 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton, g_variant_new_boolean (TRUE)); } - ui_scaling_factor = meta_settings_get_ui_scaling_factor (settings); - g_variant_builder_add (&properties_builder, "{sv}", - "legacy-ui-scaling-factor", - g_variant_new_int32 (ui_scaling_factor)); - if (meta_monitor_manager_get_max_screen_size (manager, &max_screen_width, &max_screen_height)) diff --git a/src/meson.build b/src/meson.build index 05df3bfd28..e658f98caa 100644 --- a/src/meson.build +++ b/src/meson.build @@ -949,6 +949,11 @@ dbus_interfaces = [ 'interface': 'org.gnome.Mutter.DebugControl.xml', 'prefix': 'org.gnome.Mutter', }, + { + 'name': 'meta-dbus-x11', + 'interface': 'org.gnome.Mutter.X11.xml', + 'prefix': 'org.gnome.Mutter', + }, ] if have_profiler diff --git a/src/x11/meta-x11-display.c b/src/x11/meta-x11-display.c index 65eb217aaf..8768e14dac 100644 --- a/src/x11/meta-x11-display.c +++ b/src/x11/meta-x11-display.c @@ -70,7 +70,7 @@ #include "wayland/meta-xwayland-private.h" #endif -G_DEFINE_TYPE (MetaX11Display, meta_x11_display, G_TYPE_OBJECT) +#include "meta-dbus-x11.h" static GQuark quark_x11_display_logical_monitor_data = 0; @@ -89,6 +89,14 @@ typedef struct _MetaX11DisplayLogicalMonitorData int xinerama_index; } MetaX11DisplayLogicalMonitorData; +typedef struct _MetaX11DisplayPrivate +{ + MetaDBusX11 *dbus_api; + guint dbus_name_id; +} MetaX11DisplayPrivate; + +G_DEFINE_TYPE_WITH_PRIVATE (MetaX11Display, meta_x11_display, G_TYPE_OBJECT) + static char *get_screen_name (Display *xdisplay, int number); @@ -151,13 +159,46 @@ meta_x11_event_filter_free (MetaX11EventFilter *filter) g_free (filter); } +static void +on_bus_acquired (GDBusConnection *connection, + const char *name, + gpointer user_data) +{ + MetaX11Display *x11_display = user_data; + MetaX11DisplayPrivate *priv = + meta_x11_display_get_instance_private (x11_display); + + g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (priv->dbus_api), + connection, + "/org/gnome/Mutter/X11", + NULL); +} + +static void +update_ui_scaling_factor (MetaX11Display *x11_display) +{ + MetaX11DisplayPrivate *priv = + meta_x11_display_get_instance_private (x11_display); + MetaBackend *backend = backend_from_x11_display (x11_display); + MetaSettings *settings = meta_backend_get_settings (backend); + int ui_scaling_factor; + + ui_scaling_factor = meta_settings_get_ui_scaling_factor (settings); + meta_dbus_x11_set_ui_scaling_factor (priv->dbus_api, ui_scaling_factor); +} + static void meta_x11_display_dispose (GObject *object) { MetaX11Display *x11_display = META_X11_DISPLAY (object); + MetaX11DisplayPrivate *priv = + meta_x11_display_get_instance_private (x11_display); x11_display->closing = TRUE; + g_clear_handle_id (&priv->dbus_name_id, g_bus_unown_name); + g_clear_object (&priv->dbus_api); + g_clear_pointer (&x11_display->alarm_filters, g_ptr_array_unref); g_clear_list (&x11_display->event_funcs, @@ -1220,6 +1261,23 @@ meta_x11_display_init_frames_client (MetaX11Display *x11_display) on_frames_client_died, x11_display); } +static void +initialize_dbus_interface (MetaX11Display *x11_display) +{ + MetaX11DisplayPrivate *priv = + meta_x11_display_get_instance_private (x11_display); + + priv->dbus_api = meta_dbus_x11_skeleton_new (); + priv->dbus_name_id = + g_bus_own_name (G_BUS_TYPE_SESSION, + "org.gnome.Mutter.X11", + G_BUS_NAME_OWNER_FLAGS_NONE, + on_bus_acquired, + NULL, NULL, + x11_display, NULL); + update_ui_scaling_factor (x11_display); +} + /** * meta_x11_display_new: * @@ -1314,6 +1372,8 @@ meta_x11_display_new (MetaDisplay *display, x11_display = g_object_new (META_TYPE_X11_DISPLAY, NULL); x11_display->display = display; + initialize_dbus_interface (x11_display); + /* here we use XDisplayName which is what the user * probably put in, vs. DisplayString(display) which is * canonicalized by XOpenDisplay() @@ -1975,6 +2035,8 @@ on_monitors_changed_internal (MetaMonitorManager *monitor_manager, } x11_display->has_xinerama_indices = FALSE; + + update_ui_scaling_factor (x11_display); } static Bool -- 2.46.0 From dd50b8639bcab08fceb5d3af206e2c41aa6f2f02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= Date: Tue, 20 Feb 2024 23:51:48 +0100 Subject: [PATCH 2/5] Add an experimental feature for letting Xwayland clients scale natively With the next commits we'll introduce a new mode for scaling of Xwayland apps, we'll want to put this mode behind an experimental setting though, so add that setting. Signed-off-by: Mingi Sung --- data/org.gnome.mutter.gschema.xml.in | 7 +++++++ src/backends/meta-settings-private.h | 1 + src/backends/meta-settings.c | 2 ++ 3 files changed, 10 insertions(+) diff --git a/data/org.gnome.mutter.gschema.xml.in b/data/org.gnome.mutter.gschema.xml.in index 92c97b12e3..6751a8d7a9 100644 --- a/data/org.gnome.mutter.gschema.xml.in +++ b/data/org.gnome.mutter.gschema.xml.in @@ -5,6 +5,7 @@ + diff --git a/src/backends/meta-settings-private.h b/src/backends/meta-settings-private.h index afbba054af..2081a81b1a 100644 --- a/src/backends/meta-settings-private.h +++ b/src/backends/meta-settings-private.h @@ -32,6 +32,7 @@ typedef enum _MetaExperimentalFeature META_EXPERIMENTAL_FEATURE_KMS_MODIFIERS = (1 << 1), META_EXPERIMENTAL_FEATURE_AUTOCLOSE_XWAYLAND = (1 << 2), META_EXPERIMENTAL_FEATURE_VARIABLE_REFRESH_RATE = (1 << 3), + META_EXPERIMENTAL_FEATURE_XWAYLAND_NATIVE_SCALING = (1 << 4), } MetaExperimentalFeature; typedef enum _MetaXwaylandExtension diff --git a/src/backends/meta-settings.c b/src/backends/meta-settings.c index 3703b23b07..1ae59d6360 100644 --- a/src/backends/meta-settings.c +++ b/src/backends/meta-settings.c @@ -296,6 +296,8 @@ experimental_features_handler (GVariant *features_variant, feature = META_EXPERIMENTAL_FEATURE_AUTOCLOSE_XWAYLAND; else if (g_str_equal (feature_str, "variable-refresh-rate")) feature = META_EXPERIMENTAL_FEATURE_VARIABLE_REFRESH_RATE; + else if (g_str_equal (feature_str, "xwayland-native-scaling")) + feature = META_EXPERIMENTAL_FEATURE_XWAYLAND_NATIVE_SCALING; if (feature) g_message ("Enabling experimental feature '%s'", feature_str); -- 2.46.0 From 398a04f2558877e4876ea1551907719031b5adc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Tue, 12 Dec 2023 22:42:46 +0100 Subject: [PATCH 3/5] context: Put Wayland compositor getter in the context header Signed-off-by: Mingi Sung --- src/meta/meta-context.h | 5 +++++ src/meta/meta-wayland-compositor.h | 3 --- src/meta/types.h | 4 ++++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/meta/meta-context.h b/src/meta/meta-context.h index ef36bd2c30..2adb9b07e0 100644 --- a/src/meta/meta-context.h +++ b/src/meta/meta-context.h @@ -101,3 +101,8 @@ gboolean meta_context_raise_rlimit_nofile (MetaContext *context, META_EXPORT gboolean meta_context_restore_rlimit_nofile (MetaContext *context, GError **error); + +#ifdef HAVE_WAYLAND +META_EXPORT +MetaWaylandCompositor * meta_context_get_wayland_compositor (MetaContext *context); +#endif diff --git a/src/meta/meta-wayland-compositor.h b/src/meta/meta-wayland-compositor.h index 7f4a507057..3df92fda57 100644 --- a/src/meta/meta-wayland-compositor.h +++ b/src/meta/meta-wayland-compositor.h @@ -31,9 +31,6 @@ G_DECLARE_FINAL_TYPE (MetaWaylandCompositor, META, WAYLAND_COMPOSITOR, GObject) -META_EXPORT -MetaWaylandCompositor *meta_context_get_wayland_compositor (MetaContext *context); - META_EXPORT struct wl_display *meta_wayland_compositor_get_wayland_display (MetaWaylandCompositor *compositor); diff --git a/src/meta/types.h b/src/meta/types.h index cbe2a9a3d7..8fba4a839e 100644 --- a/src/meta/types.h +++ b/src/meta/types.h @@ -38,3 +38,7 @@ typedef struct _MetaSettings MetaSettings; typedef struct _MetaWorkspaceManager MetaWorkspaceManager; typedef struct _MetaSelection MetaSelection; + +#ifdef HAVE_WAYLAND +typedef struct _MetaWaylandCompositor MetaWaylandCompositor; +#endif -- 2.46.0 From 3b799a9250aa0d1df0ab8f611a730c140dfc9017 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Tue, 12 Dec 2023 22:52:44 +0100 Subject: [PATCH 4/5] Add experimental mode to use native scaling of Xwayland clients Allow scale-aware Xwayland clients to scale by an integer scale themselves, instead of letting them render them at 1x scale and then scaling up the texture, making it look blurry. When monitor framebuffers are scaled, this special cases Xwayland and sends output regions in a way that Xwayland think everything is N times as large as the logical region, where N is the ceil of the max monitor scale. This is done by introducing a "stage" vs "protocol" coordinate space for X11, where the "protocol" coordinate space is "stage" multiplied by a scaling factor. We're guarding this behind a new experimental feature "xwayland-native-scaling", which can only come into effect when enabled together with "scale-monitor-framebuffer". Signed-off-by: Mingi Sung --- src/backends/meta-monitor-manager-private.h | 2 + src/backends/meta-monitor-manager.c | 6 + src/compositor/meta-window-actor-x11.c | 22 +- src/core/frame.c | 104 +++++-- src/wayland/meta-wayland-cursor-surface.c | 52 ++-- src/wayland/meta-wayland-outputs.c | 42 ++- src/wayland/meta-wayland-pointer.c | 14 + src/wayland/meta-wayland-private.h | 2 + src/wayland/meta-wayland-surface.c | 30 +- src/wayland/meta-window-xwayland.c | 71 ++++- src/wayland/meta-xwayland-private.h | 1 + src/wayland/meta-xwayland-surface.c | 10 +- src/wayland/meta-xwayland.c | 56 ++++ src/wayland/meta-xwayland.h | 2 + src/x11/meta-x11-display.c | 196 +++++++++++-- src/x11/window-props.c | 108 ++++++- src/x11/window-x11.c | 306 ++++++++++++++++---- src/x11/window-x11.h | 38 +++ 18 files changed, 896 insertions(+), 166 deletions(-) diff --git a/src/backends/meta-monitor-manager-private.h b/src/backends/meta-monitor-manager-private.h index 0760a341a8..6ed3fc2c3f 100644 --- a/src/backends/meta-monitor-manager-private.h +++ b/src/backends/meta-monitor-manager-private.h @@ -436,3 +436,5 @@ gboolean meta_monitor_manager_apply_monitors_config (MetaMonitorManager * MetaMonitorsConfig *config, MetaMonitorsConfigMethod method, GError **error); + +MetaLogicalMonitorLayoutMode meta_monitor_manager_get_layout_mode (MetaMonitorManager *manager); diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c index 7f98c2d983..45033d966e 100644 --- a/src/backends/meta-monitor-manager.c +++ b/src/backends/meta-monitor-manager.c @@ -4116,3 +4116,9 @@ meta_monitor_manager_get_virtual_monitors (MetaMonitorManager *manager) return priv->virtual_monitors; } + +MetaLogicalMonitorLayoutMode +meta_monitor_manager_get_layout_mode (MetaMonitorManager *manager) +{ + return manager->layout_mode; +} diff --git a/src/compositor/meta-window-actor-x11.c b/src/compositor/meta-window-actor-x11.c index 19827af331..7df10e6c15 100644 --- a/src/compositor/meta-window-actor-x11.c +++ b/src/compositor/meta-window-actor-x11.c @@ -688,11 +688,23 @@ meta_window_actor_x11_process_damage (MetaWindowActorX11 *actor_x11, surface = meta_window_actor_get_surface (META_WINDOW_ACTOR (actor_x11)); if (surface) - meta_surface_actor_process_damage (surface, - event->area.x, - event->area.y, - event->area.width, - event->area.height); + { + MetaWindow *window = + meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor_x11)); + MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); + MtkRectangle damage; + + meta_window_x11_protocol_to_stage (window_x11, + event->area.x, event->area.y, + event->area.width, event->area.height, + &damage.x, &damage.y, + &damage.width, &damage.height); + meta_surface_actor_process_damage (surface, + damage.x, + damage.y, + damage.width, + damage.height); + } meta_window_actor_notify_damaged (META_WINDOW_ACTOR (actor_x11)); } diff --git a/src/core/frame.c b/src/core/frame.c index 7a09f89f14..57daf00ee5 100644 --- a/src/core/frame.c +++ b/src/core/frame.c @@ -77,6 +77,7 @@ meta_window_x11_set_frame_xwindow (MetaWindow *window, XSetWindowAttributes attrs; gulong create_serial = 0; g_autoptr (MetaFrame) frame = NULL; + int child_x, child_y; if (window->frame) return; @@ -135,12 +136,19 @@ meta_window_x11_set_frame_xwindow (MetaWindow *window, meta_stack_tracker_record_remove (window->display->stack_tracker, meta_window_x11_get_xwindow (window), XNextRequest (x11_display->xdisplay)); + meta_window_x11_stage_to_protocol (META_WINDOW_X11 (window), + frame->child_x, + frame->child_y, + 0, 0, + &child_x, + &child_y, + NULL, NULL); XReparentWindow (x11_display->xdisplay, meta_window_x11_get_xwindow (window), frame->xwindow, - frame->child_x, - frame->child_y); + child_x, + child_y); if (mtk_x11_error_trap_pop_with_return (x11_display->xdisplay)) { @@ -235,6 +243,8 @@ meta_window_destroy_frame (MetaWindow *window) if (!x11_display->closing) { + int child_x, child_y; + if (!window->unmanaging) { meta_stack_tracker_record_add (window->display->stack_tracker, @@ -242,6 +252,14 @@ meta_window_destroy_frame (MetaWindow *window) XNextRequest (x11_display->xdisplay)); } + meta_window_x11_stage_to_protocol (META_WINDOW_X11 (window), + frame->rect.x + borders.invisible.left, + frame->rect.y + borders.invisible.top, + 0, 0, + &child_x, + &child_y, + NULL, NULL); + XReparentWindow (x11_display->xdisplay, meta_window_x11_get_xwindow (window), x11_display->xroot, @@ -249,8 +267,7 @@ meta_window_destroy_frame (MetaWindow *window) * coordinates here means we'll need to ensure a configure * notify event is sent; see bug 399552. */ - frame->rect.x + borders.invisible.left, - frame->rect.y + borders.invisible.top); + child_x, child_y); window->reparents_pending += 1; } @@ -297,6 +314,7 @@ meta_frame_query_borders (MetaFrame *frame, MetaFrameBorders *borders) { MetaWindow *window = frame->window; + MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); MetaX11Display *x11_display = window->display->x11_display; int format, res; Atom type; @@ -320,12 +338,22 @@ meta_frame_query_borders (MetaFrame *frame, if (mtk_x11_error_trap_pop_with_return (x11_display->xdisplay) == Success && res == Success && nitems == 4) { - borders->invisible = (MetaFrameBorder) { - ((long *) data)[0], - ((long *) data)[1], - ((long *) data)[2], - ((long *) data)[3], - }; + int left, right, top, bottom; + + meta_window_x11_protocol_to_stage (window_x11, + ((long *) data)[0], + ((long *) data)[1], + ((long *) data)[2], + ((long *) data)[3], + &left, + &right, + &top, + &bottom); + + borders->invisible.left = left; + borders->invisible.right = right; + borders->invisible.top = top; + borders->invisible.bottom = bottom; } else { @@ -348,12 +376,21 @@ meta_frame_query_borders (MetaFrame *frame, if (mtk_x11_error_trap_pop_with_return (x11_display->xdisplay) == Success && res == Success && nitems == 4) { - borders->visible = (MetaFrameBorder) { - ((long *) data)[0], - ((long *) data)[1], - ((long *) data)[2], - ((long *) data)[3], - }; + int left, right, top, bottom; + + meta_window_x11_protocol_to_stage (window_x11, + ((long *) data)[0], + ((long *) data)[1], + ((long *) data)[2], + ((long *) data)[3], + &left, + &right, + &top, + &bottom); + borders->visible.left = left; + borders->visible.right = right; + borders->visible.top = top; + borders->visible.bottom = bottom; } else { @@ -401,7 +438,9 @@ meta_frame_sync_to_window (MetaFrame *frame, gboolean need_resize) { MetaWindow *window = frame->window; + MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); MetaX11Display *x11_display = window->display->x11_display; + MtkRectangle rect; meta_topic (META_DEBUG_GEOMETRY, "Syncing frame geometry %d,%d %dx%d (SE: %d,%d)", @@ -412,12 +451,22 @@ meta_frame_sync_to_window (MetaFrame *frame, mtk_x11_error_trap_push (x11_display->xdisplay); + meta_window_x11_stage_to_protocol (window_x11, + frame->rect.x, + frame->rect.y, + frame->rect.width, + frame->rect.height, + &rect.x, + &rect.y, + &rect.width, + &rect.height); + XMoveResizeWindow (x11_display->xdisplay, frame->xwindow, - frame->rect.x, - frame->rect.y, - frame->rect.width, - frame->rect.height); + rect.x, + rect.y, + rect.width, + rect.height); mtk_x11_error_trap_pop (x11_display->xdisplay); @@ -454,6 +503,7 @@ static void send_configure_notify (MetaFrame *frame) { MetaX11Display *x11_display = frame->window->display->x11_display; + MetaWindowX11 *window_x11 = META_WINDOW_X11 (frame->window); XEvent event = { 0 }; /* We never get told by the frames client, just reassert the @@ -463,10 +513,16 @@ send_configure_notify (MetaFrame *frame) event.xconfigure.display = x11_display->xdisplay; event.xconfigure.event = frame->xwindow; event.xconfigure.window = frame->xwindow; - event.xconfigure.x = frame->rect.x; - event.xconfigure.y = frame->rect.y; - event.xconfigure.width = frame->rect.width; - event.xconfigure.height = frame->rect.height; + + meta_window_x11_stage_to_protocol (window_x11, + frame->rect.x, + frame->rect.y, + frame->rect.width, + frame->rect.height, + &event.xconfigure.x, + &event.xconfigure.y, + &event.xconfigure.width, + &event.xconfigure.height); event.xconfigure.border_width = 0; event.xconfigure.above = None; event.xconfigure.override_redirect = False; diff --git a/src/wayland/meta-wayland-cursor-surface.c b/src/wayland/meta-wayland-cursor-surface.c index 87a8895c88..5a16ce7d87 100644 --- a/src/wayland/meta-wayland-cursor-surface.c +++ b/src/wayland/meta-wayland-cursor-surface.c @@ -92,37 +92,29 @@ cursor_sprite_prepare_at (MetaCursorSprite *cursor_sprite, { MetaWaylandSurfaceRole *role = META_WAYLAND_SURFACE_ROLE (cursor_surface); MetaWaylandSurface *surface = meta_wayland_surface_role_get_surface (role); - - if (!meta_wayland_surface_is_xwayland (surface)) + MetaContext *context = + meta_wayland_compositor_get_context (surface->compositor); + MetaBackend *backend = meta_context_get_backend (context); + MetaMonitorManager *monitor_manager = + meta_backend_get_monitor_manager (backend); + MetaLogicalMonitor *logical_monitor; + + logical_monitor = + meta_monitor_manager_get_logical_monitor_at (monitor_manager, x, y); + if (logical_monitor) { - MetaWaylandSurfaceRole *surface_role = - META_WAYLAND_SURFACE_ROLE (cursor_surface); - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaContext *context = - meta_wayland_compositor_get_context (surface->compositor); - MetaBackend *backend = meta_context_get_backend (context); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaLogicalMonitor *logical_monitor; - - logical_monitor = - meta_monitor_manager_get_logical_monitor_at (monitor_manager, x, y); - if (logical_monitor) - { - int surface_scale = surface->applied_state.scale; - float texture_scale; - - if (meta_backend_is_stage_views_scaled (backend)) - texture_scale = 1.0 / surface_scale; - else - texture_scale = (meta_logical_monitor_get_scale (logical_monitor) / - surface_scale); - - meta_cursor_sprite_set_texture_scale (cursor_sprite, texture_scale); - meta_cursor_sprite_set_texture_transform (cursor_sprite, - surface->buffer_transform); - } + int surface_scale = surface->applied_state.scale; + float texture_scale; + + if (meta_backend_is_stage_views_scaled (backend)) + texture_scale = 1.0 / surface_scale; + else + texture_scale = (meta_logical_monitor_get_scale (logical_monitor) / + surface_scale); + + meta_cursor_sprite_set_texture_scale (cursor_sprite, texture_scale); + meta_cursor_sprite_set_texture_transform (cursor_sprite, + surface->buffer_transform); } meta_wayland_surface_update_outputs (surface); diff --git a/src/wayland/meta-wayland-outputs.c b/src/wayland/meta-wayland-outputs.c index 89ae864450..f957bc339d 100644 --- a/src/wayland/meta-wayland-outputs.c +++ b/src/wayland/meta-wayland-outputs.c @@ -31,6 +31,10 @@ #include "backends/meta-monitor-manager-private.h" #include "wayland/meta-wayland-private.h" +#ifdef HAVE_XWAYLAND +#include "wayland/meta-xwayland.h" +#endif + #include "xdg-output-unstable-v1-server-protocol.h" /* Wayland protocol headers list new additions, not deprecations */ @@ -50,6 +54,8 @@ struct _MetaWaylandOutput { GObject parent; + MetaWaylandCompositor *compositor; + struct wl_global *global; GList *resources; GList *xdg_output_resources; @@ -422,6 +428,7 @@ meta_wayland_output_new (MetaWaylandCompositor *compositor, MetaWaylandOutput *wayland_output; wayland_output = g_object_new (META_TYPE_WAYLAND_OUTPUT, NULL); + wayland_output->compositor = compositor; wayland_output->global = wl_global_create (compositor->wayland_display, &wl_output_interface, META_WL_OUTPUT_VERSION, @@ -596,6 +603,37 @@ static const struct zxdg_output_v1_interface meta_xdg_output_destroy, }; +#ifdef HAVE_XWAYLAND +static gboolean +is_xwayland_resource (MetaWaylandOutput *wayland_output, + struct wl_resource *resource) +{ + MetaXWaylandManager *manager = &wayland_output->compositor->xwayland_manager; + + return resource && wl_resource_get_client (resource) == manager->client; +} +#endif + +static void +maybe_scale_for_xwayland (MetaWaylandOutput *wayland_output, + struct wl_resource *resource, + int *x, + int *y) +{ +#ifdef HAVE_XWAYLAND + if (is_xwayland_resource (wayland_output, resource)) + { + MetaXWaylandManager *xwayland_manager = + &wayland_output->compositor->xwayland_manager; + int xwayland_scale; + + xwayland_scale = meta_xwayland_get_effective_scale (xwayland_manager); + *x *= xwayland_scale; + *y *= xwayland_scale; + } +#endif +} + static void send_xdg_output_events (struct wl_resource *resource, MetaWaylandOutput *wayland_output, @@ -616,6 +654,7 @@ send_xdg_output_events (struct wl_resource *resource, if (need_all_events || old_layout.x != layout.x || old_layout.y != layout.y) { + maybe_scale_for_xwayland (wayland_output, resource, &layout.x, &layout.y); zxdg_output_v1_send_logical_position (resource, layout.x, layout.y); need_done = TRUE; } @@ -623,6 +662,7 @@ send_xdg_output_events (struct wl_resource *resource, if (need_all_events || old_layout.width != layout.width || old_layout.height != layout.height) { + maybe_scale_for_xwayland (wayland_output, resource, &layout.width, &layout.height); zxdg_output_v1_send_logical_size (resource, layout.width, layout.height); need_done = TRUE; } @@ -745,7 +785,7 @@ meta_wayland_outputs_init (MetaWaylandCompositor *compositor) MetaMonitorManager *monitor_manager = meta_backend_get_monitor_manager (backend); - g_signal_connect (monitor_manager, "monitors-changed-internal", + g_signal_connect (monitor_manager, "monitors-changed", G_CALLBACK (on_monitors_changed), compositor); compositor->outputs = diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c index cf6008064a..b8c49849ad 100644 --- a/src/wayland/meta-wayland-pointer.c +++ b/src/wayland/meta-wayland-pointer.c @@ -1247,6 +1247,20 @@ pointer_set_cursor (struct wl_client *client, cursor_surface = META_WAYLAND_CURSOR_SURFACE (surface->role); meta_wayland_cursor_surface_set_renderer (cursor_surface, cursor_renderer); + +#ifdef HAVE_XWAYLAND + if (meta_wayland_surface_is_xwayland (surface)) + { + MetaXWaylandManager *xwayland_manager = + &surface->compositor->xwayland_manager; + int scale; + + scale = meta_xwayland_get_effective_scale (xwayland_manager); + hot_x = round (hot_x / (double) scale); + hot_y = round (hot_y / (double) scale); + } +#endif + meta_wayland_cursor_surface_set_hotspot (cursor_surface, hot_x, hot_y); diff --git a/src/wayland/meta-wayland-private.h b/src/wayland/meta-wayland-private.h index e8d442c039..834753ffdd 100644 --- a/src/wayland/meta-wayland-private.h +++ b/src/wayland/meta-wayland-private.h @@ -77,6 +77,8 @@ struct _MetaXWaylandManager int rr_error_base; gboolean should_enable_ei_portal; + + double highest_monitor_scale; }; struct _MetaWaylandCompositor diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c index d8b36ff92b..4ad95cd9d5 100644 --- a/src/wayland/meta-wayland-surface.c +++ b/src/wayland/meta-wayland-surface.c @@ -782,8 +782,19 @@ meta_wayland_surface_apply_state (MetaWaylandSurface *surface, state->buffer->type != META_WAYLAND_BUFFER_TYPE_SINGLE_PIXEL)); } - if (state->scale > 0) - surface->applied_state.scale = state->scale; + if (meta_wayland_surface_is_xwayland (surface)) + { +#ifdef HAVE_XWAYLAND + MetaXWaylandManager *xwayland_manager = + &surface->compositor->xwayland_manager; + + surface->applied_state.scale = meta_xwayland_get_effective_scale (xwayland_manager); +#endif + } + else if (state->scale > 0) + { + surface->applied_state.scale = state->scale; + } if (state->has_new_buffer_transform) surface->buffer_transform = state->buffer_transform; @@ -978,8 +989,9 @@ meta_wayland_surface_commit (MetaWaylandSurface *surface) MetaMultiTexture *committed_texture = surface->committed_state.texture; int committed_scale = surface->committed_state.scale; - if ((meta_multi_texture_get_width (committed_texture) % committed_scale != 0) || - (meta_multi_texture_get_height (committed_texture) % committed_scale != 0)) + if (((meta_multi_texture_get_width (committed_texture) % committed_scale != 0) || + (meta_multi_texture_get_height (committed_texture) % committed_scale != 0)) && + !meta_wayland_surface_is_xwayland (surface)) { if (surface->role && !META_IS_WAYLAND_CURSOR_SURFACE (surface->role)) { @@ -1507,6 +1519,16 @@ meta_wayland_surface_update_outputs (MetaWaylandSurface *surface) g_hash_table_foreach (surface->compositor->outputs, update_surface_output_state, surface); + + if (meta_wayland_surface_is_xwayland (surface)) + { +#ifdef HAVE_XWAYLAND + MetaXWaylandManager *xwayland_manager = + &surface->compositor->xwayland_manager; + + surface->applied_state.scale = meta_xwayland_get_effective_scale (xwayland_manager); +#endif + } } void diff --git a/src/wayland/meta-window-xwayland.c b/src/wayland/meta-window-xwayland.c index 1299a351ca..5fb0069626 100644 --- a/src/wayland/meta-window-xwayland.c +++ b/src/wayland/meta-window-xwayland.c @@ -27,8 +27,9 @@ #include "x11/window-x11-private.h" #include "x11/xprops.h" #include "wayland/meta-window-xwayland.h" -#include "wayland/meta-wayland.h" +#include "wayland/meta-wayland-private.h" #include "wayland/meta-wayland-surface-private.h" +#include "wayland/meta-xwayland.h" enum { @@ -315,6 +316,72 @@ meta_window_xwayland_process_property_notify (MetaWindow *window, meta_window_queue (window, META_QUEUE_MOVE_RESIZE); } +static void +meta_window_xwayland_stage_to_protocol (MetaWindowX11 *window_x11, + int stage_x, + int stage_y, + int stage_width, + int stage_height, + int *protocol_x, + int *protocol_y, + int *protocol_width, + int *protocol_height) +{ + MetaDisplay *display = meta_window_get_display (META_WINDOW (window_x11)); + MetaContext *context = meta_display_get_context (display); + MetaWaylandCompositor *wayland_compositor = + meta_context_get_wayland_compositor (context); + MetaXWaylandManager *xwayland_manager = &wayland_compositor->xwayland_manager; + int scale; + + scale = meta_xwayland_get_effective_scale (xwayland_manager); + if (protocol_x) + *protocol_x = stage_x * scale; + if (protocol_y) + *protocol_y = stage_y * scale; + if (protocol_width) + *protocol_width = stage_width * scale; + if (protocol_height) + *protocol_height = stage_height * scale; +} + +static void +meta_window_xwayland_protocol_to_stage (MetaWindowX11 *window_x11, + int protocol_x, + int protocol_y, + int protocol_width, + int protocol_height, + int *stage_x, + int *stage_y, + int *stage_width, + int *stage_height) +{ + MetaDisplay *display = meta_window_get_display (META_WINDOW (window_x11)); + MetaContext *context = meta_display_get_context (display); + MetaWaylandCompositor *wayland_compositor = + meta_context_get_wayland_compositor (context); + MetaXWaylandManager *xwayland_manager = &wayland_compositor->xwayland_manager; + MtkRectangle rect; + int scale; + + rect.x = protocol_x; + rect.y = protocol_y; + rect.width = protocol_width; + rect.height = protocol_height; + + scale = meta_xwayland_get_effective_scale (xwayland_manager); + mtk_rectangle_scale_double (&rect, 1.0 / scale, MTK_ROUNDING_STRATEGY_GROW, &rect); + + if (stage_x) + *stage_x = rect.x; + if (stage_y) + *stage_y = rect.y; + if (stage_width) + *stage_width = rect.width; + if (stage_height) + *stage_height = rect.height; +} + static void meta_window_xwayland_class_init (MetaWindowXwaylandClass *klass) { @@ -331,6 +398,8 @@ meta_window_xwayland_class_init (MetaWindowXwaylandClass *klass) window_x11_class->thaw_commits = meta_window_xwayland_thaw_commits; window_x11_class->always_update_shape = meta_window_xwayland_always_update_shape; window_x11_class->process_property_notify = meta_window_xwayland_process_property_notify; + window_x11_class->stage_to_protocol = meta_window_xwayland_stage_to_protocol; + window_x11_class->protocol_to_stage = meta_window_xwayland_protocol_to_stage; gobject_class->get_property = meta_window_xwayland_get_property; gobject_class->set_property = meta_window_xwayland_set_property; diff --git a/src/wayland/meta-xwayland-private.h b/src/wayland/meta-xwayland-private.h index 7a9cb73fdf..9e06f03155 100644 --- a/src/wayland/meta-xwayland-private.h +++ b/src/wayland/meta-xwayland-private.h @@ -20,6 +20,7 @@ #include #include "wayland/meta-wayland-private.h" +#include "wayland/meta-xwayland.h" gboolean meta_xwayland_init (MetaXWaylandManager *manager, diff --git a/src/wayland/meta-xwayland-surface.c b/src/wayland/meta-xwayland-surface.c index 8fa1c72a96..c6daf9b267 100644 --- a/src/wayland/meta-xwayland-surface.c +++ b/src/wayland/meta-xwayland-surface.c @@ -163,13 +163,19 @@ meta_xwayland_surface_get_relative_coordinates (MetaWaylandSurfaceRole *surface_ float *out_sy) { MetaXwaylandSurface *xwayland_surface = META_XWAYLAND_SURFACE (surface_role); + MetaWaylandSurface *surface = + meta_wayland_surface_role_get_surface (surface_role); + MetaWaylandCompositor *compositor = + meta_wayland_surface_get_compositor (surface); MtkRectangle window_rect = { 0 }; + int xwayland_scale; if (xwayland_surface->window) meta_window_get_buffer_rect (xwayland_surface->window, &window_rect); - *out_sx = abs_x - window_rect.x; - *out_sy = abs_y - window_rect.y; + xwayland_scale = meta_xwayland_get_effective_scale (&compositor->xwayland_manager); + *out_sx = (abs_x - window_rect.x) * xwayland_scale; + *out_sy = (abs_y - window_rect.y) * xwayland_scale; } static MetaWaylandSurface * diff --git a/src/wayland/meta-xwayland.c b/src/wayland/meta-xwayland.c index 7f2915cfeb..f6f9d01ff4 100644 --- a/src/wayland/meta-xwayland.c +++ b/src/wayland/meta-xwayland.c @@ -1051,6 +1051,29 @@ meta_xwayland_shutdown (MetaWaylandCompositor *compositor) } } +static void +update_highest_monitor_scale (MetaXWaylandManager *manager) +{ + MetaWaylandCompositor *compositor = manager->compositor; + MetaContext *context = meta_wayland_compositor_get_context (compositor); + MetaBackend *backend = meta_context_get_backend (context); + MetaMonitorManager *monitor_manager = + meta_backend_get_monitor_manager (backend); + GList *logical_monitors; + GList *l; + double scale = 1.0; + + logical_monitors = meta_monitor_manager_get_logical_monitors (monitor_manager); + for (l = logical_monitors; l; l = l->next) + { + MetaLogicalMonitor *logical_monitor = l->data; + + scale = MAX (scale, meta_logical_monitor_get_scale (logical_monitor)); + } + + manager->highest_monitor_scale = scale; +} + gboolean meta_xwayland_init (MetaXWaylandManager *manager, MetaWaylandCompositor *compositor, @@ -1058,6 +1081,9 @@ meta_xwayland_init (MetaXWaylandManager *manager, GError **error) { MetaContext *context = compositor->context; + MetaBackend *backend = meta_context_get_backend (context); + MetaMonitorManager *monitor_manager = + meta_backend_get_monitor_manager (backend); MetaX11DisplayPolicy policy; int display = 0; @@ -1121,6 +1147,10 @@ meta_xwayland_init (MetaXWaylandManager *manager, /* Xwayland specific protocol, needs to be filtered out for all other clients */ meta_xwayland_grab_keyboard_init (compositor); + g_signal_connect_swapped (monitor_manager, "monitors-changed-internal", + G_CALLBACK (update_highest_monitor_scale), manager); + update_highest_monitor_scale (manager); + return TRUE; } @@ -1313,3 +1343,29 @@ meta_xwayland_set_should_enable_ei_portal (MetaXWaylandManager *manager, { manager->should_enable_ei_portal = should_enable_ei_portal; } + +int +meta_xwayland_get_effective_scale (MetaXWaylandManager *manager) +{ + MetaWaylandCompositor *compositor = manager->compositor; + MetaContext *context = meta_wayland_compositor_get_context (compositor); + MetaBackend *backend = meta_context_get_backend (context); + MetaMonitorManager *monitor_manager = + meta_backend_get_monitor_manager (backend); + MetaSettings *settings = meta_backend_get_settings (backend); + + switch (meta_monitor_manager_get_layout_mode (monitor_manager)) + { + case META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL: + break; + + case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL: + if (meta_settings_is_experimental_feature_enabled (settings, + META_EXPERIMENTAL_FEATURE_XWAYLAND_NATIVE_SCALING) && + meta_settings_is_experimental_feature_enabled (settings, + META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER)) + return ceil (manager->highest_monitor_scale); + } + + return 1; +} diff --git a/src/wayland/meta-xwayland.h b/src/wayland/meta-xwayland.h index daf9d1abb0..ae7a06977e 100644 --- a/src/wayland/meta-xwayland.h +++ b/src/wayland/meta-xwayland.h @@ -48,3 +48,5 @@ META_EXPORT_TEST gboolean meta_xwayland_signal (MetaXWaylandManager *manager, int signum, GError **error); + +int meta_xwayland_get_effective_scale (MetaXWaylandManager *manager); diff --git a/src/x11/meta-x11-display.c b/src/x11/meta-x11-display.c index 8768e14dac..024374e7ef 100644 --- a/src/x11/meta-x11-display.c +++ b/src/x11/meta-x11-display.c @@ -130,6 +130,42 @@ backend_from_x11_display (MetaX11Display *x11_display) return meta_context_get_backend (context); } +static void +stage_to_protocol (MetaX11Display *x11_display, + int stage_x, + int stage_y, + int *protocol_x, + int *protocol_y) +{ + MetaDisplay *display = meta_x11_display_get_display (x11_display); + MetaContext *context = meta_display_get_context (display); + int scale = 1; + + switch (meta_context_get_compositor_type (context)) + { + case META_COMPOSITOR_TYPE_WAYLAND: + { +#ifdef HAVE_XWAYLAND + MetaWaylandCompositor *wayland_compositor = + meta_context_get_wayland_compositor (context); + MetaXWaylandManager *xwayland_manager = + &wayland_compositor->xwayland_manager; + + scale = meta_xwayland_get_effective_scale (xwayland_manager); +#endif + break; + } + + case META_COMPOSITOR_TYPE_X11: + break; + } + + if (protocol_x) + *protocol_x = stage_x * scale; + if (protocol_y) + *protocol_y = stage_y * scale; +} + static void meta_x11_display_unmanage_windows (MetaX11Display *x11_display) { @@ -180,10 +216,32 @@ update_ui_scaling_factor (MetaX11Display *x11_display) MetaX11DisplayPrivate *priv = meta_x11_display_get_instance_private (x11_display); MetaBackend *backend = backend_from_x11_display (x11_display); - MetaSettings *settings = meta_backend_get_settings (backend); - int ui_scaling_factor; + MetaContext *context = meta_backend_get_context (backend); + int ui_scaling_factor = 1; + + switch (meta_context_get_compositor_type (context)) + { + case META_COMPOSITOR_TYPE_WAYLAND: + { +#ifdef HAVE_XWAYLAND + MetaWaylandCompositor *wayland_compositor = + meta_context_get_wayland_compositor (context); + MetaXWaylandManager *xwayland_manager = + &wayland_compositor->xwayland_manager; + + ui_scaling_factor = meta_xwayland_get_effective_scale (xwayland_manager); +#endif + break; + } + case META_COMPOSITOR_TYPE_X11: + { + MetaSettings *settings = meta_backend_get_settings (backend); + + ui_scaling_factor = meta_settings_get_ui_scaling_factor (settings); + break; + } + } - ui_scaling_factor = meta_settings_get_ui_scaling_factor (settings); meta_dbus_x11_set_ui_scaling_factor (priv->dbus_api, ui_scaling_factor); } @@ -637,6 +695,9 @@ set_desktop_geometry_hint (MetaX11Display *x11_display) return; meta_display_get_size (x11_display->display, &monitor_width, &monitor_height); + stage_to_protocol (x11_display, + monitor_width, monitor_height, + &monitor_width, &monitor_height); data[0] = monitor_width; data[1] = monitor_height; @@ -1046,14 +1107,22 @@ set_workspace_work_area_hint (MetaWorkspace *workspace, for (l = logical_monitors; l; l = l->next) { - MtkRectangle area; + MtkRectangle stage_area; + MtkRectangle protocol_area; - meta_workspace_get_work_area_for_logical_monitor (workspace, l->data, &area); + meta_workspace_get_work_area_for_logical_monitor (workspace, l->data, + &stage_area); - tmp[0] = area.x; - tmp[1] = area.y; - tmp[2] = area.width; - tmp[3] = area.height; + stage_to_protocol (x11_display, + stage_area.x, stage_area.y, + &protocol_area.x, &protocol_area.y); + stage_to_protocol (x11_display, + stage_area.width, stage_area.height, + &protocol_area.width, &protocol_area.height); + tmp[0] = protocol_area.x; + tmp[1] = protocol_area.y; + tmp[2] = protocol_area.width; + tmp[3] = protocol_area.height; tmp += 4; } @@ -1082,7 +1151,6 @@ set_work_area_hint (MetaDisplay *display, int num_workspaces; GList *l; unsigned long *data, *tmp; - MtkRectangle area; num_workspaces = meta_workspace_manager_get_n_workspaces (workspace_manager); data = g_new (unsigned long, num_workspaces * 4); @@ -1091,14 +1159,22 @@ set_work_area_hint (MetaDisplay *display, for (l = workspace_manager->workspaces; l; l = l->next) { MetaWorkspace *workspace = l->data; + MtkRectangle stage_area; + MtkRectangle protocol_area; - meta_workspace_get_work_area_all_monitors (workspace, &area); + meta_workspace_get_work_area_all_monitors (workspace, &stage_area); set_workspace_work_area_hint (workspace, x11_display); - tmp[0] = area.x; - tmp[1] = area.y; - tmp[2] = area.width; - tmp[3] = area.height; + stage_to_protocol (x11_display, + stage_area.x, stage_area.y, + &protocol_area.x, &protocol_area.y); + stage_to_protocol (x11_display, + stage_area.width, stage_area.height, + &protocol_area.width, &protocol_area.height); + tmp[0] = protocol_area.x; + tmp[1] = protocol_area.y; + tmp[2] = protocol_area.width; + tmp[3] = protocol_area.height; tmp += 4; } @@ -1278,6 +1354,41 @@ initialize_dbus_interface (MetaX11Display *x11_display) update_ui_scaling_factor (x11_display); } +static void +experimental_features_changed (MetaSettings *settings, + MetaExperimentalFeature old_experimental_features, + MetaX11Display *x11_display) +{ + gboolean was_xwayland_native_scaling; + gboolean was_stage_views_scaled; + gboolean is_xwayland_native_scaling; + gboolean is_stage_views_scaled; + + was_xwayland_native_scaling = + !!(old_experimental_features & + META_EXPERIMENTAL_FEATURE_XWAYLAND_NATIVE_SCALING); + was_stage_views_scaled = + !!(old_experimental_features & + META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER); + + is_xwayland_native_scaling = + meta_settings_is_experimental_feature_enabled ( + settings, + META_EXPERIMENTAL_FEATURE_XWAYLAND_NATIVE_SCALING); + is_stage_views_scaled = + meta_settings_is_experimental_feature_enabled ( + settings, + META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER); + + if (is_xwayland_native_scaling != was_xwayland_native_scaling || + is_stage_views_scaled != was_stage_views_scaled) + { + update_ui_scaling_factor (x11_display); + set_desktop_geometry_hint (x11_display); + set_work_area_hint (x11_display->display, x11_display); + } +} + /** * meta_x11_display_new: * @@ -1296,6 +1407,7 @@ meta_x11_display_new (MetaDisplay *display, MetaBackend *backend = meta_context_get_backend (context); MetaMonitorManager *monitor_manager = meta_backend_get_monitor_manager (backend); + MetaSettings *settings = meta_backend_get_settings (backend); g_autoptr (MetaX11Display) x11_display = NULL; Display *xdisplay; Screen *xscreen; @@ -1466,7 +1578,7 @@ meta_x11_display_new (MetaDisplay *display, "monitors-changed-internal", G_CALLBACK (on_monitors_changed_internal), x11_display, - 0); + G_CONNECT_AFTER); init_leader_window (x11_display, ×tamp); x11_display->timestamp = timestamp; @@ -1559,6 +1671,11 @@ meta_x11_display_new (MetaDisplay *display, meta_prefs_add_listener (prefs_changed_callback, x11_display); + g_signal_connect_object (settings, + "experimental-features-changed", + G_CALLBACK (experimental_features_changed), + x11_display, 0); + set_work_area_hint (display, x11_display); g_signal_connect_object (display, "workareas-changed", @@ -1772,16 +1889,12 @@ meta_x11_display_reload_cursor (MetaX11Display *x11_display) } static void -set_cursor_theme (Display *xdisplay, - MetaBackend *backend) +set_cursor_theme (Display *xdisplay, + const char *theme, + int size) { - MetaSettings *settings = meta_backend_get_settings (backend); - int scale; - - scale = meta_settings_get_ui_scaling_factor (settings); - XcursorSetTheme (xdisplay, meta_prefs_get_cursor_theme ()); - XcursorSetDefaultSize (xdisplay, - meta_prefs_get_cursor_size () * scale); + XcursorSetTheme (xdisplay, theme); + XcursorSetDefaultSize (xdisplay, size); } static void @@ -1833,8 +1946,37 @@ static void update_cursor_theme (MetaX11Display *x11_display) { MetaBackend *backend = backend_from_x11_display (x11_display); + MetaContext *context = meta_backend_get_context (backend); + MetaSettings *settings = meta_backend_get_settings (backend); + int scale = 1; + int size; + const char *theme; + + switch (meta_context_get_compositor_type (context)) + { + case META_COMPOSITOR_TYPE_WAYLAND: + { +#ifdef HAVE_XWAYLAND + MetaWaylandCompositor *wayland_compositor = + meta_context_get_wayland_compositor (context); + MetaXWaylandManager *xwayland_manager = + &wayland_compositor->xwayland_manager; + + scale = meta_xwayland_get_effective_scale (xwayland_manager); +#endif + break; + } + + case META_COMPOSITOR_TYPE_X11: + scale = meta_settings_get_ui_scaling_factor (settings); + break; + } + + size = meta_prefs_get_cursor_size () * scale; + + theme = meta_prefs_get_cursor_theme (); - set_cursor_theme (x11_display->xdisplay, backend); + set_cursor_theme (x11_display->xdisplay, theme, size); schedule_reload_x11_cursor (x11_display); if (META_IS_BACKEND_X11 (backend)) @@ -1842,7 +1984,7 @@ update_cursor_theme (MetaX11Display *x11_display) MetaBackendX11 *backend_x11 = META_BACKEND_X11 (backend); Display *xdisplay = meta_backend_x11_get_xdisplay (backend_x11); - set_cursor_theme (xdisplay, backend); + set_cursor_theme (xdisplay, theme, size); meta_backend_x11_reload_cursor (backend_x11); } } diff --git a/src/x11/window-props.c b/src/x11/window-props.c index c18b3eab59..494fbe8431 100644 --- a/src/x11/window-props.c +++ b/src/x11/window-props.c @@ -305,10 +305,15 @@ reload_icon_geometry (MetaWindow *window, { MtkRectangle geometry; - geometry.x = (int)value->v.cardinal_list.cardinals[0]; - geometry.y = (int)value->v.cardinal_list.cardinals[1]; - geometry.width = (int)value->v.cardinal_list.cardinals[2]; - geometry.height = (int)value->v.cardinal_list.cardinals[3]; + meta_window_x11_protocol_to_stage (META_WINDOW_X11 (window), + value->v.cardinal_list.cardinals[0], + value->v.cardinal_list.cardinals[1], + value->v.cardinal_list.cardinals[2], + value->v.cardinal_list.cardinals[3], + &geometry.x, + &geometry.y, + &geometry.width, + &geometry.height); meta_window_set_icon_geometry (window, &geometry); } @@ -370,11 +375,24 @@ reload_gtk_frame_extents (MetaWindow *window, } else { + int left, right, top, bottom; MetaFrameBorder extents; - extents.left = (int)value->v.cardinal_list.cardinals[0]; - extents.right = (int)value->v.cardinal_list.cardinals[1]; - extents.top = (int)value->v.cardinal_list.cardinals[2]; - extents.bottom = (int)value->v.cardinal_list.cardinals[3]; + + meta_window_x11_protocol_to_stage (META_WINDOW_X11 (window), + value->v.cardinal_list.cardinals[0], + value->v.cardinal_list.cardinals[1], + value->v.cardinal_list.cardinals[2], + value->v.cardinal_list.cardinals[3], + &left, + &right, + &top, + &bottom); + + extents.left = left; + extents.right = right; + extents.top = top; + extents.bottom = bottom; + meta_window_set_custom_frame_extents (window, &extents, initial); } } @@ -678,10 +696,16 @@ reload_opaque_region (MetaWindow *window, { MtkRectangle *rect = &rects[rect_index]; - rect->x = region[i++]; - rect->y = region[i++]; - rect->width = region[i++]; - rect->height = region[i++]; + meta_window_x11_protocol_to_stage (META_WINDOW_X11 (window), + region[i + 0], + region[i + 1], + region[i + 2], + region[i + 3], + &rect->x, + &rect->y, + &rect->width, + &rect->height); + i += 4; rect_index++; } @@ -1245,9 +1269,65 @@ meta_set_normal_hints (MetaWindow *window, * as if flags were zero */ if (hints) - window->size_hints = *(MetaSizeHints*)(hints); + { + MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); + + window->size_hints = *(MetaSizeHints *) hints; + + meta_window_x11_protocol_to_stage (window_x11, + hints->x, hints->y, + hints->width, hints->height, + &window->size_hints.x, + &window->size_hints.y, + &window->size_hints.width, + &window->size_hints.height); + + meta_window_x11_protocol_to_stage (window_x11, + hints->min_width, hints->min_height, + 0, 0, + &window->size_hints.min_width, + &window->size_hints.min_height, + NULL, NULL); + + meta_window_x11_protocol_to_stage (window_x11, + hints->max_width, hints->max_height, + 0, 0, + &window->size_hints.max_width, + &window->size_hints.max_height, + NULL, NULL); + + meta_window_x11_protocol_to_stage (window_x11, + hints->width_inc, hints->height_inc, + 0, 0, + &window->size_hints.width_inc, + &window->size_hints.height_inc, + NULL, NULL); + + meta_window_x11_protocol_to_stage (window_x11, + hints->min_aspect.x, hints->min_aspect.y, + 0, 0, + &window->size_hints.min_aspect.x, + &window->size_hints.min_aspect.y, + NULL, NULL); + + meta_window_x11_protocol_to_stage (window_x11, + hints->max_aspect.x, hints->max_aspect.y, + 0, 0, + &window->size_hints.max_aspect.x, + &window->size_hints.max_aspect.y, + NULL, NULL); + + meta_window_x11_protocol_to_stage (window_x11, + hints->base_width, hints->base_height, + 0, 0, + &window->size_hints.base_width, + &window->size_hints.base_height, + NULL, NULL); + } else - window->size_hints.flags = 0; + { + window->size_hints.flags = 0; + } /* Put back saved ConfigureRequest. */ window->size_hints.x = x; diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c index 443f40f284..ccbd75d1a9 100644 --- a/src/x11/window-x11.c +++ b/src/x11/window-x11.c @@ -110,6 +110,113 @@ meta_window_x11_get_private (MetaWindowX11 *window_x11) return meta_window_x11_get_instance_private (window_x11); } +static void +meta_window_x11_real_stage_to_protocol (MetaWindowX11 *window_x11, + int stage_x, + int stage_y, + int stage_width, + int stage_height, + int *protocol_x, + int *protocol_y, + int *protocol_width, + int *protocol_height) +{ + if (protocol_x) + *protocol_x = stage_x; + if (protocol_y) + *protocol_y = stage_y; + if (protocol_width) + *protocol_width = stage_width; + if (protocol_height) + *protocol_height = stage_height; +} + +static void +meta_window_x11_real_protocol_to_stage (MetaWindowX11 *window_x11, + int protocol_x, + int protocol_y, + int protocol_width, + int protocol_height, + int *stage_x, + int *stage_y, + int *stage_width, + int *stage_height) +{ + if (stage_x) + *stage_x = protocol_x; + if (stage_y) + *stage_y = protocol_y; + if (stage_width) + *stage_width = protocol_width; + if (stage_height) + *stage_height = protocol_height; +} + +void +meta_window_x11_stage_to_protocol (MetaWindowX11 *window_x11, + int stage_x, + int stage_y, + int stage_width, + int stage_height, + int *protocol_x, + int *protocol_y, + int *protocol_width, + int *protocol_height) +{ + MetaWindowX11Class *klass = META_WINDOW_X11_GET_CLASS (window_x11); + + klass->stage_to_protocol (window_x11, + stage_x, stage_y, + stage_width, stage_height, + protocol_x, protocol_y, + protocol_width, protocol_height); +} + +void +meta_window_x11_protocol_to_stage (MetaWindowX11 *window_x11, + int protocol_x, + int protocol_y, + int protocol_width, + int protocol_height, + int *stage_x, + int *stage_y, + int *stage_width, + int *stage_height) +{ + MetaWindowX11Class *klass = META_WINDOW_X11_GET_CLASS (window_x11); + + klass->protocol_to_stage (window_x11, + protocol_x, protocol_y, + protocol_width, protocol_height, + stage_x, stage_y, + stage_width, stage_height); +} + +static MtkRegion * +region_protocol_to_stage (MtkRegion *region, + MetaWindowX11 *window_x11) +{ + int n_rects, i; + MtkRectangle *rects; + MtkRegion *scaled_region; + + n_rects = mtk_region_num_rectangles (region); + MTK_RECTANGLE_CREATE_ARRAY_SCOPED (n_rects, rects); + for (i = 0; i < n_rects; i++) + { + rects[i] = mtk_region_get_rectangle (region, i); + meta_window_x11_protocol_to_stage (window_x11, + rects[i].x, rects[i].y, + rects[i].width, rects[i].height, + &rects[i].x, &rects[i].y, + &rects[i].width, &rects[i].height); + } + + scaled_region = mtk_region_create_rectangles (rects, n_rects); + + return scaled_region; +} + static void send_icccm_message (MetaWindow *window, Atom atom, @@ -254,8 +361,14 @@ send_configure_notify (MetaWindow *window) event.xconfigure.display = x11_display->xdisplay; event.xconfigure.event = priv->xwindow; event.xconfigure.window = priv->xwindow; - event.xconfigure.x = priv->client_rect.x - priv->border_width; - event.xconfigure.y = priv->client_rect.y - priv->border_width; + meta_window_x11_stage_to_protocol (window_x11, + priv->client_rect.x - priv->border_width, + priv->client_rect.y - priv->border_width, + 0, 0, + &event.xconfigure.x, + &event.xconfigure.y, + NULL, NULL); + if (window->frame) { if (window->withdrawn) @@ -267,19 +380,42 @@ send_configure_notify (MetaWindow *window) meta_frame_calc_borders (window->frame, &borders); - event.xconfigure.x = window->frame->rect.x + borders.invisible.left; - event.xconfigure.y = window->frame->rect.y + borders.invisible.top; + meta_window_x11_stage_to_protocol (window_x11, + window->frame->rect.x + borders.invisible.left, + window->frame->rect.y + borders.invisible.top, + 0, 0, + &event.xconfigure.x, + &event.xconfigure.y, + NULL, NULL); } else { + int dx, dy; + /* Need to be in root window coordinates */ - event.xconfigure.x += window->frame->rect.x; - event.xconfigure.y += window->frame->rect.y; + meta_window_x11_stage_to_protocol (window_x11, + window->frame->rect.x, + window->frame->rect.y, + 0, 0, + &dx, + &dy, + NULL, NULL); + event.xconfigure.x += dx; + event.xconfigure.y += dy; } } - event.xconfigure.width = priv->client_rect.width; - event.xconfigure.height = priv->client_rect.height; - event.xconfigure.border_width = priv->border_width; /* requested not actual */ + meta_window_x11_stage_to_protocol (window_x11, + priv->client_rect.width, + priv->client_rect.height, + 0, 0, + &event.xconfigure.width, + &event.xconfigure.height, + NULL, NULL); + meta_window_x11_stage_to_protocol (window_x11, + priv->border_width, + 0, 0, 0, + &event.xconfigure.border_width, + NULL, NULL, NULL); event.xconfigure.above = None; /* FIXME */ event.xconfigure.override_redirect = False; @@ -1137,20 +1273,26 @@ static void update_net_frame_extents (MetaWindow *window) { MetaX11Display *x11_display = window->display->x11_display; - + int left, right, top, bottom; unsigned long data[4]; MetaFrameBorders borders; Window xwindow = meta_window_x11_get_xwindow (window); meta_frame_calc_borders (window->frame, &borders); - /* Left */ - data[0] = borders.visible.left; - /* Right */ - data[1] = borders.visible.right; - /* Top */ - data[2] = borders.visible.top; - /* Bottom */ - data[3] = borders.visible.bottom; + meta_window_x11_stage_to_protocol (META_WINDOW_X11 (window), + borders.visible.left, + borders.visible.right, + borders.visible.top, + borders.visible.bottom, + &left, + &right, + &top, + &bottom); + + data[0] = left; + data[1] = right; + data[2] = top; + data[3] = bottom; meta_topic (META_DEBUG_GEOMETRY, "Setting _NET_FRAME_EXTENTS on managed window 0x%lx " @@ -1482,10 +1624,11 @@ meta_window_x11_move_resize_internal (MetaWindow *window, configure_frame_first = size_dx + size_dy >= 0; values.border_width = 0; - values.x = client_rect.x; - values.y = client_rect.y; - values.width = client_rect.width; - values.height = client_rect.height; + meta_window_x11_stage_to_protocol (window_x11, + client_rect.x, client_rect.y, + client_rect.width, client_rect.height, + &values.x, &values.y, + &values.width, &values.height); mask = 0; if (is_configure_request && priv->border_width != 0) @@ -1591,6 +1734,10 @@ meta_window_x11_update_struts (MetaWindow *window) strut_begin = struts[4+(i*2)]; strut_end = struts[4+(i*2)+1]; + meta_window_x11_protocol_to_stage (META_WINDOW_X11 (window), + strut_begin, strut_end, thickness, 0, + &strut_begin, &strut_end, &thickness, NULL); + temp = g_new0 (MetaStrut, 1); temp->side = 1 << i; /* See MetaSide def. Matches nicely, eh? */ meta_display_get_size (window->display, @@ -1655,6 +1802,10 @@ meta_window_x11_update_struts (MetaWindow *window) if (thickness == 0) continue; + meta_window_x11_protocol_to_stage (META_WINDOW_X11 (window), + thickness, 0, 0, 0, + &thickness, NULL, NULL, NULL); + temp = g_new0 (MetaStrut, 1); temp->side = 1 << i; meta_display_get_size (window->display, @@ -2040,9 +2191,10 @@ static void meta_window_x11_constructed (GObject *object) { MetaWindow *window = META_WINDOW (object); - MetaWindowX11 *x11_window = META_WINDOW_X11 (object); - MetaWindowX11Private *priv = meta_window_x11_get_instance_private (x11_window); + MetaWindowX11 *window_x11 = META_WINDOW_X11 (object); + MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11); XWindowAttributes attrs = priv->attributes; + MtkRectangle rect; meta_verbose ("attrs->map_state = %d (%s)", attrs.map_state, @@ -2057,16 +2209,17 @@ meta_window_x11_constructed (GObject *object) window->client_type = META_WINDOW_CLIENT_TYPE_X11; window->override_redirect = attrs.override_redirect; - window->rect.x = attrs.x; - window->rect.y = attrs.y; - window->rect.width = attrs.width; - window->rect.height = attrs.height; + meta_window_x11_protocol_to_stage (window_x11, + attrs.x, attrs.y, attrs.width, attrs.height, + &rect.x, &rect.y, &rect.width, &rect.height); + + window->rect = rect; /* size_hints are the "request" */ - window->size_hints.x = attrs.x; - window->size_hints.y = attrs.y; - window->size_hints.width = attrs.width; - window->size_hints.height = attrs.height; + window->size_hints.x = rect.x; + window->size_hints.y = rect.y; + window->size_hints.width = rect.width; + window->size_hints.height = rect.height; window->depth = attrs.depth; priv->xvisual = attrs.visual; @@ -2076,11 +2229,11 @@ meta_window_x11_constructed (GObject *object) window->decorated = TRUE; window->hidden = FALSE; - priv->border_width = attrs.border_width; priv->xclient_leader = None; - priv->keys_grabbed = FALSE; - priv->grab_on_frame = FALSE; + meta_window_x11_protocol_to_stage (window_x11, + attrs.border_width, 0, 0, 0, + &priv->border_width, NULL, NULL, NULL); g_signal_connect (window, "notify::decorated", G_CALLBACK (meta_window_x11_update_input_region), @@ -2192,6 +2345,8 @@ meta_window_x11_class_init (MetaWindowX11Class *klass) klass->thaw_commits = meta_window_x11_impl_thaw_commits; klass->always_update_shape = meta_window_x11_impl_always_update_shape; klass->process_property_notify = meta_window_x11_impl_process_property_notify; + klass->stage_to_protocol = meta_window_x11_real_stage_to_protocol; + klass->protocol_to_stage = meta_window_x11_real_protocol_to_stage; obj_props[PROP_ATTRIBUTES] = g_param_spec_pointer ("attributes", NULL, NULL, @@ -2473,7 +2628,10 @@ meta_window_x11_update_input_region (MetaWindow *window) else { /* Window has a custom shape. */ - region = region_create_from_x_rectangles (rects, n_rects); + g_autoptr (MtkRegion) protocol_region = NULL; + + protocol_region = region_create_from_x_rectangles (rects, n_rects); + region = region_protocol_to_stage (protocol_region, window_x11); } meta_XFree (rects); @@ -2549,7 +2707,10 @@ meta_window_x11_update_shape_region (MetaWindow *window) if (rects) { - region = region_create_from_x_rectangles (rects, n_rects); + g_autoptr (MtkRegion) protocol_region = NULL; + + protocol_region = region_create_from_x_rectangles (rects, n_rects); + region = region_protocol_to_stage (protocol_region, window_x11); XFree (rects); } } @@ -2818,6 +2979,7 @@ meta_window_x11_configure_request (MetaWindow *window, { MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11); + int new_x, new_y, new_width, new_height; /* Note that x, y is the corner of the window border, * and width, height is the size of the window inside @@ -2826,15 +2988,25 @@ meta_window_x11_configure_request (MetaWindow *window, * requested border here. */ if (event->xconfigurerequest.value_mask & CWBorderWidth) - priv->border_width = event->xconfigurerequest.border_width; + { + meta_window_x11_protocol_to_stage (window_x11, + event->xconfigurerequest.border_width, 0, 0, 0, + &priv->border_width, NULL, NULL, NULL); + } - meta_window_move_resize_request(window, - event->xconfigurerequest.value_mask, - window->size_hints.win_gravity, - event->xconfigurerequest.x, - event->xconfigurerequest.y, - event->xconfigurerequest.width, - event->xconfigurerequest.height); + meta_window_x11_protocol_to_stage (window_x11, + event->xconfigurerequest.x, event->xconfigurerequest.y, + event->xconfigurerequest.width, event->xconfigurerequest.height, + &new_x, &new_y, + &new_width, &new_height); + + meta_window_move_resize_request (window, + event->xconfigurerequest.value_mask, + window->size_hints.win_gravity, + new_x, + new_y, + new_width, + new_height); /* Handle stacking. We only handle raises/lowers, mostly because * stack.c really can't deal with anything else. I guess we'll fix @@ -3330,8 +3502,13 @@ meta_window_x11_client_message (MetaWindow *window, guint32 timestamp; MetaWindowDrag *window_drag; - x_root = event->xclient.data.l[0]; - y_root = event->xclient.data.l[1]; + meta_window_x11_protocol_to_stage (window_x11, + event->xclient.data.l[0], + event->xclient.data.l[1], + 0, 0, + &x_root, + &y_root, + NULL, NULL); action = event->xclient.data.l[2]; button = event->xclient.data.l[3]; @@ -3495,6 +3672,7 @@ meta_window_x11_client_message (MetaWindow *window, { MetaGravity gravity; guint value_mask; + int x, y, width, height; gravity = (MetaGravity) (event->xclient.data.l[0] & 0xff); value_mask = (event->xclient.data.l[0] & 0xf00) >> 8; @@ -3503,13 +3681,20 @@ meta_window_x11_client_message (MetaWindow *window, if (gravity == 0) gravity = window->size_hints.win_gravity; + meta_window_x11_protocol_to_stage (window_x11, + event->xclient.data.l[1], + event->xclient.data.l[2], + event->xclient.data.l[3], + event->xclient.data.l[4], + &x, &y, &width, &height); + meta_window_move_resize_request(window, value_mask, gravity, - event->xclient.data.l[1], /* x */ - event->xclient.data.l[2], /* y */ - event->xclient.data.l[3], /* width */ - event->xclient.data.l[4]); /* height */ + x, + y, + width, + height); } else if (event->xclient.message_type == x11_display->atom__NET_ACTIVE_WINDOW && @@ -3566,11 +3751,15 @@ meta_window_x11_client_message (MetaWindow *window, else if (event->xclient.message_type == x11_display->atom__GTK_SHOW_WINDOW_MENU) { - gulong x, y; + int x, y; /* l[0] is device_id, which we don't use */ - x = event->xclient.data.l[1]; - y = event->xclient.data.l[2]; + meta_window_x11_protocol_to_stage (window_x11, + event->xclient.data.l[1], + event->xclient.data.l[2], + 0, 0, + &x, &y, + NULL, NULL); meta_window_show_menu (window, META_WINDOW_MENU_WM, x, y); } @@ -4092,10 +4281,11 @@ meta_window_x11_configure_notify (MetaWindow *window, g_assert (window->override_redirect); g_assert (window->frame == NULL); - window->rect.x = event->x; - window->rect.y = event->y; - window->rect.width = event->width; - window->rect.height = event->height; + meta_window_x11_protocol_to_stage (window_x11, + event->x, event->y, + event->width, event->height, + &window->rect.x, &window->rect.y, + &window->rect.width, &window->rect.height); priv->client_rect = window->rect; window->buffer_rect = window->rect; diff --git a/src/x11/window-x11.h b/src/x11/window-x11.h index 205eaaa632..fa3fbea6a8 100644 --- a/src/x11/window-x11.h +++ b/src/x11/window-x11.h @@ -45,6 +45,24 @@ struct _MetaWindowX11Class gboolean (*always_update_shape) (MetaWindow *window); void (*process_property_notify) (MetaWindow *window, XPropertyEvent *event); + void (*stage_to_protocol) (MetaWindowX11 *window_x11, + int stage_x, + int stage_y, + int stage_width, + int stage_height, + int *protocol_x, + int *protocol_y, + int *protocol_width, + int *protocol_height); + void (*protocol_to_stage) (MetaWindowX11 *window_x11, + int protocol_x, + int protocol_y, + int protocol_width, + int protocol_height, + int *stage_x, + int *stage_y, + int *stage_width, + int *stage_height); }; MetaWindow * meta_window_x11_new (MetaDisplay *display, @@ -112,3 +130,23 @@ gboolean meta_window_x11_has_alpha_channel (MetaWindow *window); META_EXPORT Window meta_window_x11_get_xwindow (MetaWindow *window); + +void meta_window_x11_stage_to_protocol (MetaWindowX11 *window_x11, + int stage_x, + int stage_y, + int stage_width, + int stage_heigth, + int *protocol_x, + int *protocol_y, + int *protocol_width, + int *protocol_height); + +void meta_window_x11_protocol_to_stage (MetaWindowX11 *window_x11, + int protocol_x, + int protocol_y, + int protocol_width, + int protocol_height, + int *stage_x, + int *stage_y, + int *stage_width, + int *stage_heigth); -- 2.46.0 From 6f35aed57a4a98ef878e483958e930840a6667ae Mon Sep 17 00:00:00 2001 From: HydroH Date: Tue, 21 May 2024 19:15:36 +0800 Subject: [PATCH 5/5] Correctly set bounding region for undecorated windows Signed-off-by: Mingi Sung --- src/x11/window-x11.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c index ccbd75d1a9..5f37c634ac 100644 --- a/src/x11/window-x11.c +++ b/src/x11/window-x11.c @@ -2573,8 +2573,13 @@ meta_window_x11_update_input_region (MetaWindow *window) else { xwindow = priv->xwindow; - bounding_rect.width = priv->client_rect.width; - bounding_rect.height = priv->client_rect.height; + meta_window_x11_stage_to_protocol(window_x11, + 0, 0, + priv->client_rect.width, + priv->client_rect.height, + NULL, NULL, + &bounding_rect.width, + &bounding_rect.height); } if (META_X11_DISPLAY_HAS_SHAPE (x11_display)) -- 2.46.0