-
Notifications
You must be signed in to change notification settings - Fork 280
/
xwlScaling.diff
254 lines (230 loc) · 9.44 KB
/
xwlScaling.diff
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
diff --git a/hw/xwayland/xwayland-output.c b/hw/xwayland/xwayland-output.c
index 7c8ebd49a..0bd8e8957 100644
--- a/hw/xwayland/xwayland-output.c
+++ b/hw/xwayland/xwayland-output.c
@@ -194,6 +194,13 @@ update_screen_size(struct xwl_screen *xwl_screen, int width, int height)
if (xwl_screen_get_height(xwl_screen) != height)
xwl_screen->height = height;
+ /* In rootless mode, if global_surface_scale is set, we must scale accordingly here */
+ /* This is because xscale is never set if we are not running rootful */
+ if (xwl_screen->rootless && xwl_screen->global_surface_scale > 1) {
+ width *= xwl_screen->global_surface_scale;
+ height *= xwl_screen->global_surface_scale;
+ }
+
if (xwl_screen->root_clip_mode == ROOT_CLIP_FULL)
SetRootClip(xwl_screen->screen, ROOT_CLIP_NONE);
@@ -617,14 +624,15 @@ maybe_update_fullscreen_state(struct xwl_output *xwl_output)
}
}
-static void
-apply_output_change(struct xwl_output *xwl_output)
+void
+xwl_output_apply_changes(struct xwl_output *xwl_output)
{
struct xwl_screen *xwl_screen = xwl_output->xwl_screen;
struct xwl_output *it;
int mode_width, mode_height, count;
int width = 0, height = 0, has_this_output = 0;
RRModePtr *randr_modes;
+ int32_t scale = xwl_screen->global_surface_scale;
/* Clear out the "done" received flags */
xwl_output->wl_output_done = FALSE;
@@ -643,10 +651,10 @@ apply_output_change(struct xwl_output *xwl_output)
}
if (xwl_output->randr_output) {
/* Build a fresh modes array using the current refresh rate */
- randr_modes = output_get_rr_modes(xwl_output, mode_width, mode_height, &count);
+ randr_modes = output_get_rr_modes(xwl_output, mode_width * scale, mode_height * scale, &count);
RROutputSetModes(xwl_output->randr_output, randr_modes, count, 1);
RRCrtcNotify(xwl_output->randr_crtc, randr_modes[0],
- xwl_output->x, xwl_output->y,
+ xwl_output->x * scale, xwl_output->y * scale,
xwl_output->rotation, NULL, 1, &xwl_output->randr_output);
/* RROutputSetModes takes ownership of the passed in modes, so we only
* have to free the pointer array.
@@ -740,7 +748,7 @@ output_handle_done(void *data, struct wl_output *wl_output)
*/
if (xwl_output->xdg_output_done || !xwl_output->xdg_output ||
zxdg_output_v1_get_version(xwl_output->xdg_output) >= 3)
- apply_output_change(xwl_output);
+ xwl_output_apply_changes(xwl_output);
}
static void
@@ -808,7 +816,7 @@ xdg_output_handle_done(void *data, struct zxdg_output_v1 *xdg_output)
if (xwl_output->wl_output_done &&
zxdg_output_v1_get_version(xdg_output) < 3)
- apply_output_change(xwl_output);
+ xwl_output_apply_changes(xwl_output);
}
static void
@@ -944,6 +952,8 @@ xwl_output_create(struct xwl_screen *xwl_screen, uint32_t id,
RROutputSetConnection(xwl_output->randr_output,
connected ? RR_Connected : RR_Disconnected);
+ xwl_output->scale = 1;
+
/* We want the output to be in the list as soon as created so we can
* use it when binding to the xdg-output protocol...
*/
diff --git a/hw/xwayland/xwayland-output.h b/hw/xwayland/xwayland-output.h
index 0d36f459a..123d01380 100644
--- a/hw/xwayland/xwayland-output.h
+++ b/hw/xwayland/xwayland-output.h
@@ -121,4 +121,6 @@ void xwl_output_set_window_randr_emu_props(struct xwl_screen *xwl_screen,
void xwl_screen_init_xdg_output(struct xwl_screen *xwl_screen);
+void xwl_output_apply_changes(struct xwl_output *xwl_output);
+
#endif /* XWAYLAND_OUTPUT_H */
diff --git a/hw/xwayland/xwayland-present.c b/hw/xwayland/xwayland-present.c
index 4d2410568..2ebe166cf 100644
--- a/hw/xwayland/xwayland-present.c
+++ b/hw/xwayland/xwayland-present.c
@@ -911,6 +911,7 @@ xwl_present_flip(present_vblank_ptr vblank, RegionPtr damage)
/* We can flip directly to the main surface (full screen window without clips) */
wl_surface_attach(xwl_window->surface, buffer, 0, 0);
+ wl_surface_set_buffer_scale(xwl_window->surface, xwl_window->xwl_screen->global_surface_scale);
if (xorg_list_is_empty(&xwl_present_window->frame_callback_list)) {
xorg_list_add(&xwl_present_window->frame_callback_list,
diff --git a/hw/xwayland/xwayland-screen.c b/hw/xwayland/xwayland-screen.c
index 287fe8b06..c9f0c9da6 100644
--- a/hw/xwayland/xwayland-screen.c
+++ b/hw/xwayland/xwayland-screen.c
@@ -124,6 +124,12 @@ xwl_screen_has_resolution_change_emulation(struct xwl_screen *xwl_screen)
return xwl_screen->rootless && xwl_screen_has_viewport_support(xwl_screen);
}
+int
+xwl_scale_to(struct xwl_screen *xwl_screen, int value)
+{
+ return value / (double)xwl_screen->global_surface_scale + 0.5;
+}
+
/* Return the output @ 0x0, falling back to the first output in the list */
struct xwl_output *
xwl_screen_get_first_output(struct xwl_screen *xwl_screen)
@@ -721,8 +727,14 @@ void xwl_surface_damage(struct xwl_screen *xwl_screen,
{
if (wl_surface_get_version(surface) >= WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION)
wl_surface_damage_buffer(surface, x, y, width, height);
- else
+ else {
+ x = xwl_scale_to(xwl_screen, x);
+ y = xwl_scale_to(xwl_screen, y);
+ width = xwl_scale_to(xwl_screen, width);
+ height = xwl_scale_to(xwl_screen, height);
+
wl_surface_damage(surface, x, y, width, height);
+ }
}
void
@@ -854,6 +866,18 @@ xwl_screen_update_global_surface_scale(struct xwl_screen *xwl_screen)
return (xwl_screen->global_surface_scale != old_scale);
}
+void
+xwl_screen_set_global_scale( struct xwl_screen *xwl_screen, int32_t scale)
+{
+ struct xwl_output *it;
+ xwl_screen->global_surface_scale = scale;
+
+ /* change randr resolutions and positions */
+ xorg_list_for_each_entry(it, &xwl_screen->output_list, link) {
+ xwl_output_apply_changes(it);
+ }
+}
+
Bool
xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
{
@@ -894,6 +918,7 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
#ifdef XWL_HAS_GLAMOR
xwl_screen->glamor = XWL_GLAMOR_DEFAULT;
#endif
+ xwl_screen->global_surface_scale = 1;
for (i = 1; i < argc; i++) {
if (strcmp(argv[i], "-rootless") == 0) {
diff --git a/hw/xwayland/xwayland-screen.h b/hw/xwayland/xwayland-screen.h
index 0800fb392..a49813a16 100644
--- a/hw/xwayland/xwayland-screen.h
+++ b/hw/xwayland/xwayland-screen.h
@@ -181,5 +181,7 @@ int xwl_screen_get_next_output_serial(struct xwl_screen * xwl_screen);
void xwl_screen_lost_focus(struct xwl_screen *xwl_screen);
Bool xwl_screen_update_global_surface_scale(struct xwl_screen *xwl_screen);
Bool xwl_screen_should_use_fractional_scale(struct xwl_screen *xwl_screen);
+int xwl_scale_to(struct xwl_screen *xwl_screen, int value);
+void xwl_screen_set_global_scale( struct xwl_screen *xwl_screen, int32_t scale);
#endif /* XWAYLAND_SCREEN_H */
diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c
index 05f45e16f..56e4338be 100644
--- a/hw/xwayland/xwayland-window.c
+++ b/hw/xwayland/xwayland-window.c
@@ -1317,7 +1317,8 @@ xwl_create_root_surface(struct xwl_window *xwl_window)
}
wl_region_add(region, 0, 0,
- window->drawable.width, window->drawable.height);
+ xwl_scale_to(xwl_screen, window->drawable.width),
+ xwl_scale_to(xwl_screen, window->drawable.height));
wl_surface_set_opaque_region(xwl_window->surface, region);
wl_region_destroy(region);
@@ -1955,6 +1956,7 @@ xwl_window_attach_buffer(struct xwl_window *xwl_window)
}
wl_surface_attach(xwl_window->surface, buffer, 0, 0);
+ wl_surface_set_buffer_scale(xwl_window->surface, xwl_screen->global_surface_scale);
/* Arbitrary limit to try to avoid flooding the Wayland
* connection. If we flood it too much anyway, this could
diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c
index cbd2437d6..0d0587b74 100644
--- a/hw/xwayland/xwayland.c
+++ b/hw/xwayland/xwayland.c
@@ -333,6 +333,18 @@ xwl_log_handler(const char *format, va_list args)
#ifdef XWL_HAS_XWAYLAND_EXTENSION
#include <X11/extensions/xwaylandproto.h>
+// Custom extensions for xwl for setting scale
+#define X_XwlSetScale 1
+
+typedef struct {
+ CARD8 reqType; /* always XwaylandReqCode */
+ CARD8 xwaylandReqType; /* always X_XwaylandSetScale */
+ CARD16 length;
+ CARD16 screen;
+ CARD16 scale;
+} xXwaylandSetScaleReq;
+#define sz_xXwaylandSetScaleReq 8
+
Bool noXwaylandExtension = FALSE;
static int
@@ -386,6 +398,28 @@ SProcXwlQueryVersion(ClientPtr client)
return ProcXwlQueryVersion(client);
}
+static int
+ProcXwlSetScale(ClientPtr client)
+{
+ REQUEST(xXwaylandSetScaleReq);
+ REQUEST_SIZE_MATCH(xXwaylandSetScaleReq);
+
+ if (stuff->screen >= screenInfo.numScreens)
+ return BadValue;
+ ScreenPtr pScreen = screenInfo.screens[stuff->screen];
+
+ struct xwl_screen* xwl_screen = xwl_screen_get(pScreen);
+ if (xwl_screen == NULL)
+ return BadImplementation;
+
+ if (stuff->scale < 1)
+ return BadValue;
+
+ xwl_screen_set_global_scale(xwl_screen, stuff->scale);
+
+ return Success;
+}
+
static int
ProcXwaylandDispatch(ClientPtr client)
{
@@ -394,6 +428,8 @@ ProcXwaylandDispatch(ClientPtr client)
switch (stuff->data) {
case X_XwlQueryVersion:
return ProcXwlQueryVersion(client);
+ case X_XwlSetScale:
+ return ProcXwlSetScale(client);
}
return BadRequest;
}