Release focus when panels drop exclusivity

b6e528e08c94a67eaa54700cd174f6fc55b91084
Alexis Sellier committed ago 1 parent 1e7a40ee
swm.c +25 -1
1868 1868
            wlr_scene_rect_set_size(l->dim, full_area.width, full_area.height);
1869 1869
        }
1870 1870
    }
1871 1871
}
1872 1872
1873 +
/* Track the layer surface with exclusive keyboard focus. */
1874 +
static bool layer_focus_update(monitor_t *m, layer_surface_t *target) {
1875 +
    layer_surface_t *l;
1876 +
    size_t           i;
1877 +
1878 +
    if (target) {
1879 +
        exclusive_focus = target;
1880 +
        return false;
1881 +
    }
1882 +
    if (!exclusive_focus)
1883 +
        return false;
1884 +
1885 +
    for (i = 0; i < LENGTH(m->layers); i++)
1886 +
        wl_list_for_each(l, &m->layers[i], link) {
1887 +
            if (l == exclusive_focus) {
1888 +
                exclusive_focus = nullptr;
1889 +
                return true;
1890 +
            }
1891 +
        }
1892 +
    return false;
1893 +
}
1894 +
1873 1895
/* Arrange desktop layers and give keyboard focus to the highest eligible surface. */
1874 1896
void arrange_layers(monitor_t *m) {
1875 1897
    int              i;
1876 1898
    struct wlr_box   usable_area = m->m;
1877 1899
    layer_surface_t *l;
1903 1925
                    ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE ||
1904 1926
                !l->mapped)
1905 1927
                continue;
1906 1928
            /* Deactivate the focused client. */
1907 1929
            focus_client(nullptr, 0);
1908 -
            exclusive_focus = l;
1930 +
            layer_focus_update(m, l);
1909 1931
            client_notify_enter(l->layer_surface->surface, wlr_seat_get_keyboard(seat));
1910 1932
            return;
1911 1933
        }
1912 1934
    }
1935 +
    if (layer_focus_update(m, nullptr))
1936 +
        focus_client(focus_top(selmon), 1);
1913 1937
}
1914 1938
1915 1939
/* Expand $NAME variables into caller-owned stack storage. */
1916 1940
void expand_argv(const char *const *argv, char **expanded, char *storage) {
1917 1941
    size_t i, remaining = MAX_COMMAND_SIZE, size;
test/unit.c +16 -0
872 872
    };
873 873
874 874
    assert(layer_surface_output_monitor(&wrapper) == &monitor);
875 875
}
876 876
877 +
/* Verify a layer relinquishing exclusivity releases keyboard focus. */
878 +
static void test_layer_focus_release(void) {
879 +
    monitor_t       monitor = {};
880 +
    layer_surface_t layer   = { .mon = &monitor };
881 +
    size_t          i;
882 +
883 +
    for (i = 0; i < LENGTH(monitor.layers); i++)
884 +
        wl_list_init(&monitor.layers[i]);
885 +
    wl_list_insert(&monitor.layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &layer.link);
886 +
887 +
    exclusive_focus = &layer;
888 +
    assert(layer_focus_update(&monitor, nullptr));
889 +
    assert(exclusive_focus == nullptr);
890 +
}
891 +
877 892
/* Verify deleting X11 WM_HINTS clears a previously urgent window. */
878 893
static void test_x11_urgency(void) {
879 894
    struct wlr_xwayland_surface xsurface = {};
880 895
    client_t                    client   = { .type = X11, .is_urgent = true };
881 896
1108 1123
        { "window-state", test_window_state_storage },
1109 1124
        { "child-reaping", test_child_reaping },
1110 1125
        { "spawn-tracking", test_spawn_tracking },
1111 1126
        { "layer-unmap-monitor", test_layer_unmap_monitor },
1112 1127
        { "command-failure-notification", test_command_failure_notification },
1128 +
        { "layer-focus-release", test_layer_focus_release },
1113 1129
        { "commands-without-clients", test_commands_without_clients },
1114 1130
        { "small-helpers", test_small_helpers },
1115 1131
        { "pointer-grab-button", test_pointer_grab_button },
1116 1132
        { "client-accessors", test_client_accessors },
1117 1133
        { "autostart", test_autostart_execution },