Allow resizing maximized windows
3e943cc16d4fcc1ea8cc94a556fe6855966cfe54
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) |