From b0cee5e7033787e0720af1f128a33e967231b323 Mon Sep 17 00:00:00 2001 From: Olivier Fourdan <ofourdan@redhat.com> Date: Tue, 26 Apr 2022 15:28:50 +0200 Subject: [PATCH] xwayland: add a fixed geometry size for rootful When running rootless as well as rootful, Xwayland gets its outputs configuration from the Wayland compositor. When running rootful, it means that we end up with a large black surface the size of all monitors combined, that's not very convenient and there is no way for set the desired size of the Xwayland window. Add a new command line option "-geometry" to force a specific mode when running rootful for the user to specify the root window size to use for Xwayland. That option has no effect when Xwayland is running rootless. v2: Not using libxcvt as the mode may not be a valid CVT mode. v3: Add a set of XRandR modes and the RR hooks to make that work. Update the man page for Xwayland. v4: Add RandR 1.0 support for older clients v5: Fix XVidMode failing with a BadMatch v6: Add a separate xwl_output specifically for fixed mode, instead of using the existing output list - that will allow for further improvements like a fullscreen mode eventually. v7: Sort the RR modes v8: Fix RandR 1.0 v9: Add physical size v10: Cleanup Signed-off-by: Olivier Fourdan <ofourdan@redhat.com> Reviewed-by: Adam Jackson <ajax@redhat.com> Closes: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1338 --- hw/xwayland/man/Xwayland.man | 5 + hw/xwayland/xwayland-output.c | 265 +++++++++++++++++++++++++++------ hw/xwayland/xwayland-output.h | 7 +- hw/xwayland/xwayland-screen.c | 44 +++++- hw/xwayland/xwayland-screen.h | 2 + hw/xwayland/xwayland-vidmode.c | 39 +++-- hw/xwayland/xwayland.c | 5 + hw/xwayland/xwayland.pc.in | 1 + 8 files changed, 307 insertions(+), 61 deletions(-) diff --git a/hw/xwayland/man/Xwayland.man b/hw/xwayland/man/Xwayland.man index 2ceec94325..b9202160c8 100644 --- a/hw/xwayland/man/Xwayland.man +++ b/hw/xwayland/man/Xwayland.man @@ -53,6 +53,11 @@ backend first, then fallback to the GBM backend if EGLStream is not supported by the Wayland server. Without this option, \fIXwayland\fP tries the GBM backend first, and fallback to EGLStream if GBM is not usable. .TP 8 +.B \-geometry \fIWxH\fP +Sets the geometry of the \fIXwayland\fP window to \fIWxH\fP when running rootful. + +This option is not compatible with rootless mode (\fI-rootless\fP). +.TP 8 .B \-initfd \fIfd\fP Add the given \fIfd\fP as a listen socket for initialization of X clients. This options is aimed at \fIWayland\fP servers which run \fIXwayland\fP diff --git a/hw/xwayland/xwayland-output.c b/hw/xwayland/xwayland-output.c index bdce261912..3d9ef3677a 100644 --- a/hw/xwayland/xwayland-output.c +++ b/hw/xwayland/xwayland-output.c @@ -88,10 +88,12 @@ output_handle_geometry(void *data, struct wl_output *wl_output, int x, int y, { struct xwl_output *xwl_output = data; - RROutputSetPhysicalSize(xwl_output->randr_output, - physical_width, physical_height); - RROutputSetSubpixelOrder(xwl_output->randr_output, - wl_subpixel_to_xrandr(subpixel)); + if (xwl_output->randr_output) { + RROutputSetPhysicalSize(xwl_output->randr_output, + physical_width, physical_height); + RROutputSetSubpixelOrder(xwl_output->randr_output, + wl_subpixel_to_xrandr(subpixel)); + } /* Apply the change from wl_output only if xdg-output is not supported */ if (!xwl_output->xdg_output) { @@ -221,6 +223,10 @@ xwl_output_get_emulated_mode_for_client(struct xwl_output *xwl_output, if (!xwl_output) return NULL; + /* We don't do XRandr emulation when rootful */ + if (!xwl_output->xwl_screen->rootless) + 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) @@ -611,17 +617,18 @@ apply_output_change(struct xwl_output *xwl_output) mode_width = xwl_output->height; mode_height = xwl_output->width; } - - /* 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); + if (xwl_output->randr_output) { + /* 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 @@ -643,7 +650,8 @@ apply_output_change(struct xwl_output *xwl_output) --xwl_screen->expecting_event; } - update_screen_size(xwl_screen, width, height); + if (xwl_screen->fixed_output == NULL) + update_screen_size(xwl_screen, width, height); } static void @@ -745,7 +753,7 @@ xwl_output_set_emulated(struct xwl_output *xwl_output) } struct xwl_output * -xwl_output_create(struct xwl_screen *xwl_screen, uint32_t id) +xwl_output_create(struct xwl_screen *xwl_screen, uint32_t id, Bool with_xrandr) { struct xwl_output *xwl_output; char name[256]; @@ -766,30 +774,32 @@ xwl_output_create(struct xwl_screen *xwl_screen, uint32_t id) xwl_output->server_output_id = id; wl_output_add_listener(xwl_output->output, &output_listener, xwl_output); - snprintf(name, sizeof name, "XWAYLAND%d", - xwl_screen_get_next_output_serial(xwl_screen)); - xwl_output->xwl_screen = xwl_screen; - xwl_output->randr_crtc = RRCrtcCreate(xwl_screen->screen, xwl_output); - if (!xwl_output->randr_crtc) { - ErrorF("Failed creating RandR CRTC\n"); - goto err; - } - RRCrtcSetRotations (xwl_output->randr_crtc, ALL_ROTATIONS); - xwl_output->randr_output = RROutputCreate(xwl_screen->screen, name, - strlen(name), xwl_output); - if (!xwl_output->randr_output) { - ErrorF("Failed creating RandR Output\n"); - goto err; - } - xwl_output_set_emulated(xwl_output); + if (with_xrandr) { + snprintf(name, sizeof name, "XWAYLAND%d", + xwl_screen_get_next_output_serial(xwl_screen)); - RRCrtcGammaSetSize(xwl_output->randr_crtc, 256); - RROutputSetCrtcs(xwl_output->randr_output, &xwl_output->randr_crtc, 1); - RROutputSetConnection(xwl_output->randr_output, RR_Connected); - RRTellChanged(xwl_screen->screen); + xwl_output->randr_crtc = RRCrtcCreate(xwl_screen->screen, xwl_output); + if (!xwl_output->randr_crtc) { + ErrorF("Failed creating RandR CRTC\n"); + goto err; + } + RRCrtcSetRotations (xwl_output->randr_crtc, ALL_ROTATIONS); + + xwl_output->randr_output = RROutputCreate(xwl_screen->screen, name, + strlen(name), xwl_output); + if (!xwl_output->randr_output) { + ErrorF("Failed creating RandR Output\n"); + goto err; + } + xwl_output_set_emulated(xwl_output); + RRCrtcGammaSetSize(xwl_output->randr_crtc, 256); + RROutputSetCrtcs(xwl_output->randr_output, &xwl_output->randr_crtc, 1); + RROutputSetConnection(xwl_output->randr_output, RR_Connected); + RRTellChanged(xwl_screen->screen); + } /* We want the output to be in the list as soon as created so we can * use it when binding to the xdg-output protocol... */ @@ -831,16 +841,21 @@ xwl_output_remove(struct xwl_output *xwl_output) xorg_list_del(&xwl_output->link); - RROutputSetConnection(xwl_output->randr_output, RR_Disconnected); - - xorg_list_for_each_entry(it, &xwl_screen->output_list, link) - output_get_new_size(it, &width, &height); - update_screen_size(xwl_screen, width, height); + if (xwl_output->randr_output) + RROutputSetConnection(xwl_output->randr_output, RR_Disconnected); - RRCrtcDestroy(xwl_output->randr_crtc); - RROutputDestroy(xwl_output->randr_output); - RRTellChanged(xwl_screen->screen); + if (xwl_screen->fixed_output == NULL) { + xorg_list_for_each_entry(it, &xwl_screen->output_list, link) + output_get_new_size(it, &width, &height); + update_screen_size(xwl_screen, width, height); + } + if (xwl_output->randr_crtc) + RRCrtcDestroy(xwl_output->randr_crtc); + if (xwl_output->randr_output) { + RROutputDestroy(xwl_output->randr_output); + RRTellChanged(xwl_screen->screen); + } xwl_output_destroy(xwl_output); } @@ -980,6 +995,166 @@ xwl_screen_init_output(struct xwl_screen *xwl_screen) return TRUE; } +static int +mode_sort(const void *left, const void *right) +{ + const RRModePtr *mode_a = left; + const RRModePtr *mode_b = right; + + if ((*mode_b)->mode.width == (*mode_a)->mode.width) + return (*mode_b)->mode.height - (*mode_a)->mode.height; + + return (*mode_b)->mode.width - (*mode_a)->mode.width; +} + +static Bool +xwl_randr_add_modes_fixed(struct xwl_output *xwl_output, + int current_width, int current_height) +{ + RRModePtr *modes = NULL; + RRModePtr mode; + xRRModeInfo mode_info = { 0, }; + char mode_name[128]; + int i, nmodes, current; + + + modes = xallocarray(ARRAY_SIZE(xwl_output_fake_modes) + 1, sizeof(RRModePtr)); + if (!modes) { + ErrorF("Failed to allocated RandR modes\n"); + return FALSE; + } + + nmodes = 0; + current = 0; + + /* Add fake modes */ + for (i = 0; i < ARRAY_SIZE(xwl_output_fake_modes); i++) { + if (xwl_output_fake_modes[i][0] == current_width && + xwl_output_fake_modes[i][1] == current_height) + current = 1; + + mode = xwayland_cvt(xwl_output_fake_modes[i][0], + xwl_output_fake_modes[i][1], + 60, 0, 0); + + if (mode) + modes[nmodes++] = mode; + } + + if (!current) { + /* Add the current mode as it's not part of the fake modes. + * Not using libcvt as the size is set from the command line and + * may not be a valid CVT mode. + */ + mode_info.width = current_width; + mode_info.height = current_height; + mode_info.hTotal = current_width; + mode_info.vTotal = current_height; + mode_info.dotClock = 60 * 1000 * 1000; + + snprintf(mode_name, sizeof(mode_name), "%dx%d", + current_width, current_height); + mode_info.nameLength = strlen(mode_name); + + modes[nmodes++] = RRModeGet(&mode_info, mode_name); + } + + qsort(modes, nmodes, sizeof(RRModePtr), mode_sort); + RROutputSetModes(xwl_output->randr_output, modes, nmodes, 1); + free(modes); + + return TRUE; +} + +void +xwl_output_set_mode_fixed(struct xwl_output *xwl_output, RRModePtr mode) +{ + struct xwl_screen *xwl_screen = xwl_output->xwl_screen; + + update_screen_size(xwl_screen, mode->mode.width, mode->mode.height); + + RRCrtcNotify(xwl_output->randr_crtc, mode, 0, 0, RR_Rotate_0, + NULL, 1, &xwl_output->randr_output); +} + +static Bool +xwl_randr_set_config_fixed(ScreenPtr pScreen, + Rotation randr, int rate, RRScreenSizePtr pSize) +{ + struct xwl_screen *xwl_screen = xwl_screen_get(pScreen); + + update_screen_size(xwl_screen, pSize->width, pSize->height); + + return TRUE; +} + +/* Create a single RR output/mode used with a fixed geometry */ +Bool +xwl_screen_init_randr_fixed(struct xwl_screen *xwl_screen) +{ + struct xwl_output *xwl_output; + rrScrPrivPtr rp; + RRModePtr mode; + + xwl_output = calloc(1, sizeof *xwl_output); + if (xwl_output == NULL) { + ErrorF("%s ENOMEM\n", __func__); + return FALSE; + } + + if (!RRScreenInit(xwl_screen->screen)) + goto err; + + RRScreenSetSizeRange(xwl_screen->screen, 16, 16, 32767, 32767); + + rp = rrGetScrPriv(xwl_screen->screen); + rp->rrGetInfo = xwl_randr_get_info; + rp->rrSetConfig = xwl_randr_set_config_fixed; + + xwl_output->randr_output = RROutputCreate(xwl_screen->screen, "XWAYLAND0", 9, NULL); + if (!xwl_output->randr_output) { + ErrorF("Failed to create RandR output\n"); + goto err; + } + + xwl_output->randr_crtc = RRCrtcCreate(xwl_screen->screen, xwl_output); + if (!xwl_output->randr_crtc) { + ErrorF("Failed to create RandR CRTC\n"); + goto err; + } + RRCrtcSetRotations (xwl_output->randr_crtc, RR_Rotate_0); + RRCrtcGammaSetSize(xwl_output->randr_crtc, 256); + RROutputSetCrtcs(xwl_output->randr_output, &xwl_output->randr_crtc, 1); + + xwl_randr_add_modes_fixed(xwl_output, + xwl_screen->width, xwl_screen->height); + /* Current mode */ + mode = xwl_output_find_mode(xwl_output, + xwl_screen->width, xwl_screen->height); + RRCrtcNotify(xwl_output->randr_crtc, mode, 0, 0, RR_Rotate_0, + NULL, 1, &xwl_output->randr_output); + + RROutputSetPhysicalSize(xwl_output->randr_output, + (xwl_screen->width * 25.4) / monitorResolution, + (xwl_screen->height * 25.4) / monitorResolution); + + RROutputSetConnection(xwl_output->randr_output, RR_Connected); + + xwl_output->xwl_screen = xwl_screen; + xwl_screen->fixed_output = xwl_output; + + return TRUE; + +err: + if (xwl_output->randr_crtc) + RRCrtcDestroy(xwl_output->randr_crtc); + if (xwl_output->randr_output) + RROutputDestroy(xwl_output->randr_output); + free(xwl_output); + + return FALSE; +} + static void xwl_output_get_xdg_output(struct xwl_output *xwl_output) { diff --git a/hw/xwayland/xwayland-output.h b/hw/xwayland/xwayland-output.h index 10a353ddc9..63aee82444 100644 --- a/hw/xwayland/xwayland-output.h +++ b/hw/xwayland/xwayland-output.h @@ -74,8 +74,13 @@ struct xwl_emulated_mode { Bool xwl_screen_init_output(struct xwl_screen *xwl_screen); +Bool xwl_screen_init_randr_fixed(struct xwl_screen *xwl_screen); + +void xwl_output_set_mode_fixed(struct xwl_output *xwl_output, + RRModePtr mode); + struct xwl_output *xwl_output_create(struct xwl_screen *xwl_screen, - uint32_t id); + uint32_t id, Bool with_xrandr); void xwl_output_destroy(struct xwl_output *xwl_output); diff --git a/hw/xwayland/xwayland-screen.c b/hw/xwayland/xwayland-screen.c index c9b93a2da0..771f262b07 100644 --- a/hw/xwayland/xwayland-screen.c +++ b/hw/xwayland/xwayland-screen.c @@ -127,6 +127,15 @@ xwl_screen_get_first_output(struct xwl_screen *xwl_screen) return xorg_list_first_entry(&xwl_screen->output_list, struct xwl_output, link); } +struct xwl_output * +xwl_screen_get_fixed_or_first_output(struct xwl_screen *xwl_screen) +{ + if (xwl_screen->fixed_output) + return xwl_screen->fixed_output; + + return xwl_screen_get_first_output(xwl_screen); +} + static void xwl_property_callback(CallbackListPtr *pcbl, void *closure, void *calldata) @@ -180,6 +189,9 @@ xwl_close_screen(ScreenPtr screen) &xwl_screen->output_list, link) xwl_output_destroy(xwl_output); + if (xwl_screen->fixed_output) + xwl_output_destroy(xwl_screen->fixed_output); + xorg_list_for_each_entry_safe(xwl_seat, next_xwl_seat, &xwl_screen->seat_list, link) xwl_seat_destroy(xwl_seat); @@ -406,7 +418,7 @@ registry_global(void *data, struct wl_registry *registry, uint32_t id, NULL); } else if (strcmp(interface, "wl_output") == 0 && version >= 2) { - if (xwl_output_create(xwl_screen, id)) + if (xwl_output_create(xwl_screen, id, (xwl_screen->fixed_output == NULL))) xwl_screen->expecting_event++; } else if (strcmp(interface, "zxdg_output_manager_v1") == 0) { @@ -594,9 +606,12 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv) struct xwl_screen *xwl_screen; Pixel red_mask, blue_mask, green_mask; int ret, bpc, green_bpc, i; + unsigned int xwl_width = 0; + unsigned int xwl_height = 0; #ifdef XWL_HAS_GLAMOR Bool use_eglstreams = FALSE; #endif + Bool use_fixed_size = FALSE; if (!dixRegisterPrivateKey(&xwl_screen_private_key, PRIVATE_SCREEN, 0)) return FALSE; @@ -653,6 +668,24 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv) else if (strcmp(argv[i], "-force-xrandr-emulation") == 0) { xwl_screen->force_xrandr_emulation = 1; } + else if (strcmp(argv[i], "-geometry") == 0) { + sscanf(argv[i + 1], "%ix%i", &xwl_width, &xwl_height); + if (xwl_width == 0 || xwl_height == 0) { + ErrorF("invalid argument for -geometry %s\n", argv[i + 1]); + return FALSE; + } + use_fixed_size = 1; + } + } + + if (use_fixed_size) { + if (xwl_screen->rootless) { + ErrorF("error, cannot set a geometry when running rootless\n"); + return FALSE; + } else { + xwl_screen->width = xwl_width; + xwl_screen->height = xwl_height; + } } #ifdef XWL_HAS_GLAMOR @@ -685,8 +718,13 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv) return FALSE; } - if (!xwl_screen_init_output(xwl_screen)) - return FALSE; + if (use_fixed_size) { + if (!xwl_screen_init_randr_fixed(xwl_screen)) + return FALSE; + } else { + if (!xwl_screen_init_output(xwl_screen)) + return FALSE; + } xwl_screen->expecting_event = 0; xwl_screen->registry = wl_display_get_registry(xwl_screen->display); diff --git a/hw/xwayland/xwayland-screen.h b/hw/xwayland/xwayland-screen.h index a4738882a4..5f2782d330 100644 --- a/hw/xwayland/xwayland-screen.h +++ b/hw/xwayland/xwayland-screen.h @@ -93,6 +93,7 @@ struct xwl_screen { struct xorg_list drm_lease_devices; struct xorg_list queued_drm_lease_devices; struct xorg_list drm_leases; + struct xwl_output *fixed_output; uint32_t serial; #define XWL_FORMAT_ARGB8888 (1 << 0) @@ -134,6 +135,7 @@ Bool xwl_screen_has_viewport_support(struct xwl_screen *xwl_screen); Bool xwl_screen_has_resolution_change_emulation(struct xwl_screen *xwl_screen); void xwl_screen_check_resolution_change_emulation(struct xwl_screen *xwl_screen); struct xwl_output *xwl_screen_get_first_output(struct xwl_screen *xwl_screen); +struct xwl_output *xwl_screen_get_fixed_or_first_output(struct xwl_screen *xwl_screen); Bool xwl_close_screen(ScreenPtr screen); Bool xwl_screen_init(ScreenPtr pScreen, int argc, char **argv); void xwl_sync_events (struct xwl_screen *xwl_screen); diff --git a/hw/xwayland/xwayland-vidmode.c b/hw/xwayland/xwayland-vidmode.c index 87e9c3d73a..eed60256e4 100644 --- a/hw/xwayland/xwayland-vidmode.c +++ b/hw/xwayland/xwayland-vidmode.c @@ -110,8 +110,9 @@ static RRModePtr xwlVidModeGetRRMode(ScreenPtr pScreen, int32_t width, int32_t height) { struct xwl_screen *xwl_screen = xwl_screen_get(pScreen); - struct xwl_output *xwl_output = xwl_screen_get_first_output(xwl_screen); + struct xwl_output *xwl_output; + xwl_output = xwl_screen_get_fixed_or_first_output(xwl_screen); if (!xwl_output) return NULL; @@ -122,9 +123,10 @@ 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; + xwl_output = xwl_screen_get_fixed_or_first_output(xwl_screen); if (!xwl_output) return NULL; @@ -238,14 +240,18 @@ static Bool xwlVidModeGetNextModeline(ScreenPtr pScreen, DisplayModePtr *mode, int *dotClock) { struct xwl_screen *xwl_screen = xwl_screen_get(pScreen); - struct xwl_output *xwl_output = xwl_screen_get_first_output(xwl_screen); + struct xwl_output *xwl_output; VidModePtr pVidMode; DisplayModePtr pMod; intptr_t index; + xwl_output = xwl_screen_get_fixed_or_first_output(xwl_screen); + if (xwl_output == NULL) + return FALSE; + pMod = dixLookupPrivate(&pScreen->devPrivates, xwlVidModePrivateKey); pVidMode = VidModeGetPtr(pScreen); - if (xwl_output == NULL || pMod == NULL || pVidMode == NULL) + if (pMod == NULL || pVidMode == NULL) return FALSE; index = (intptr_t)pVidMode->Next; @@ -294,9 +300,10 @@ static Bool xwlVidModeSetViewPort(ScreenPtr pScreen, int x, int y) { struct xwl_screen *xwl_screen = xwl_screen_get(pScreen); - struct xwl_output *xwl_output = xwl_screen_get_first_output(xwl_screen); + struct xwl_output *xwl_output; - if (!xwl_output) + xwl_output = xwl_screen_get_fixed_or_first_output(xwl_screen); + if (xwl_output == NULL) return FALSE; /* Support only default viewport */ @@ -307,9 +314,10 @@ static Bool xwlVidModeGetViewPort(ScreenPtr pScreen, int *x, int *y) { struct xwl_screen *xwl_screen = xwl_screen_get(pScreen); - struct xwl_output *xwl_output = xwl_screen_get_first_output(xwl_screen); + struct xwl_output *xwl_output; - if (!xwl_output) + xwl_output = xwl_screen_get_fixed_or_first_output(xwl_screen); + if (xwl_output == NULL) return FALSE; *x = xwl_output->x; @@ -322,17 +330,22 @@ static Bool xwlVidModeSwitchMode(ScreenPtr pScreen, DisplayModePtr mode) { struct xwl_screen *xwl_screen = xwl_screen_get(pScreen); - struct xwl_output *xwl_output = xwl_screen_get_first_output(xwl_screen); + struct xwl_output *xwl_output; RRModePtr rrmode; - if (!xwl_output) + xwl_output = xwl_screen_get_fixed_or_first_output(xwl_screen); + if (xwl_output == NULL) 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); + if (xwl_screen->rootless) + xwl_output_set_emulated_mode(xwl_output, GetCurrentClient(), rrmode, TRUE); + else if (xwl_screen->fixed_output) + xwl_output_set_mode_fixed(xwl_screen->fixed_output, rrmode); + return TRUE; } @@ -388,7 +401,9 @@ static int xwlVidModeGetNumOfModes(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_output *xwl_output; + + xwl_output = xwl_screen_get_fixed_or_first_output(xwl_screen); return xwl_output ? xwl_output->randr_output->numModes : 0; } diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c index 6cc5f8e0fc..d28d6f8e71 100644 --- a/hw/xwayland/xwayland.c +++ b/hw/xwayland/xwayland.c @@ -91,6 +91,7 @@ void ddxUseMsg(void) { ErrorF("-rootless run rootless, requires wm support\n"); + ErrorF("-geometry WxH set Xwayland window size when rootful\n"); ErrorF("-wm fd create X client for wm on given fd\n"); ErrorF("-initfd fd add given fd as a listen socket for initialization clients\n"); ErrorF("-listenfd fd add given fd as a listen socket\n"); @@ -224,6 +225,10 @@ ddxProcessArgument(int argc, char *argv[], int i) touchEmulatePointer = FALSE; return 1; } + else if (strcmp(argv[i], "-geometry") == 0) { + CHECK_FOR_REQUIRED_ARGUMENTS(1); + return 2; + } return 0; } diff --git a/hw/xwayland/xwayland.pc.in b/hw/xwayland/xwayland.pc.in index e2c06b8013..0b21e7acc1 100644 --- a/hw/xwayland/xwayland.pc.in +++ b/hw/xwayland/xwayland.pc.in @@ -13,3 +13,4 @@ have_verbose=true have_terminate_delay=true have_no_touch_pointer_emulation=true have_force_xrandr_emulation=true +have_geometry=true -- GitLab