Preserve proportional window centers between monitors

348a25f752e3219db00ffc4bd5f8a3f84b9c5149
Alexis Sellier committed ago 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;