Created
May 1, 2020 21:28
-
-
Save foxyfocus/50f9c260821f11b8b0f2887290ea14ee to your computer and use it in GitHub Desktop.
PKGBUILD for modified wlroots for Xwayland HIDPI support
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Maintainer: Adrian Perez de Castro <[email protected]> | |
pkgname=wlroots-git | |
pkgver=0.10.0.r81.gf81aa6a1 | |
pkgrel=1 | |
license=(custom:MIT) | |
pkgdesc='Modular Wayland compositor library' | |
url=https://github.com/swaywm/wlroots | |
arch=(x86_64) | |
provides=("wlroots=${pkgver%%.r*}") | |
conflicts=(wlroots) | |
options=(debug) | |
depends=(libcap systemd wayland opengl-driver libxcb xcb-util-errors | |
xcb-util-wm pixman libinput libxkbcommon) | |
makedepends=(meson ninja git wayland-protocols xorgproto) | |
source=("${pkgname}::git+${url}") | |
sha512sums=('SKIP') | |
pkgver () { | |
cd "${pkgname}" | |
( | |
set -o pipefail | |
git describe --long 2>/dev/null | sed 's/\([^-]*-g\)/r\1/;s/-/./g' || | |
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)" | |
) | |
} | |
prepare() { | |
cd "${pkgname}" | |
patch -Np1 -i ../../scale.patch | |
} | |
build () { | |
cd "${pkgname}" | |
rm -rf build | |
meson build \ | |
--prefix /usr \ | |
--buildtype debug \ | |
-Dlibcap=enabled \ | |
-Dlogind=enabled \ | |
-Dlogind-provider=systemd \ | |
-Dxcb-errors=enabled \ | |
-Dxcb-icccm=enabled \ | |
-Dxwayland=enabled \ | |
-Dx11-backend=enabled \ | |
-Dexamples=true | |
ninja -C build | |
} | |
package () { | |
cd "${pkgname}" | |
DESTDIR="${pkgdir}" ninja -C build install | |
install -Dm644 LICENSE "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE" | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 182d8c449bd38d66230717d8e8fef5abf80332aa Mon Sep 17 00:00:00 2001 | |
From: Dario Nieuwenhuis <[email protected]> | |
Date: Fri, 31 Jan 2020 22:57:48 +0100 | |
Subject: [PATCH 1/2] Xwayland HiDPI | |
This does the necessary changes to support HiDPI in xwayland | |
applications, with the following xwayland patch: | |
https://gitlab.freedesktop.org/xorg/xserver/merge_requests/111 | |
--- | |
include/wlr/xwayland.h | 4 ++++ | |
xwayland/xwayland.c | 8 +++++++- | |
xwayland/xwm.c | 42 +++++++++++++++++++++++++++++++----------- | |
3 files changed, 42 insertions(+), 12 deletions(-) | |
diff --git a/include/wlr/xwayland.h b/include/wlr/xwayland.h | |
index 8646e7acb..d1b705f62 100644 | |
--- a/include/wlr/xwayland.h | |
+++ b/include/wlr/xwayland.h | |
@@ -30,6 +30,8 @@ struct wlr_xwayland { | |
time_t server_start; | |
+ int32_t scale; | |
+ | |
/* Anything above display is reset on Xwayland restart, rest is conserved */ | |
int display; | |
@@ -205,6 +207,8 @@ struct wlr_xwayland *wlr_xwayland_create(struct wl_display *wl_display, | |
void wlr_xwayland_destroy(struct wlr_xwayland *wlr_xwayland); | |
+void wlr_xwayland_set_scale(struct wlr_xwayland *wlr_xwayland, int32_t scale); | |
+ | |
void wlr_xwayland_set_cursor(struct wlr_xwayland *wlr_xwayland, | |
uint8_t *pixels, uint32_t stride, uint32_t width, uint32_t height, | |
int32_t hotspot_x, int32_t hotspot_y); | |
diff --git a/xwayland/xwayland.c b/xwayland/xwayland.c | |
index 77698f449..3c90aff27 100644 | |
--- a/xwayland/xwayland.c | |
+++ b/xwayland/xwayland.c | |
@@ -66,7 +66,7 @@ _Noreturn static void exec_xwayland(struct wlr_xwayland *wlr_xwayland) { | |
char *argv[] = { | |
"Xwayland", NULL /* display, e.g. :1 */, | |
- "-rootless", "-terminate", | |
+ "-rootless", "-terminate", "-max-factor-rescale", | |
"-listen", NULL /* x_fd[0] */, | |
"-listen", NULL /* x_fd[1] */, | |
"-wm", NULL /* wm_fd[1] */, | |
@@ -409,6 +409,8 @@ struct wlr_xwayland *wlr_xwayland_create(struct wl_display *wl_display, | |
wlr_xwayland->wl_fd[0] = wlr_xwayland->wl_fd[1] = -1; | |
wlr_xwayland->wm_fd[0] = wlr_xwayland->wm_fd[1] = -1; | |
+ wlr_xwayland->scale = 1; | |
+ | |
wl_signal_init(&wlr_xwayland->events.new_surface); | |
wl_signal_init(&wlr_xwayland->events.ready); | |
@@ -436,6 +438,10 @@ struct wlr_xwayland *wlr_xwayland_create(struct wl_display *wl_display, | |
return NULL; | |
} | |
+void wlr_xwayland_set_scale(struct wlr_xwayland *wlr_xwayland, int32_t scale) { | |
+ wlr_xwayland->scale = scale; | |
+} | |
+ | |
void wlr_xwayland_set_cursor(struct wlr_xwayland *wlr_xwayland, | |
uint8_t *pixels, uint32_t stride, uint32_t width, uint32_t height, | |
int32_t hotspot_x, int32_t hotspot_y) { | |
diff --git a/xwayland/xwm.c b/xwayland/xwm.c | |
index b19efbcf1..8c8bc696d 100644 | |
--- a/xwayland/xwm.c | |
+++ b/xwayland/xwm.c | |
@@ -16,6 +16,15 @@ | |
#include "util/signal.h" | |
#include "xwayland/xwm.h" | |
+ | |
+static int32_t scale(struct wlr_xwm *xwm, int32_t val) { | |
+ return val * xwm->xwayland->scale; | |
+} | |
+ | |
+static int32_t unscale(struct wlr_xwm *xwm, int32_t val) { | |
+ return (val + xwm->xwayland->scale/2) / xwm->xwayland->scale; | |
+} | |
+ | |
const char *atom_map[ATOM_LAST] = { | |
[WL_SURFACE_ID] = "WL_SURFACE_ID", | |
[WM_DELETE_WINDOW] = "WM_DELETE_WINDOW", | |
@@ -834,8 +843,13 @@ 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, | |
@@ -866,10 +880,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 = unscale(xwm, mask & XCB_CONFIG_WINDOW_X ? ev->x : surface->x), | |
+ .y = unscale(xwm, mask & XCB_CONFIG_WINDOW_Y ? ev->y : surface->y), | |
+ .width = unscale(xwm, mask & XCB_CONFIG_WINDOW_WIDTH ? ev->width : surface->width), | |
+ .height = unscale(xwm, mask & XCB_CONFIG_WINDOW_HEIGHT ? ev->height : surface->height), | |
.mask = mask, | |
}; | |
wlr_log(WLR_DEBUG, "XCB_CONFIGURE_REQUEST (%u) [%ux%u+%d,%d]", ev->window, | |
@@ -885,10 +899,10 @@ static void xwm_handle_configure_notify(struct wlr_xwm *xwm, | |
return; | |
} | |
- 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) { | |
xsurface->override_redirect = ev->override_redirect; | |
@@ -1431,7 +1445,13 @@ 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(xsurface->xwm, x), | |
+ scale(xsurface->xwm, y), | |
+ scale(xsurface->xwm, width), | |
+ scale(xsurface->xwm, height), | |
+ 0, | |
+ }; | |
xcb_configure_window(xwm->xcb_conn, xsurface->window_id, mask, values); | |
xcb_flush(xwm->xcb_conn); | |
} | |
From 9fcf9dd38b9658ae029d2baa0fb42fcb65039b97 Mon Sep 17 00:00:00 2001 | |
From: Dario Nieuwenhuis <[email protected]> | |
Date: Tue, 10 Mar 2020 23:21:11 +0100 | |
Subject: [PATCH 2/2] Make xwayland scale factor configurable on the fly via X | |
extension and xsettings. | |
--- | |
include/xwayland/xwm.h | 9 +++ | |
xwayland/xwayland.c | 3 + | |
xwayland/xwm.c | 122 +++++++++++++++++++++++++++++++++++++++++ | |
3 files changed, 134 insertions(+) | |
diff --git a/include/xwayland/xwm.h b/include/xwayland/xwm.h | |
index 351fce441..2c3ba1b68 100644 | |
--- a/include/xwayland/xwm.h | |
+++ b/include/xwayland/xwm.h | |
@@ -80,6 +80,9 @@ enum atom_name { | |
DND_ACTION_ASK, | |
DND_ACTION_PRIVATE, | |
NET_CLIENT_LIST, | |
+ XSETTINGS_SETTINGS, | |
+ XSETTINGS_S0, | |
+ MANAGER, | |
ATOM_LAST // keep last | |
}; | |
@@ -106,6 +109,9 @@ struct wlr_xwm { | |
xcb_render_pictformat_t render_format_id; | |
xcb_cursor_t cursor; | |
+ xcb_window_t xsettings_window; | |
+ int32_t xsettings_serial; | |
+ | |
xcb_window_t selection_window; | |
struct wlr_xwm_selection clipboard_selection; | |
struct wlr_xwm_selection primary_selection; | |
@@ -122,6 +128,7 @@ struct wlr_xwm { | |
struct wlr_xwayland_surface *drag_focus; | |
const xcb_query_extension_reply_t *xfixes; | |
+ const xcb_query_extension_reply_t *xwayland_ext; | |
#if WLR_HAS_XCB_ERRORS | |
xcb_errors_context_t *errors_context; | |
#endif | |
@@ -155,4 +162,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 3c90aff27..10c7c17f0 100644 | |
--- a/xwayland/xwayland.c | |
+++ b/xwayland/xwayland.c | |
@@ -440,6 +440,9 @@ struct wlr_xwayland *wlr_xwayland_create(struct wl_display *wl_display, | |
void wlr_xwayland_set_scale(struct wlr_xwayland *wlr_xwayland, int32_t scale) { | |
wlr_xwayland->scale = scale; | |
+ if (wlr_xwayland->xwm != NULL) { | |
+ xwm_scale_changed(wlr_xwayland->xwm); | |
+ } | |
} | |
void wlr_xwayland_set_cursor(struct wlr_xwayland *wlr_xwayland, | |
diff --git a/xwayland/xwm.c b/xwayland/xwm.c | |
index 8c8bc696d..3761ba83c 100644 | |
--- a/xwayland/xwm.c | |
+++ b/xwayland/xwm.c | |
@@ -13,6 +13,7 @@ | |
#include <xcb/composite.h> | |
#include <xcb/render.h> | |
#include <xcb/xfixes.h> | |
+#include <xcb/xcbext.h> | |
#include "util/signal.h" | |
#include "xwayland/xwm.h" | |
@@ -25,6 +26,10 @@ static int32_t unscale(struct wlr_xwm *xwm, int32_t val) { | |
return (val + xwm->xwayland->scale/2) / xwm->xwayland->scale; | |
} | |
+static xcb_extension_t xwayland_ext_id = { | |
+ .name = "XWAYLAND", | |
+}; | |
+ | |
const char *atom_map[ATOM_LAST] = { | |
[WL_SURFACE_ID] = "WL_SURFACE_ID", | |
[WM_DELETE_WINDOW] = "WM_DELETE_WINDOW", | |
@@ -87,6 +92,9 @@ const char *atom_map[ATOM_LAST] = { | |
[DND_ACTION_ASK] = "XdndActionAsk", | |
[DND_ACTION_PRIVATE] = "XdndActionPrivate", | |
[NET_CLIENT_LIST] = "_NET_CLIENT_LIST", | |
+ [XSETTINGS_SETTINGS] = "_XSETTINGS_SETTINGS", | |
+ [XSETTINGS_S0] = "_XSETTINGS_S0", | |
+ [MANAGER] = "MANAGER", | |
}; | |
static const struct wlr_surface_role xwayland_surface_role; | |
@@ -1517,6 +1525,7 @@ void xwm_destroy(struct wlr_xwm *xwm) { | |
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, &xwayland_ext_id); // TODO what if extension is not present?? | |
size_t i; | |
xcb_intern_atom_cookie_t cookies[ATOM_LAST]; | |
@@ -1548,6 +1557,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 = | |
@@ -1613,6 +1624,75 @@ static void xwm_create_wm_window(struct wlr_xwm *xwm) { | |
XCB_CURRENT_TIME); | |
} | |
+static void xwm_xsettings_set(struct wlr_xwm *xwm) { | |
+ uint8_t data[] = { | |
+ XCB_IMAGE_ORDER_LSB_FIRST, | |
+ 0, 0, 0, | |
+ xwm->xsettings_serial, 0, 0, 0, // serial | |
+ 1, 0, 0, 0, // setting count | |
+ | |
+ 0, // type: XSettingsTypeInteger | |
+ 0, // unused | |
+ 23, 0, // name len | |
+ 71, 100, 107, 47, 87, 105, 110, 100, 111, 119, 83, 99, 97, 108, 105, 110, 103, 70, 97, 99, 116, 111, 114, // name | |
+ 0, // name padding (round up to multiple of 4) | |
+ xwm->xsettings_serial, 0, 0, 0, // serial | |
+ xwm->xwayland->scale, 0, 0, 0, // value | |
+ }; | |
+ | |
+ xcb_change_property(xwm->xcb_conn, | |
+ XCB_PROP_MODE_REPLACE, | |
+ xwm->xsettings_window, | |
+ xwm->atoms[XSETTINGS_SETTINGS], | |
+ xwm->atoms[XSETTINGS_SETTINGS], | |
+ 8, | |
+ sizeof(data), | |
+ data | |
+ ); | |
+ | |
+ wlr_log(WLR_ERROR, "xwm_xsettings_set window %x scale %d serial %d", xwm->window, xwm->xwayland->scale, xwm->xsettings_serial); | |
+} | |
+ | |
+static void xwm_xsettings_init(struct wlr_xwm *xwm) { | |
+ wlr_log(WLR_ERROR, "xwm_xsettings_init"); | |
+ | |
+ xwm->xsettings_serial = 1; | |
+ xwm->xsettings_window = xcb_generate_id(xwm->xcb_conn); | |
+ | |
+ xcb_create_window(xwm->xcb_conn, | |
+ XCB_COPY_FROM_PARENT, | |
+ xwm->xsettings_window, | |
+ xwm->screen->root, | |
+ 0, 0, | |
+ 10, 10, | |
+ 0, | |
+ XCB_WINDOW_CLASS_INPUT_OUTPUT, | |
+ xwm->screen->root_visual, | |
+ 0, NULL); | |
+ | |
+ xwm_xsettings_set(xwm); | |
+ xcb_set_selection_owner(xwm->xcb_conn, xwm->xsettings_window, xwm->atoms[XSETTINGS_S0], XCB_CURRENT_TIME); | |
+ | |
+ xcb_client_message_event_t event = { | |
+ .response_type = XCB_CLIENT_MESSAGE, | |
+ .format = 32, | |
+ .sequence = 0, | |
+ .window = xwm->screen->root, | |
+ .type = xwm->atoms[MANAGER], | |
+ .data = { | |
+ .data32 = { | |
+ 0, //timestamp | |
+ xwm->atoms[XSETTINGS_S0], | |
+ xwm->xsettings_window, | |
+ 0, | |
+ } | |
+ }, | |
+ }; | |
+ | |
+ xcb_send_event(xwm->xcb_conn, false, xwm->screen->root, XCB_EVENT_MASK_STRUCTURE_NOTIFY, (char*)&event); | |
+ xcb_flush(xwm->xcb_conn); | |
+} | |
+ | |
// TODO use me to support 32 bit color somehow | |
static void xwm_get_visual_and_colormap(struct wlr_xwm *xwm) { | |
xcb_depth_iterator_t d_iter; | |
@@ -1725,6 +1805,7 @@ struct wlr_xwm *xwm_create(struct wlr_xwayland *wlr_xwayland) { | |
wl_list_init(&xwm->surfaces); | |
wl_list_init(&xwm->unpaired_surfaces); | |
xwm->ping_timeout = 10000; | |
+ xwm->xsettings_serial = 1; | |
xwm->xcb_conn = xcb_connect_to_fd(wlr_xwayland->wm_fd[0], NULL); | |
@@ -1809,6 +1890,8 @@ struct wlr_xwm *xwm_create(struct wlr_xwayland *wlr_xwayland) { | |
xwm_create_wm_window(xwm); | |
+ xwm_xsettings_init(xwm); | |
+ | |
xcb_flush(xwm->xcb_conn); | |
return xwm; | |
@@ -1878,3 +1961,42 @@ bool wlr_xwayland_or_surface_wants_focus( | |
return ret; | |
} | |
+ | |
+ | |
+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) { | |
+ xwm->xsettings_serial++; | |
+ xwm_xsettings_set(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->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); | |
+} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment