summarylogtreecommitdiffstats
path: root/0001-xwayland-support-HiDPI-scale.patch
blob: a9e86fb3ac31011b8b30c047128daab705a45959 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
From 48f97d24d4b7f9d5fd0d4accdbaa009b365bd61b Mon Sep 17 00:00:00 2001
From: lilydjwg <lilydjwg@gmail.com>
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         | 51 +++++++++++++++++++++++++++++++-----------
 2 files changed, 40 insertions(+), 13 deletions(-)

diff --git a/include/xwayland/xwm.h b/include/xwayland/xwm.h
index c69504e8..1a332b6c 100644
--- a/include/xwayland/xwm.h
+++ b/include/xwayland/xwm.h
@@ -88,6 +88,7 @@ enum atom_name {
 	DND_ACTION_PRIVATE,
 	NET_CLIENT_LIST,
 	NET_CLIENT_LIST_STACKING,
+        XWAYLAND_GLOBAL_OUTPUT_SCALE,
 	ATOM_LAST // keep last
 };
 
@@ -98,6 +99,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 5a36dc21..8449977e 100644
--- a/xwayland/xwm.c
+++ b/xwayland/xwm.c
@@ -19,6 +19,14 @@
 #include <xcb/xfixes.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",
 	[WL_SURFACE_SERIAL] = "WL_SURFACE_SERIAL",
@@ -90,6 +98,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="
@@ -968,8 +977,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,
@@ -1000,10 +1009,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,
 	};
 
@@ -1018,14 +1027,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) {
@@ -1135,7 +1144,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;
 	}
 
@@ -1772,7 +1796,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
@@ -2125,6 +2149,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);
-- 
2.39.2