From 9f2755f083be057edd1f70f21b5c6e83758c5488 Mon Sep 17 00:00:00 2001 From: lilydjwg Date: Wed, 17 Nov 2021 19:34:58 +0800 Subject: [PATCH 1/3] 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 | 63 +++++++++++++++++++++++++++++------------- 2 files changed, 46 insertions(+), 19 deletions(-) diff --git a/include/xwayland/xwm.h b/include/xwayland/xwm.h index da3515da..b6ad4492 100644 --- a/include/xwayland/xwm.h +++ b/include/xwayland/xwm.h @@ -89,6 +89,7 @@ enum atom_name { NET_CLIENT_LIST, NET_CLIENT_LIST_STACKING, NET_WORKAREA, + XWAYLAND_GLOBAL_OUTPUT_SCALE, ATOM_LAST // keep last }; @@ -97,6 +98,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 db4a8c0f..8167a2fc 100644 --- a/xwayland/xwm.c +++ b/xwayland/xwm.c @@ -19,6 +19,14 @@ #include #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; +} + static const char *const atom_map[ATOM_LAST] = { [WL_SURFACE_ID] = "WL_SURFACE_ID", [WL_SURFACE_SERIAL] = "WL_SURFACE_SERIAL", @@ -91,6 +99,7 @@ static const char *const atom_map[ATOM_LAST] = { [NET_CLIENT_LIST] = "_NET_CLIENT_LIST", [NET_CLIENT_LIST_STACKING] = "_NET_CLIENT_LIST_STACKING", [NET_WORKAREA] = "_NET_WORKAREA", + [XWAYLAND_GLOBAL_OUTPUT_SCALE] = "_XWAYLAND_GLOBAL_OUTPUT_SCALE", }; #define STARTUP_INFO_REMOVE_PREFIX "remove: ID=" @@ -957,8 +966,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, @@ -989,10 +998,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, }; @@ -1007,14 +1016,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) { @@ -1131,7 +1140,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; } @@ -1775,7 +1799,7 @@ void wlr_xwayland_surface_configure(struct wlr_xwayland_surface *xsurface, 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); // If the window size did not change, then we cannot rely on @@ -2128,6 +2152,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); @@ -2335,15 +2360,15 @@ void wlr_xwayland_set_workareas(struct wlr_xwayland *wlr_xwayland, if (!data) { return; } - + struct wlr_xwm *xwm = wlr_xwayland->xwm; + for (size_t i = 0; i < num_workareas; i++) { - data[4 * i] = workareas[i].x; - data[4 * i + 1] = workareas[i].y; - data[4 * i + 2] = workareas[i].width; - data[4 * i + 3] = workareas[i].height; + data[4 * i] = scale(xwm, workareas[i].x); + data[4 * i + 1] = scale(xwm, workareas[i].y); + data[4 * i + 2] = scale(xwm, workareas[i].width); + data[4 * i + 3] = scale(xwm, workareas[i].height); } - struct wlr_xwm *xwm = wlr_xwayland->xwm; xcb_change_property(xwm->xcb_conn, XCB_PROP_MODE_REPLACE, xwm->screen->root, xwm->atoms[NET_WORKAREA], XCB_ATOM_CARDINAL, 32, 4 * num_workareas, data); -- 2.42.0