Update scale after workspace output changes

a6b319677420c481832377dac58f9051688efe12
Alexis Sellier committed ago 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 },