Update scale after workspace output changes
a6b319677420c481832377dac58f9051688efe12
1 parent
9dcf7d3a
Makefile
+3 -1
| 187 | 187 | ||
| 188 | 188 | $(TEST_BIN)/unit: test/unit.c $(TEST_COMMON) | $(TEST_BIN) |
|
| 189 | 189 | @echo "cc test/unit.c => $@" |
|
| 190 | 190 | @$(CC) $(TEST_CPPFLAGS) $(TEST_CFLAGS) test/unit.c util.c \ |
|
| 191 | 191 | ext-workspace-v1-protocol.c swm-toplevel-v1-protocol.c \ |
|
| 192 | - | swm-workspace-v1-protocol.c $(LDLIBS) -o $@ |
|
| 192 | + | swm-workspace-v1-protocol.c \ |
|
| 193 | + | -Wl,--wrap=wlr_fractional_scale_v1_notify_scale \ |
|
| 194 | + | -Wl,--wrap=wlr_surface_set_preferred_buffer_scale $(LDLIBS) -o $@ |
|
| 193 | 195 | ||
| 194 | 196 | $(TEST_BIN)/ctl-unit: test/ctl_unit.c swmctl.c \ |
|
| 195 | 197 | ext-foreign-toplevel-list-v1-client-protocol.h \ |
|
| 196 | 198 | swm-toplevel-v1-client-protocol.h swm-workspace-v1-client-protocol.h \ |
|
| 197 | 199 | ext-foreign-toplevel-list-v1-protocol.c swm-toplevel-v1-protocol.c \ |
swm.c
+12 -7
| 1164 | 1164 | static inline void client_set_scale(struct wlr_surface *s, float scale) { |
|
| 1165 | 1165 | wlr_fractional_scale_v1_notify_scale(s, scale); |
|
| 1166 | 1166 | wlr_surface_set_preferred_buffer_scale(s, (int32_t)ceilf(scale)); |
|
| 1167 | 1167 | } |
|
| 1168 | 1168 | ||
| 1169 | + | /* Change a client's output and immediately publish that output's scale. */ |
|
| 1170 | + | static inline void client_assign_monitor(client_t *c, monitor_t *m) { |
|
| 1171 | + | c->mon = m; |
|
| 1172 | + | ||
| 1173 | + | if (m) |
|
| 1174 | + | client_set_scale(client_surface(c), m->wlr_output->scale); |
|
| 1175 | + | } |
|
| 1176 | + | ||
| 1169 | 1177 | /* Compare Wayland serials while preserving their wraparound ordering. */ |
|
| 1170 | 1178 | static inline bool serial_at_least(uint32_t serial, uint32_t target) { |
|
| 1171 | 1179 | return (int32_t)(serial - target) >= 0; |
|
| 1172 | 1180 | } |
|
| 1173 | 1181 |
| 2189 | 2197 | ||
| 2190 | 2198 | if (c->is_floating && selmon) { |
|
| 2191 | 2199 | geom.x = selmon->m.x + c->geom.x - m->m.x; |
|
| 2192 | 2200 | geom.y = selmon->m.y + c->geom.y - m->m.y; |
|
| 2193 | 2201 | } |
|
| 2194 | - | c->mon = selmon; |
|
| 2202 | + | client_assign_monitor(c, selmon); |
|
| 2195 | 2203 | ||
| 2196 | 2204 | if (selmon) |
|
| 2197 | 2205 | resize(c, c->is_fullscreen ? selmon->m : geom, 0); |
|
| 2198 | 2206 | } |
|
| 2199 | 2207 | if (c->ftl_monitor == m) { |
| 5238 | 5246 | if (oldmon == m) { |
|
| 5239 | 5247 | if (m) |
|
| 5240 | 5248 | arrange(m); |
|
| 5241 | 5249 | return; |
|
| 5242 | 5250 | } |
|
| 5243 | - | c->mon = m; |
|
| 5244 | - | ||
| 5245 | - | if (m) |
|
| 5246 | - | client_set_scale(client_surface(c), m->wlr_output->scale); |
|
| 5251 | + | client_assign_monitor(c, m); |
|
| 5247 | 5252 | ||
| 5248 | 5253 | if (!c->is_fullscreen) |
|
| 5249 | 5254 | c->prev = c->geom; |
|
| 5250 | 5255 | ||
| 5251 | 5256 | /* Moving this node tells applications which displays they overlap. */ |
| 5269 | 5274 | if (!clients_related(w, main)) |
|
| 5270 | 5275 | continue; |
|
| 5271 | 5276 | w->ws = ws; |
|
| 5272 | 5277 | ||
| 5273 | 5278 | if (ws->mon && ws->mon != w->mon) { |
|
| 5274 | - | w->mon = ws->mon; |
|
| 5279 | + | client_assign_monitor(w, ws->mon); |
|
| 5275 | 5280 | ||
| 5276 | 5281 | if (!w->is_fullscreen) |
|
| 5277 | 5282 | w->prev = w->geom; |
|
| 5278 | 5283 | client_place(w); |
|
| 5279 | 5284 | } |
| 5302 | 5307 | wl_list_for_each(c, &clients, link) { |
|
| 5303 | 5308 | if (c->ws != ws) |
|
| 5304 | 5309 | continue; |
|
| 5305 | 5310 | ||
| 5306 | 5311 | if (c->mon != m) { |
|
| 5307 | - | c->mon = m; |
|
| 5312 | + | client_assign_monitor(c, m); |
|
| 5308 | 5313 | ||
| 5309 | 5314 | if (!c->is_fullscreen) |
|
| 5310 | 5315 | c->prev = c->geom; |
|
| 5311 | 5316 | resize(c, c->geom, 0); |
|
| 5312 | 5317 | } |
test/unit.c
+41 -0
| 7 | 7 | ||
| 8 | 8 | #define main swm_program_main |
|
| 9 | 9 | #include "swm.c" |
|
| 10 | 10 | #undef main |
|
| 11 | 11 | ||
| 12 | + | static struct wlr_surface *scaled_surface; |
|
| 13 | + | static float fractional_scale; |
|
| 14 | + | static int32_t buffer_scale; |
|
| 15 | + | ||
| 16 | + | void __wrap_wlr_fractional_scale_v1_notify_scale(struct wlr_surface *surface, double scale) { |
|
| 17 | + | scaled_surface = surface; |
|
| 18 | + | fractional_scale = (float)scale; |
|
| 19 | + | } |
|
| 20 | + | ||
| 21 | + | void __wrap_wlr_surface_set_preferred_buffer_scale(struct wlr_surface *surface, int32_t scale) { |
|
| 22 | + | scaled_surface = surface; |
|
| 23 | + | buffer_scale = scale; |
|
| 24 | + | } |
|
| 25 | + | ||
| 12 | 26 | /* Verify that releasing a pool item clears its storage. */ |
|
| 13 | 27 | static void test_pool(pool_t *pool) { |
|
| 14 | 28 | unsigned char *item = pool_take(pool); |
|
| 15 | 29 | size_t i; |
|
| 16 | 30 |
| 265 | 279 | toplevel->base = surface; |
|
| 266 | 280 | toplevel->app_id = (char *)appid; |
|
| 267 | 281 | toplevel->title = (char *)title; |
|
| 268 | 282 | } |
|
| 269 | 283 | ||
| 284 | + | /* Verify workspace swaps update clients for the destination output scale. */ |
|
| 285 | + | static void test_workspace_scale(void) { |
|
| 286 | + | client_t client; |
|
| 287 | + | struct wlr_surface surface = {}; |
|
| 288 | + | struct wlr_xdg_surface xdg; |
|
| 289 | + | struct wlr_xdg_toplevel toplevel; |
|
| 290 | + | struct wlr_output output = { .scale = 2.0f }; |
|
| 291 | + | monitor_t monitor = { .wlr_output = &output }; |
|
| 292 | + | workspace_t workspace = {}; |
|
| 293 | + | ||
| 294 | + | init_xdg_client(&client, &xdg, &toplevel, "app", "Window"); |
|
| 295 | + | scaled_surface = nullptr; |
|
| 296 | + | fractional_scale = 0; |
|
| 297 | + | buffer_scale = 0; |
|
| 298 | + | xdg.surface = &surface; |
|
| 299 | + | client.ws = &workspace; |
|
| 300 | + | wl_list_init(&clients); |
|
| 301 | + | wl_list_insert(&clients, &client.link); |
|
| 302 | + | assign_workspace(&workspace, &monitor); |
|
| 303 | + | assert(client.mon == &monitor); |
|
| 304 | + | assert(scaled_surface == &surface); |
|
| 305 | + | assert(fractional_scale == 2.0f); |
|
| 306 | + | assert(buffer_scale == 2); |
|
| 307 | + | wl_list_remove(&client.link); |
|
| 308 | + | } |
|
| 309 | + | ||
| 270 | 310 | /* Verify matching rules update client state and workspace assignment. */ |
|
| 271 | 311 | static void test_rule_application(void) { |
|
| 272 | 312 | client_t client; |
|
| 273 | 313 | struct wlr_xdg_surface surface; |
|
| 274 | 314 | struct wlr_xdg_toplevel toplevel; |
| 923 | 963 | { "pools", test_pools }, |
|
| 924 | 964 | { "workspaces", test_workspace_queries }, |
|
| 925 | 965 | { "paths-and-borders", test_paths_and_border_policy }, |
|
| 926 | 966 | { "rules", test_rule_application }, |
|
| 927 | 967 | { "focus", test_focus_queries }, |
|
| 968 | + | { "workspace-scale", test_workspace_scale }, |
|
| 928 | 969 | { "window-state", test_window_state_storage }, |
|
| 929 | 970 | { "child-reaping", test_child_reaping }, |
|
| 930 | 971 | { "spawn-tracking", test_spawn_tracking }, |
|
| 931 | 972 | { "command-failure-notification", test_command_failure_notification }, |
|
| 932 | 973 | { "commands-without-clients", test_commands_without_clients }, |