From 6c5ffcd1fee9e44780a6a8792f74ecfbe24a1ca7 Mon Sep 17 00:00:00 2001 From: lilydjwg Date: Wed, 17 Nov 2021 19:34:58 +0800 Subject: [PATCH] xwayland: support HiDPI scale This supports the xorg-xwayland patch at https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/733 --- include/xwayland/xwm.h | 2 ++ xwayland/xwm.c | 54 +++++++++++++++++++++++++++++++----------- 2 files changed, 42 insertions(+), 14 deletions(-) diff --git a/include/xwayland/xwm.h b/include/xwayland/xwm.h index 0cdf6ea1..e272a326 100644 --- a/include/xwayland/xwm.h +++ b/include/xwayland/xwm.h @@ -84,6 +84,7 @@ enum atom_name { DND_ACTION_PRIVATE, NET_CLIENT_LIST, NET_CLIENT_LIST_STACKING, + XWAYLAND_GLOBAL_OUTPUT_SCALE, ATOM_LAST // keep last }; @@ -94,6 +95,7 @@ struct wlr_xwm { struct wl_event_source *event_source; struct wlr_seat *seat; uint32_t ping_timeout; + uint32_t scale; xcb_atom_t atoms[ATOM_LAST]; xcb_connection_t *xcb_conn; diff --git a/xwayland/xwm.c b/xwayland/xwm.c index 313bfc0a..1abe2147 100644 --- a/xwayland/xwm.c +++ b/xwayland/xwm.c @@ -20,6 +20,14 @@ #include "util/signal.h" #include "xwayland/xwm.h" +static int32_t scale(struct wlr_xwm *xwm, uint32_t val) { + return val * xwm->scale; +} + +static int32_t unscale(struct wlr_xwm *xwm, uint32_t val) { + return (val + xwm->scale/2) / xwm->scale; +} + const char *const atom_map[ATOM_LAST] = { [WL_SURFACE_ID] = "WL_SURFACE_ID", [WM_DELETE_WINDOW] = "WM_DELETE_WINDOW", @@ -89,6 +97,7 @@ const char *const atom_map[ATOM_LAST] = { [DND_ACTION_PRIVATE] = "XdndActionPrivate", [NET_CLIENT_LIST] = "_NET_CLIENT_LIST", [NET_CLIENT_LIST_STACKING] = "_NET_CLIENT_LIST_STACKING", + [XWAYLAND_GLOBAL_OUTPUT_SCALE] = "_XWAYLAND_GLOBAL_OUTPUT_SCALE", }; #define STARTUP_INFO_REMOVE_PREFIX "remove: ID=" @@ -948,8 +957,8 @@ static void xwm_handle_create_notify(struct wlr_xwm *xwm, return; } - xwayland_surface_create(xwm, ev->window, ev->x, ev->y, - ev->width, ev->height, ev->override_redirect); + xwayland_surface_create(xwm, ev->window, unscale(xwm, ev->x), unscale(xwm, ev->y), + unscale(xwm, ev->width), unscale(xwm, ev->height), ev->override_redirect); } static void xwm_handle_destroy_notify(struct wlr_xwm *xwm, @@ -980,10 +989,10 @@ static void xwm_handle_configure_request(struct wlr_xwm *xwm, struct wlr_xwayland_surface_configure_event wlr_event = { .surface = surface, - .x = mask & XCB_CONFIG_WINDOW_X ? ev->x : surface->x, - .y = mask & XCB_CONFIG_WINDOW_Y ? ev->y : surface->y, - .width = mask & XCB_CONFIG_WINDOW_WIDTH ? ev->width : surface->width, - .height = mask & XCB_CONFIG_WINDOW_HEIGHT ? ev->height : surface->height, + .x = mask & XCB_CONFIG_WINDOW_X ? unscale(xwm, ev->x) : surface->x, + .y = mask & XCB_CONFIG_WINDOW_Y ? unscale(xwm, ev->y) : surface->y, + .width = mask & XCB_CONFIG_WINDOW_WIDTH ? unscale(xwm, ev->width) : surface->width, + .height = mask & XCB_CONFIG_WINDOW_HEIGHT ? unscale(xwm, ev->height) : surface->height, .mask = mask, }; @@ -998,14 +1007,14 @@ static void xwm_handle_configure_notify(struct wlr_xwm *xwm, } bool geometry_changed = - (xsurface->x != ev->x || xsurface->y != ev->y || - xsurface->width != ev->width || xsurface->height != ev->height); + (xsurface->x != unscale(xwm, ev->x) || xsurface->y != unscale(xwm, ev->y) || + xsurface->width != unscale(xwm, ev->width) || xsurface->height != unscale(xwm, ev->height)); if (geometry_changed) { - xsurface->x = ev->x; - xsurface->y = ev->y; - xsurface->width = ev->width; - xsurface->height = ev->height; + xsurface->x = unscale(xwm, ev->x); + xsurface->y = unscale(xwm, ev->y); + xsurface->width = unscale(xwm, ev->width); + xsurface->height = unscale(xwm, ev->height); } if (xsurface->override_redirect != ev->override_redirect) { @@ -1114,7 +1123,22 @@ static void xwm_handle_unmap_notify(struct wlr_xwm *xwm, static void xwm_handle_property_notify(struct wlr_xwm *xwm, xcb_property_notify_event_t *ev) { struct wlr_xwayland_surface *xsurface = lookup_surface(xwm, ev->window); + if (xsurface == NULL) { + if (ev->atom == xwm->atoms[XWAYLAND_GLOBAL_OUTPUT_SCALE]) { + xcb_get_property_cookie_t cookie = xcb_get_property(xwm->xcb_conn, 0, + ev->window, ev->atom, XCB_ATOM_ANY, 0, 2048); + xcb_get_property_reply_t *reply = xcb_get_property_reply(xwm->xcb_conn, + cookie, NULL); + if (reply == NULL) { + return; + } + if (reply->type == XCB_ATOM_CARDINAL) { + xwm->scale = *(uint32_t*)xcb_get_property_value(reply); + } + free(reply); + } + return; } @@ -1708,16 +1732,17 @@ void wlr_xwayland_surface_activate(struct wlr_xwayland_surface *xsurface, void wlr_xwayland_surface_configure(struct wlr_xwayland_surface *xsurface, int16_t x, int16_t y, uint16_t width, uint16_t height) { + struct wlr_xwm *xwm = xsurface->xwm; + xsurface->x = x; xsurface->y = y; xsurface->width = width; xsurface->height = height; - struct wlr_xwm *xwm = xsurface->xwm; uint32_t mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT | XCB_CONFIG_WINDOW_BORDER_WIDTH; - uint32_t values[] = {x, y, width, height, 0}; + uint32_t values[] = {scale(xwm, x), scale(xwm, y), scale(xwm, width), scale(xwm, height), 0}; xcb_configure_window(xwm->xcb_conn, xsurface->window_id, mask, values); xcb_flush(xwm->xcb_conn); } @@ -2046,6 +2071,7 @@ struct wlr_xwm *xwm_create(struct wlr_xwayland *xwayland, int wm_fd) { wl_list_init(&xwm->pending_startup_ids); xwm->ping_timeout = 10000; + xwm->scale = 1; xwm->xcb_conn = xcb_connect_to_fd(wm_fd, NULL); int rc = xcb_connection_has_error(xwm->xcb_conn); -- GitLab