diff --git a/hw/xwayland/xwayland-output.c b/hw/xwayland/xwayland-output.c index abbddddf9..f91e676c6 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 9c7fb6691..5a2397cdc 100644 --- a/hw/xwayland/xwayland.h +++ b/hw/xwayland/xwayland.h @@ -377,7 +377,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]; }; struct xwl_client *xwl_client_get(ClientPtr client); @@ -421,6 +435,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);