Fix focus preservation after workspace switch

9f249ed5e7cc76f1b7f4b107f65b5828ee4c8eca
Alexis Sellier committed ago 1 parent 4ce74dba
swm.c +5 -3
5226 5226
void view_workspace(workspace_t *ws, monitor_t *m) {
5227 5227
    /* show workspace ws on output m; if ws is visible on another output,
5228 5228
     * the two displays exchange workspaces. */
5229 5229
    monitor_t   *other;
5230 5230
    workspace_t *old;
5231 +
    client_t    *focus;
5231 5232
5232 5233
    if (!m || !ws || ws == m->ws)
5233 5234
        return;
5234 5235
    old = m->ws;
5235 5236
5243 5244
        assign_workspace(old, nullptr);
5244 5245
    }
5245 5246
    m->previous_workspace = old;
5246 5247
    m->ws                 = ws;
5247 5248
    assign_workspace(ws, m);
5249 +
    focus = focus_top(m);
5248 5250
    arrange(m);
5249 5251
5250 5252
    if (other)
5251 5253
        arrange(other);
5252 -
    /* Arrange first, then transfer keyboard focus to the workspace's most
5253 -
     * recently focused client. */
5254 -
    focus_client(focus_top(m), 1);
5254 +
    /* Pointer focus can change during arrangement. Restore the workspace's
5255 +
     * most recently focused client after its windows move. */
5256 +
    focus_client(focus, 1);
5255 5257
    print_status();
5256 5258
}
5257 5259
5258 5260
/* Send one workspace's ephemeral metadata to a control client. */
5259 5261
static void workspace_metadata_send(struct wl_resource *resource, workspace_t *ws) {
test/run.py +20 -0
407 407
        eventually("third layout window removed", lambda: current_title() != "three-layout")
408 408
409 409
    test("layouts and fullscreen", layouts)
410 410
411 411
    def workspaces() -> None:
412 +
        switcher = start_client("workspace-switcher", "8855ffdd")
413 +
        virtual_keyboard(3, 1)
414 +
        protocol("pointer", 100)
415 +
        pointer_target = current_title()
416 +
        virtual_keyboard(36)
417 +
        active_target = current_title()
418 +
        if active_target == pointer_target:
419 +
            raise Failure("could not select the second workspace tile")
420 +
        virtual_keyboard(3)
421 +
        wait_title("workspace-switcher")
422 +
        for _ in range(2):
423 +
            virtual_keyboard(15)
424 +
            wait_title(active_target)
425 +
            virtual_keyboard(15)
426 +
            wait_title("workspace-switcher")
427 +
        virtual_keyboard(15)
428 +
        wait_title(active_target)
429 +
        terminate(switcher)
430 +
        protocol("pointer", 100)
431 +
412 432
        current = current_title()
413 433
        virtual_keyboard(20)
414 434
        virtual_keyboard(20)
415 435
        virtual_keyboard(3, 1)
416 436
        eventually("focus after moving client", lambda: current_title() not in {"", current})