Preserve proportional window centers between monitors
348a25f752e3219db00ffc4bd5f8a3f84b9c5149
1 parent
78eecfbb
swm.c
+27 -3
| 5515 | 5515 | c->maxstack_prev.x += dx; |
|
| 5516 | 5516 | c->maxstack_prev.y += dy; |
|
| 5517 | 5517 | } |
|
| 5518 | 5518 | } |
|
| 5519 | 5519 | ||
| 5520 | - | /* Preserve a window's position relative to its display during directed moves. */ |
|
| 5520 | + | /* Map a window's center between display work areas without changing its size. */ |
|
| 5521 | + | static void box_map_center( |
|
| 5522 | + | struct wlr_box *box, const struct wlr_box *old, const struct wlr_box *new |
|
| 5523 | + | ) { |
|
| 5524 | + | if (old->width <= 0 || old->height <= 0) { |
|
| 5525 | + | box->x = new->x + (new->width - box->width) / 2; |
|
| 5526 | + | box->y = new->y + (new->height - box->height) / 2; |
|
| 5527 | + | return; |
|
| 5528 | + | } |
|
| 5529 | + | ||
| 5530 | + | box->x = (int)lround( |
|
| 5531 | + | new->x + ((double)box->x - old->x + box->width / 2.0) * new->width / old->width - |
|
| 5532 | + | box->width / 2.0 |
|
| 5533 | + | ); |
|
| 5534 | + | box->y = (int)lround( |
|
| 5535 | + | new->y + ((double)box->y - old->y + box->height / 2.0) * new->height / old->height - |
|
| 5536 | + | box->height / 2.0 |
|
| 5537 | + | ); |
|
| 5538 | + | } |
|
| 5539 | + | ||
| 5540 | + | /* Preserve the proportional center of current and saved geometry during directed moves. */ |
|
| 5521 | 5541 | static void client_translate_monitor(client_t *c, monitor_t *oldmon, monitor_t *newmon) { |
|
| 5522 | - | if (c && oldmon && newmon && oldmon != newmon) |
|
| 5523 | - | client_translate_geometry(c, newmon->m.x - oldmon->m.x, newmon->m.y - oldmon->m.y); |
|
| 5542 | + | if (!c || !oldmon || !newmon || oldmon == newmon) |
|
| 5543 | + | return; |
|
| 5544 | + | ||
| 5545 | + | box_map_center(c->is_fullscreen ? &c->prev : &c->geom, &oldmon->w, &newmon->w); |
|
| 5546 | + | if (c->is_max_stacked) |
|
| 5547 | + | box_map_center(&c->maxstack_prev, &oldmon->w, &newmon->w); |
|
| 5524 | 5548 | } |
|
| 5525 | 5549 | ||
| 5526 | 5550 | /* Fit a window to the display it was just moved to. */ |
|
| 5527 | 5551 | void client_place(client_t *c) { |
|
| 5528 | 5552 | /* An initial commit may assign a monitor before map_notify() creates the |
test/unit.c
+39 -17
| 401 | 401 | wl_list_insert(lock.surfaces.prev, &removed.link); |
|
| 402 | 402 | wl_list_insert(lock.surfaces.prev, &remaining.link); |
|
| 403 | 403 | assert(lock_surface_next(&lock, &removed) == &remaining); |
|
| 404 | 404 | } |
|
| 405 | 405 | ||
| 406 | - | /* Verify directed output moves preserve a window's display-relative position. */ |
|
| 406 | + | /* Verify directed moves preserve proportional centers and window sizes. */ |
|
| 407 | 407 | static void test_monitor_translation(void) { |
|
| 408 | - | monitor_t oldmon = { .m = { 0, 0, 1920, 1080 } }; |
|
| 409 | - | monitor_t newmon = { .m = { 1920, 100, 2560, 1440 } }; |
|
| 410 | - | client_t client = { .geom = { 100, 50, 640, 480 }, .prev = { 200, 75, 800, 600 } }; |
|
| 408 | + | monitor_t oldmon = { .w = { 0, 30, 2000, 1200 } }; |
|
| 409 | + | monitor_t newmon = { .w = { -1000, 60, 1000, 600 } }; |
|
| 410 | + | client_t client = { .geom = { 1200, 730, 400, 200 } }; |
|
| 411 | 411 | ||
| 412 | 412 | client_translate_monitor(&client, &oldmon, &newmon); |
|
| 413 | - | assert(client.geom.x == 2020 && client.geom.y == 150); |
|
| 414 | - | ||
| 415 | - | client.is_fullscreen = true; |
|
| 413 | + | assert_box(*(struct swm_box *)&client.geom, -500, 360, 400, 200); |
|
| 416 | 414 | client_translate_monitor(&client, &newmon, &oldmon); |
|
| 417 | - | assert(client.prev.x == -1720 && client.prev.y == -25); |
|
| 415 | + | assert_box(*(struct swm_box *)&client.geom, 1200, 730, 400, 200); |
|
| 418 | 416 | ||
| 419 | - | client.is_fullscreen = false; |
|
| 420 | - | client.is_max_stacked = true; |
|
| 421 | - | client.geom = oldmon.m; |
|
| 422 | - | client.maxstack_prev = (struct wlr_box){ 100, 50, 640, 480 }; |
|
| 417 | + | client.geom = (struct wlr_box){ 800, 530, 400, 200 }; |
|
| 423 | 418 | client_translate_monitor(&client, &oldmon, &newmon); |
|
| 424 | - | assert(client.geom.x == 1920 && client.geom.y == 100); |
|
| 425 | - | assert_box(*(struct swm_box *)&client.maxstack_prev, 2020, 150, 640, 480); |
|
| 419 | + | assert_box(*(struct swm_box *)&client.geom, -700, 260, 400, 200); |
|
| 426 | 420 | ||
| 427 | 421 | client.is_fullscreen = true; |
|
| 428 | - | client.prev = client.geom; |
|
| 422 | + | client.prev = (struct wlr_box){ 1200, 730, 400, 200 }; |
|
| 423 | + | client_translate_monitor(&client, &oldmon, &newmon); |
|
| 424 | + | assert_box(*(struct swm_box *)&client.prev, -500, 360, 400, 200); |
|
| 425 | + | assert_box(*(struct swm_box *)&client.geom, -700, 260, 400, 200); |
|
| 426 | + | ||
| 427 | + | client.is_max_stacked = true; |
|
| 428 | + | client.maxstack_prev = (struct wlr_box){ -500, 360, 400, 200 }; |
|
| 429 | 429 | client_translate_monitor(&client, &newmon, &oldmon); |
|
| 430 | - | assert(client.prev.x == 0 && client.prev.y == 0); |
|
| 431 | - | assert_box(*(struct swm_box *)&client.maxstack_prev, 100, 50, 640, 480); |
|
| 430 | + | assert_box(*(struct swm_box *)&client.prev, 1200, 730, 400, 200); |
|
| 431 | + | assert_box(*(struct swm_box *)&client.maxstack_prev, 1200, 730, 400, 200); |
|
| 432 | + | ||
| 433 | + | client.is_fullscreen = false; |
|
| 434 | + | client.geom = oldmon.w; |
|
| 435 | + | client_translate_monitor(&client, &oldmon, &newmon); |
|
| 436 | + | assert_box(*(struct swm_box *)&client.geom, -1500, -240, 2000, 1200); |
|
| 437 | + | assert_box(*(struct swm_box *)&client.maxstack_prev, -500, 360, 400, 200); |
|
| 438 | + | ||
| 439 | + | client_translate_monitor(&client, &newmon, &newmon); |
|
| 440 | + | client_translate_monitor(&client, nullptr, &newmon); |
|
| 441 | + | client_translate_monitor(&client, &newmon, nullptr); |
|
| 442 | + | client_translate_monitor(nullptr, &oldmon, &newmon); |
|
| 443 | + | assert_box(*(struct swm_box *)&client.geom, -1500, -240, 2000, 1200); |
|
| 444 | + | ||
| 445 | + | oldmon.w = (struct wlr_box){ 0 }; |
|
| 446 | + | client.geom = (struct wlr_box){ 100, 100, 400, 200 }; |
|
| 447 | + | client_translate_monitor(&client, &oldmon, &newmon); |
|
| 448 | + | assert_box(*(struct swm_box *)&client.geom, -700, 260, 400, 200); |
|
| 449 | + | ||
| 450 | + | oldmon.w = (struct wlr_box){ 0, 30, 1000, 600 }; |
|
| 451 | + | client.geom = (struct wlr_box){ 100, 130, 400, 200 }; |
|
| 452 | + | client_translate_monitor(&client, &oldmon, &newmon); |
|
| 453 | + | assert_box(*(struct swm_box *)&client.geom, -900, 160, 400, 200); |
|
| 432 | 454 | } |
|
| 433 | 455 | ||
| 434 | 456 | /* Verify focus queries across mapped, hidden, and unmanaged clients. */ |
|
| 435 | 457 | static void test_focus_queries(void) { |
|
| 436 | 458 | client_t first, second, hidden; |