Allow resizing maximized windows

3e943cc16d4fcc1ea8cc94a556fe6855966cfe54
Alexis Sellier committed ago 1 parent 707d9a3f
swm.c +22 -5
550 550
static void      listen_static(struct wl_signal *signal, wl_notify_func_t notify);
551 551
static void      listener_release(struct wl_listener *listener);
552 552
static void      map_notify(struct wl_listener *listener, void *data);
553 553
static void      maximize_notify(struct wl_listener *listener, void *data);
554 554
static void      max_stack(monitor_t *m);
555 +
static void      restore_max_stack(monitor_t *m);
555 556
static void      motion_absolute(struct wl_listener *listener, void *data);
556 557
static void      motion_notify(
557 558
    uint32_t                 time,
558 559
    struct wlr_input_device *device,
559 560
    double                   sx,
4419 4420
    wlr_pointer_gestures_v1_send_hold_end(
4420 4421
        pointer_gestures, seat, event->time_msec, event->cancelled
4421 4422
    );
4422 4423
}
4423 4424
4425 +
/* Restore the normal workspace layout before direct window manipulation. */
4426 +
static void restore_max_stack(monitor_t *m) {
4427 +
    workspace_t *ws;
4428 +
4429 +
    if (!m || !(ws = m->ws) || !ws->lt || ws->lt->arrange != max_stack)
4430 +
        return;
4431 +
4432 +
    ws->lt = ws->prevlt && ws->prevlt->arrange != max_stack ? ws->prevlt : &layouts[0];
4433 +
    arrange(m);
4434 +
    print_status();
4435 +
}
4436 +
4424 4437
/* Begin moving or resizing the window under the pointer. */
4425 4438
void move_resize(const arg_t *arg) {
4426 4439
    if (cursor_mode != CURSOR_NORMAL && cursor_mode != CURSOR_PRESSED)
4427 4440
        return;
4428 4441
    point_to_node(cursor->x, cursor->y, nullptr, &grabc, nullptr, nullptr, nullptr);
4431 4444
        return;
4432 4445
4433 4446
    if (grabc->is_fullscreen)
4434 4447
        set_fullscreen(grabc, 0);
4435 4448
4449 +
    restore_max_stack(grabc->mon);
4450 +
4436 4451
    /* Float the window and let pointer motion move or resize it. */
4437 4452
    grabc->persist_float = 1;
4438 4453
    set_floating(grabc, 1);
4439 4454
4440 4455
    switch (cursor_mode = arg->u) {
6041 6056
    client_t *sel = focus_top(selmon);
6042 6057
    /* Fullscreen windows cannot become floating. */
6043 6058
    if (!sel || sel->is_fullscreen)
6044 6059
        return;
6045 6060
6061 +
    restore_max_stack(sel->mon);
6046 6062
    if (sel->is_floating) {
6047 6063
        sel->persist_float = 0;
6048 6064
        set_floating(sel, 0);
6049 6065
        forget_client(sel);
6050 6066
    } else {
6077 6093
            break;
6078 6094
        }
6079 6095
    if (!max)
6080 6096
        return;
6081 6097
6082 -
    if (ws->lt == max)
6083 -
        ws->lt = ws->prevlt && ws->prevlt != max ? ws->prevlt : &layouts[0];
6084 -
    else {
6085 -
        ws->prevlt = ws->lt;
6086 -
        ws->lt     = max;
6098 +
    if (ws->lt == max) {
6099 +
        restore_max_stack(selmon);
6100 +
        return;
6087 6101
    }
6102 +
6103 +
    ws->prevlt = ws->lt;
6104 +
    ws->lt     = max;
6088 6105
    arrange(selmon);
6089 6106
    print_status();
6090 6107
}
6091 6108
6092 6109
/* Remove the active session lock after the locker authenticates the user. */
test/run.py +61 -4
345 345
        wait_title("two" if before == "one" else "one")
346 346
347 347
    test("window publication and focus", publication)
348 348
349 349
    def layouts() -> None:
350 +
        three = start_client("three-layout", "ffcc8855")
351 +
        names = ("one", "two", "three-layout")
352 +
        normal = {name: geometry(name)[:2] for name in names}
350 353
        virtual_keyboard(33)
351 -
        eventually("max-stack geometry", lambda: geometry("one")[:2] == geometry("two")[:2])
352 -
        virtual_keyboard(33)
354 +
        eventually(
355 +
            "max-stack geometry",
356 +
            lambda: len({tuple(geometry(name)[:2]) for name in names}) == 1,
357 +
        )
353 358
        focused = current_title()
359 +
        others = tuple(name for name in names if name != focused)
360 +
        maximized = geometry(focused)[:2]
361 +
        held_pointer_click("max-stack-resize", 100, "right")
362 +
        eventually(
363 +
            "normal layout restored",
364 +
            lambda: all(geometry(name)[:2] != maximized for name in others),
365 +
        )
366 +
        eventually(
367 +
            "max-stack resize persisted",
368 +
            lambda: geometry(focused)[:2] != normal[focused],
369 +
        )
370 +
        for _ in names:
371 +
            if current_title() == focused:
372 +
                break
373 +
            virtual_keyboard(36)
374 +
        wait_title(focused)
375 +
        virtual_keyboard(20)
376 +
        fullscreen_target = focused
354 377
        virtual_keyboard(33, 1)
355 -
        eventually("fullscreen enable", lambda: geometry(focused)[2] == 1)
378 +
        eventually("fullscreen enable", lambda: geometry(fullscreen_target)[2] == 1)
356 379
        virtual_keyboard(33, 1)
357 -
        eventually("fullscreen disable", lambda: geometry(focused)[2] == 0)
380 +
        eventually("fullscreen disable", lambda: geometry(fullscreen_target)[2] == 0)
381 +
        terminate(three)
382 +
        eventually("third layout window removed", lambda: current_title() != "three-layout")
358 383
359 384
    test("layouts and fullscreen", layouts)
360 385
361 386
    def workspaces() -> None:
362 387
        current = current_title()
481 506
        terminate(three)
482 507
        terminate(full)
483 508
484 509
    test("fullscreen isolation", isolation)
485 510
511 +
    def max_stack_floating() -> None:
512 +
        protocol("workspace", 3)
513 +
        wait_title("")
514 +
        first = start_client("max-float-one", "55aaffcc")
515 +
        second = start_client("max-float-two", "ffaa55cc")
516 +
        third = start_client("max-float-three", "aa55ffcc")
517 +
        names = ("max-float-one", "max-float-two", "max-float-three")
518 +
        virtual_keyboard(33)
519 +
        eventually(
520 +
            "max-stack geometry before floating toggle",
521 +
            lambda: len({tuple(geometry(name)[:2]) for name in names}) == 1,
522 +
        )
523 +
        virtual_keyboard(20)
524 +
        eventually(
525 +
            "normal layout restored by floating toggle",
526 +
            lambda: len({tuple(geometry(name)[:2]) for name in names}) > 1,
527 +
        )
528 +
        protocol("workspace", 1)
529 +
        eventually("workspace left after floating toggle", lambda: current_title() in {"one", "two"})
530 +
        protocol("workspace", 3)
531 +
        eventually("workspace returned after floating toggle", lambda: current_title() in names)
532 +
        time.sleep(0.1)
533 +
        if current_title() not in names:
534 +
            raise Failure("workspace did not remain selected after floating toggle")
535 +
        terminate(first)
536 +
        terminate(second)
537 +
        terminate(third)
538 +
        protocol("workspace", 1)
539 +
        eventually("workspace restored after floating toggle", lambda: current_title() in {"one", "two"})
540 +
541 +
    test("max-stack floating transition", max_stack_floating)
542 +
486 543
    def lifecycle() -> None:
487 544
        terminate(one)
488 545
        terminate(two)
489 546
        protocol("xdg-lifecycle", 2)
490 547
        protocol("transient", 2)