[mutter/cherry-pick-4f544b63] xwayland: Set xrandr primary output
- From: Marge Bot <marge-bot src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter/cherry-pick-4f544b63] xwayland: Set xrandr primary output
- Date: Tue, 15 Dec 2020 19:34:30 +0000 (UTC)
commit 00e247ed7af9d762186779024bec4c3c5b9439c7
Author: Aleksandr Mezin <mezin alexander gmail com>
Date: Wed Nov 11 12:17:14 2020 +0000
xwayland: Set xrandr primary output
To find XWayland output that should be the primary one, iterate through all
XWayland outputs, and compare their geometry to the geometry of the primary
logical monitor.
To avoid possible race conditions (Mutter's monitor configuration already
updated, but Xrandr not yet), set the output both after Randr notifications and
after 'monitors-changed' signal.
https://gitlab.gnome.org/GNOME/mutter/-/issues/1407
Signed-off-by: Aleksandr Mezin <mezin alexander gmail com>
(cherry picked from commit 4f544b63626aa98a0e706c3862def62b41adb628)
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1638>
src/wayland/meta-wayland-private.h | 4 ++
src/wayland/meta-xwayland-private.h | 3 +
src/wayland/meta-xwayland.c | 115 ++++++++++++++++++++++++++++++++++++
src/x11/events.c | 2 +-
4 files changed, 123 insertions(+), 1 deletion(-)
---
diff --git a/src/wayland/meta-wayland-private.h b/src/wayland/meta-wayland-private.h
index da0b56571d..82a256f60f 100644
--- a/src/wayland/meta-wayland-private.h
+++ b/src/wayland/meta-wayland-private.h
@@ -71,6 +71,10 @@ typedef struct
GList *x11_windows;
MetaXWaylandDnd *dnd;
+
+ gboolean has_xrandr;
+ int rr_event_base;
+ int rr_error_base;
} MetaXWaylandManager;
struct _MetaWaylandCompositor
diff --git a/src/wayland/meta-xwayland-private.h b/src/wayland/meta-xwayland-private.h
index 51dfa633b9..79bf45ade6 100644
--- a/src/wayland/meta-xwayland-private.h
+++ b/src/wayland/meta-xwayland-private.h
@@ -35,6 +35,9 @@ meta_xwayland_complete_init (MetaDisplay *display,
void
meta_xwayland_shutdown (MetaXWaylandManager *manager);
+gboolean
+meta_xwayland_handle_xevent (XEvent *event);
+
/* wl_data_device/X11 selection interoperation */
void meta_xwayland_init_dnd (Display *xdisplay);
void meta_xwayland_shutdown_dnd (Display *xdisplay);
diff --git a/src/wayland/meta-xwayland.c b/src/wayland/meta-xwayland.c
index fc184426ad..cd95d6886a 100644
--- a/src/wayland/meta-xwayland.c
+++ b/src/wayland/meta-xwayland.c
@@ -37,8 +37,10 @@
#include <linux/random.h>
#endif
#include <unistd.h>
+#include <X11/extensions/Xrandr.h>
#include <X11/Xauth.h>
+#include "backends/meta-monitor-manager-private.h"
#include "backends/meta-settings-private.h"
#include "core/main-private.h"
#include "meta/main.h"
@@ -50,6 +52,9 @@ static int display_number_override = -1;
static void meta_xwayland_stop_xserver (MetaXWaylandManager *manager);
+static void
+meta_xwayland_set_primary_output (Display *xdisplay);
+
void
meta_xwayland_associate_window_with_surface (MetaWindow *window,
MetaWaylandSurface *surface)
@@ -833,17 +838,50 @@ meta_xwayland_init (MetaXWaylandManager *manager,
return TRUE;
}
+static void
+monitors_changed_cb (MetaMonitorManager *monitor_manager)
+{
+ MetaX11Display *x11_display = meta_get_display ()->x11_display;
+
+ meta_xwayland_set_primary_output (x11_display->xdisplay);
+}
+
static void
on_x11_display_closing (MetaDisplay *display)
{
Display *xdisplay = meta_x11_display_get_xdisplay (display->x11_display);
meta_xwayland_shutdown_dnd (xdisplay);
+ g_signal_handlers_disconnect_by_func (meta_monitor_manager_get (),
+ monitors_changed_cb,
+ NULL);
g_signal_handlers_disconnect_by_func (display,
on_x11_display_closing,
NULL);
}
+static void
+meta_xwayland_init_xrandr (MetaXWaylandManager *manager,
+ Display *xdisplay)
+{
+ MetaMonitorManager *monitor_manager = meta_monitor_manager_get ();
+
+ manager->has_xrandr = XRRQueryExtension (xdisplay,
+ &manager->rr_event_base,
+ &manager->rr_error_base);
+
+ if (!manager->has_xrandr)
+ return;
+
+ XRRSelectInput (xdisplay, DefaultRootWindow (xdisplay),
+ RRCrtcChangeNotifyMask | RROutputChangeNotifyMask);
+
+ g_signal_connect (monitor_manager, "monitors-changed",
+ G_CALLBACK (monitors_changed_cb), NULL);
+
+ meta_xwayland_set_primary_output (xdisplay);
+}
+
/* To be called right after connecting */
void
meta_xwayland_complete_init (MetaDisplay *display,
@@ -863,6 +901,7 @@ meta_xwayland_complete_init (MetaDisplay *display,
G_CALLBACK (on_x11_display_closing), NULL);
meta_xwayland_init_dnd (xdisplay);
add_local_user_to_xhost (xdisplay);
+ meta_xwayland_init_xrandr (manager, xdisplay);
if (meta_get_x11_display_policy () == META_DISPLAY_POLICY_ON_DEMAND)
{
@@ -904,3 +943,79 @@ meta_xwayland_shutdown (MetaXWaylandManager *manager)
g_clear_pointer (&manager->auth_file, g_free);
}
}
+
+static void
+meta_xwayland_set_primary_output (Display *xdisplay)
+{
+ XRRScreenResources *resources;
+ MetaMonitorManager *monitor_manager;
+ MetaLogicalMonitor *primary_monitor;
+ int i;
+
+ monitor_manager = meta_monitor_manager_get ();
+ primary_monitor =
+ meta_monitor_manager_get_primary_logical_monitor (monitor_manager);
+
+ if (!primary_monitor)
+ return;
+
+ resources = XRRGetScreenResourcesCurrent (xdisplay,
+ DefaultRootWindow (xdisplay));
+ if (!resources)
+ return;
+
+ for (i = 0; i < resources->noutput; i++)
+ {
+ RROutput output_id = resources->outputs[i];
+ XRROutputInfo *xrandr_output;
+ XRRCrtcInfo *crtc_info = NULL;
+ MetaRectangle crtc_geometry;
+
+ xrandr_output = XRRGetOutputInfo (xdisplay, resources, output_id);
+ if (!xrandr_output)
+ continue;
+
+ if (xrandr_output->crtc)
+ crtc_info = XRRGetCrtcInfo (xdisplay, resources, xrandr_output->crtc);
+
+ XRRFreeOutputInfo (xrandr_output);
+
+ if (!crtc_info)
+ continue;
+
+ crtc_geometry.x = crtc_info->x;
+ crtc_geometry.y = crtc_info->y;
+ crtc_geometry.width = crtc_info->width;
+ crtc_geometry.height = crtc_info->height;
+
+ XRRFreeCrtcInfo (crtc_info);
+
+ if (meta_rectangle_equal (&crtc_geometry, &primary_monitor->rect))
+ {
+ XRRSetOutputPrimary (xdisplay, DefaultRootWindow (xdisplay),
+ output_id);
+ break;
+ }
+ }
+
+ XRRFreeScreenResources (resources);
+}
+
+gboolean
+meta_xwayland_handle_xevent (XEvent *event)
+{
+ MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
+ MetaXWaylandManager *manager = &compositor->xwayland_manager;
+
+ if (meta_xwayland_dnd_handle_event (event))
+ return TRUE;
+
+ if (manager->has_xrandr && event->type == manager->rr_event_base + RRNotify)
+ {
+ MetaX11Display *x11_display = meta_get_display ()->x11_display;
+ meta_xwayland_set_primary_output (x11_display->xdisplay);
+ return TRUE;
+ }
+
+ return FALSE;
+}
diff --git a/src/x11/events.c b/src/x11/events.c
index 8c78b2ff1c..6d0e10a3f2 100644
--- a/src/x11/events.c
+++ b/src/x11/events.c
@@ -1793,7 +1793,7 @@ meta_x11_display_handle_xevent (MetaX11Display *x11_display,
#ifdef HAVE_WAYLAND
if (meta_is_wayland_compositor () &&
- meta_xwayland_dnd_handle_event (event))
+ meta_xwayland_handle_xevent (event))
{
bypass_gtk = bypass_compositor = TRUE;
goto out;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]