From faf53a8900a82b09b31c0098b8eb2aca95286ff3 Mon Sep 17 00:00:00 2001 From: yangcheng1203 Date: Mon, 27 Dec 2021 15:17:42 +0800 Subject: [PATCH] provide xwayland --- ...p_viewport-wayland-extension-support.patch | 119 +++++ ...fer_damage-instead-of-surface-damage.patch | 160 ++++++ ...e-output-modes-to-xrandr-output-mode.patch | 207 ++++++++ ...ayland-Use-RandR-1.2-interface-rev-2.patch | 139 ++++++ ...xwayland-Add-per-client-private-data.patch | 80 +++ ...port-for-storing-per-client-per-outp.patch | 149 ++++++ ...port-for-randr-resolution-change-emu.patch | 462 ++++++++++++++++++ ...lRRModeToDisplayMode-helper-function.patch | 101 ++++ ...VidModeGetCurrentRRMode-helper-to-th.patch | 193 ++++++++ ...mode-mode-changing-emulation-support.patch | 236 +++++++++ ...dow_should_enable_viewport-Add-extra.patch | 57 +++ ...AYLAND_RANDR_EMU_MONITOR_RECTS-prope.patch | 205 ++++++++ ...lient-id-for-the-window-manager-clie.patch | 137 ++++++ ...Reuse-viewport-instead-of-recreating.patch | 50 ++ ...Recurse-on-finding-the-none-wm-owner.patch | 81 +++ ...ndow_get_none_wm_owner-return-a-Wind.patch | 82 ++++ ...-emulation-on-client-toplevel-resize.patch | 121 +++++ ...eck-resolution-change-emulation-when.patch | 45 ++ ...Also-hook-screen-s-MoveWindow-method.patch | 83 ++++ ...lated-modes-not-being-removed-when-s.patch | 63 +++ ...l_window_check_resolution_change_emu.patch | 48 ++ ...ting-of-_XWAYLAND_RANDR_EMU_MONITOR_.patch | 76 +++ ...unnecessary-xwl_window_is_toplevel-c.patch | 49 ++ xorg-x11-server.spec | 40 +- 24 files changed, 2981 insertions(+), 2 deletions(-) create mode 100644 0002-xwayland-Add-wp_viewport-wayland-extension-support.patch create mode 100644 0003-xwayland-Use-buffer_damage-instead-of-surface-damage.patch create mode 100644 0004-xwayland-Add-fake-output-modes-to-xrandr-output-mode.patch create mode 100644 0005-xwayland-Use-RandR-1.2-interface-rev-2.patch create mode 100644 0006-xwayland-Add-per-client-private-data.patch create mode 100644 0007-xwayland-Add-support-for-storing-per-client-per-outp.patch create mode 100644 0008-xwayland-Add-support-for-randr-resolution-change-emu.patch create mode 100644 0009-xwayland-Add-xwlRRModeToDisplayMode-helper-function.patch create mode 100644 0010-xwayland-Add-xwlVidModeGetCurrentRRMode-helper-to-th.patch create mode 100644 0011-xwayland-Add-vidmode-mode-changing-emulation-support.patch create mode 100644 0012-xwayland-xwl_window_should_enable_viewport-Add-extra.patch create mode 100644 0013-xwayland-Set-_XWAYLAND_RANDR_EMU_MONITOR_RECTS-prope.patch create mode 100644 0014-xwayland-Cache-client-id-for-the-window-manager-clie.patch create mode 100644 0015-xwayland-Reuse-viewport-instead-of-recreating.patch create mode 100644 0016-xwayland-Recurse-on-finding-the-none-wm-owner.patch create mode 100644 0017-xwayland-Make-window_get_none_wm_owner-return-a-Wind.patch create mode 100644 0018-xwayland-Check-emulation-on-client-toplevel-resize.patch create mode 100644 0019-xwayland-Also-check-resolution-change-emulation-when.patch create mode 100644 0020-xwayland-Also-hook-screen-s-MoveWindow-method.patch create mode 100644 0021-xwayland-Fix-emulated-modes-not-being-removed-when-s.patch create mode 100644 0022-xwayland-Call-xwl_window_check_resolution_change_emu.patch create mode 100644 0023-xwayland-Fix-setting-of-_XWAYLAND_RANDR_EMU_MONITOR_.patch create mode 100644 0024-xwayland-Remove-unnecessary-xwl_window_is_toplevel-c.patch diff --git a/0002-xwayland-Add-wp_viewport-wayland-extension-support.patch b/0002-xwayland-Add-wp_viewport-wayland-extension-support.patch new file mode 100644 index 0000000..441bf4c --- /dev/null +++ b/0002-xwayland-Add-wp_viewport-wayland-extension-support.patch @@ -0,0 +1,119 @@ +From c0981af6a683266e3f2adfdd7d6539104f502233 Mon Sep 17 00:00:00 2001 +From: Robert Mader +Date: Mon, 22 Jan 2018 22:02:32 +0100 +Subject: [PATCH xserver 02/24] xwayland: Add wp_viewport wayland extension + support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This commit adds support for the wayland wp_viewport extension, note +nothing uses this yet. + +This is a preparation patch for adding support for fake mode-changes through +xrandr for apps which want to change the resolution when going fullscreen. + +[hdegoede@redhat.com: Split the code for the extension out into its own patch] + +Reviewed-by: Olivier Fourdan +Acked-by: Michel Dänzer +Signed-off-by: Hans de Goede +(cherry picked from commit 47bba4625339592d08b375bcd8e51029c0000850) +--- + hw/xwayland/Makefile.am | 9 ++++++++- + hw/xwayland/meson.build | 3 +++ + hw/xwayland/xwayland.c | 3 +++ + hw/xwayland/xwayland.h | 2 ++ + 4 files changed, 16 insertions(+), 1 deletion(-) + +diff --git a/hw/xwayland/Makefile.am b/hw/xwayland/Makefile.am +index bc1cb8506..49aae3d8b 100644 +--- a/hw/xwayland/Makefile.am ++++ b/hw/xwayland/Makefile.am +@@ -71,7 +71,9 @@ Xwayland_built_sources += \ + xdg-output-unstable-v1-protocol.c \ + xdg-output-unstable-v1-client-protocol.h \ + linux-dmabuf-unstable-v1-client-protocol.h \ +- linux-dmabuf-unstable-v1-protocol.c ++ linux-dmabuf-unstable-v1-protocol.c \ ++ viewporter-client-protocol.h \ ++ viewporter-protocol.c + + if XWAYLAND_EGLSTREAM + Xwayland_built_sources += \ +@@ -120,6 +122,11 @@ linux-dmabuf-unstable-v1-protocol.c : $(WAYLAND_PROTOCOLS_DATADIR)/unstable/linu + linux-dmabuf-unstable-v1-client-protocol.h : $(WAYLAND_PROTOCOLS_DATADIR)/unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml + $(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@ + ++viewporter-protocol.c: $(WAYLAND_PROTOCOLS_DATADIR)/stable/viewporter/viewporter.xml ++ $(AM_V_GEN)$(WAYLAND_SCANNER) @SCANNER_ARG@ < $< > $@ ++viewporter-client-protocol.h: $(WAYLAND_PROTOCOLS_DATADIR)/stable/viewporter/viewporter.xml ++ $(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@ ++ + wayland-eglstream-client-protocol.h : $(WAYLAND_EGLSTREAM_DATADIR)/wayland-eglstream.xml + $(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@ + wayland-eglstream-controller-client-protocol.h : $(WAYLAND_EGLSTREAM_DATADIR)/wayland-eglstream-controller.xml +diff --git a/hw/xwayland/meson.build b/hw/xwayland/meson.build +index 36bf2133a..4a8d171bb 100644 +--- a/hw/xwayland/meson.build ++++ b/hw/xwayland/meson.build +@@ -21,6 +21,7 @@ tablet_xml = join_paths(protodir, 'unstable', 'tablet', 'tablet-unstable-v2.xml' + kbgrab_xml = join_paths(protodir, 'unstable', 'xwayland-keyboard-grab', 'xwayland-keyboard-grab-unstable-v1.xml') + xdg_output_xml = join_paths(protodir, 'unstable', 'xdg-output', 'xdg-output-unstable-v1.xml') + dmabuf_xml = join_paths(protodir, 'unstable', 'linux-dmabuf', 'linux-dmabuf-unstable-v1.xml') ++viewporter_xml = join_paths(protodir, 'stable', 'viewporter', 'viewporter.xml') + + client_header = generator(scanner, + output : '@BASENAME@-client-protocol.h', +@@ -43,12 +44,14 @@ srcs += client_header.process(tablet_xml) + srcs += client_header.process(kbgrab_xml) + srcs += client_header.process(xdg_output_xml) + srcs += client_header.process(dmabuf_xml) ++srcs += client_header.process(viewporter_xml) + srcs += code.process(relative_xml) + srcs += code.process(pointer_xml) + srcs += code.process(tablet_xml) + srcs += code.process(kbgrab_xml) + srcs += code.process(xdg_output_xml) + srcs += code.process(dmabuf_xml) ++srcs += code.process(viewporter_xml) + + xwayland_glamor = [] + eglstream_srcs = [] +diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c +index ed9f2e3c2..2084f2afb 100644 +--- a/hw/xwayland/xwayland.c ++++ b/hw/xwayland/xwayland.c +@@ -923,6 +923,9 @@ registry_global(void *data, struct wl_registry *registry, uint32_t id, + wl_registry_bind(registry, id, &zxdg_output_manager_v1_interface, 1); + xwl_screen_init_xdg_output(xwl_screen); + } ++ else if (strcmp(interface, "wp_viewporter") == 0) { ++ xwl_screen->viewporter = wl_registry_bind(registry, id, &wp_viewporter_interface, 1); ++ } + #ifdef XWL_HAS_GLAMOR + else if (xwl_screen->glamor) { + xwl_glamor_init_wl_registry(xwl_screen, registry, id, interface, +diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h +index daa719209..f949ea157 100644 +--- a/hw/xwayland/xwayland.h ++++ b/hw/xwayland/xwayland.h +@@ -48,6 +48,7 @@ + #include "xwayland-keyboard-grab-unstable-v1-client-protocol.h" + #include "xdg-output-unstable-v1-client-protocol.h" + #include "linux-dmabuf-unstable-v1-client-protocol.h" ++#include "viewporter-client-protocol.h" + + struct xwl_format { + uint32_t format; +@@ -151,6 +152,7 @@ struct xwl_screen { + struct zwp_pointer_constraints_v1 *pointer_constraints; + struct zwp_xwayland_keyboard_grab_manager_v1 *wp_grab; + struct zxdg_output_manager_v1 *xdg_output_manager; ++ struct wp_viewporter *viewporter; + uint32_t serial; + + #define XWL_FORMAT_ARGB8888 (1 << 0) +-- +2.25.2 + diff --git a/0003-xwayland-Use-buffer_damage-instead-of-surface-damage.patch b/0003-xwayland-Use-buffer_damage-instead-of-surface-damage.patch new file mode 100644 index 0000000..a33623f --- /dev/null +++ b/0003-xwayland-Use-buffer_damage-instead-of-surface-damage.patch @@ -0,0 +1,160 @@ +From 30859f64d1718d1476648dcddbb3d81c2f932828 Mon Sep 17 00:00:00 2001 +From: Robert Mader +Date: Tue, 2 Jul 2019 12:03:12 +0200 +Subject: [PATCH xserver 03/25] xwayland: Use buffer_damage instead of surface + damage if available +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When a viewport is set, damage will only work properly when using +wl_surface_damage_buffer instead of wl_surface_damage. + +When no viewport is set, there should be no difference between +surface and buffer damage. + +This is a preparation patch for using viewport to add support for fake +mode-changes through xrandr for apps which want to change the resolution +when going fullscreen. + +Changes by Hans de Goede : +-Split the damage changes out into their own patch +-Add xwl_surface_damage helper +-Also use buffer_damage / the new helper for the present and cursor code + +Reviewed-by: Olivier Fourdan +Acked-by: Michel Dänzer +Signed-off-by: Hans de Goede +(cherry picked from commit 7c6f17790d3aedb164481264b0f05a8a14103731) +--- + hw/xwayland/xwayland-cursor.c | 12 ++++++------ + hw/xwayland/xwayland-present.c | 10 +++++----- + hw/xwayland/xwayland.c | 29 +++++++++++++++++++++++------ + hw/xwayland/xwayland.h | 3 +++ + 4 files changed, 37 insertions(+), 17 deletions(-) + +diff --git a/hw/xwayland/xwayland-cursor.c b/hw/xwayland/xwayland-cursor.c +index 66720bcc0..cbc715061 100644 +--- a/hw/xwayland/xwayland-cursor.c ++++ b/hw/xwayland/xwayland-cursor.c +@@ -165,9 +165,9 @@ xwl_seat_set_cursor(struct xwl_seat *xwl_seat) + xwl_seat->x_cursor->bits->yhot); + wl_surface_attach(xwl_cursor->surface, + xwl_shm_pixmap_get_wl_buffer(pixmap), 0, 0); +- wl_surface_damage(xwl_cursor->surface, 0, 0, +- xwl_seat->x_cursor->bits->width, +- xwl_seat->x_cursor->bits->height); ++ xwl_surface_damage(xwl_seat->xwl_screen, xwl_cursor->surface, 0, 0, ++ xwl_seat->x_cursor->bits->width, ++ xwl_seat->x_cursor->bits->height); + + xwl_cursor->frame_cb = wl_surface_frame(xwl_cursor->surface); + wl_callback_add_listener(xwl_cursor->frame_cb, &frame_listener, xwl_cursor); +@@ -217,9 +217,9 @@ xwl_tablet_tool_set_cursor(struct xwl_tablet_tool *xwl_tablet_tool) + xwl_seat->x_cursor->bits->yhot); + wl_surface_attach(xwl_cursor->surface, + xwl_shm_pixmap_get_wl_buffer(pixmap), 0, 0); +- wl_surface_damage(xwl_cursor->surface, 0, 0, +- xwl_seat->x_cursor->bits->width, +- xwl_seat->x_cursor->bits->height); ++ xwl_surface_damage(xwl_seat->xwl_screen, xwl_cursor->surface, 0, 0, ++ xwl_seat->x_cursor->bits->width, ++ xwl_seat->x_cursor->bits->height); + + xwl_cursor->frame_cb = wl_surface_frame(xwl_cursor->surface); + wl_callback_add_listener(xwl_cursor->frame_cb, &frame_listener, xwl_cursor); +diff --git a/hw/xwayland/xwayland-present.c b/hw/xwayland/xwayland-present.c +index d177abdd8..f4027f91e 100644 +--- a/hw/xwayland/xwayland-present.c ++++ b/hw/xwayland/xwayland-present.c +@@ -505,11 +505,11 @@ xwl_present_flip(WindowPtr present_window, + /* Realign timer */ + xwl_present_reset_timer(xwl_present_window); + +- wl_surface_damage(xwl_window->surface, +- damage_box->x1 - present_window->drawable.x, +- damage_box->y1 - present_window->drawable.y, +- damage_box->x2 - damage_box->x1, +- damage_box->y2 - damage_box->y1); ++ xwl_surface_damage(xwl_window->xwl_screen, xwl_window->surface, ++ damage_box->x1 - present_window->drawable.x, ++ damage_box->y1 - present_window->drawable.y, ++ damage_box->x2 - damage_box->x1, ++ damage_box->y2 - damage_box->y1); + + wl_surface_commit(xwl_window->surface); + +diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c +index a70c1002f..811257b00 100644 +--- a/hw/xwayland/xwayland.c ++++ b/hw/xwayland/xwayland.c +@@ -792,6 +792,16 @@ xwl_destroy_window(WindowPtr window) + return ret; + } + ++void xwl_surface_damage(struct xwl_screen *xwl_screen, ++ struct wl_surface *surface, ++ int32_t x, int32_t y, int32_t width, int32_t height) ++{ ++ if (wl_surface_get_version(surface) >= WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION) ++ wl_surface_damage_buffer(surface, x, y, width, height); ++ else ++ wl_surface_damage(surface, x, y, width, height); ++} ++ + static void + xwl_window_post_damage(struct xwl_window *xwl_window) + { +@@ -828,13 +838,15 @@ xwl_window_post_damage(struct xwl_window *xwl_window) + */ + if (RegionNumRects(region) > 256) { + box = RegionExtents(region); +- wl_surface_damage(xwl_window->surface, box->x1, box->y1, +- box->x2 - box->x1, box->y2 - box->y1); ++ xwl_surface_damage(xwl_screen, xwl_window->surface, box->x1, box->y1, ++ box->x2 - box->x1, box->y2 - box->y1); + } else { + box = RegionRects(region); +- for (i = 0; i < RegionNumRects(region); i++, box++) +- wl_surface_damage(xwl_window->surface, box->x1, box->y1, +- box->x2 - box->x1, box->y2 - box->y1); ++ for (i = 0; i < RegionNumRects(region); i++, box++) { ++ xwl_surface_damage(xwl_screen, xwl_window->surface, ++ box->x1, box->y1, ++ box->x2 - box->x1, box->y2 - box->y1); ++ } + } + + xwl_window_create_frame_callback(xwl_window); +@@ -893,8 +905,13 @@ registry_global(void *data, struct wl_registry *registry, uint32_t id, + struct xwl_screen *xwl_screen = data; + + if (strcmp(interface, "wl_compositor") == 0) { ++ uint32_t request_version = 1; ++ ++ if (version >= WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION) ++ request_version = WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION; ++ + xwl_screen->compositor = +- wl_registry_bind(registry, id, &wl_compositor_interface, 1); ++ wl_registry_bind(registry, id, &wl_compositor_interface, request_version); + } + else if (strcmp(interface, "wl_shm") == 0) { + xwl_screen->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1); +diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h +index 91ae21eeb..1244d2e91 100644 +--- a/hw/xwayland/xwayland.h ++++ b/hw/xwayland/xwayland.h +@@ -382,6 +382,9 @@ struct xwl_output { + void xwl_window_create_frame_callback(struct xwl_window *xwl_window); + + void xwl_sync_events (struct xwl_screen *xwl_screen); ++void xwl_surface_damage(struct xwl_screen *xwl_screen, ++ struct wl_surface *surface, ++ int32_t x, int32_t y, int32_t width, int32_t height); + + void xwl_screen_roundtrip (struct xwl_screen *xwl_screen); + +-- +2.28.0 + diff --git a/0004-xwayland-Add-fake-output-modes-to-xrandr-output-mode.patch b/0004-xwayland-Add-fake-output-modes-to-xrandr-output-mode.patch new file mode 100644 index 0000000..4e05547 --- /dev/null +++ b/0004-xwayland-Add-fake-output-modes-to-xrandr-output-mode.patch @@ -0,0 +1,207 @@ +From 6ff9bf9f005ce81b587d3b4345232c73fc12da53 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Wed, 26 Jun 2019 16:46:54 +0200 +Subject: [PATCH xserver 04/24] xwayland: Add fake output modes to xrandr + output mode lists +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This is a preparation patch for adding support for apps which want to +change the resolution when they go fullscreen because they are hardcoded +to render at a specific resolution, e.g. 640x480. + +Follow up patches will fake the mode-switch these apps want by using +WPviewport to scale there pixmap to cover the entire output. + +Reviewed-by: Olivier Fourdan +Acked-by: Michel Dänzer +Signed-off-by: Hans de Goede +(cherry picked from commit 0d656d796071fb637e4969ea800855fe5d1c9728) +--- + hw/xwayland/xwayland-output.c | 112 ++++++++++++++++++++++++++++++++-- + hw/xwayland/xwayland.c | 17 ++++++ + hw/xwayland/xwayland.h | 1 + + 3 files changed, 124 insertions(+), 6 deletions(-) + +diff --git a/hw/xwayland/xwayland-output.c b/hw/xwayland/xwayland-output.c +index aa6f37864..2ccc3ca60 100644 +--- a/hw/xwayland/xwayland-output.c ++++ b/hw/xwayland/xwayland-output.c +@@ -245,14 +245,110 @@ update_screen_size(struct xwl_output *xwl_output, int width, int height) + update_desktop_dimensions(); + } + ++/* From hw/xfree86/common/xf86DefModeSet.c with some obscure modes dropped */ ++const int32_t xwl_output_fake_modes[][2] = { ++ /* 4:3 (1.33) */ ++ { 2048, 1536 }, ++ { 1920, 1440 }, ++ { 1600, 1200 }, ++ { 1440, 1080 }, ++ { 1400, 1050 }, ++ { 1280, 1024 }, /* 5:4 (1.25) */ ++ { 1280, 960 }, ++ { 1152, 864 }, ++ { 1024, 768 }, ++ { 800, 600 }, ++ { 640, 480 }, ++ { 320, 240 }, ++ /* 16:10 (1.6) */ ++ { 2560, 1600 }, ++ { 1920, 1200 }, ++ { 1680, 1050 }, ++ { 1440, 900 }, ++ { 1280, 800 }, ++ { 720, 480 }, /* 3:2 (1.5) */ ++ { 640, 400 }, ++ { 320, 200 }, ++ /* 16:9 (1.77) */ ++ { 5120, 2880 }, ++ { 4096, 2304 }, ++ { 3840, 2160 }, ++ { 3200, 1800 }, ++ { 2880, 1620 }, ++ { 2560, 1440 }, ++ { 2048, 1152 }, ++ { 1920, 1080 }, ++ { 1600, 900 }, ++ { 1368, 768 }, ++ { 1280, 720 }, ++ { 1024, 576 }, ++ { 864, 486 }, ++ { 720, 400 }, ++ { 640, 350 }, ++}; ++ ++/* Build an array with RRModes the first mode is the actual output mode, the ++ * rest are fake modes from the xwl_output_fake_modes list. We do this for apps ++ * which want to change resolution when they go fullscreen. ++ * When an app requests a mode-change, we fake it using WPviewport. ++ */ ++static RRModePtr * ++output_get_rr_modes(struct xwl_output *xwl_output, ++ int32_t width, int32_t height, ++ int *count) ++{ ++ struct xwl_screen *xwl_screen = xwl_output->xwl_screen; ++ RRModePtr *rr_modes; ++ int i; ++ ++ rr_modes = xallocarray(ARRAY_SIZE(xwl_output_fake_modes) + 1, sizeof(RRModePtr)); ++ if (!rr_modes) ++ goto err; ++ ++ /* Add actual output mode */ ++ rr_modes[0] = xwayland_cvt(width, height, xwl_output->refresh / 1000.0, 0, 0); ++ if (!rr_modes[0]) ++ goto err; ++ ++ *count = 1; ++ ++ if (!xwl_screen_has_resolution_change_emulation(xwl_screen)) ++ return rr_modes; ++ ++ /* Add fake modes */ ++ for (i = 0; i < ARRAY_SIZE(xwl_output_fake_modes); i++) { ++ /* Skip actual output mode, already added */ ++ if (xwl_output_fake_modes[i][0] == width && ++ xwl_output_fake_modes[i][1] == height) ++ continue; ++ ++ /* Skip modes which are too big, avoid downscaling */ ++ if (xwl_output_fake_modes[i][0] > width || ++ xwl_output_fake_modes[i][1] > height) ++ continue; ++ ++ rr_modes[*count] = xwayland_cvt(xwl_output_fake_modes[i][0], ++ xwl_output_fake_modes[i][1], ++ xwl_output->refresh / 1000.0, 0, 0); ++ if (!rr_modes[*count]) ++ goto err; ++ ++ (*count)++; ++ } ++ ++ return rr_modes; ++err: ++ FatalError("Failed to allocate memory for list of RR modes"); ++} ++ + static void + apply_output_change(struct xwl_output *xwl_output) + { + struct xwl_screen *xwl_screen = xwl_output->xwl_screen; + struct xwl_output *it; +- int mode_width, mode_height; ++ int mode_width, mode_height, count; + int width = 0, height = 0, has_this_output = 0; +- RRModePtr randr_mode; ++ RRModePtr *randr_modes; + Bool need_rotate; + + /* Clear out the "done" received flags */ +@@ -271,12 +367,16 @@ apply_output_change(struct xwl_output *xwl_output) + mode_height = xwl_output->width; + } + +- randr_mode = xwayland_cvt(mode_width, mode_height, +- xwl_output->refresh / 1000.0, 0, 0); +- RROutputSetModes(xwl_output->randr_output, &randr_mode, 1, 1); +- RRCrtcNotify(xwl_output->randr_crtc, randr_mode, ++ /* Build a fresh modes array using the current refresh rate */ ++ randr_modes = output_get_rr_modes(xwl_output, mode_width, mode_height, &count); ++ RROutputSetModes(xwl_output->randr_output, randr_modes, count, 1); ++ RRCrtcNotify(xwl_output->randr_crtc, randr_modes[0], + xwl_output->x, xwl_output->y, + xwl_output->rotation, NULL, 1, &xwl_output->randr_output); ++ /* RROutputSetModes takes ownership of the passed in modes, so we only ++ * have to free the pointer array. ++ */ ++ free(randr_modes); + + xorg_list_for_each_entry(it, &xwl_screen->output_list, link) { + /* output done event is sent even when some property +diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c +index 942981834..3c50396f1 100644 +--- a/hw/xwayland/xwayland.c ++++ b/hw/xwayland/xwayland.c +@@ -152,6 +152,23 @@ xwl_screen_get(ScreenPtr screen) + return dixLookupPrivate(&screen->devPrivates, &xwl_screen_private_key); + } + ++static Bool ++xwl_screen_has_viewport_support(struct xwl_screen *xwl_screen) ++{ ++ return wl_compositor_get_version(xwl_screen->compositor) >= ++ WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION && ++ xwl_screen->viewporter != NULL; ++} ++ ++Bool ++xwl_screen_has_resolution_change_emulation(struct xwl_screen *xwl_screen) ++{ ++ /* Resolution change emulation is only supported in rootless mode and ++ * it requires viewport support. ++ */ ++ return xwl_screen->rootless && xwl_screen_has_viewport_support(xwl_screen); ++} ++ + static void + xwl_window_set_allow_commits(struct xwl_window *xwl_window, Bool allow, + const char *debug_msg) +diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h +index fa78b5ab9..c66997f00 100644 +--- a/hw/xwayland/xwayland.h ++++ b/hw/xwayland/xwayland.h +@@ -389,6 +389,7 @@ void xwl_surface_damage(struct xwl_screen *xwl_screen, + Bool xwl_screen_init_cursor(struct xwl_screen *xwl_screen); + + struct xwl_screen *xwl_screen_get(ScreenPtr screen); ++Bool xwl_screen_has_resolution_change_emulation(struct xwl_screen *xwl_screen); + + void xwl_tablet_tool_set_cursor(struct xwl_tablet_tool *tool); + void xwl_seat_set_cursor(struct xwl_seat *xwl_seat); +-- +2.25.2 + diff --git a/0005-xwayland-Use-RandR-1.2-interface-rev-2.patch b/0005-xwayland-Use-RandR-1.2-interface-rev-2.patch new file mode 100644 index 0000000..8585f82 --- /dev/null +++ b/0005-xwayland-Use-RandR-1.2-interface-rev-2.patch @@ -0,0 +1,139 @@ +From d837f7003d22c5e0d5bd05d41e872e7ee331dfa4 Mon Sep 17 00:00:00 2001 +From: Robert Mader +Date: Mon, 22 Jan 2018 17:57:38 +0100 +Subject: [PATCH xserver 05/24] xwayland: Use RandR 1.2 interface (rev 2) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This adds the RandR 1.2 interface to xwayland and allows modes +advertised by the compositor to be set in an undistructive manner. + +With this patch, applications that try to set the resolution will usually +succeed and work while other apps using the same xwayland +instance are not affected at all. + +The RandR 1.2 interface will be needed to implement fake-mode-setting and +already makes applications work much cleaner and predictive when a mode +was set. + +[hdegoede@redhat.com: Make crtc_set only succeed if the mode matches + the desktop resolution] + +Reviewed-by: Olivier Fourdan +Acked-by: Michel Dänzer +Signed-off-by: Hans de Goede +(cherry picked from commit e89872f51aa834fa9d94a4ca4822f03b0341ab4f) +--- + hw/xwayland/xwayland-output.c | 81 +++++++++++++++++++++++++++++++++++ + 1 file changed, 81 insertions(+) + +diff --git a/hw/xwayland/xwayland-output.c b/hw/xwayland/xwayland-output.c +index 2ccc3ca60..67e99bdab 100644 +--- a/hw/xwayland/xwayland-output.c ++++ b/hw/xwayland/xwayland-output.c +@@ -561,12 +561,80 @@ xwl_randr_get_info(ScreenPtr pScreen, Rotation * rotations) + return TRUE; + } + ++#ifdef RANDR_10_INTERFACE + static Bool + xwl_randr_set_config(ScreenPtr pScreen, + Rotation rotation, int rate, RRScreenSizePtr pSize) + { + return FALSE; + } ++#endif ++ ++#if RANDR_12_INTERFACE ++static Bool ++xwl_randr_screen_set_size(ScreenPtr pScreen, ++ CARD16 width, ++ CARD16 height, ++ CARD32 mmWidth, CARD32 mmHeight) ++{ ++ return TRUE; ++} ++ ++static Bool ++xwl_randr_crtc_set(ScreenPtr pScreen, ++ RRCrtcPtr crtc, ++ RRModePtr mode, ++ int x, ++ int y, ++ Rotation rotation, ++ int numOutputs, RROutputPtr * outputs) ++{ ++ struct xwl_output *xwl_output = crtc->devPrivate; ++ ++ if (!mode || (mode->mode.width == xwl_output->width && ++ mode->mode.height == xwl_output->height)) { ++ RRCrtcChanged(crtc, TRUE); ++ return TRUE; ++ } ++ ++ return FALSE; ++} ++ ++static Bool ++xwl_randr_crtc_set_gamma(ScreenPtr pScreen, RRCrtcPtr crtc) ++{ ++ return TRUE; ++} ++ ++static Bool ++xwl_randr_crtc_get_gamma(ScreenPtr pScreen, RRCrtcPtr crtc) ++{ ++ return TRUE; ++} ++ ++static Bool ++xwl_randr_output_set_property(ScreenPtr pScreen, ++ RROutputPtr output, ++ Atom property, ++ RRPropertyValuePtr value) ++{ ++ return TRUE; ++} ++ ++static Bool ++xwl_output_validate_mode(ScreenPtr pScreen, ++ RROutputPtr output, ++ RRModePtr mode) ++{ ++ return TRUE; ++} ++ ++static void ++xwl_randr_mode_destroy(ScreenPtr pScreen, RRModePtr mode) ++{ ++ return; ++} ++#endif + + Bool + xwl_screen_init_output(struct xwl_screen *xwl_screen) +@@ -580,7 +648,20 @@ xwl_screen_init_output(struct xwl_screen *xwl_screen) + + rp = rrGetScrPriv(xwl_screen->screen); + rp->rrGetInfo = xwl_randr_get_info; ++ ++#if RANDR_10_INTERFACE + rp->rrSetConfig = xwl_randr_set_config; ++#endif ++ ++#if RANDR_12_INTERFACE ++ rp->rrScreenSetSize = xwl_randr_screen_set_size; ++ rp->rrCrtcSet = xwl_randr_crtc_set; ++ rp->rrCrtcSetGamma = xwl_randr_crtc_set_gamma; ++ rp->rrCrtcGetGamma = xwl_randr_crtc_get_gamma; ++ rp->rrOutputSetProperty = xwl_randr_output_set_property; ++ rp->rrOutputValidateMode = xwl_output_validate_mode; ++ rp->rrModeDestroy = xwl_randr_mode_destroy; ++#endif + + return TRUE; + } +-- +2.25.2 + diff --git a/0006-xwayland-Add-per-client-private-data.patch b/0006-xwayland-Add-per-client-private-data.patch new file mode 100644 index 0000000..fc4b473 --- /dev/null +++ b/0006-xwayland-Add-per-client-private-data.patch @@ -0,0 +1,80 @@ +From 80ca38c4428a499a795084dc696c390b707749b9 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Thu, 29 Aug 2019 22:45:12 +0200 +Subject: [PATCH xserver 06/24] xwayland: Add per client private data +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add per client private data, which for now is empty. + +This is a preparation patch for adding randr/vidmode resolution +change emulation. + +Reviewed-by: Olivier Fourdan +Acked-by: Michel Dänzer +Signed-off-by: Hans de Goede +(cherry picked from commit 905cb8b9e27add5f49a45fe167a0005bf05218bc) +--- + hw/xwayland/xwayland.c | 14 ++++++++++++++ + hw/xwayland/xwayland.h | 5 +++++ + 2 files changed, 19 insertions(+) + +diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c +index 3c50396f1..b0e37ceb9 100644 +--- a/hw/xwayland/xwayland.c ++++ b/hw/xwayland/xwayland.c +@@ -135,11 +135,18 @@ ddxProcessArgument(int argc, char *argv[], int i) + return 0; + } + ++static DevPrivateKeyRec xwl_client_private_key; + static DevPrivateKeyRec xwl_window_private_key; + static DevPrivateKeyRec xwl_screen_private_key; + static DevPrivateKeyRec xwl_pixmap_private_key; + static DevPrivateKeyRec xwl_damage_private_key; + ++struct xwl_client * ++xwl_client_get(ClientPtr client) ++{ ++ return dixLookupPrivate(&client->devPrivates, &xwl_client_private_key); ++} ++ + static struct xwl_window * + xwl_window_get(WindowPtr window) + { +@@ -1143,6 +1150,13 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv) + return FALSE; + if (!dixRegisterPrivateKey(&xwl_damage_private_key, PRIVATE_WINDOW, 0)) + return FALSE; ++ /* There are no easy to use new / delete client hooks, we could use a ++ * ClientStateCallback, but it is easier to let the dix code manage the ++ * memory for us. This will zero fill the initial xwl_client data. ++ */ ++ if (!dixRegisterPrivateKey(&xwl_client_private_key, PRIVATE_CLIENT, ++ sizeof(struct xwl_client))) ++ return FALSE; + + dixSetPrivate(&pScreen->devPrivates, &xwl_screen_private_key, xwl_screen); + xwl_screen->screen = pScreen; +diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h +index c66997f00..593e92b64 100644 +--- a/hw/xwayland/xwayland.h ++++ b/hw/xwayland/xwayland.h +@@ -379,8 +379,13 @@ struct xwl_output { + Bool xdg_output_done; + }; + ++struct xwl_client { ++}; ++ + void xwl_window_create_frame_callback(struct xwl_window *xwl_window); + ++struct xwl_client *xwl_client_get(ClientPtr client); ++ + void xwl_sync_events (struct xwl_screen *xwl_screen); + void xwl_surface_damage(struct xwl_screen *xwl_screen, + struct wl_surface *surface, +-- +2.25.2 + diff --git a/0007-xwayland-Add-support-for-storing-per-client-per-outp.patch b/0007-xwayland-Add-support-for-storing-per-client-per-outp.patch new file mode 100644 index 0000000..4d9b532 --- /dev/null +++ b/0007-xwayland-Add-support-for-storing-per-client-per-outp.patch @@ -0,0 +1,149 @@ +From 879fed575deea57462217fc31eb331db8d23637c Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Thu, 29 Aug 2019 23:04:36 +0200 +Subject: [PATCH xserver 07/24] xwayland: Add support for storing per client + per output emulated resolution +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add support for storing per output randr/vidmode emulated resolution +into the per client data. + +Since we do not have a free/delete callback for the client this uses +a simple static array. The entries are tied to a specific output by the +server_output_id, with a server_output_id of 0 indicating a free slot +(0 is the "None" Wayland object id). + +Note that even if we were to store this in a linked list, we would still +need the server_output_id as this is *per client* *per output*. + +This is a preparation patch for adding randr/vidmode resolution +change emulation. + +Reviewed-by: Olivier Fourdan +Acked-by: Michel Dänzer +Signed-off-by: Hans de Goede +(cherry picked from commit aca0a588eb40a5e6669094a2ab7f71ca0ba06b16) +--- + hw/xwayland/xwayland-output.c | 67 +++++++++++++++++++++++++++++++++++ + hw/xwayland/xwayland.h | 17 +++++++++ + 2 files changed, 84 insertions(+) + +diff --git a/hw/xwayland/xwayland-output.c b/hw/xwayland/xwayland-output.c +index 67e99bdab..82ff5db70 100644 +--- a/hw/xwayland/xwayland-output.c ++++ b/hw/xwayland/xwayland-output.c +@@ -245,6 +245,73 @@ update_screen_size(struct xwl_output *xwl_output, int width, int height) + update_desktop_dimensions(); + } + ++struct xwl_emulated_mode * ++xwl_output_get_emulated_mode_for_client(struct xwl_output *xwl_output, ++ ClientPtr client) ++{ ++ struct xwl_client *xwl_client = xwl_client_get(client); ++ int i; ++ ++ if (!xwl_output) ++ return NULL; ++ ++ for (i = 0; i < XWL_CLIENT_MAX_EMULATED_MODES; i++) { ++ if (xwl_client->emulated_modes[i].server_output_id == ++ xwl_output->server_output_id) ++ return &xwl_client->emulated_modes[i]; ++ } ++ ++ return NULL; ++} ++ ++static void ++xwl_output_add_emulated_mode_for_client(struct xwl_output *xwl_output, ++ ClientPtr client, ++ RRModePtr mode, ++ Bool from_vidmode) ++{ ++ struct xwl_client *xwl_client = xwl_client_get(client); ++ struct xwl_emulated_mode *emulated_mode; ++ int i; ++ ++ emulated_mode = xwl_output_get_emulated_mode_for_client(xwl_output, client); ++ if (!emulated_mode) { ++ /* Find a free spot in the emulated modes array */ ++ for (i = 0; i < XWL_CLIENT_MAX_EMULATED_MODES; i++) { ++ if (xwl_client->emulated_modes[i].server_output_id == 0) { ++ emulated_mode = &xwl_client->emulated_modes[i]; ++ break; ++ } ++ } ++ } ++ if (!emulated_mode) { ++ static Bool warned; ++ ++ if (!warned) { ++ ErrorF("Ran out of space for emulated-modes, not adding mode"); ++ warned = TRUE; ++ } ++ ++ return; ++ } ++ ++ emulated_mode->server_output_id = xwl_output->server_output_id; ++ emulated_mode->width = mode->mode.width; ++ emulated_mode->height = mode->mode.height; ++ emulated_mode->from_vidmode = from_vidmode; ++} ++ ++static void ++xwl_output_remove_emulated_mode_for_client(struct xwl_output *xwl_output, ++ ClientPtr client) ++{ ++ struct xwl_emulated_mode *emulated_mode; ++ ++ emulated_mode = xwl_output_get_emulated_mode_for_client(xwl_output, client); ++ if (emulated_mode) ++ memset(emulated_mode, 0, sizeof(*emulated_mode)); ++} ++ + /* From hw/xfree86/common/xf86DefModeSet.c with some obscure modes dropped */ + const int32_t xwl_output_fake_modes[][2] = { + /* 4:3 (1.33) */ +diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h +index 593e92b64..0e6f92e63 100644 +--- a/hw/xwayland/xwayland.h ++++ b/hw/xwayland/xwayland.h +@@ -379,7 +379,21 @@ struct xwl_output { + Bool xdg_output_done; + }; + ++/* Per client per output emulated randr/vidmode resolution info. */ ++struct xwl_emulated_mode { ++ uint32_t server_output_id; ++ int32_t width; ++ int32_t height; ++ Bool from_vidmode; ++}; ++ ++/* Apps which use randr/vidmode to change the mode when going fullscreen, ++ * usually change the mode of only a single monitor, so this should be plenty. ++ */ ++#define XWL_CLIENT_MAX_EMULATED_MODES 16 ++ + struct xwl_client { ++ struct xwl_emulated_mode emulated_modes[XWL_CLIENT_MAX_EMULATED_MODES]; + }; + + void xwl_window_create_frame_callback(struct xwl_window *xwl_window); +@@ -425,6 +439,9 @@ void xwl_output_destroy(struct xwl_output *xwl_output); + + void xwl_output_remove(struct xwl_output *xwl_output); + ++struct xwl_emulated_mode *xwl_output_get_emulated_mode_for_client( ++ struct xwl_output *xwl_output, ClientPtr client); ++ + RRModePtr xwayland_cvt(int HDisplay, int VDisplay, + float VRefresh, Bool Reduced, Bool Interlaced); + +-- +2.25.2 + diff --git a/0008-xwayland-Add-support-for-randr-resolution-change-emu.patch b/0008-xwayland-Add-support-for-randr-resolution-change-emu.patch new file mode 100644 index 0000000..a509852 --- /dev/null +++ b/0008-xwayland-Add-support-for-randr-resolution-change-emu.patch @@ -0,0 +1,462 @@ +From 2f2a6b8556bd104740d76126640abcfe4705047c Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Tue, 2 Jul 2019 11:55:26 +0200 +Subject: [PATCH xserver 08/25] xwayland: Add support for randr-resolution + change emulation using viewport +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add support for per client randr-resolution change emulation using viewport, +for apps which want to change the resolution when going fullscreen. + +Partly based on earlier work on this by Robert Mader + +Note SDL2 and SFML do not restore randr resolution when going from +fullscreen -> windowed, I believe this is caused by us still reporting the +desktop resolution when they query the resolution. This is not a problem +because when windowed the toplevel window size includes the window-decorations +so it never matches the emulated resolution. + +One exception would be the window being resizable in Windowed mode and the +user resizing the window so that including decorations it matches the +emulated resolution *and* the window being at pos 0x0. But this is an +extreme corner case. Still I will submit patches upstream to SDL2 +and SFML to always restore the desktop resolution under Xwayland, +disabling resolution emulation all together when going windowed. + +Reviewed-by: Olivier Fourdan +Acked-by: Michel Dänzer +Signed-off-by: Hans de Goede +(cherry picked from commit d99b9ff0f237d15e7eb507484493c73b393d5dba) +--- + hw/xwayland/xwayland-input.c | 5 + + hw/xwayland/xwayland-output.c | 63 ++++++++++- + hw/xwayland/xwayland.c | 199 ++++++++++++++++++++++++++++++++++ + hw/xwayland/xwayland.h | 15 +++ + 4 files changed, 276 insertions(+), 6 deletions(-) + +diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c +index a05d178ff..7d75a8f54 100644 +--- a/hw/xwayland/xwayland-input.c ++++ b/hw/xwayland/xwayland-input.c +@@ -488,6 +488,11 @@ dispatch_pointer_motion_event(struct xwl_seat *xwl_seat) + int dx = xwl_seat->focus_window->window->drawable.x; + int dy = xwl_seat->focus_window->window->drawable.y; + ++ if (xwl_window_has_viewport_enabled(xwl_seat->focus_window)) { ++ sx *= xwl_seat->focus_window->scale_x; ++ sy *= xwl_seat->focus_window->scale_y; ++ } ++ + x = dx + sx; + y = dy + sy; + } else { +diff --git a/hw/xwayland/xwayland-output.c b/hw/xwayland/xwayland-output.c +index 64794dee7..e09d00108 100644 +--- a/hw/xwayland/xwayland-output.c ++++ b/hw/xwayland/xwayland-output.c +@@ -371,6 +371,42 @@ err: + FatalError("Failed to allocate memory for list of RR modes"); + } + ++RRModePtr ++xwl_output_find_mode(struct xwl_output *xwl_output, ++ int32_t width, int32_t height) ++{ ++ RROutputPtr output = xwl_output->randr_output; ++ int i; ++ ++ /* width & height -1 means we want the actual output mode, which is idx 0 */ ++ if (width == -1 && height == -1 && output->modes) ++ return output->modes[0]; ++ ++ for (i = 0; i < output->numModes; i++) { ++ if (output->modes[i]->mode.width == width && output->modes[i]->mode.height == height) ++ return output->modes[i]; ++ } ++ ++ ErrorF("XWAYLAND: mode %dx%d is not available\n", width, height); ++ return NULL; ++} ++ ++void ++xwl_output_set_emulated_mode(struct xwl_output *xwl_output, ClientPtr client, ++ RRModePtr mode, Bool from_vidmode) ++{ ++ DebugF("XWAYLAND: xwl_output_set_emulated_mode from %s: %dx%d\n", ++ from_vidmode ? "vidmode" : "randr", ++ mode->mode.width, mode->mode.height); ++ ++ if (mode->mode.width == xwl_output->width && mode->mode.height == xwl_output->height) ++ xwl_output_remove_emulated_mode_for_client(xwl_output, client); ++ else ++ xwl_output_add_emulated_mode_for_client(xwl_output, client, mode, from_vidmode); ++ ++ xwl_screen_check_resolution_change_emulation(xwl_output->xwl_screen); ++} ++ + static void + apply_output_change(struct xwl_output *xwl_output) + { +@@ -613,21 +649,36 @@ xwl_randr_screen_set_size(ScreenPtr pScreen, + static Bool + xwl_randr_crtc_set(ScreenPtr pScreen, + RRCrtcPtr crtc, +- RRModePtr mode, ++ RRModePtr new_mode, + int x, + int y, + Rotation rotation, + int numOutputs, RROutputPtr * outputs) + { + struct xwl_output *xwl_output = crtc->devPrivate; ++ RRModePtr mode; + +- if (!mode || (mode->mode.width == xwl_output->width && +- mode->mode.height == xwl_output->height)) { +- RRCrtcChanged(crtc, TRUE); +- return TRUE; ++ if (new_mode) { ++ mode = xwl_output_find_mode(xwl_output, ++ new_mode->mode.width, ++ new_mode->mode.height); ++ } else { ++ mode = xwl_output_find_mode(xwl_output, -1, -1); + } ++ if (!mode) ++ return FALSE; + +- return FALSE; ++ xwl_output_set_emulated_mode(xwl_output, GetCurrentClient(), mode, FALSE); ++ ++ /* A real randr implementation would call: ++ * RRCrtcNotify(xwl_output->randr_crtc, mode, xwl_output->x, xwl_output->y, ++ * xwl_output->rotation, NULL, 1, &xwl_output->randr_output); ++ * here to update the mode reported to clients querying the randr settings ++ * but that influences *all* clients and we do randr mode change emulation ++ * on a per client basis. So we just return success here. ++ */ ++ ++ return TRUE; + } + + static Bool +diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c +index f422cfc29..87870a5f1 100644 +--- a/hw/xwayland/xwayland.c ++++ b/hw/xwayland/xwayland.c +@@ -178,6 +178,23 @@ xwl_screen_has_resolution_change_emulation(struct xwl_screen *xwl_screen) + return xwl_screen->rootless && xwl_screen_has_viewport_support(xwl_screen); + } + ++/* Return the output @ 0x0, falling back to the first output in the list */ ++struct xwl_output * ++xwl_screen_get_first_output(struct xwl_screen *xwl_screen) ++{ ++ struct xwl_output *xwl_output; ++ ++ xorg_list_for_each_entry(xwl_output, &xwl_screen->output_list, link) { ++ if (xwl_output->x == 0 && xwl_output->y == 0) ++ return xwl_output; ++ } ++ ++ if (xorg_list_is_empty(&xwl_screen->output_list)) ++ return NULL; ++ ++ return xorg_list_first_entry(&xwl_screen->output_list, struct xwl_output, link); ++} ++ + static void + xwl_window_set_allow_commits(struct xwl_window *xwl_window, Bool allow, + const char *debug_msg) +@@ -501,6 +518,150 @@ xwl_pixmap_get(PixmapPtr pixmap) + return dixLookupPrivate(&pixmap->devPrivates, &xwl_pixmap_private_key); + } + ++Bool ++xwl_window_has_viewport_enabled(struct xwl_window *xwl_window) ++{ ++ return (xwl_window->viewport != NULL); ++} ++ ++static void ++xwl_window_disable_viewport(struct xwl_window *xwl_window) ++{ ++ assert (xwl_window->viewport); ++ ++ DebugF("XWAYLAND: disabling viewport\n"); ++ wp_viewport_destroy(xwl_window->viewport); ++ xwl_window->viewport = NULL; ++} ++ ++static void ++xwl_window_enable_viewport(struct xwl_window *xwl_window, ++ struct xwl_output *xwl_output, ++ struct xwl_emulated_mode *emulated_mode) ++{ ++ /* If necessary disable old viewport to apply new settings */ ++ if (xwl_window_has_viewport_enabled(xwl_window)) ++ xwl_window_disable_viewport(xwl_window); ++ ++ DebugF("XWAYLAND: enabling viewport %dx%d -> %dx%d\n", ++ emulated_mode->width, emulated_mode->height, ++ xwl_output->width, xwl_output->height); ++ ++ xwl_window->viewport = ++ wp_viewporter_get_viewport(xwl_window->xwl_screen->viewporter, ++ xwl_window->surface); ++ ++ wp_viewport_set_source(xwl_window->viewport, ++ wl_fixed_from_int(0), ++ wl_fixed_from_int(0), ++ wl_fixed_from_int(emulated_mode->width), ++ wl_fixed_from_int(emulated_mode->height)); ++ wp_viewport_set_destination(xwl_window->viewport, ++ xwl_output->width, ++ xwl_output->height); ++ ++ xwl_window->scale_x = (float)emulated_mode->width / xwl_output->width; ++ xwl_window->scale_y = (float)emulated_mode->height / xwl_output->height; ++} ++ ++static Bool ++xwl_screen_client_is_window_manager(struct xwl_screen *xwl_screen, ++ ClientPtr client) ++{ ++ WindowPtr root = xwl_screen->screen->root; ++ OtherClients *others; ++ ++ for (others = wOtherClients(root); others; others = others->next) { ++ if (SameClient(others, client)) { ++ if (others->mask & (SubstructureRedirectMask | ResizeRedirectMask)) ++ return TRUE; ++ } ++ } ++ ++ return FALSE; ++} ++ ++static ClientPtr ++xwl_window_get_owner(struct xwl_window *xwl_window) ++{ ++ WindowPtr window = xwl_window->window; ++ ClientPtr client = wClient(window); ++ ++ /* If the toplevel window is owned by the window-manager, then the ++ * actual client toplevel window has been reparented to a window-manager ++ * decoration window. In that case return the client of the ++ * first *and only* child of the toplevel (decoration) window. ++ */ ++ if (xwl_screen_client_is_window_manager(xwl_window->xwl_screen, client)) { ++ if (window->firstChild && window->firstChild == window->lastChild) ++ return wClient(window->firstChild); ++ else ++ return NULL; /* Should never happen, skip resolution emulation */ ++ } ++ ++ return client; ++} ++ ++static Bool ++xwl_window_should_enable_viewport(struct xwl_window *xwl_window, ++ struct xwl_output **xwl_output_ret, ++ struct xwl_emulated_mode **emulated_mode_ret) ++{ ++ struct xwl_screen *xwl_screen = xwl_window->xwl_screen; ++ struct xwl_emulated_mode *emulated_mode; ++ struct xwl_output *xwl_output; ++ ClientPtr owner; ++ ++ if (!xwl_screen_has_resolution_change_emulation(xwl_screen)) ++ return FALSE; ++ ++ owner = xwl_window_get_owner(xwl_window); ++ if (!owner) ++ return FALSE; ++ ++ /* 1. Test if the window matches the emulated mode on one of the outputs ++ * This path gets hit by most games / libs (e.g. SDL, SFML, OGRE) ++ */ ++ xorg_list_for_each_entry(xwl_output, &xwl_screen->output_list, link) { ++ emulated_mode = xwl_output_get_emulated_mode_for_client(xwl_output, owner); ++ if (!emulated_mode) ++ continue; ++ ++ if (xwl_window->x == xwl_output->x && ++ xwl_window->y == xwl_output->y && ++ xwl_window->width == emulated_mode->width && ++ xwl_window->height == emulated_mode->height) { ++ ++ *emulated_mode_ret = emulated_mode; ++ *xwl_output_ret = xwl_output; ++ return TRUE; ++ } ++ } ++ ++ return FALSE; ++} ++ ++static void ++xwl_window_check_resolution_change_emulation(struct xwl_window *xwl_window) ++{ ++ struct xwl_emulated_mode *emulated_mode; ++ struct xwl_output *xwl_output; ++ ++ if (xwl_window_should_enable_viewport(xwl_window, &xwl_output, &emulated_mode)) ++ xwl_window_enable_viewport(xwl_window, xwl_output, emulated_mode); ++ else if (xwl_window_has_viewport_enabled(xwl_window)) ++ xwl_window_disable_viewport(xwl_window); ++} ++ ++void ++xwl_screen_check_resolution_change_emulation(struct xwl_screen *xwl_screen) ++{ ++ struct xwl_window *xwl_window; ++ ++ xorg_list_for_each_entry(xwl_window, &xwl_screen->window_list, link_window) ++ xwl_window_check_resolution_change_emulation(xwl_window); ++} ++ + static void + xwl_window_init_allow_commits(struct xwl_window *xwl_window) + { +@@ -571,6 +732,8 @@ ensure_surface_for_window(WindowPtr window) + + xwl_window->xwl_screen = xwl_screen; + xwl_window->window = window; ++ xwl_window->width = window->drawable.width; ++ xwl_window->height = window->drawable.height; + xwl_window->surface = wl_compositor_create_surface(xwl_screen->compositor); + if (xwl_window->surface == NULL) { + ErrorF("wl_display_create_surface failed\n"); +@@ -612,6 +775,7 @@ ensure_surface_for_window(WindowPtr window) + + dixSetPrivate(&window->devPrivates, &xwl_window_private_key, xwl_window); + xorg_list_init(&xwl_window->link_damage); ++ xorg_list_add(&xwl_window->link_window, &xwl_screen->window_list); + + #ifdef GLAMOR_HAS_GBM + xorg_list_init(&xwl_window->frame_callback_list); +@@ -705,8 +869,12 @@ xwl_unrealize_window(WindowPtr window) + if (!xwl_window) + return ret; + ++ if (xwl_window_has_viewport_enabled(xwl_window)) ++ xwl_window_disable_viewport(xwl_window); ++ + wl_surface_destroy(xwl_window->surface); + xorg_list_del(&xwl_window->link_damage); ++ xorg_list_del(&xwl_window->link_window); + unregister_damage(window); + + if (xwl_window->frame_callback) +@@ -756,6 +924,33 @@ xwl_set_window_pixmap(WindowPtr window, + ensure_surface_for_window(window); + } + ++static void ++xwl_resize_window(WindowPtr window, ++ int x, int y, ++ unsigned int width, unsigned int height, ++ WindowPtr sib) ++{ ++ ScreenPtr screen = window->drawable.pScreen; ++ struct xwl_screen *xwl_screen; ++ struct xwl_window *xwl_window; ++ ++ xwl_screen = xwl_screen_get(screen); ++ xwl_window = xwl_window_get(window); ++ ++ screen->ResizeWindow = xwl_screen->ResizeWindow; ++ (*screen->ResizeWindow) (window, x, y, width, height, sib); ++ xwl_screen->ResizeWindow = screen->ResizeWindow; ++ screen->ResizeWindow = xwl_resize_window; ++ ++ if (xwl_window) { ++ xwl_window->x = x; ++ xwl_window->y = y; ++ xwl_window->width = width; ++ xwl_window->height = height; ++ xwl_window_check_resolution_change_emulation(xwl_window); ++ } ++} ++ + static void + frame_callback(void *data, + struct wl_callback *callback, +@@ -1233,6 +1428,7 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv) + xorg_list_init(&xwl_screen->output_list); + xorg_list_init(&xwl_screen->seat_list); + xorg_list_init(&xwl_screen->damage_window_list); ++ xorg_list_init(&xwl_screen->window_list); + xwl_screen->depth = 24; + + if (!monitorResolution) +@@ -1332,6 +1528,9 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv) + xwl_screen->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = xwl_close_screen; + ++ xwl_screen->ResizeWindow = pScreen->ResizeWindow; ++ pScreen->ResizeWindow = xwl_resize_window; ++ + if (xwl_screen->rootless) { + xwl_screen->SetWindowPixmap = pScreen->SetWindowPixmap; + pScreen->SetWindowPixmap = xwl_set_window_pixmap; +diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h +index c886d77e9..36c4c4c8b 100644 +--- a/hw/xwayland/xwayland.h ++++ b/hw/xwayland/xwayland.h +@@ -135,10 +135,12 @@ struct xwl_screen { + DestroyWindowProcPtr DestroyWindow; + XYToWindowProcPtr XYToWindow; + SetWindowPixmapProcPtr SetWindowPixmap; ++ ResizeWindowProcPtr ResizeWindow; + + struct xorg_list output_list; + struct xorg_list seat_list; + struct xorg_list damage_window_list; ++ struct xorg_list window_list; + + int wayland_fd; + struct wl_display *display; +@@ -179,9 +181,13 @@ struct xwl_screen { + struct xwl_window { + struct xwl_screen *xwl_screen; + struct wl_surface *surface; ++ struct wp_viewport *viewport; ++ int32_t x, y, width, height; ++ float scale_x, scale_y; + struct wl_shell_surface *shell_surface; + WindowPtr window; + struct xorg_list link_damage; ++ struct xorg_list link_window; + struct wl_callback *frame_callback; + Bool allow_commits; + #ifdef GLAMOR_HAS_GBM +@@ -411,6 +417,9 @@ Bool xwl_screen_init_cursor(struct xwl_screen *xwl_screen); + + struct xwl_screen *xwl_screen_get(ScreenPtr screen); + Bool xwl_screen_has_resolution_change_emulation(struct xwl_screen *xwl_screen); ++struct xwl_output *xwl_screen_get_first_output(struct xwl_screen *xwl_screen); ++void xwl_screen_check_resolution_change_emulation(struct xwl_screen *xwl_screen); ++Bool xwl_window_has_viewport_enabled(struct xwl_window *xwl_window); + + void xwl_tablet_tool_set_cursor(struct xwl_tablet_tool *tool); + void xwl_seat_set_cursor(struct xwl_seat *xwl_seat); +@@ -444,6 +453,12 @@ void xwl_output_remove(struct xwl_output *xwl_output); + struct xwl_emulated_mode *xwl_output_get_emulated_mode_for_client( + struct xwl_output *xwl_output, ClientPtr client); + ++RRModePtr xwl_output_find_mode(struct xwl_output *xwl_output, ++ int32_t width, int32_t height); ++void xwl_output_set_emulated_mode(struct xwl_output *xwl_output, ++ ClientPtr client, RRModePtr mode, ++ Bool from_vidmode); ++ + RRModePtr xwayland_cvt(int HDisplay, int VDisplay, + float VRefresh, Bool Reduced, Bool Interlaced); + +-- +2.28.0 + diff --git a/0009-xwayland-Add-xwlRRModeToDisplayMode-helper-function.patch b/0009-xwayland-Add-xwlRRModeToDisplayMode-helper-function.patch new file mode 100644 index 0000000..403f950 --- /dev/null +++ b/0009-xwayland-Add-xwlRRModeToDisplayMode-helper-function.patch @@ -0,0 +1,101 @@ +From 62e8b2ff7471f1a48b8bac9f41cceecea4931c03 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Mon, 8 Jul 2019 14:00:27 +0200 +Subject: [PATCH xserver 09/24] xwayland: Add xwlRRModeToDisplayMode() helper + function +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This is a preparation patch for adding emulated mode/resolution change +support to Xwayland's XF86 vidmode extension emulation, using the +Wayland viewport extension. + +Reviewed-by: Olivier Fourdan +Acked-by: Michel Dänzer +Signed-off-by: Hans de Goede +(cherry picked from commit 43c80078126f6f33c6ab7d3cf4668733bde03366) +--- + hw/xwayland/xwayland-vidmode.c | 51 +++++++++++++++++++--------------- + 1 file changed, 28 insertions(+), 23 deletions(-) + +diff --git a/hw/xwayland/xwayland-vidmode.c b/hw/xwayland/xwayland-vidmode.c +index 0bcd11401..a59c9f6a9 100644 +--- a/hw/xwayland/xwayland-vidmode.c ++++ b/hw/xwayland/xwayland-vidmode.c +@@ -78,13 +78,37 @@ mode_refresh(const xRRModeInfo *mode_info) + return rate; + } + ++static void ++xwlRRModeToDisplayMode(RRModePtr rrmode, DisplayModePtr mode) ++{ ++ const xRRModeInfo *mode_info = &rrmode->mode; ++ ++ mode->next = mode; ++ mode->prev = mode; ++ mode->name = ""; ++ mode->VScan = 1; ++ mode->Private = NULL; ++ mode->HDisplay = mode_info->width; ++ mode->HSyncStart = mode_info->hSyncStart; ++ mode->HSyncEnd = mode_info->hSyncEnd; ++ mode->HTotal = mode_info->hTotal; ++ mode->HSkew = mode_info->hSkew; ++ mode->VDisplay = mode_info->height; ++ mode->VSyncStart = mode_info->vSyncStart; ++ mode->VSyncEnd = mode_info->vSyncEnd; ++ mode->VTotal = mode_info->vTotal; ++ mode->Flags = mode_info->modeFlags; ++ mode->Clock = mode_info->dotClock / 1000.0; ++ mode->VRefresh = mode_refresh(mode_info); /* Or RRVerticalRefresh() */ ++ mode->HSync = mode_hsync(mode_info); ++} ++ + static Bool + xwlVidModeGetCurrentModeline(ScreenPtr pScreen, DisplayModePtr *mode, int *dotClock) + { + DisplayModePtr pMod; + RROutputPtr output; + RRCrtcPtr crtc; +- xRRModeInfo rrmode; + + pMod = dixLookupPrivate(&pScreen->devPrivates, xwlVidModePrivateKey); + if (pMod == NULL) +@@ -98,30 +122,11 @@ xwlVidModeGetCurrentModeline(ScreenPtr pScreen, DisplayModePtr *mode, int *dotCl + if (crtc == NULL) + return FALSE; + +- rrmode = crtc->mode->mode; +- +- pMod->next = pMod; +- pMod->prev = pMod; +- pMod->name = ""; +- pMod->VScan = 1; +- pMod->Private = NULL; +- pMod->HDisplay = rrmode.width; +- pMod->HSyncStart = rrmode.hSyncStart; +- pMod->HSyncEnd = rrmode.hSyncEnd; +- pMod->HTotal = rrmode.hTotal; +- pMod->HSkew = rrmode.hSkew; +- pMod->VDisplay = rrmode.height; +- pMod->VSyncStart = rrmode.vSyncStart; +- pMod->VSyncEnd = rrmode.vSyncEnd; +- pMod->VTotal = rrmode.vTotal; +- pMod->Flags = rrmode.modeFlags; +- pMod->Clock = rrmode.dotClock / 1000.0; +- pMod->VRefresh = mode_refresh(&rrmode); /* Or RRVerticalRefresh() */ +- pMod->HSync = mode_hsync(&rrmode); +- *mode = pMod; ++ xwlRRModeToDisplayMode(crtc->mode, pMod); + ++ *mode = pMod; + if (dotClock != NULL) +- *dotClock = rrmode.dotClock / 1000.0; ++ *dotClock = pMod->Clock; + + return TRUE; + } +-- +2.25.2 + diff --git a/0010-xwayland-Add-xwlVidModeGetCurrentRRMode-helper-to-th.patch b/0010-xwayland-Add-xwlVidModeGetCurrentRRMode-helper-to-th.patch new file mode 100644 index 0000000..7fa5a19 --- /dev/null +++ b/0010-xwayland-Add-xwlVidModeGetCurrentRRMode-helper-to-th.patch @@ -0,0 +1,193 @@ +From 3ecabb250841ff0423744cd2291aaebf87b4239a Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Mon, 8 Jul 2019 18:35:27 +0200 +Subject: [PATCH xserver 10/24] xwayland: Add xwlVidModeGetCurrentRRMode helper + to the vidmode code +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +crtc->mode reflects the mode set through the xrandr extension, once we +add support for also changing the mode through the vidmode extension this +will no longer correctly reflect the emulated resolution. + +Add a new xwlVidModeGetCurrentRRMode helper which determines the mode by +looking at the emulated_mode instead. + +Likewise add a xwlVidModeGetRRMode helper and use that in +xwlVidModeCheckModeForMonitor/xwlVidModeCheckModeForDriver to allow any +mode listed in the randr_output's mode list. + +This is a preparation patch for adding emulated mode/resolution change +support to Xwayland's XF86 vidmode extension emulation. + +Reviewed-by: Olivier Fourdan +Acked-by: Michel Dänzer +Signed-off-by: Hans de Goede +(cherry picked from commit bcad1b813a04b9f3ff225f57a4baad09bd6315b9) +--- + hw/xwayland/xwayland-vidmode.c | 90 +++++++++++++++++++++------------- + 1 file changed, 56 insertions(+), 34 deletions(-) + +diff --git a/hw/xwayland/xwayland-vidmode.c b/hw/xwayland/xwayland-vidmode.c +index a59c9f6a9..e9aea7269 100644 +--- a/hw/xwayland/xwayland-vidmode.c ++++ b/hw/xwayland/xwayland-vidmode.c +@@ -103,26 +103,56 @@ xwlRRModeToDisplayMode(RRModePtr rrmode, DisplayModePtr mode) + mode->HSync = mode_hsync(mode_info); + } + ++static RRModePtr ++xwlVidModeGetRRMode(ScreenPtr pScreen, int32_t width, int32_t height) ++{ ++ RROutputPtr output = RRFirstOutput(pScreen); ++ ++ if (output == NULL) ++ return NULL; ++ ++ return xwl_output_find_mode(output->devPrivate, width, height); ++} ++ ++static RRModePtr ++xwlVidModeGetCurrentRRMode(ScreenPtr pScreen) ++{ ++ struct xwl_emulated_mode *emulated_mode; ++ struct xwl_output *xwl_output; ++ RROutputPtr output; ++ ++ output = RRFirstOutput(pScreen); ++ if (output == NULL) ++ return NULL; ++ ++ xwl_output = output->devPrivate; ++ emulated_mode = ++ xwl_output_get_emulated_mode_for_client(xwl_output, GetCurrentClient()); ++ ++ if (emulated_mode) { ++ return xwl_output_find_mode(xwl_output, ++ emulated_mode->width, ++ emulated_mode->height); ++ } else { ++ return xwl_output_find_mode(xwl_output, -1, -1); ++ } ++} ++ + static Bool + xwlVidModeGetCurrentModeline(ScreenPtr pScreen, DisplayModePtr *mode, int *dotClock) + { + DisplayModePtr pMod; +- RROutputPtr output; +- RRCrtcPtr crtc; ++ RRModePtr rrmode; + + pMod = dixLookupPrivate(&pScreen->devPrivates, xwlVidModePrivateKey); + if (pMod == NULL) + return FALSE; + +- output = RRFirstOutput(pScreen); +- if (output == NULL) +- return FALSE; +- +- crtc = output->crtc; +- if (crtc == NULL) ++ rrmode = xwlVidModeGetCurrentRRMode(pScreen); ++ if (rrmode == NULL) + return FALSE; + +- xwlRRModeToDisplayMode(crtc->mode, pMod); ++ xwlRRModeToDisplayMode(rrmode, pMod); + + *mode = pMod; + if (dotClock != NULL) +@@ -135,9 +165,10 @@ static vidMonitorValue + xwlVidModeGetMonitorValue(ScreenPtr pScreen, int valtyp, int indx) + { + vidMonitorValue ret = { NULL, }; +- DisplayModePtr pMod; ++ RRModePtr rrmode; + +- if (!xwlVidModeGetCurrentModeline(pScreen, &pMod, NULL)) ++ rrmode = xwlVidModeGetCurrentRRMode(pScreen); ++ if (rrmode == NULL) + return ret; + + switch (valtyp) { +@@ -155,11 +186,11 @@ xwlVidModeGetMonitorValue(ScreenPtr pScreen, int valtyp, int indx) + break; + case VIDMODE_MON_HSYNC_LO: + case VIDMODE_MON_HSYNC_HI: +- ret.f = 100.0 * pMod->HSync; ++ ret.f = mode_hsync(&rrmode->mode) * 100.0; + break; + case VIDMODE_MON_VREFRESH_LO: + case VIDMODE_MON_VREFRESH_HI: +- ret.f = 100.0 * pMod->VRefresh; ++ ret.f = mode_refresh(&rrmode->mode) * 100.0; + break; + } + return ret; +@@ -168,13 +199,13 @@ xwlVidModeGetMonitorValue(ScreenPtr pScreen, int valtyp, int indx) + static int + xwlVidModeGetDotClock(ScreenPtr pScreen, int Clock) + { +- DisplayModePtr pMod; ++ RRModePtr rrmode; + +- if (!xwlVidModeGetCurrentModeline(pScreen, &pMod, NULL)) ++ rrmode = xwlVidModeGetCurrentRRMode(pScreen); ++ if (rrmode == NULL) + return 0; + +- return pMod->Clock; +- ++ return rrmode->mode.dotClock / 1000.0; + } + + static int +@@ -272,14 +303,15 @@ xwlVidModeLockZoom(ScreenPtr pScreen, Bool lock) + static ModeStatus + xwlVidModeCheckModeForMonitor(ScreenPtr pScreen, DisplayModePtr mode) + { +- DisplayModePtr pMod; ++ RRModePtr rrmode; + +- /* This should not happen */ +- if (!xwlVidModeGetCurrentModeline(pScreen, &pMod, NULL)) ++ rrmode = xwlVidModeGetRRMode(pScreen, mode->HDisplay, mode->VDisplay); ++ if (rrmode == NULL) + return MODE_ERROR; + + /* Only support mode with the same HSync/VRefresh as we advertise */ +- if (mode->HSync == pMod->HSync && mode->VRefresh == pMod->VRefresh) ++ if (mode->HSync == mode_hsync(&rrmode->mode) && ++ mode->VRefresh == mode_refresh(&rrmode->mode)) + return MODE_OK; + + /* All the rest is unsupported - If we want to succeed, return MODE_OK instead */ +@@ -289,20 +321,10 @@ xwlVidModeCheckModeForMonitor(ScreenPtr pScreen, DisplayModePtr mode) + static ModeStatus + xwlVidModeCheckModeForDriver(ScreenPtr pScreen, DisplayModePtr mode) + { +- DisplayModePtr pMod; +- +- /* This should not happen */ +- if (!xwlVidModeGetCurrentModeline(pScreen, &pMod, NULL)) +- return MODE_ERROR; +- +- if (mode->HTotal != pMod->HTotal) +- return MODE_BAD_HVALUE; ++ RRModePtr rrmode; + +- if (mode->VTotal != pMod->VTotal) +- return MODE_BAD_VVALUE; +- +- /* Unsupported for now, but pretend it works */ +- return MODE_OK; ++ rrmode = xwlVidModeGetRRMode(pScreen, mode->HDisplay, mode->VDisplay); ++ return rrmode ? MODE_OK : MODE_ERROR; + } + + static void +-- +2.25.2 + diff --git a/0011-xwayland-Add-vidmode-mode-changing-emulation-support.patch b/0011-xwayland-Add-vidmode-mode-changing-emulation-support.patch new file mode 100644 index 0000000..cf706e3 --- /dev/null +++ b/0011-xwayland-Add-vidmode-mode-changing-emulation-support.patch @@ -0,0 +1,236 @@ +From 86e32a877ded8d67ec26ed2bcc06bd80ec2a5915 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Tue, 9 Jul 2019 09:31:13 +0200 +Subject: [PATCH xserver 11/24] xwayland: Add vidmode mode changing emulation + support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add support for fake mode changes using viewport, for apps which want to +change the resolution when going fullscreen. + +Reviewed-by: Olivier Fourdan +Acked-by: Michel Dänzer +Signed-off-by: Hans de Goede +(cherry picked from commit 38de6260816674b5430144cc38a8a27d93d1bf19) +--- + hw/xwayland/xwayland-vidmode.c | 130 ++++++++++++++++++++++----------- + 1 file changed, 86 insertions(+), 44 deletions(-) + +diff --git a/hw/xwayland/xwayland-vidmode.c b/hw/xwayland/xwayland-vidmode.c +index e9aea7269..56aac693a 100644 +--- a/hw/xwayland/xwayland-vidmode.c ++++ b/hw/xwayland/xwayland-vidmode.c +@@ -106,26 +106,25 @@ xwlRRModeToDisplayMode(RRModePtr rrmode, DisplayModePtr mode) + static RRModePtr + xwlVidModeGetRRMode(ScreenPtr pScreen, int32_t width, int32_t height) + { +- RROutputPtr output = RRFirstOutput(pScreen); ++ struct xwl_screen *xwl_screen = xwl_screen_get(pScreen); ++ struct xwl_output *xwl_output = xwl_screen_get_first_output(xwl_screen); + +- if (output == NULL) ++ if (!xwl_output) + return NULL; + +- return xwl_output_find_mode(output->devPrivate, width, height); ++ return xwl_output_find_mode(xwl_output, width, height); + } + + static RRModePtr + xwlVidModeGetCurrentRRMode(ScreenPtr pScreen) + { ++ struct xwl_screen *xwl_screen = xwl_screen_get(pScreen); ++ struct xwl_output *xwl_output = xwl_screen_get_first_output(xwl_screen); + struct xwl_emulated_mode *emulated_mode; +- struct xwl_output *xwl_output; +- RROutputPtr output; + +- output = RRFirstOutput(pScreen); +- if (output == NULL) ++ if (!xwl_output) + return NULL; + +- xwl_output = output->devPrivate; + emulated_mode = + xwl_output_get_emulated_mode_for_client(xwl_output, GetCurrentClient()); + +@@ -199,39 +198,79 @@ xwlVidModeGetMonitorValue(ScreenPtr pScreen, int valtyp, int indx) + static int + xwlVidModeGetDotClock(ScreenPtr pScreen, int Clock) + { +- RRModePtr rrmode; +- +- rrmode = xwlVidModeGetCurrentRRMode(pScreen); +- if (rrmode == NULL) +- return 0; +- +- return rrmode->mode.dotClock / 1000.0; ++ return Clock; + } + + static int + xwlVidModeGetNumOfClocks(ScreenPtr pScreen, Bool *progClock) + { +- return 1; ++ /* We emulate a programmable clock, rather then a fixed set of clocks */ ++ *progClock = TRUE; ++ return 0; + } + + static Bool + xwlVidModeGetClocks(ScreenPtr pScreen, int *Clocks) + { +- *Clocks = xwlVidModeGetDotClock(pScreen, 0); +- +- return TRUE; ++ return FALSE; /* Programmable clock, no clock list */ + } + ++/* GetFirstModeline and GetNextModeline are used from Xext/vidmode.c like this: ++ * if (pVidMode->GetFirstModeline(pScreen, &mode, &dotClock)) { ++ * do { ++ * ... ++ * if (...) ++ * break; ++ * } while (pVidMode->GetNextModeline(pScreen, &mode, &dotClock)); ++ * } ++ * IOW our caller basically always loops over all the modes. There never is a ++ * return to the mainloop between GetFirstModeline and NextModeline calls where ++ * other parts of the server may change our state so we do not need to worry ++ * about xwl_output->randr_output->modes changing underneath us. ++ * Thus we can simply implement these two callbacks by storing the enumeration ++ * index in pVidMode->Next. ++ */ ++ + static Bool + xwlVidModeGetNextModeline(ScreenPtr pScreen, DisplayModePtr *mode, int *dotClock) + { +- return FALSE; ++ struct xwl_screen *xwl_screen = xwl_screen_get(pScreen); ++ struct xwl_output *xwl_output = xwl_screen_get_first_output(xwl_screen); ++ VidModePtr pVidMode; ++ DisplayModePtr pMod; ++ intptr_t index; ++ ++ pMod = dixLookupPrivate(&pScreen->devPrivates, xwlVidModePrivateKey); ++ pVidMode = VidModeGetPtr(pScreen); ++ if (xwl_output == NULL || pMod == NULL || pVidMode == NULL) ++ return FALSE; ++ ++ index = (intptr_t)pVidMode->Next; ++ if (index >= xwl_output->randr_output->numModes) ++ return FALSE; ++ xwlRRModeToDisplayMode(xwl_output->randr_output->modes[index], pMod); ++ index++; ++ pVidMode->Next = (void *)index; ++ ++ *mode = pMod; ++ if (dotClock != NULL) ++ *dotClock = pMod->Clock; ++ ++ return TRUE; + } + + static Bool + xwlVidModeGetFirstModeline(ScreenPtr pScreen, DisplayModePtr *mode, int *dotClock) + { +- return xwlVidModeGetCurrentModeline(pScreen, mode, dotClock); ++ VidModePtr pVidMode; ++ intptr_t index = 0; ++ ++ pVidMode = VidModeGetPtr(pScreen); ++ if (pVidMode == NULL) ++ return FALSE; ++ ++ pVidMode->Next = (void *)index; /* 0 */ ++ return xwlVidModeGetNextModeline(pScreen, mode, dotClock); + } + + static Bool +@@ -251,37 +290,27 @@ xwlVidModeZoomViewport(ScreenPtr pScreen, int zoom) + static Bool + xwlVidModeSetViewPort(ScreenPtr pScreen, int x, int y) + { +- RROutputPtr output; +- RRCrtcPtr crtc; ++ struct xwl_screen *xwl_screen = xwl_screen_get(pScreen); ++ struct xwl_output *xwl_output = xwl_screen_get_first_output(xwl_screen); + +- output = RRFirstOutput(pScreen); +- if (output == NULL) +- return FALSE; +- +- crtc = output->crtc; +- if (crtc == NULL) ++ if (!xwl_output) + return FALSE; + + /* Support only default viewport */ +- return (x == crtc->x && y == crtc->y); ++ return (x == xwl_output->x && y == xwl_output->y); + } + + static Bool + xwlVidModeGetViewPort(ScreenPtr pScreen, int *x, int *y) + { +- RROutputPtr output; +- RRCrtcPtr crtc; ++ struct xwl_screen *xwl_screen = xwl_screen_get(pScreen); ++ struct xwl_output *xwl_output = xwl_screen_get_first_output(xwl_screen); + +- output = RRFirstOutput(pScreen); +- if (output == NULL) ++ if (!xwl_output) + return FALSE; + +- crtc = output->crtc; +- if (crtc == NULL) +- return FALSE; +- +- *x = crtc->x; +- *y = crtc->y; ++ *x = xwl_output->x; ++ *y = xwl_output->y; + + return TRUE; + } +@@ -289,8 +318,19 @@ xwlVidModeGetViewPort(ScreenPtr pScreen, int *x, int *y) + static Bool + xwlVidModeSwitchMode(ScreenPtr pScreen, DisplayModePtr mode) + { +- /* Unsupported for now */ +- return FALSE; ++ struct xwl_screen *xwl_screen = xwl_screen_get(pScreen); ++ struct xwl_output *xwl_output = xwl_screen_get_first_output(xwl_screen); ++ RRModePtr rrmode; ++ ++ if (!xwl_output) ++ return FALSE; ++ ++ rrmode = xwl_output_find_mode(xwl_output, mode->HDisplay, mode->VDisplay); ++ if (rrmode == NULL) ++ return FALSE; ++ ++ xwl_output_set_emulated_mode(xwl_output, GetCurrentClient(), rrmode, TRUE); ++ return TRUE; + } + + static Bool +@@ -344,8 +384,10 @@ xwlVidModeAddModeline(ScreenPtr pScreen, DisplayModePtr mode) + static int + xwlVidModeGetNumOfModes(ScreenPtr pScreen) + { +- /* We have only one mode */ +- return 1; ++ struct xwl_screen *xwl_screen = xwl_screen_get(pScreen); ++ struct xwl_output *xwl_output = xwl_screen_get_first_output(xwl_screen); ++ ++ return xwl_output ? xwl_output->randr_output->numModes : 0; + } + + static Bool +-- +2.25.2 + diff --git a/0012-xwayland-xwl_window_should_enable_viewport-Add-extra.patch b/0012-xwayland-xwl_window_should_enable_viewport-Add-extra.patch new file mode 100644 index 0000000..573ab8e --- /dev/null +++ b/0012-xwayland-xwl_window_should_enable_viewport-Add-extra.patch @@ -0,0 +1,57 @@ +From fd95c9a52e35e994e140a925cfc01587257d4511 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Mon, 26 Aug 2019 12:26:34 +0200 +Subject: [PATCH xserver 12/24] xwayland: xwl_window_should_enable_viewport: + Add extra test +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Games based on the allegro gaming library or on ClanLib-1.0 do not size +their window to match the fullscreen resolution, instead they use a +window covering the entire screen, drawing only the fullscreen resolution +part of it. + +This commit adds a check for these games, so that we correctly apply a +viewport to them making fullscreen work properly for these games under +Xwayland. + +Reviewed-by: Olivier Fourdan +Acked-by: Michel Dänzer +Signed-off-by: Hans de Goede +(cherry picked from commit 0c305dbff8a44f3fa3d6aefd372a967029a7a527) +--- + hw/xwayland/xwayland.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c +index 1ab5b3a28..85036adfe 100644 +--- a/hw/xwayland/xwayland.c ++++ b/hw/xwayland/xwayland.c +@@ -649,6 +649,23 @@ xwl_window_should_enable_viewport(struct xwl_window *xwl_window, + } + } + ++ /* 2. Test if the window uses override-redirect + vidmode ++ * and matches (fully covers) the entire screen. ++ * This path gets hit by: allegro4, ClanLib-1.0. ++ */ ++ xwl_output = xwl_screen_get_first_output(xwl_screen); ++ emulated_mode = xwl_output_get_emulated_mode_for_client(xwl_output, owner); ++ if (xwl_output && xwl_window->window->overrideRedirect && ++ emulated_mode && emulated_mode->from_vidmode && ++ xwl_window->x == 0 && xwl_window->y == 0 && ++ xwl_window->width == xwl_screen->width && ++ xwl_window->height == xwl_screen->height) { ++ ++ *emulated_mode_ret = emulated_mode; ++ *xwl_output_ret = xwl_output; ++ return TRUE; ++ } ++ + return FALSE; + } + +-- +2.25.2 + diff --git a/0013-xwayland-Set-_XWAYLAND_RANDR_EMU_MONITOR_RECTS-prope.patch b/0013-xwayland-Set-_XWAYLAND_RANDR_EMU_MONITOR_RECTS-prope.patch new file mode 100644 index 0000000..f9dd737 --- /dev/null +++ b/0013-xwayland-Set-_XWAYLAND_RANDR_EMU_MONITOR_RECTS-prope.patch @@ -0,0 +1,205 @@ +From 48bc25613f91b69d9ee68e8211f8bf22317aa40a Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Mon, 2 Sep 2019 17:32:45 +0200 +Subject: [PATCH xserver 13/25] xwayland: Set _XWAYLAND_RANDR_EMU_MONITOR_RECTS + property for resolution emulation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Apps using randr to change the resolution when going fullscreen, in +combination with _NET_WM_STATE_FULLSCREEN to tell the window-manager (WM) +to make their window fullscreen, expect the WM to give the fullscreen window +the size of the emulated resolution as would happen when run under Xorg (*). + +We need the WM to emulate this behavior for these apps to work correctly, +with Xwaylands resolution change emulation. For the WM to emulate this, +it needs to know about the emulated resolution for the Windows owning +client for each monitor. + +This commit adds a _XWAYLAND_RANDR_EMU_MONITOR_RECTS property, which +contains 4 Cardinals (32 bit integers) per monitor with resolution +emulation info. Window-managers can use this to get the emulated +resolution for the client and size the window correctly. + +*) Since under Xorg the resolution will actually be changed and after that +going fullscreen through NET_WM_STATE_FULLSCREEN will size the window to +be equal to the new resolution. + +Reviewed-by: Olivier Fourdan +Acked-by: Michel Dänzer +Signed-off-by: Hans de Goede +(cherry picked from commit 5315f988d9f175e4850f4259f691a68d95ce7ac2) +--- + hw/xwayland/xwayland-output.c | 77 +++++++++++++++++++++++++++++++++++ + hw/xwayland/xwayland.c | 23 +++++++++++ + hw/xwayland/xwayland.h | 3 ++ + 3 files changed, 103 insertions(+) + +diff --git a/hw/xwayland/xwayland-output.c b/hw/xwayland/xwayland-output.c +index e09d00108..0d6b9ac9f 100644 +--- a/hw/xwayland/xwayland-output.c ++++ b/hw/xwayland/xwayland-output.c +@@ -29,6 +29,7 @@ + + #include "xwayland.h" + #include ++#include + + #define ALL_ROTATIONS (RR_Rotate_0 | \ + RR_Rotate_90 | \ +@@ -391,6 +392,80 @@ xwl_output_find_mode(struct xwl_output *xwl_output, + return NULL; + } + ++struct xwl_output_randr_emu_prop { ++ Atom atom; ++ uint32_t rects[XWL_CLIENT_MAX_EMULATED_MODES][4]; ++ int rect_count; ++}; ++ ++static void ++xwl_output_randr_emu_prop(struct xwl_screen *xwl_screen, ClientPtr client, ++ struct xwl_output_randr_emu_prop *prop) ++{ ++ static const char atom_name[] = "_XWAYLAND_RANDR_EMU_MONITOR_RECTS"; ++ struct xwl_emulated_mode *emulated_mode; ++ struct xwl_output *xwl_output; ++ int index = 0; ++ ++ prop->atom = MakeAtom(atom_name, strlen(atom_name), TRUE); ++ ++ xorg_list_for_each_entry(xwl_output, &xwl_screen->output_list, link) { ++ emulated_mode = xwl_output_get_emulated_mode_for_client(xwl_output, client); ++ if (!emulated_mode) ++ continue; ++ ++ prop->rects[index][0] = xwl_output->x; ++ prop->rects[index][1] = xwl_output->y; ++ prop->rects[index][2] = emulated_mode->width; ++ prop->rects[index][3] = emulated_mode->height; ++ index++; ++ } ++ ++ prop->rect_count = index; ++} ++ ++static void ++xwl_output_set_randr_emu_prop(WindowPtr window, ++ struct xwl_output_randr_emu_prop *prop) ++{ ++ if (!xwl_window_is_toplevel(window)) ++ return; ++ ++ if (prop->rect_count) { ++ dixChangeWindowProperty(serverClient, window, prop->atom, ++ XA_CARDINAL, 32, PropModeReplace, ++ prop->rect_count * 4, prop->rects, TRUE); ++ } else { ++ DeleteProperty(serverClient, window, prop->atom); ++ } ++} ++ ++static void ++xwl_output_set_randr_emu_prop_callback(void *resource, XID id, void *user_data) ++{ ++ xwl_output_set_randr_emu_prop(resource, user_data); ++} ++ ++static void ++xwl_output_set_randr_emu_props(struct xwl_screen *xwl_screen, ClientPtr client) ++{ ++ struct xwl_output_randr_emu_prop prop = {}; ++ ++ xwl_output_randr_emu_prop(xwl_screen, client, &prop); ++ FindClientResourcesByType(client, RT_WINDOW, ++ xwl_output_set_randr_emu_prop_callback, &prop); ++} ++ ++void ++xwl_output_set_window_randr_emu_props(struct xwl_screen *xwl_screen, ++ WindowPtr window) ++{ ++ struct xwl_output_randr_emu_prop prop = {}; ++ ++ xwl_output_randr_emu_prop(xwl_screen, wClient(window), &prop); ++ xwl_output_set_randr_emu_prop(window, &prop); ++} ++ + void + xwl_output_set_emulated_mode(struct xwl_output *xwl_output, ClientPtr client, + RRModePtr mode, Bool from_vidmode) +@@ -405,6 +480,8 @@ xwl_output_set_emulated_mode(struct xwl_output *xwl_output, ClientPtr client, + xwl_output_add_emulated_mode_for_client(xwl_output, client, mode, from_vidmode); + + xwl_screen_check_resolution_change_emulation(xwl_output->xwl_screen); ++ ++ xwl_output_set_randr_emu_props(xwl_output->xwl_screen, client); + } + + static void +diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c +index 9175396f7..32442d88e 100644 +--- a/hw/xwayland/xwayland.c ++++ b/hw/xwayland/xwayland.c +@@ -679,6 +679,27 @@ xwl_screen_check_resolution_change_emulation(struct xwl_screen *xwl_screen) + xwl_window_check_resolution_change_emulation(xwl_window); + } + ++/* This checks if the passed in Window is a toplevel client window, note this ++ * returns false for window-manager decoration windows and returns true for ++ * the actual client top-level window even if it has been reparented to ++ * a window-manager decoration window. ++ */ ++Bool ++xwl_window_is_toplevel(WindowPtr window) ++{ ++ struct xwl_screen *xwl_screen = xwl_screen_get(window->drawable.pScreen); ++ ++ if (xwl_screen_client_is_window_manager(xwl_screen, wClient(window))) ++ return FALSE; ++ ++ /* CSD and override-redirect toplevel windows */ ++ if (window_get_damage(window)) ++ return TRUE; ++ ++ /* Normal toplevel client windows, reparented to decoration window */ ++ return (window->parent && window_get_damage(window->parent)); ++} ++ + static void + xwl_window_init_allow_commits(struct xwl_window *xwl_window) + { +@@ -844,6 +865,8 @@ xwl_realize_window(WindowPtr window) + return FALSE; + } + ++ xwl_output_set_window_randr_emu_props(xwl_screen, window); ++ + return ensure_surface_for_window(window); + } + +diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h +index 36c4c4c8b..1317ae5bb 100644 +--- a/hw/xwayland/xwayland.h ++++ b/hw/xwayland/xwayland.h +@@ -420,6 +420,7 @@ Bool xwl_screen_has_resolution_change_emulation(struct xwl_screen *xwl_screen); + struct xwl_output *xwl_screen_get_first_output(struct xwl_screen *xwl_screen); + void xwl_screen_check_resolution_change_emulation(struct xwl_screen *xwl_screen); + Bool xwl_window_has_viewport_enabled(struct xwl_window *xwl_window); ++Bool xwl_window_is_toplevel(WindowPtr window); + + void xwl_tablet_tool_set_cursor(struct xwl_tablet_tool *tool); + void xwl_seat_set_cursor(struct xwl_seat *xwl_seat); +@@ -458,6 +459,8 @@ RRModePtr xwl_output_find_mode(struct xwl_output *xwl_output, + void xwl_output_set_emulated_mode(struct xwl_output *xwl_output, + ClientPtr client, RRModePtr mode, + Bool from_vidmode); ++void xwl_output_set_window_randr_emu_props(struct xwl_screen *xwl_screen, ++ WindowPtr window); + + RRModePtr xwayland_cvt(int HDisplay, int VDisplay, + float VRefresh, Bool Reduced, Bool Interlaced); +-- +2.28.0 + \ No newline at end of file diff --git a/0014-xwayland-Cache-client-id-for-the-window-manager-clie.patch b/0014-xwayland-Cache-client-id-for-the-window-manager-clie.patch new file mode 100644 index 0000000..08c605f --- /dev/null +++ b/0014-xwayland-Cache-client-id-for-the-window-manager-clie.patch @@ -0,0 +1,137 @@ +From aa0f9ba1aa3f12f7e65ed64ac03114f27c8bff1f Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Mon, 27 Jan 2020 11:08:00 +0100 +Subject: [PATCH xserver 14/24] xwayland: Cache client-id for the + window-manager client + +Instead of iterating over all clients which are listening for events on the +root window and checking if the client we are dealing with is the one +listening for SubstructureRedirectMask | ResizeRedirectMask events and thus +is the window-manager, cache the client-id of the window-manager in +xwl_screen and use that when checking if a client is the window-manager. + +Note that we cache and compare the client-id rather then the ClienPtr, +this saves reading the ClientPtr from the global clients array when doing +the comparison. + +Suggested-by: Olivier Fourdan +Acked-by: Olivier Fourdan +Signed-off-by: Hans de Goede +(cherry picked from commit ded89300c1dd541f59fe6e93c5c69d7fe7088244) +--- + hw/xwayland/xwayland.c | 48 ++++++++++++++++++++++++++++-------------- + hw/xwayland/xwayland.h | 2 ++ + 2 files changed, 34 insertions(+), 16 deletions(-) + +diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c +index e43f3de96..f4d433bca 100644 +--- a/hw/xwayland/xwayland.c ++++ b/hw/xwayland/xwayland.c +@@ -576,20 +576,11 @@ xwl_window_enable_viewport(struct xwl_window *xwl_window, + } + + static Bool +-xwl_screen_client_is_window_manager(struct xwl_screen *xwl_screen, +- ClientPtr client) ++window_is_wm_window(WindowPtr window) + { +- WindowPtr root = xwl_screen->screen->root; +- OtherClients *others; +- +- for (others = wOtherClients(root); others; others = others->next) { +- if (SameClient(others, client)) { +- if (others->mask & (SubstructureRedirectMask | ResizeRedirectMask)) +- return TRUE; +- } +- } ++ struct xwl_screen *xwl_screen = xwl_screen_get(window->drawable.pScreen); + +- return FALSE; ++ return CLIENT_ID(window->drawable.id) == xwl_screen->wm_client_id; + } + + static ClientPtr +@@ -603,7 +594,7 @@ xwl_window_get_owner(struct xwl_window *xwl_window) + * decoration window. In that case return the client of the + * first *and only* child of the toplevel (decoration) window. + */ +- if (xwl_screen_client_is_window_manager(xwl_window->xwl_screen, client)) { ++ if (window_is_wm_window(window)) { + if (window->firstChild && window->firstChild == window->lastChild) + return wClient(window->firstChild); + else +@@ -698,9 +689,7 @@ xwl_screen_check_resolution_change_emulation(struct xwl_screen *xwl_screen) + Bool + xwl_window_is_toplevel(WindowPtr window) + { +- struct xwl_screen *xwl_screen = xwl_screen_get(window->drawable.pScreen); +- +- if (xwl_screen_client_is_window_manager(xwl_screen, wClient(window))) ++ if (window_is_wm_window(window)) + return FALSE; + + /* CSD and override-redirect toplevel windows */ +@@ -975,6 +964,30 @@ xwl_set_window_pixmap(WindowPtr window, + ensure_surface_for_window(window); + } + ++static Bool ++xwl_change_window_attributes(WindowPtr window, unsigned long mask) ++{ ++ ScreenPtr screen = window->drawable.pScreen; ++ struct xwl_screen *xwl_screen = xwl_screen_get(screen); ++ OtherClients *others; ++ Bool ret; ++ ++ screen->ChangeWindowAttributes = xwl_screen->ChangeWindowAttributes; ++ ret = (*screen->ChangeWindowAttributes) (window, mask); ++ xwl_screen->ChangeWindowAttributes = screen->ChangeWindowAttributes; ++ screen->ChangeWindowAttributes = xwl_change_window_attributes; ++ ++ if (window != screen->root || !(mask & CWEventMask)) ++ return ret; ++ ++ for (others = wOtherClients(window); others; others = others->next) { ++ if (others->mask & (SubstructureRedirectMask | ResizeRedirectMask)) ++ xwl_screen->wm_client_id = CLIENT_ID(others->resource); ++ } ++ ++ return ret; ++} ++ + static void + xwl_resize_window(WindowPtr window, + int x, int y, +@@ -1552,6 +1565,9 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv) + xwl_screen->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = xwl_close_screen; + ++ xwl_screen->ChangeWindowAttributes = pScreen->ChangeWindowAttributes; ++ pScreen->ChangeWindowAttributes = xwl_change_window_attributes; ++ + xwl_screen->ResizeWindow = pScreen->ResizeWindow; + pScreen->ResizeWindow = xwl_resize_window; + +diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h +index eb8c4bd70..126af8823 100644 +--- a/hw/xwayland/xwayland.h ++++ b/hw/xwayland/xwayland.h +@@ -118,6 +118,7 @@ struct xwl_screen { + int height; + int depth; + ScreenPtr screen; ++ int wm_client_id; + int expecting_event; + enum RootClipMode root_clip_mode; + +@@ -135,6 +136,7 @@ struct xwl_screen { + DestroyWindowProcPtr DestroyWindow; + XYToWindowProcPtr XYToWindow; + SetWindowPixmapProcPtr SetWindowPixmap; ++ ChangeWindowAttributesProcPtr ChangeWindowAttributes; + ResizeWindowProcPtr ResizeWindow; + + struct xorg_list output_list; +-- +2.25.2 + diff --git a/0015-xwayland-Reuse-viewport-instead-of-recreating.patch b/0015-xwayland-Reuse-viewport-instead-of-recreating.patch new file mode 100644 index 0000000..3f6cb2d --- /dev/null +++ b/0015-xwayland-Reuse-viewport-instead-of-recreating.patch @@ -0,0 +1,50 @@ +From 1f39cb2ef51c72ec0c448c5d9571540bb0d9f3eb Mon Sep 17 00:00:00 2001 +From: Roman Gilg +Date: Fri, 3 Jan 2020 17:12:14 +0100 +Subject: [PATCH xserver 15/24] xwayland: Reuse viewport instead of recreating + +When a viewport is already created we can reuse this object instead of +destroying it and getting a new one for updating the source rectangle and +destination size. + +Signed-off-by: Roman Gilg +Reviewed-by: Hans de Goede +Acked-by: Olivier Fourdan +Signed-off-by: Hans de Goede +(cherry picked from commit 948e02872feb641a176b3af82b6ef1201c97bb16) +--- + hw/xwayland/xwayland.c | 18 +++++++----------- + 1 file changed, 7 insertions(+), 11 deletions(-) + +diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c +index f4d433bca..320589dde 100644 +--- a/hw/xwayland/xwayland.c ++++ b/hw/xwayland/xwayland.c +@@ -550,17 +550,13 @@ xwl_window_enable_viewport(struct xwl_window *xwl_window, + struct xwl_output *xwl_output, + struct xwl_emulated_mode *emulated_mode) + { +- /* If necessary disable old viewport to apply new settings */ +- if (xwl_window_has_viewport_enabled(xwl_window)) +- xwl_window_disable_viewport(xwl_window); +- +- DebugF("XWAYLAND: enabling viewport %dx%d -> %dx%d\n", +- emulated_mode->width, emulated_mode->height, +- xwl_output->width, xwl_output->height); +- +- xwl_window->viewport = +- wp_viewporter_get_viewport(xwl_window->xwl_screen->viewporter, +- xwl_window->surface); ++ if (!xwl_window_has_viewport_enabled(xwl_window)) { ++ DebugF("XWAYLAND: enabling viewport %dx%d -> %dx%d\n", ++ emulated_mode->width, emulated_mode->height, ++ xwl_output->width, xwl_output->height); ++ xwl_window->viewport = wp_viewporter_get_viewport(xwl_window->xwl_screen->viewporter, ++ xwl_window->surface); ++ } + + wp_viewport_set_source(xwl_window->viewport, + wl_fixed_from_int(0), +-- +2.25.2 + diff --git a/0016-xwayland-Recurse-on-finding-the-none-wm-owner.patch b/0016-xwayland-Recurse-on-finding-the-none-wm-owner.patch new file mode 100644 index 0000000..8299c92 --- /dev/null +++ b/0016-xwayland-Recurse-on-finding-the-none-wm-owner.patch @@ -0,0 +1,81 @@ +From 8cedbfd448edf410a45c57addcee0e7304f11b86 Mon Sep 17 00:00:00 2001 +From: Roman Gilg +Date: Fri, 3 Jan 2020 17:27:28 +0100 +Subject: [PATCH xserver 16/24] xwayland: Recurse on finding the none-wm owner + +An X11 window manager might add a chain of parent windows when reparenting to a +decoration window. + +That is for example the case for KWin, which reparents client windows to one +decoration and another wrapper parent window. + +Account for that by a recursion into the tree. For now assume as before that +all X11 window managers reparent with one child only for these parent windows. + +Changes by Hans de Goede: +- Move the xwl_window_is_toplevel() from a later patch in this series here + as it really belongs together with these changes +- Drop no longer necessary xwl_window argument from window_get_none_wm_owner + parameters + +Signed-off-by: Roman Gilg +Reviewed-by: Hans de Goede +Acked-by: Olivier Fourdan +Signed-off-by: Hans de Goede +(cherry picked from commit a69f7fbb54efc8ffad320c8afd23cb41fc9edc27) +--- + hw/xwayland/xwayland.c | 17 ++++++++--------- + 1 file changed, 8 insertions(+), 9 deletions(-) + +diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c +index 320589dde..f42b80b90 100644 +--- a/hw/xwayland/xwayland.c ++++ b/hw/xwayland/xwayland.c +@@ -580,19 +580,18 @@ window_is_wm_window(WindowPtr window) + } + + static ClientPtr +-xwl_window_get_owner(struct xwl_window *xwl_window) ++window_get_none_wm_owner(WindowPtr window) + { +- WindowPtr window = xwl_window->window; + ClientPtr client = wClient(window); + + /* If the toplevel window is owned by the window-manager, then the +- * actual client toplevel window has been reparented to a window-manager +- * decoration window. In that case return the client of the +- * first *and only* child of the toplevel (decoration) window. ++ * actual client toplevel window has been reparented to some window-manager ++ * decoration/wrapper windows. In that case recurse by checking the client ++ * of the first *and only* child of the decoration/wrapper window. + */ + if (window_is_wm_window(window)) { + if (window->firstChild && window->firstChild == window->lastChild) +- return wClient(window->firstChild); ++ return window_get_none_wm_owner(window->firstChild); + else + return NULL; /* Should never happen, skip resolution emulation */ + } +@@ -613,7 +612,7 @@ xwl_window_should_enable_viewport(struct xwl_window *xwl_window, + if (!xwl_screen_has_resolution_change_emulation(xwl_screen)) + return FALSE; + +- owner = xwl_window_get_owner(xwl_window); ++ owner = window_get_none_wm_owner(xwl_window->window); + if (!owner) + return FALSE; + +@@ -692,8 +691,8 @@ xwl_window_is_toplevel(WindowPtr window) + if (window_get_damage(window)) + return TRUE; + +- /* Normal toplevel client windows, reparented to decoration window */ +- return (window->parent && window_get_damage(window->parent)); ++ /* Normal toplevel client windows, reparented to a window-manager window */ ++ return window->parent && window_is_wm_window(window->parent); + } + + static void +-- +2.25.2 + diff --git a/0017-xwayland-Make-window_get_none_wm_owner-return-a-Wind.patch b/0017-xwayland-Make-window_get_none_wm_owner-return-a-Wind.patch new file mode 100644 index 0000000..b9a2331 --- /dev/null +++ b/0017-xwayland-Make-window_get_none_wm_owner-return-a-Wind.patch @@ -0,0 +1,82 @@ +From 939a78925a1d591e6aaf291a6609b9c6e54ee6ce Mon Sep 17 00:00:00 2001 +From: Roman Gilg +Date: Wed, 15 Jan 2020 10:07:58 +0100 +Subject: [PATCH xserver 17/24] xwayland: Make window_get_none_wm_owner return + a Window instead of a Client + +Make window_get_none_wm_owner return the first non-wm-window instead of the +owner (client) of the first non-wm-window and rename it to +window_get_client_toplevel to match its new behavior. + +This is a preparation patch for switching to using the drawable coordinates +in xwl_window_should_enable_viewport() + +Changes by Hans de Goede: +- Split this change out into a separate patch for easier reviewing +- Rename window_get_none_wm_owner to window_get_client_toplevel to match + its new behavior + +Signed-off-by: Roman Gilg +Acked-by: Olivier Fourdan +Signed-off-by: Hans de Goede +(cherry picked from commit 060f10062eb1761515b762b46cba56c7a53db72c) +--- + hw/xwayland/xwayland.c | 17 ++++++++++------- + 1 file changed, 10 insertions(+), 7 deletions(-) + +diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c +index f42b80b90..d70d729ae 100644 +--- a/hw/xwayland/xwayland.c ++++ b/hw/xwayland/xwayland.c +@@ -579,10 +579,10 @@ window_is_wm_window(WindowPtr window) + return CLIENT_ID(window->drawable.id) == xwl_screen->wm_client_id; + } + +-static ClientPtr +-window_get_none_wm_owner(WindowPtr window) ++static WindowPtr ++window_get_client_toplevel(WindowPtr window) + { +- ClientPtr client = wClient(window); ++ assert(window); + + /* If the toplevel window is owned by the window-manager, then the + * actual client toplevel window has been reparented to some window-manager +@@ -591,12 +591,12 @@ window_get_none_wm_owner(WindowPtr window) + */ + if (window_is_wm_window(window)) { + if (window->firstChild && window->firstChild == window->lastChild) +- return window_get_none_wm_owner(window->firstChild); ++ return window_get_client_toplevel(window->firstChild); + else + return NULL; /* Should never happen, skip resolution emulation */ + } + +- return client; ++ return window; + } + + static Bool +@@ -608,14 +608,17 @@ xwl_window_should_enable_viewport(struct xwl_window *xwl_window, + struct xwl_emulated_mode *emulated_mode; + struct xwl_output *xwl_output; + ClientPtr owner; ++ WindowPtr window; + + if (!xwl_screen_has_resolution_change_emulation(xwl_screen)) + return FALSE; + +- owner = window_get_none_wm_owner(xwl_window->window); +- if (!owner) ++ window = window_get_client_toplevel(xwl_window->window); ++ if (!window) + return FALSE; + ++ owner = wClient(window); ++ + /* 1. Test if the window matches the emulated mode on one of the outputs + * This path gets hit by most games / libs (e.g. SDL, SFML, OGRE) + */ +-- +2.25.2 + diff --git a/0018-xwayland-Check-emulation-on-client-toplevel-resize.patch b/0018-xwayland-Check-emulation-on-client-toplevel-resize.patch new file mode 100644 index 0000000..dcc0f5e --- /dev/null +++ b/0018-xwayland-Check-emulation-on-client-toplevel-resize.patch @@ -0,0 +1,121 @@ +From c5d9cb5f4bc4f703b66fc524a76247c742490b30 Mon Sep 17 00:00:00 2001 +From: Roman Gilg +Date: Fri, 3 Jan 2020 17:55:28 +0100 +Subject: [PATCH xserver 18/24] xwayland: Check emulation on client toplevel + resize + +When a reparented window is resized directly check the emulation instead of +doing this only when the window manager parent window is resized, what might +never happen. + +For that to work we need to make sure that we compare the current size of the +client toplevel when looking for an emulated mode. + +Changes by Hans de Goede: +- Remove xwl_window x, y, width and height members as those are no longer used. +- Add check for xwl_window_from_window() returning NULL. + +Signed-off-by: Roman Gilg +Acked-by: Olivier Fourdan +Signed-off-by: Hans de Goede +(cherry picked from commit 6d98f840da6dfcf2a69e03a1b3fa0bf602ba1f27) +--- + hw/xwayland/xwayland.c | 27 +++++++++++---------------- + hw/xwayland/xwayland.h | 1 - + 2 files changed, 11 insertions(+), 17 deletions(-) + +diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c +index d70d729ae..14227a327 100644 +--- a/hw/xwayland/xwayland.c ++++ b/hw/xwayland/xwayland.c +@@ -609,6 +609,7 @@ xwl_window_should_enable_viewport(struct xwl_window *xwl_window, + struct xwl_output *xwl_output; + ClientPtr owner; + WindowPtr window; ++ DrawablePtr drawable; + + if (!xwl_screen_has_resolution_change_emulation(xwl_screen)) + return FALSE; +@@ -618,6 +619,7 @@ xwl_window_should_enable_viewport(struct xwl_window *xwl_window, + return FALSE; + + owner = wClient(window); ++ drawable = &window->drawable; + + /* 1. Test if the window matches the emulated mode on one of the outputs + * This path gets hit by most games / libs (e.g. SDL, SFML, OGRE) +@@ -627,10 +629,10 @@ xwl_window_should_enable_viewport(struct xwl_window *xwl_window, + if (!emulated_mode) + continue; + +- if (xwl_window->x == xwl_output->x && +- xwl_window->y == xwl_output->y && +- xwl_window->width == emulated_mode->width && +- xwl_window->height == emulated_mode->height) { ++ if (drawable->x == xwl_output->x && ++ drawable->y == xwl_output->y && ++ drawable->width == emulated_mode->width && ++ drawable->height == emulated_mode->height) { + + *emulated_mode_ret = emulated_mode; + *xwl_output_ret = xwl_output; +@@ -646,9 +648,9 @@ xwl_window_should_enable_viewport(struct xwl_window *xwl_window, + emulated_mode = xwl_output_get_emulated_mode_for_client(xwl_output, owner); + if (xwl_output && xwl_window->window->overrideRedirect && + emulated_mode && emulated_mode->from_vidmode && +- xwl_window->x == 0 && xwl_window->y == 0 && +- xwl_window->width == xwl_screen->width && +- xwl_window->height == xwl_screen->height) { ++ drawable->x == 0 && drawable->y == 0 && ++ drawable->width == xwl_screen->width && ++ drawable->height == xwl_screen->height) { + + *emulated_mode_ret = emulated_mode; + *xwl_output_ret = xwl_output; +@@ -768,8 +770,6 @@ ensure_surface_for_window(WindowPtr window) + + xwl_window->xwl_screen = xwl_screen; + xwl_window->window = window; +- xwl_window->width = window->drawable.width; +- xwl_window->height = window->drawable.height; + xwl_window->surface = wl_compositor_create_surface(xwl_screen->compositor); + if (xwl_window->surface == NULL) { + ErrorF("wl_display_create_surface failed\n"); +@@ -997,20 +997,15 @@ xwl_resize_window(WindowPtr window, + struct xwl_window *xwl_window; + + xwl_screen = xwl_screen_get(screen); +- xwl_window = xwl_window_get(window); ++ xwl_window = xwl_window_from_window(window); + + screen->ResizeWindow = xwl_screen->ResizeWindow; + (*screen->ResizeWindow) (window, x, y, width, height, sib); + xwl_screen->ResizeWindow = screen->ResizeWindow; + screen->ResizeWindow = xwl_resize_window; + +- if (xwl_window) { +- xwl_window->x = x; +- xwl_window->y = y; +- xwl_window->width = width; +- xwl_window->height = height; ++ if (xwl_window && xwl_window_is_toplevel(window)) + xwl_window_check_resolution_change_emulation(xwl_window); +- } + } + + static void +diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h +index 126af8823..01aef27d2 100644 +--- a/hw/xwayland/xwayland.h ++++ b/hw/xwayland/xwayland.h +@@ -184,7 +184,6 @@ struct xwl_window { + struct xwl_screen *xwl_screen; + struct wl_surface *surface; + struct wp_viewport *viewport; +- int32_t x, y, width, height; + float scale_x, scale_y; + struct wl_shell_surface *shell_surface; + WindowPtr window; +-- +2.25.2 + diff --git a/0019-xwayland-Also-check-resolution-change-emulation-when.patch b/0019-xwayland-Also-check-resolution-change-emulation-when.patch new file mode 100644 index 0000000..a1c0e84 --- /dev/null +++ b/0019-xwayland-Also-check-resolution-change-emulation-when.patch @@ -0,0 +1,45 @@ +From 63b0c0d76d1020f0cac331f3eff30fba07f79965 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Wed, 15 Jan 2020 14:36:45 +0100 +Subject: [PATCH xserver 19/24] xwayland: Also check + resolution-change-emulation when the xwl_window itself moves + +The recent change to use the top-level non-window-manager Window drawable +coordinates from xwl_window_check_resolution_change_emulation() in +combination with only calling it on a resize when the top-level window +is moved breaks things with mutter/gnome-shell. + +When fullscreening a X11 window, mutter moves its window-decoration Window +wrapping the top-level Window to the monitor's origin coordinates (e.g. 0x0) +last. This updates the top-level's drawable coordinates, but as the +actual MoveWindow is called on the wrapper Window and not on the toplevel +we do not call xwl_window_check_resolution_change_emulation() and we never +enable the viewport. + +This commit fixes this by also calling +xwl_window_check_resolution_change_emulation() if the Window being moved +is an xwl_window itself. + +Acked-by: Olivier Fourdan +Signed-off-by: Hans de Goede +(cherry picked from commit 4fc107460a349a1a46f0e5251e6fd2a31f4c0428) +--- + hw/xwayland/xwayland.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c +index 14227a327..298ef3ac8 100644 +--- a/hw/xwayland/xwayland.c ++++ b/hw/xwayland/xwayland.c +@@ -1004,7 +1004,7 @@ xwl_resize_window(WindowPtr window, + xwl_screen->ResizeWindow = screen->ResizeWindow; + screen->ResizeWindow = xwl_resize_window; + +- if (xwl_window && xwl_window_is_toplevel(window)) ++ if (xwl_window && (xwl_window_get(window) || xwl_window_is_toplevel(window))) + xwl_window_check_resolution_change_emulation(xwl_window); + } + +-- +2.25.2 + diff --git a/0020-xwayland-Also-hook-screen-s-MoveWindow-method.patch b/0020-xwayland-Also-hook-screen-s-MoveWindow-method.patch new file mode 100644 index 0000000..51f3fe8 --- /dev/null +++ b/0020-xwayland-Also-hook-screen-s-MoveWindow-method.patch @@ -0,0 +1,83 @@ +From 309e6e549adc5a164541d16822745c022cd8574b Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Thu, 9 Jan 2020 11:00:36 +0100 +Subject: [PATCH xserver 20/24] xwayland: Also hook screen's MoveWindow method + +Not only hook the ResizeWindow method of the screen (which really is +MoveAndResize) but also hook the MoveWindow method for checking if we +need to setup a viewport for resolution change emulation. + +Our resolution change emulation check if the windows origin matches +the monitors origin and the windows origin can also be changed by just +a move without being resized. + +Also checking on a move becomes esp. important when we move to checking +on changes to the top-level non-window-manager client (X11)Window instead +of on changes to the xwl_window later on in this patch series. + +Acked-by: Olivier Fourdan +Signed-off-by: Hans de Goede +(cherry picked from commit 10df0437a2b142e61c4d84ffffa9592ac6846ef1) +--- + hw/xwayland/xwayland.c | 25 +++++++++++++++++++++++++ + hw/xwayland/xwayland.h | 1 + + 2 files changed, 26 insertions(+) + +diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c +index 298ef3ac8..1294ff1d8 100644 +--- a/hw/xwayland/xwayland.c ++++ b/hw/xwayland/xwayland.c +@@ -1008,6 +1008,28 @@ xwl_resize_window(WindowPtr window, + xwl_window_check_resolution_change_emulation(xwl_window); + } + ++static void ++xwl_move_window(WindowPtr window, ++ int x, int y, ++ WindowPtr next_sib, ++ VTKind kind) ++{ ++ ScreenPtr screen = window->drawable.pScreen; ++ struct xwl_screen *xwl_screen; ++ struct xwl_window *xwl_window; ++ ++ xwl_screen = xwl_screen_get(screen); ++ xwl_window = xwl_window_from_window(window); ++ ++ screen->MoveWindow = xwl_screen->MoveWindow; ++ (*screen->MoveWindow) (window, x, y, next_sib, kind); ++ xwl_screen->MoveWindow = screen->MoveWindow; ++ screen->MoveWindow = xwl_move_window; ++ ++ if (xwl_window && (xwl_window_get(window) || xwl_window_is_toplevel(window))) ++ xwl_window_check_resolution_change_emulation(xwl_window); ++} ++ + static void + frame_callback(void *data, + struct wl_callback *callback, +@@ -1564,6 +1586,9 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv) + xwl_screen->ResizeWindow = pScreen->ResizeWindow; + pScreen->ResizeWindow = xwl_resize_window; + ++ xwl_screen->MoveWindow = pScreen->MoveWindow; ++ pScreen->MoveWindow = xwl_move_window; ++ + if (xwl_screen->rootless) { + xwl_screen->SetWindowPixmap = pScreen->SetWindowPixmap; + pScreen->SetWindowPixmap = xwl_set_window_pixmap; +diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h +index 01aef27d2..72225374b 100644 +--- a/hw/xwayland/xwayland.h ++++ b/hw/xwayland/xwayland.h +@@ -138,6 +138,7 @@ struct xwl_screen { + SetWindowPixmapProcPtr SetWindowPixmap; + ChangeWindowAttributesProcPtr ChangeWindowAttributes; + ResizeWindowProcPtr ResizeWindow; ++ MoveWindowProcPtr MoveWindow; + + struct xorg_list output_list; + struct xorg_list seat_list; +-- +2.25.2 + diff --git a/0021-xwayland-Fix-emulated-modes-not-being-removed-when-s.patch b/0021-xwayland-Fix-emulated-modes-not-being-removed-when-s.patch new file mode 100644 index 0000000..2b1bc84 --- /dev/null +++ b/0021-xwayland-Fix-emulated-modes-not-being-removed-when-s.patch @@ -0,0 +1,63 @@ +From 52bbef1f55d17229684b0d76a478ec639c4032ed Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Mon, 7 Oct 2019 14:27:49 +0200 +Subject: [PATCH xserver 21/24] xwayland: Fix emulated modes not being removed + when screen rotation is used + +The code building the mode-list does the following to deal with screen +rotation: + + if (need_rotate || xwl_output->rotation & (RR_Rotate_0 | RR_Rotate_180)) { + mode_width = xwl_output->width; + mode_height = xwl_output->height; + } else { + mode_width = xwl_output->height; + mode_height = xwl_output->width; + } + +This means we need to do something similar in xwl_output_set_emulated_mode() +to determine if the mode being set is the actual (not-emulated) output mode +and we this should remove any emulated modes set by the client. + +All callers of xwl_output_set_emulated_mode always pass a mode pointer +to a member of xwl_output->randr_output->modes, so we do not need to +duplicate this code, instead we can simply check that the passed in mode +is modes[0] which always is the actual output mode. + +Acked-by: Olivier Fourdan +Signed-off-by: Hans de Goede +(cherry picked from commit 88342353de45e64f408c38bb10cd1506ba0f159a) +--- + hw/xwayland/xwayland-output.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/hw/xwayland/xwayland-output.c b/hw/xwayland/xwayland-output.c +index 20c254962..7d705d919 100644 +--- a/hw/xwayland/xwayland-output.c ++++ b/hw/xwayland/xwayland-output.c +@@ -309,8 +309,11 @@ xwl_output_remove_emulated_mode_for_client(struct xwl_output *xwl_output, + struct xwl_emulated_mode *emulated_mode; + + emulated_mode = xwl_output_get_emulated_mode_for_client(xwl_output, client); +- if (emulated_mode) ++ if (emulated_mode) { ++ DebugF("XWAYLAND: xwl_output_remove_emulated_mode: %dx%d\n", ++ emulated_mode->width, emulated_mode->height); + memset(emulated_mode, 0, sizeof(*emulated_mode)); ++ } + } + + /* From hw/xfree86/common/xf86DefModeSet.c with some obscure modes dropped */ +@@ -511,7 +514,8 @@ xwl_output_set_emulated_mode(struct xwl_output *xwl_output, ClientPtr client, + from_vidmode ? "vidmode" : "randr", + mode->mode.width, mode->mode.height); + +- if (mode->mode.width == xwl_output->width && mode->mode.height == xwl_output->height) ++ /* modes[0] is the actual (not-emulated) output mode */ ++ if (mode == xwl_output->randr_output->modes[0]) + xwl_output_remove_emulated_mode_for_client(xwl_output, client); + else + xwl_output_add_emulated_mode_for_client(xwl_output, client, mode, from_vidmode); +-- +2.25.2 + diff --git a/0022-xwayland-Call-xwl_window_check_resolution_change_emu.patch b/0022-xwayland-Call-xwl_window_check_resolution_change_emu.patch new file mode 100644 index 0000000..0b6a07b --- /dev/null +++ b/0022-xwayland-Call-xwl_window_check_resolution_change_emu.patch @@ -0,0 +1,48 @@ +From 57d0ad44fd0b04fff98e9b484816dc95068a90cc Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Mon, 4 Nov 2019 11:46:49 +0100 +Subject: [PATCH xserver 22/24] xwayland: Call + xwl_window_check_resolution_change_emulation() on newly created O-R windows + +Some clients, which use vidmode to change the resolution when going fullscreen, +create an override-redirect window and never trigger the screen->ResizeWindow +callback we rely on to do the xwl_window_check_resolution_change_emulation(). + +This causes us to not apply a viewport to them, causing the fullscreen window +to not fill the entire monitor. + +This commit adds a call to xwl_window_check_resolution_change_emulation() +at the end of ensure_surface_for_window() to fix this. Note that +ensure_surface_for_window() exits early without creating an xwl_window +for new windows which will not be backed by a wayland surface and which +thus will not have an xwl_window. + +This fixes ClanLib-0.6.x and alleggl-4.4.x using apps not properly +fullscreening. + +Acked-by: Olivier Fourdan +Signed-off-by: Hans de Goede +(cherry picked from commit 4cfc2677f5c82ca5db0919de549b9b077f1ba113) +--- + hw/xwayland/xwayland.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c +index 1294ff1d8..6b86e56bd 100644 +--- a/hw/xwayland/xwayland.c ++++ b/hw/xwayland/xwayland.c +@@ -819,6 +819,11 @@ ensure_surface_for_window(WindowPtr window) + + xwl_window_init_allow_commits(xwl_window); + ++ if (!window_is_wm_window(window)) { ++ /* CSD or O-R toplevel window, check viewport on creation */ ++ xwl_window_check_resolution_change_emulation(xwl_window); ++ } ++ + return TRUE; + + err_surf: +-- +2.25.2 + diff --git a/0023-xwayland-Fix-setting-of-_XWAYLAND_RANDR_EMU_MONITOR_.patch b/0023-xwayland-Fix-setting-of-_XWAYLAND_RANDR_EMU_MONITOR_.patch new file mode 100644 index 0000000..611bea4 --- /dev/null +++ b/0023-xwayland-Fix-setting-of-_XWAYLAND_RANDR_EMU_MONITOR_.patch @@ -0,0 +1,76 @@ +From 049333a0ecf8574a0612bf27850f9682f0f70533 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Mon, 4 Nov 2019 14:32:29 +0100 +Subject: [PATCH xserver 23/25] xwayland: Fix setting of + _XWAYLAND_RANDR_EMU_MONITOR_RECTS prop on new windows + +For window-manager managed windows, xwl_realize_window is only called for +the window-manager's decoration window and not for the actual client window +on which we should set the _XWAYLAND_RANDR_EMU_MONITOR_RECTS prop. + +Usualy this is not a problem since we walk all client windows to update +the property when the resolution is changed through a randr call. + +But for apps which first do the randr change and only then create their +window this does not work, and our xwl_output_set_window_randr_emu_props +call in xwl_realize_window is a no-op as that is only called for the wm +decoration window and not for the actual client's window. + +This commit fixes this by making ensure_surface_for_window() call +xwl_output_set_window_randr_emu_props on the first and only child of +window-manager managed windows. + +Note this also removes the non-functional xwl_output_set_window_randr_emu_props +call from xwl_realize_window, which was intended to do this, but does not +work. + +This fixes apps using the ogre3d library always running at the +monitors native resolution. + +Acked-by: Olivier Fourdan +Signed-off-by: Hans de Goede +(cherry picked from commit 148f428dfccf606b932a00d5a00af06e8dca8a7e) +--- + hw/xwayland/xwayland.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c +index 5bb7a68e9..1600c00cd 100644 +--- a/hw/xwayland/xwayland.c ++++ b/hw/xwayland/xwayland.c +@@ -738,6 +738,7 @@ ensure_surface_for_window(WindowPtr window) + struct xwl_screen *xwl_screen; + struct xwl_window *xwl_window; + struct wl_region *region; ++ WindowPtr toplevel; + + if (xwl_window_from_window(window)) + return TRUE; +@@ -808,7 +809,14 @@ ensure_surface_for_window(WindowPtr window) + + xwl_window_init_allow_commits(xwl_window); + +- if (!window_is_wm_window(window)) { ++ /* When a new window-manager window is realized, then the randr emulation ++ * props may have not been set on the managed client window yet. ++ */ ++ if (window_is_wm_window(window)) { ++ toplevel = window_get_client_toplevel(window); ++ if (toplevel) ++ xwl_output_set_window_randr_emu_props(xwl_screen, toplevel); ++ } else { + /* CSD or O-R toplevel window, check viewport on creation */ + xwl_window_check_resolution_change_emulation(xwl_window); + } +@@ -857,8 +865,6 @@ xwl_realize_window(WindowPtr window) + return FALSE; + } + +- xwl_output_set_window_randr_emu_props(xwl_screen, window); +- + return ensure_surface_for_window(window); + } + +-- +2.28.0 + \ No newline at end of file diff --git a/0024-xwayland-Remove-unnecessary-xwl_window_is_toplevel-c.patch b/0024-xwayland-Remove-unnecessary-xwl_window_is_toplevel-c.patch new file mode 100644 index 0000000..c4925c2 --- /dev/null +++ b/0024-xwayland-Remove-unnecessary-xwl_window_is_toplevel-c.patch @@ -0,0 +1,49 @@ +From 231d5e2da2e1b0aee3cfe6febc54daf7a0e4b4c7 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Mon, 4 Nov 2019 15:01:18 +0100 +Subject: [PATCH xserver 24/24] xwayland: Remove unnecessary + xwl_window_is_toplevel() check from xwl_output_set_window_randr_emu_props() + +Since the recent fix to call xwl_output_set_window_randr_emu_props() from +ensure_surface_for_window(), it is now only called on a toplevel window, +so the is-toplevel check is not necessary for the +xwl_output_set_window_randr_emu_props() case. + +This commit moves the check to xwl_output_set_randr_emu_prop_callback() +so that we only do it when we are walking over all Windows of a client +to update the property on a change of the emulated resolution. + +Acked-by: Olivier Fourdan +Signed-off-by: Hans de Goede +(cherry picked from commit d4faab8708779df265239b203ed5f020bff681bf) +--- + hw/xwayland/xwayland-output.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/hw/xwayland/xwayland-output.c b/hw/xwayland/xwayland-output.c +index 7d705d919..084b669e4 100644 +--- a/hw/xwayland/xwayland-output.c ++++ b/hw/xwayland/xwayland-output.c +@@ -468,9 +468,6 @@ static void + xwl_output_set_randr_emu_prop(WindowPtr window, + struct xwl_output_randr_emu_prop *prop) + { +- if (!xwl_window_is_toplevel(window)) +- return; +- + if (prop->rect_count) { + dixChangeWindowProperty(serverClient, window, prop->atom, + XA_CARDINAL, 32, PropModeReplace, +@@ -483,7 +480,8 @@ xwl_output_set_randr_emu_prop(WindowPtr window, + static void + xwl_output_set_randr_emu_prop_callback(void *resource, XID id, void *user_data) + { +- xwl_output_set_randr_emu_prop(resource, user_data); ++ if (xwl_window_is_toplevel(resource)) ++ xwl_output_set_randr_emu_prop(resource, user_data); + } + + static void +-- +2.25.2 + diff --git a/xorg-x11-server.spec b/xorg-x11-server.spec index 9b92921..3ef2b4b 100644 --- a/xorg-x11-server.spec +++ b/xorg-x11-server.spec @@ -16,7 +16,7 @@ Name: xorg-x11-server Version: 1.20.11 -Release: 2 +Release: 3 Summary: X.Org X11 X server License: MIT and GPLv2 URL: https://www.x.org @@ -49,6 +49,33 @@ Patch0003: 0001-autobind-GPUs-to-the-screen.patch # because the display-managers are not ready yet, do not upstream Patch0004: 0001-Fedora-hack-Make-the-suid-root-wrapper-always-start-.patch +# Backports from current stable "server-1.20-branch": +# Backports from "master" upstream: +# Backported Xwayland randr resolution change emulation support +Patch0005: 0001-dix-Add-GetCurrentClient-helper.patch +Patch0006: 0002-xwayland-Add-wp_viewport-wayland-extension-support.patch +Patch0007: 0003-xwayland-Use-buffer_damage-instead-of-surface-damage.patch +Patch0008: 0004-xwayland-Add-fake-output-modes-to-xrandr-output-mode.patch +Patch0009: 0005-xwayland-Use-RandR-1.2-interface-rev-2.patch +Patch0010: 0006-xwayland-Add-per-client-private-data.patch +Patch0011: 0007-xwayland-Add-support-for-storing-per-client-per-outp.patch +Patch0012: 0008-xwayland-Add-support-for-randr-resolution-change-emu.patch +Patch0013: 0009-xwayland-Add-xwlRRModeToDisplayMode-helper-function.patch +Patch0014: 0010-xwayland-Add-xwlVidModeGetCurrentRRMode-helper-to-th.patch +Patch0015: 0011-xwayland-Add-vidmode-mode-changing-emulation-support.patch +Patch0016: 0012-xwayland-xwl_window_should_enable_viewport-Add-extra.patch +Patch0017: 0013-xwayland-Set-_XWAYLAND_RANDR_EMU_MONITOR_RECTS-prope.patch +Patch0018: 0014-xwayland-Cache-client-id-for-the-window-manager-clie.patch +Patch0019: 0015-xwayland-Reuse-viewport-instead-of-recreating.patch +Patch0020: 0016-xwayland-Recurse-on-finding-the-none-wm-owner.patch +Patch0021: 0017-xwayland-Make-window_get_none_wm_owner-return-a-Wind.patch +Patch0022: 0018-xwayland-Check-emulation-on-client-toplevel-resize.patch +Patch0023: 0019-xwayland-Also-check-resolution-change-emulation-when.patch +Patch0024: 0020-xwayland-Also-hook-screen-s-MoveWindow-method.patch +Patch0025: 0021-xwayland-Fix-emulated-modes-not-being-removed-when-s.patch +Patch0026: 0022-xwayland-Call-xwl_window_check_resolution_change_emu.patch +Patch0027: 0023-xwayland-Fix-setting-of-_XWAYLAND_RANDR_EMU_MONITOR_.patch +Patch0028: 0024-xwayland-Remove-unnecessary-xwl_window_is_toplevel-c.patch Patch0029: xorg-s11-server-CVE-2018-20839.patch Patch6000: backport-CVE-2021-4008.patch @@ -70,6 +97,7 @@ BuildRequires: xorg-x11-xtrans-devel >= 1.3.2 xorg-x11-util-macros >= 1.17 xorg BuildRequires: xorg-x11-font-utils >= 7.2 libselinux-devel >= 2.0.86 BuildRequires: libxshmfence-devel >= 1.1 pixman-devel >= 0.30.0 libdrm-devel >= 2.4.0 BuildRequires: mesa-libGL-devel >= 9.2 libpciaccess-devel >= 0.13.1 +BuildRequires: wayland-devel wayland-protocols-devel egl-wayland-devel %ifarch aarch64 %{arm} x86_64 BuildRequires: libunwind-devel @@ -79,6 +107,9 @@ Requires: pixman >= 0.30.0 xkeyboard-config xkbcomp Requires: system-setup-keyboard xorg-x11-drv-libinput libEGL Requires: xorg-x11-xauth +Obsoletes: %{name}-Xorg < %{version}-%{release} %{name}-Xwayland < %{version}-%{release} +Provides: %{name}-Xorg = %{version}-%{release} %{name}-Xorg%{?_isa} = %{version}-%{release} %{name}-Xwayland = %{version}-%{release} %{name}-Xwayland%{?_isa} = %{version}-%{release} + Provides: Xorg = %{version}-%{release} Obsoletes: Xorg < %{version}-%{release} Provides: Xserver = %{version}-%{release} @@ -235,6 +266,7 @@ autoreconf -ivf || exit 1 %configure %{xservers} \ --enable-dependency-tracking \ + --enable-xwayland-eglstream \ --with-pic \ %{?no_int10} --with-int10=x86emu \ --with-default-font-path=%{default_font_path} \ @@ -249,7 +281,7 @@ autoreconf -ivf || exit 1 --enable-config-udev \ --disable-unit-tests \ --enable-dmx \ - --disable-xwayland \ + --enable-xwayland \ %{dri_flags} %{?bodhi_flags} \ ${CONFIGURE} @@ -324,6 +356,7 @@ find %{inst_srcdir}/hw/xfree86 -name \*.c -delete %config %attr(0644,root,root) %{_sysconfdir}/pam.d/xserver %{_bindir}/X %{_bindir}/Xorg +%{_bindir}/Xwayland %{_libexecdir}/Xorg %{Xorgperms} %{_libexecdir}/Xorg.wrap %{_bindir}/cvt @@ -396,6 +429,9 @@ find %{inst_srcdir}/hw/xfree86 -name \*.c -delete %{_libdir}/xorg/protocol.txt %changelog +* Mon Dec 27 2021 yangcheng - 1.20.11-3 +- provide xorg-x11-server-Xorg and xorg-x11-server-Xwayland + * Sat Dec 25 2021 yangcheng - 1.20.11-2 - Type:CVE - Id:CVE-2021-4008 CVE-2021-4009 CVE-2021-4010 CVE-2021-4011 -- Gitee