[PATCH] desktop-shell: Properly handle seat hotplugging

Kristian Høgsberg hoegsberg at gmail.com
Tue Apr 29 16:52:44 PDT 2014


On Mon, Apr 21, 2014 at 07:42:58PM -0500, Jason Ekstrand wrote:
> 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.
> 
> This fixes bug #77649

Thanks Jason, that's better.  Patch committed.

Kristian

> ---
>  desktop-shell/shell.c | 84 +++++++++++++++++++++++++++++++--------------------
>  desktop-shell/shell.h |  1 +
>  2 files changed, 53 insertions(+), 32 deletions(-)
> 
> diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
> index 0e4329b..ac03a15 100644
> --- a/desktop-shell/shell.c
> +++ b/desktop-shell/shell.c
> @@ -211,6 +211,10 @@ struct shell_seat {
>  	struct wl_listener seat_destroy_listener;
>  	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 weston_pointer_grab grab;
>  		struct wl_list surfaces_list;
> @@ -1918,19 +1922,6 @@ handle_pointer_focus(struct wl_listener *listener, void *data)
>  }
>  
>  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
>  shell_surface_lose_keyboard_focus(struct shell_surface *shsurf)
>  {
>  	if (--shsurf->focus_count == 0)
> @@ -1968,19 +1959,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
>  shell_client_pong(struct shell_client *sc, uint32_t serial)
>  {
>  	if (sc->ping_serial != serial)
> @@ -2771,6 +2749,30 @@ destroy_shell_seat(struct wl_listener *listener, void *data)
>  	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 *
>  create_shell_seat(struct weston_seat *seat)
>  {
> @@ -2789,6 +2791,17 @@ create_shell_seat(struct weston_seat *seat)
>  	wl_signal_add(&seat->destroy_signal,
>  	              &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;
>  }
>  
> @@ -2798,8 +2811,7 @@ get_shell_seat(struct weston_seat *seat)
>  	struct wl_listener *listener;
>  
>  	listener = wl_signal_get(&seat->destroy_signal, destroy_shell_seat);
> -	if (listener == NULL)
> -		return create_shell_seat(seat);
> +	assert(listener != NULL);
>  
>  	return container_of(listener,
>  			    struct shell_seat, seat_destroy_listener);
> @@ -5916,6 +5928,14 @@ shell_add_bindings(struct weston_compositor *ec, struct desktop_shell *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
>  module_init(struct weston_compositor *ec,
>  	    int *argc, char *argv[])
> @@ -6015,10 +6035,10 @@ module_init(struct weston_compositor *ec,
>  	shell->screensaver.timer =
>  		wl_event_loop_add_timer(loop, screensaver_timeout, shell);
>  
> -	wl_list_for_each(seat, &ec->seat_list, link) {
> -		create_pointer_focus_listener(seat);
> -		create_keyboard_focus_listener(seat);
> -	}
> +	wl_list_for_each(seat, &ec->seat_list, link)
> +		handle_seat_created(NULL, seat);
> +	shell->seat_create_listener.notify = handle_seat_created;
> +	wl_signal_add(&ec->seat_created_signal, &shell->seat_create_listener);
>  
>  	screenshooter_create(ec);
>  
> diff --git a/desktop-shell/shell.h b/desktop-shell/shell.h
> index 5d127c6..9685cb2 100644
> --- a/desktop-shell/shell.h
> +++ b/desktop-shell/shell.h
> @@ -199,6 +199,7 @@ struct desktop_shell {
>  
>  	struct weston_layer minimized_layer;
>  
> +	struct wl_listener seat_create_listener;
>  	struct wl_listener output_create_listener;
>  	struct wl_listener output_move_listener;
>  	struct wl_list output_list;
> -- 
> 1.9.0
> 
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel


More information about the wayland-devel mailing list