desktop-shell: Properly handle seat hotplugging
Previously, desktop-shell would only create its internal shell_seat object for each seat available when the desktop-shell module is loaded. This is a problem any time seats are created dynamically. In particular, the Wayland and RDP backends create seats on an as-needed basis and they weren't getting picked up proprely by desktop-shell. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=77649
This commit is contained in:
committed by
Kristian Høgsberg
parent
3434b33b19
commit
024177cecb
+52
-32
@@ -217,6 +217,10 @@ struct shell_seat {
|
|||||||
struct wl_listener seat_destroy_listener;
|
struct wl_listener seat_destroy_listener;
|
||||||
struct weston_surface *focused_surface;
|
struct weston_surface *focused_surface;
|
||||||
|
|
||||||
|
struct wl_listener caps_changed_listener;
|
||||||
|
struct wl_listener pointer_focus_listener;
|
||||||
|
struct wl_listener keyboard_focus_listener;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct weston_pointer_grab grab;
|
struct weston_pointer_grab grab;
|
||||||
struct wl_list surfaces_list;
|
struct wl_list surfaces_list;
|
||||||
@@ -1984,19 +1988,6 @@ handle_pointer_focus(struct wl_listener *listener, void *data)
|
|||||||
ping_handler(view->surface, serial);
|
ping_handler(view->surface, serial);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
create_pointer_focus_listener(struct weston_seat *seat)
|
|
||||||
{
|
|
||||||
struct wl_listener *listener;
|
|
||||||
|
|
||||||
if (!seat->pointer)
|
|
||||||
return;
|
|
||||||
|
|
||||||
listener = malloc(sizeof *listener);
|
|
||||||
listener->notify = handle_pointer_focus;
|
|
||||||
wl_signal_add(&seat->pointer->focus_signal, listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
shell_surface_lose_keyboard_focus(struct shell_surface *shsurf)
|
shell_surface_lose_keyboard_focus(struct shell_surface *shsurf)
|
||||||
{
|
{
|
||||||
@@ -2034,19 +2025,6 @@ handle_keyboard_focus(struct wl_listener *listener, void *data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
create_keyboard_focus_listener(struct weston_seat *seat)
|
|
||||||
{
|
|
||||||
struct wl_listener *listener;
|
|
||||||
|
|
||||||
if (!seat->keyboard)
|
|
||||||
return;
|
|
||||||
|
|
||||||
listener = malloc(sizeof *listener);
|
|
||||||
listener->notify = handle_keyboard_focus;
|
|
||||||
wl_signal_add(&seat->keyboard->focus_signal, listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
shell_client_pong(struct shell_client *sc, uint32_t serial)
|
shell_client_pong(struct shell_client *sc, uint32_t serial)
|
||||||
{
|
{
|
||||||
@@ -2850,6 +2828,30 @@ destroy_shell_seat(struct wl_listener *listener, void *data)
|
|||||||
free(shseat);
|
free(shseat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shell_seat_caps_changed(struct wl_listener *listener, void *data)
|
||||||
|
{
|
||||||
|
struct shell_seat *seat;
|
||||||
|
|
||||||
|
seat = container_of(listener, struct shell_seat, caps_changed_listener);
|
||||||
|
|
||||||
|
if (seat->seat->keyboard &&
|
||||||
|
wl_list_empty(&seat->keyboard_focus_listener.link)) {
|
||||||
|
wl_signal_add(&seat->seat->keyboard->focus_signal,
|
||||||
|
&seat->keyboard_focus_listener);
|
||||||
|
} else if (!seat->seat->keyboard) {
|
||||||
|
wl_list_init(&seat->keyboard_focus_listener.link);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (seat->seat->pointer &&
|
||||||
|
wl_list_empty(&seat->pointer_focus_listener.link)) {
|
||||||
|
wl_signal_add(&seat->seat->pointer->focus_signal,
|
||||||
|
&seat->pointer_focus_listener);
|
||||||
|
} else if (!seat->seat->pointer) {
|
||||||
|
wl_list_init(&seat->pointer_focus_listener.link);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static struct shell_seat *
|
static struct shell_seat *
|
||||||
create_shell_seat(struct weston_seat *seat)
|
create_shell_seat(struct weston_seat *seat)
|
||||||
{
|
{
|
||||||
@@ -2868,6 +2870,17 @@ create_shell_seat(struct weston_seat *seat)
|
|||||||
wl_signal_add(&seat->destroy_signal,
|
wl_signal_add(&seat->destroy_signal,
|
||||||
&shseat->seat_destroy_listener);
|
&shseat->seat_destroy_listener);
|
||||||
|
|
||||||
|
shseat->keyboard_focus_listener.notify = handle_keyboard_focus;
|
||||||
|
wl_list_init(&shseat->keyboard_focus_listener.link);
|
||||||
|
|
||||||
|
shseat->pointer_focus_listener.notify = handle_pointer_focus;
|
||||||
|
wl_list_init(&shseat->pointer_focus_listener.link);
|
||||||
|
|
||||||
|
shseat->caps_changed_listener.notify = shell_seat_caps_changed;
|
||||||
|
wl_signal_add(&seat->updated_caps_signal,
|
||||||
|
&shseat->caps_changed_listener);
|
||||||
|
shell_seat_caps_changed(&shseat->caps_changed_listener, NULL);
|
||||||
|
|
||||||
return shseat;
|
return shseat;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2877,8 +2890,7 @@ get_shell_seat(struct weston_seat *seat)
|
|||||||
struct wl_listener *listener;
|
struct wl_listener *listener;
|
||||||
|
|
||||||
listener = wl_signal_get(&seat->destroy_signal, destroy_shell_seat);
|
listener = wl_signal_get(&seat->destroy_signal, destroy_shell_seat);
|
||||||
if (listener == NULL)
|
assert(listener != NULL);
|
||||||
return create_shell_seat(seat);
|
|
||||||
|
|
||||||
return container_of(listener,
|
return container_of(listener,
|
||||||
struct shell_seat, seat_destroy_listener);
|
struct shell_seat, seat_destroy_listener);
|
||||||
@@ -6060,6 +6072,14 @@ shell_add_bindings(struct weston_compositor *ec, struct desktop_shell *shell)
|
|||||||
debug_binding, shell);
|
debug_binding, shell);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_seat_created(struct wl_listener *listener, void *data)
|
||||||
|
{
|
||||||
|
struct weston_seat *seat = data;
|
||||||
|
|
||||||
|
create_shell_seat(seat);
|
||||||
|
}
|
||||||
|
|
||||||
WL_EXPORT int
|
WL_EXPORT int
|
||||||
module_init(struct weston_compositor *ec,
|
module_init(struct weston_compositor *ec,
|
||||||
int *argc, char *argv[])
|
int *argc, char *argv[])
|
||||||
@@ -6159,10 +6179,10 @@ module_init(struct weston_compositor *ec,
|
|||||||
shell->screensaver.timer =
|
shell->screensaver.timer =
|
||||||
wl_event_loop_add_timer(loop, screensaver_timeout, shell);
|
wl_event_loop_add_timer(loop, screensaver_timeout, shell);
|
||||||
|
|
||||||
wl_list_for_each(seat, &ec->seat_list, link) {
|
wl_list_for_each(seat, &ec->seat_list, link)
|
||||||
create_pointer_focus_listener(seat);
|
handle_seat_created(NULL, seat);
|
||||||
create_keyboard_focus_listener(seat);
|
shell->seat_create_listener.notify = handle_seat_created;
|
||||||
}
|
wl_signal_add(&ec->seat_created_signal, &shell->seat_create_listener);
|
||||||
|
|
||||||
screenshooter_create(ec);
|
screenshooter_create(ec);
|
||||||
|
|
||||||
|
|||||||
@@ -199,6 +199,7 @@ struct desktop_shell {
|
|||||||
|
|
||||||
struct weston_layer minimized_layer;
|
struct weston_layer minimized_layer;
|
||||||
|
|
||||||
|
struct wl_listener seat_create_listener;
|
||||||
struct wl_listener output_create_listener;
|
struct wl_listener output_create_listener;
|
||||||
struct wl_listener output_move_listener;
|
struct wl_listener output_move_listener;
|
||||||
struct wl_list output_list;
|
struct wl_list output_list;
|
||||||
|
|||||||
Reference in New Issue
Block a user