From 29cb694655db4a5891227eea6b9cc1ca8f3d14dd Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 10 Mar 2020 23:21:11 +0100 Subject: [PATCH] xwayland: add support for changing global scale factor on the fly via x extension. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [Antonin Décimo: rebase after 1eb38e0] [Antonin Décimo: rebase after 79be26f] --- include/xwayland/xwm.h | 3 +++ xwayland/xwayland.c | 3 +++ xwayland/xwm.c | 44 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+) diff --git a/include/xwayland/xwm.h b/include/xwayland/xwm.h index 41e35ef39e..62994f56f6 100644 --- a/include/xwayland/xwm.h +++ b/include/xwayland/xwm.h @@ -122,6 +122,7 @@ struct wlr_xwm { const xcb_query_extension_reply_t *xfixes; const xcb_query_extension_reply_t *xres; + const xcb_query_extension_reply_t *xwayland_ext; uint32_t xfixes_major_version; #if HAS_XCB_ERRORS xcb_errors_context_t *errors_context; @@ -157,4 +158,6 @@ char *xwm_get_atom_name(struct wlr_xwm *xwm, xcb_atom_t atom); bool xwm_atoms_contains(struct wlr_xwm *xwm, xcb_atom_t *atoms, size_t num_atoms, enum atom_name needle); +void xwm_scale_changed(struct wlr_xwm *xwm); + #endif diff --git a/xwayland/xwayland.c b/xwayland/xwayland.c index 05d8e4b562..fa1d97b838 100644 --- a/xwayland/xwayland.c +++ b/xwayland/xwayland.c @@ -110,6 +110,9 @@ struct wlr_xwayland *wlr_xwayland_create(struct wl_display *wl_display, void wlr_xwayland_set_scale(struct wlr_xwayland *xwayland, int32_t scale) { xwayland->server->scale = scale; + if (xwayland->xwm != NULL) { + xwm_scale_changed(xwayland->xwm); + } } void wlr_xwayland_set_cursor(struct wlr_xwayland *xwayland, diff --git a/xwayland/xwm.c b/xwayland/xwm.c index 93ad853bb7..3234d48804 100644 --- a/xwayland/xwm.c +++ b/xwayland/xwm.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include "xwayland/xwm.h" @@ -26,6 +27,10 @@ static int32_t unscale(struct wlr_xwm *xwm, int32_t val) { return (val + xwm->xwayland->server->scale/2) / xwm->xwayland->server->scale; } +static xcb_extension_t xwayland_ext_id = { + .name = "XWAYLAND", +}; + const char *const atom_map[ATOM_LAST] = { [WL_SURFACE_ID] = "WL_SURFACE_ID", [WM_DELETE_WINDOW] = "WM_DELETE_WINDOW", @@ -1810,6 +1815,7 @@ static void xwm_get_resources(struct wlr_xwm *xwm) { xcb_prefetch_extension_data(xwm->xcb_conn, &xcb_xfixes_id); xcb_prefetch_extension_data(xwm->xcb_conn, &xcb_composite_id); xcb_prefetch_extension_data(xwm->xcb_conn, &xcb_res_id); + xcb_prefetch_extension_data(xwm->xcb_conn, &xwayland_ext_id); // TODO what if extension is not present?? size_t i; xcb_intern_atom_cookie_t cookies[ATOM_LAST]; @@ -1841,6 +1847,8 @@ static void xwm_get_resources(struct wlr_xwm *xwm) { wlr_log(WLR_DEBUG, "xfixes not available"); } + xwm->xwayland_ext = xcb_get_extension_data(xwm->xcb_conn, &xwayland_ext_id); + xcb_xfixes_query_version_cookie_t xfixes_cookie; xcb_xfixes_query_version_reply_t *xfixes_reply; xfixes_cookie = @@ -2240,3 +2248,39 @@ enum wlr_xwayland_icccm_input_model wlr_xwayland_icccm_input_model( } return WLR_ICCCM_INPUT_MODEL_NONE; } + + +typedef struct { + uint8_t major_opcode; + uint8_t minor_opcode; + uint16_t length; + uint16_t screen; + uint16_t scale; +} xwayland_ext_set_scale_request_t; + +void xwm_scale_changed(struct wlr_xwm *xwm) { + xcb_protocol_request_t req = { + .count = 1, + .ext = &xwayland_ext_id, + .opcode = 1, + .isvoid = false, + }; + + xwayland_ext_set_scale_request_t xcb_out = { + .screen = 0, + .scale = xwm->xwayland->server->scale, + }; + + struct iovec xcb_parts[3]; + xcb_parts[2].iov_base = (char *) &xcb_out; + xcb_parts[2].iov_len = sizeof(xcb_out); + xcb_send_request(xwm->xcb_conn, 0, xcb_parts+2, &req); + + // Reconfigure all surfaces with the new scale. + struct wlr_xwayland_surface *surface; + wl_list_for_each(surface, &xwm->surfaces, link) { + wlr_xwayland_surface_configure(surface, surface->x, surface->y, surface->width, surface->height); + } + + xcb_flush(xwm->xcb_conn); +}