Fix floating window screenshot selection

1fdf63d77e00705f25cc50e7cc2a211cf8a74197
Alexis Sellier committed ago 1 parent 1d08f0a2
swm.c +15 -7
4622 4622
}
4623 4623
4624 4624
/* Publish visible window rectangles in slurp's predefined-region format. */
4625 4625
void publish_windows(const char *runtime) {
4626 4626
    client_t *c;
4627 +
    bool      floating;
4627 4628
    FILE     *file;
4628 4629
    char      path[MAX_STATE_PATH], tmppath[MAX_STATE_PATH], title[MAX_WINDOW_STATE_FIELD];
4629 4630
4630 4631
    if (!runtime || snprintf(path, sizeof(path), "%s/swm-windows", runtime) >= (int)sizeof(path) ||
4631 4632
        !(file = file_replace_begin(path, tmppath, sizeof(tmppath))))
4632 4633
        return;
4633 4634
4634 -
    wl_list_for_each(c, &clients, link) {
4635 -
        if (!c->mon || !client_surface(c)->mapped || !c->scene->node.enabled)
4636 -
            continue;
4637 -
        status_field(title, sizeof(title), client_get_title(c));
4638 -
        fprintf(
4639 -
            file, "%d,%d %dx%d %s\n", c->geom.x, c->geom.y, c->geom.width, c->geom.height, title
4640 -
        );
4635 +
    /* slurp resolves equal overlapping regions in input order. Publish the
4636 +
     * floating layer last so its windows remain selectable above tiled windows. */
4637 +
    for (floating = false;; floating = true) {
4638 +
        wl_list_for_each(c, &clients, link) {
4639 +
            if (c->is_floating != floating || !c->mon || !client_surface(c)->mapped ||
4640 +
                !c->scene->node.enabled)
4641 +
                continue;
4642 +
            status_field(title, sizeof(title), client_get_title(c));
4643 +
            fprintf(
4644 +
                file, "%d,%d %dx%d %s\n", c->geom.x, c->geom.y, c->geom.width, c->geom.height, title
4645 +
            );
4646 +
        }
4647 +
        if (floating)
4648 +
            break;
4641 4649
    }
4642 4650
    file_replace_commit(file, tmppath, path);
4643 4651
}
4644 4652
4645 4653
/* Publish the status once the current batch of changes has settled. */
test/run.py +10 -1
338 338
339 339
    one = start_client("one", "ff5588dd")
340 340
    two = start_client("two", "ff55aa88")
341 341
342 342
    def publication() -> None:
343 -
        windows = (Path(os.environ["XDG_RUNTIME_DIR"]) / "swm-windows").read_text()
343 +
        windows_path = Path(os.environ["XDG_RUNTIME_DIR"]) / "swm-windows"
344 +
        windows = windows_path.read_text()
344 345
        if not re.search(r"^\d+,\d+ \d+x\d+ one$", windows, re.MULTILINE):
345 346
            raise Failure("missing published rectangle for one")
346 347
        if not re.search(r"^\d+,\d+ \d+x\d+ two$", windows, re.MULTILINE):
347 348
            raise Failure("missing published rectangle for two")
349 +
        virtual_keyboard(36)
350 +
        wait_title("one")
351 +
        virtual_keyboard(20)
352 +
        eventually(
353 +
            "floating window publication order",
354 +
            lambda: windows_path.read_text().index("two") < windows_path.read_text().index("one"),
355 +
        )
356 +
        virtual_keyboard(20)
348 357
        before = current_title()
349 358
        virtual_keyboard(36)
350 359
        wait_title("two" if before == "one" else "one")
351 360
352 361
    test("window publication and focus", publication)