[RFC] weston: implement inert objects for keyboard/pointer/touch

Hardening rdp.effort at gmail.com
Fri Oct 16 08:16:52 PDT 2015


Le 16/10/2015 11:53, David FORT a écrit :
> This patch implements inert objects for wl_keyboard, wl_pointer and wl_touch.
> The target case is when the server has just send a capability event about a
> disappearing object, and the client binds the corresponding object. We bind an
> inert object: an object does nothing when it is requested. If the client behave
> correctly, this object should be released when the capability event is received
> and treated (calling the corresponding release request).
> As a consequence, we can rely on seat->[keyboard|pointer|touch]_state to know
> if the seat has the corresponding object.
> Weston doesn't really handle multiple mice for one wl_pointer, so I have removed
> the corresponding code and tests (it was quite a weston_test hack BTW).
> Finally I have fixed a wrong behaviour: the capabilities event's documentation states
> that the capabilities should be sent when a new capability is set on the seat. So
> attaching a second mouse to an existing wl_pointer should not broadcast seat
> capabilities (and the same for keyboard and touch).
> ---
>  desktop-shell/exposay.c  |  16 ++--
>  desktop-shell/shell.c    |  21 +++--
>  src/compositor-wayland.c |  10 +-
>  src/compositor-x11.c     |  12 ++-
>  src/compositor.h         |   3 -
>  src/input.c              | 235 ++++++++++++++++++++++++++---------------------
>  src/libinput-device.c    |   2 +-
>  src/screen-share.c       |   2 +
>  src/text-backend.c       |  44 +++++----
>  src/zoom.c               |   7 +-
>  tests/devices-test.c     |  20 ----
>  tests/weston-test.c      |  18 ++--
>  xwayland/dnd.c           |   3 +-
>  13 files changed, 216 insertions(+), 177 deletions(-)
> 
> diff --git a/desktop-shell/exposay.c b/desktop-shell/exposay.c
> index 08b86a3..d6919b3 100644
> --- a/desktop-shell/exposay.c
> +++ b/desktop-shell/exposay.c
> @@ -574,21 +574,23 @@ exposay_transition_active(struct desktop_shell *shell)
>  	bool animate = false;
>  
>  	shell->exposay.workspace = get_current_workspace(shell);
> -	shell->exposay.focus_prev = get_default_view(keyboard->focus);
> -	shell->exposay.focus_current = get_default_view(keyboard->focus);
> +	if (keyboard) {
> +		shell->exposay.focus_prev = get_default_view(keyboard->focus);
> +		shell->exposay.focus_current = get_default_view(keyboard->focus);
> +	}
>  	shell->exposay.clicked = NULL;
>  	wl_list_init(&shell->exposay.surface_list);
>  
>  	lower_fullscreen_layer(shell, NULL);
>  	shell->exposay.grab_kbd.interface = &exposay_kbd_grab;
> -	weston_keyboard_start_grab(keyboard,
> -	                           &shell->exposay.grab_kbd);
> -	weston_keyboard_set_focus(keyboard, NULL);
> +	if (keyboard) {
> +		weston_keyboard_start_grab(keyboard, &shell->exposay.grab_kbd);
> +		weston_keyboard_set_focus(keyboard, NULL);
> +	}
>  
>  	shell->exposay.grab_ptr.interface = &exposay_ptr_grab;
>  	if (pointer) {
> -		weston_pointer_start_grab(pointer,
> -		                          &shell->exposay.grab_ptr);
> +		weston_pointer_start_grab(pointer, &shell->exposay.grab_ptr);
>  		weston_pointer_clear_focus(pointer);
>  	}
>  	wl_list_for_each(shell_output, &shell->output_list, link) {
> diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
> index 3eb3f5c..cdddf09 100644
> --- a/desktop-shell/shell.c
> +++ b/desktop-shell/shell.c
> @@ -380,7 +380,8 @@ shell_grab_start(struct shell_grab *grab,
>  	struct desktop_shell *shell = shsurf->shell;
>  	struct weston_touch *touch = weston_seat_get_touch(pointer->seat);
>  
> -	popup_grab_end(pointer);
> +	if (pointer)
> +		popup_grab_end(pointer);
>  	if (touch)
>  		touch_popup_grab_end(touch);
>  
> @@ -391,11 +392,13 @@ shell_grab_start(struct shell_grab *grab,
>  		      &grab->shsurf_destroy_listener);
>  
>  	shsurf->grabbed = 1;
> -	weston_pointer_start_grab(pointer, &grab->grab);
> +	if (pointer)
> +		weston_pointer_start_grab(pointer, &grab->grab);
>  	if (shell->child.desktop_shell) {
>  		desktop_shell_send_grab_cursor(shell->child.desktop_shell,
>  					       cursor);
> -		weston_pointer_set_focus(pointer,
> +		if (pointer)
> +			weston_pointer_set_focus(pointer,
>  					 get_default_view(shell->grab_surface),
>  					 wl_fixed_from_int(0),
>  					 wl_fixed_from_int(0));
> @@ -925,12 +928,10 @@ restore_focus_state(struct desktop_shell *shell, struct workspace *ws)
>  		wl_list_insert(&shell->compositor->seat_list,
>  			       &state->seat->link);
>  
> -		if (!keyboard)
> -			continue;
> -
>  		surface = state->keyboard_focus;
>  
> -		weston_keyboard_set_focus(keyboard, surface);
> +		if (keyboard)
> +			weston_keyboard_set_focus(keyboard, surface);
>  	}
>  
>  	/* For any remaining seats that we don't have a focus state
> @@ -955,6 +956,9 @@ replace_focus_state(struct desktop_shell *shell, struct workspace *ws,
>  	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
>  	struct focus_state *state;
>  
> +	if (!keyboard)
> +		return;
> +
>  	wl_list_for_each(state, &ws->focus_list, link) {
>  		if (state->seat == seat) {
>  			focus_state_set_focus(state, keyboard->focus);
> @@ -1483,6 +1487,9 @@ take_surface_to_workspace_by_seat(struct desktop_shell *shell,
>  	struct workspace *to;
>  	struct focus_state *state;
>  
> +	if (!keyboard)
> +		return;
> +
>  	surface = weston_surface_get_main_surface(keyboard->focus);
>  	view = get_default_view(surface);
>  	if (view == NULL ||
> diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c
> index 7b11ae4..2cdf7a5 100644
> --- a/src/compositor-wayland.c
> +++ b/src/compositor-wayland.c
> @@ -1589,10 +1589,12 @@ input_handle_modifiers(void *data, struct wl_keyboard *wl_keyboard,
>  		serial_out = wl_display_next_serial(b->compositor->wl_display);
>  
>  	keyboard = weston_seat_get_keyboard(&input->base);
> -	xkb_state_update_mask(keyboard->xkb_state.state,
> -			      mods_depressed, mods_latched,
> -			      mods_locked, 0, 0, group);
> -	notify_modifiers(&input->base, serial_out);
> +	if (keyboard) {
> +		xkb_state_update_mask(keyboard->xkb_state.state,
> +					  mods_depressed, mods_latched,
> +					  mods_locked, 0, 0, group);
> +		notify_modifiers(&input->base, serial_out);
> +	}
>  }
>  
>  static void
> diff --git a/src/compositor-x11.c b/src/compositor-x11.c
> index 9a23996..42356e6 100644
> --- a/src/compositor-x11.c
> +++ b/src/compositor-x11.c
> @@ -189,11 +189,15 @@ x11_backend_get_keymap(struct x11_backend *b)
>  static uint32_t
>  get_xkb_mod_mask(struct x11_backend *b, uint32_t in)
>  {
> -	struct weston_keyboard *keyboard =
> -		weston_seat_get_keyboard(&b->core_seat);
> -	struct weston_xkb_info *info = keyboard->xkb_info;
> +	struct weston_keyboard *keyboard = weston_seat_get_keyboard(&b->core_seat);
> +	struct weston_xkb_info *info;
>  	uint32_t ret = 0;
>  
> +	if (!keyboard)
> +		return 0;
> +
> +	info = keyboard->xkb_info;
> +
>  	if ((in & ShiftMask) && info->shift_mod != XKB_MOD_INVALID)
>  		ret |= (1 << info->shift_mod);
>  	if ((in & LockMask) && info->caps_mod != XKB_MOD_INVALID)
> @@ -1028,6 +1032,8 @@ update_xkb_state_from_core(struct x11_backend *b, uint16_t x11_mask)
>  	struct weston_keyboard *keyboard
>  		= weston_seat_get_keyboard(&b->core_seat);
>  
> +	if (!keyboard)
> +		return;
>  	xkb_state_update_mask(keyboard->xkb_state.state,
>  			      keyboard->modifiers.mods_depressed & mask,
>  			      keyboard->modifiers.mods_latched & mask,
> diff --git a/src/compositor.h b/src/compositor.h
> index 2e2a185..de38514 100644
> --- a/src/compositor.h
> +++ b/src/compositor.h
> @@ -508,9 +508,6 @@ struct weston_seat {
>  	struct weston_pointer *pointer_state;
>  	struct weston_keyboard *keyboard_state;
>  	struct weston_touch *touch_state;
> -	int pointer_device_count;
> -	int keyboard_device_count;
> -	int touch_device_count;
>  
>  	struct weston_output *output; /* constraint */
>  
> diff --git a/src/input.c b/src/input.c
> index 500c39a..6cd2650 100644
> --- a/src/input.c
> +++ b/src/input.c
> @@ -55,10 +55,8 @@ weston_seat_repick(struct weston_seat *seat)
>  {
>  	const struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>  
> -	if (!pointer)
> -		return;
> -
> -	pointer->grab->interface->focus(pointer->grab);
> +	if (pointer)
> +		pointer->grab->interface->focus(pointer->grab);
>  }
>  
>  static void
> @@ -618,11 +616,11 @@ seat_send_updated_caps(struct weston_seat *seat)
>  	enum wl_seat_capability caps = 0;
>  	struct wl_resource *resource;
>  
> -	if (seat->pointer_device_count > 0)
> +	if (seat->pointer_state)
>  		caps |= WL_SEAT_CAPABILITY_POINTER;
> -	if (seat->keyboard_device_count > 0)
> +	if (seat->keyboard_state)
>  		caps |= WL_SEAT_CAPABILITY_KEYBOARD;
> -	if (seat->touch_device_count > 0)
> +	if (seat->touch_state)
>  		caps |= WL_SEAT_CAPABILITY_TOUCH;
>  
>  	wl_resource_for_each(resource, &seat->base_resource_list) {
> @@ -982,7 +980,8 @@ notify_motion(struct weston_seat *seat,
>  	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>  
>  	weston_compositor_wake(ec);
> -	pointer->grab->interface->motion(pointer->grab, time, pointer->x + dx, pointer->y + dy);
> +	if (pointer)
> +		pointer->grab->interface->motion(pointer->grab, time, pointer->x + dx, pointer->y + dy);
>  }
>  
>  static void
> @@ -1029,7 +1028,8 @@ notify_motion_absolute(struct weston_seat *seat,
>  	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>  
>  	weston_compositor_wake(ec);
> -	pointer->grab->interface->motion(pointer->grab, time, x, y);
> +	if (pointer)
> +		pointer->grab->interface->motion(pointer->grab, time, x, y);
>  }
>  
>  WL_EXPORT void
> @@ -1054,6 +1054,9 @@ notify_button(struct weston_seat *seat, uint32_t time, int32_t button,
>  	struct weston_compositor *compositor = seat->compositor;
>  	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>  
> +	if (!pointer)
> +		return;
> +
>  	if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
>  		weston_compositor_idle_inhibit(compositor);
>  		if (pointer->button_count == 0) {
> @@ -1092,7 +1095,7 @@ notify_axis(struct weston_seat *seat, uint32_t time, uint32_t axis,
>  	if (!value)
>  		return;
>  
> -	if (weston_compositor_run_axis_binding(compositor, pointer,
> +	if (!pointer || weston_compositor_run_axis_binding(compositor, pointer,
>  					       time, axis, value))
>  		return;
>  
> @@ -1159,12 +1162,16 @@ WL_EXPORT void
>  notify_modifiers(struct weston_seat *seat, uint32_t serial)
>  {
>  	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
> -	struct weston_keyboard_grab *grab = keyboard->grab;
> +	struct weston_keyboard_grab *grab;
>  	uint32_t mods_depressed, mods_latched, mods_locked, group;
>  	uint32_t mods_lookup;
>  	enum weston_led leds = 0;
>  	int changed = 0;
>  
> +	if (!keyboard)
> +		return;
> +
> +	grab = keyboard->grab;
>  	/* Serialize and update our internal state, checking to see if it's
>  	 * different to the previous state. */
>  	mods_depressed = xkb_state_serialize_mods(keyboard->xkb_state.state,
> @@ -1233,6 +1240,9 @@ update_modifier_state(struct weston_seat *seat, uint32_t serial, uint32_t key,
>  	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
>  	enum xkb_key_direction direction;
>  
> +	if (!keyboard)
> +		return;
> +
>  	/* Keyboard modifiers don't exist in raw keyboard mode */
>  	if (!seat->compositor->use_xkbcommon)
>  		return;
> @@ -1281,6 +1291,9 @@ update_keymap(struct weston_seat *seat)
>  	xkb_mod_mask_t latched_mods;
>  	xkb_mod_mask_t locked_mods;
>  
> +	if (!keyboard)
> +		return;
> +
>  	xkb_info = weston_xkb_info_create(keyboard->pending_keymap);
>  
>  	xkb_keymap_unref(keyboard->pending_keymap);
> @@ -1353,8 +1366,8 @@ notify_key(struct weston_seat *seat, uint32_t time, uint32_t key,
>  	   enum weston_key_state_update update_state)
>  {
>  	struct weston_compositor *compositor = seat->compositor;
> -	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
> -	struct weston_keyboard_grab *grab = keyboard->grab;
> +	struct weston_keyboard *keyboard;
> +	struct weston_keyboard_grab *grab;
>  	uint32_t *k, *end;
>  
>  	if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
> @@ -1363,6 +1376,11 @@ notify_key(struct weston_seat *seat, uint32_t time, uint32_t key,
>  		weston_compositor_idle_release(compositor);
>  	}
>  
> +	keyboard = weston_seat_get_keyboard(seat);
> +	if (!keyboard)
> +		return;
> +	grab = keyboard->grab;
> +
>  	end = keyboard->keys.data + keyboard->keys.size;
>  	for (k = keyboard->keys.data; k < end; k++) {
>  		if (*k == key) {
> @@ -1412,7 +1430,7 @@ notify_pointer_focus(struct weston_seat *seat, struct weston_output *output,
>  {
>  	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>  
> -	if (output) {
> +	if (output && pointer) {
>  		weston_pointer_move(pointer, x, y);
>  	} else {
>  		/* FIXME: We should call weston_pointer_set_focus(seat,
> @@ -1440,6 +1458,9 @@ notify_keyboard_focus_in(struct weston_seat *seat, struct wl_array *keys,
>  	struct weston_surface *surface;
>  	uint32_t *k, serial;
>  
> +	if (!keyboard)
> +		return;
> +
>  	serial = wl_display_next_serial(compositor->wl_display);
>  	wl_array_copy(&keyboard->keys, keys);
>  	wl_array_for_each(k, &keyboard->keys) {
> @@ -1466,25 +1487,30 @@ notify_keyboard_focus_out(struct weston_seat *seat)
>  	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>  	uint32_t *k, serial;
>  
> -	serial = wl_display_next_serial(compositor->wl_display);
> -	wl_array_for_each(k, &keyboard->keys) {
> -		weston_compositor_idle_release(compositor);
> -		update_modifier_state(seat, serial, *k,
> -				      WL_KEYBOARD_KEY_STATE_RELEASED);
> +	if (keyboard) {
> +		serial = wl_display_next_serial(compositor->wl_display);
> +		wl_array_for_each(k, &keyboard->keys) {
> +			weston_compositor_idle_release(compositor);
> +			update_modifier_state(seat, serial, *k,
> +						  WL_KEYBOARD_KEY_STATE_RELEASED);
> +		}
>  	}
>  
>  	seat->modifier_state = 0;
>  
> -	if (keyboard->focus) {
> -		seat->saved_kbd_focus = keyboard->focus;
> -		seat->saved_kbd_focus_listener.notify =
> -			destroy_device_saved_kbd_focus;
> -		wl_signal_add(&keyboard->focus->destroy_signal,
> -			      &seat->saved_kbd_focus_listener);
> +	if (keyboard) {
> +		if (keyboard->focus) {
> +			seat->saved_kbd_focus = keyboard->focus;
> +			seat->saved_kbd_focus_listener.notify =
> +				destroy_device_saved_kbd_focus;
> +			wl_signal_add(&keyboard->focus->destroy_signal,
> +					  &seat->saved_kbd_focus_listener);
> +		}
> +
> +		weston_keyboard_set_focus(keyboard, NULL);
> +		weston_keyboard_cancel_grab(keyboard);
>  	}
>  
> -	weston_keyboard_set_focus(keyboard, NULL);
> -	weston_keyboard_cancel_grab(keyboard);
>  	if (pointer)
>  		weston_pointer_cancel_grab(pointer);
>  }
> @@ -1545,10 +1571,15 @@ notify_touch(struct weston_seat *seat, uint32_t time, int touch_id,
>  {
>  	struct weston_compositor *ec = seat->compositor;
>  	struct weston_touch *touch = weston_seat_get_touch(seat);
> -	struct weston_touch_grab *grab = touch->grab;
> +	struct weston_touch_grab *grab;
>  	struct weston_view *ev;
>  	wl_fixed_t sx, sy;
>  
> +	if (!touch)
> +		return;
> +
> +	grab = touch->grab;
> +
>  	/* Update grab's global coordinates. */
>  	if (touch_id == touch->grab_touch_id && touch_type != WL_TOUCH_UP) {
>  		touch->grab_x = x;
> @@ -1620,9 +1651,12 @@ WL_EXPORT void
>  notify_touch_frame(struct weston_seat *seat)
>  {
>  	struct weston_touch *touch = weston_seat_get_touch(seat);
> -	struct weston_touch_grab *grab = touch->grab;
> +	struct weston_touch_grab *grab;
>  
> -	grab->interface->frame(grab);
> +	if (touch) {
> +		grab = touch->grab;
> +		grab->interface->frame(grab);
> +	}
>  }
>  
>  static int
> @@ -1735,34 +1769,46 @@ static const struct wl_pointer_interface pointer_interface = {
>  };
>  
>  static void
> +inert_pointer_set_cursor(struct wl_client *client, struct wl_resource *resource,
> +		   uint32_t serial, struct wl_resource *surface_resource,
> +		   int32_t x, int32_t y)
> +{
> +	/* in the "normal" pointer_set_cursor, we're setting a surface role only
> +	 * if we have pointer focus. An inert pointer doesn't really have a focus so
> +	 * we don't do anything on the surface */
> +}
> +
> +static const struct wl_pointer_interface inert_pointer_interface = {
> +	inert_pointer_set_cursor,
> +	pointer_release
> +};
> +
> +static void
>  seat_get_pointer(struct wl_client *client, struct wl_resource *resource,
>  		 uint32_t id)
>  {
>  	struct weston_seat *seat = wl_resource_get_user_data(resource);
> -	/* We use the pointer_state directly, which means we'll
> -	 * give a wl_pointer if the seat has ever had one - even though
> -	 * the spec explicitly states that this request only takes effect
> -	 * if the seat has the pointer capability.
> -	 *
> -	 * This prevents a race between the compositor sending new
> -	 * capabilities and the client trying to use the old ones.
> -	 */
>  	struct weston_pointer *pointer = seat->pointer_state;
>  	struct wl_resource *cr;
>  
> -	if (!pointer)
> -		return;
> -
> -        cr = wl_resource_create(client, &wl_pointer_interface,
> -				wl_resource_get_version(resource), id);
> +	cr = wl_resource_create(client, &wl_pointer_interface,
> +			wl_resource_get_version(resource), id);
>  	if (cr == NULL) {
>  		wl_client_post_no_memory(client);
>  		return;
>  	}
>  
> +	if (!pointer) {
> +		/*weston_log("binding inert pointer for seat %p\n", seat);*/
> +		wl_resource_set_implementation(cr, &inert_pointer_interface, NULL,
> +					       NULL);
> +		return;
> +	}
> +
>  	/* May be moved to focused list later by either
>  	 * weston_pointer_set_focus or directly if this client is already
>  	 * focused */
> +
>  	wl_list_insert(&pointer->resource_list, wl_resource_get_link(cr));
>  	wl_resource_set_implementation(cr, &pointer_interface, pointer,
>  				       unbind_resource);
> @@ -1796,6 +1842,10 @@ static const struct wl_keyboard_interface keyboard_interface = {
>  	keyboard_release
>  };
>  
> +static const struct wl_keyboard_interface inert_keyboard_interface = {
> +	keyboard_release
> +};
> +
>  static bool
>  should_send_modifiers_to_client(struct weston_seat *seat,
>  				struct wl_client *client)
> @@ -1823,27 +1873,23 @@ seat_get_keyboard(struct wl_client *client, struct wl_resource *resource,
>  		  uint32_t id)
>  {
>  	struct weston_seat *seat = wl_resource_get_user_data(resource);
> -	/* We use the keyboard_state directly, which means we'll
> -	 * give a wl_keyboard if the seat has ever had one - even though
> -	 * the spec explicitly states that this request only takes effect
> -	 * if the seat has the keyboard capability.
> -	 *
> -	 * This prevents a race between the compositor sending new
> -	 * capabilities and the client trying to use the old ones.
> -	 */
>  	struct weston_keyboard *keyboard = seat->keyboard_state;
>  	struct wl_resource *cr;
>  
> -	if (!keyboard)
> -		return;
> -
> -        cr = wl_resource_create(client, &wl_keyboard_interface,
> -				wl_resource_get_version(resource), id);
> +	cr = wl_resource_create(client, &wl_keyboard_interface,
> +			wl_resource_get_version(resource), id);
>  	if (cr == NULL) {
>  		wl_client_post_no_memory(client);
>  		return;
>  	}
>  
> +	if (!keyboard) {
> +		/*weston_log("binding inert keyboard for seat %p\n", seat);*/
> +		wl_resource_set_implementation(cr, &inert_keyboard_interface, NULL,
> +				NULL);
> +		return;
> +	}
> +
>  	/* May be moved to focused list later by either
>  	 * weston_keyboard_set_focus or directly if this client is already
>  	 * focused */
> @@ -1906,32 +1952,32 @@ static const struct wl_touch_interface touch_interface = {
>  	touch_release
>  };
>  
> +static const struct wl_touch_interface inert_touch_interface = {
> +	touch_release
> +};
> +
>  static void
>  seat_get_touch(struct wl_client *client, struct wl_resource *resource,
>  	       uint32_t id)
>  {
>  	struct weston_seat *seat = wl_resource_get_user_data(resource);
> -	/* We use the touch_state directly, which means we'll
> -	 * give a wl_touch if the seat has ever had one - even though
> -	 * the spec explicitly states that this request only takes effect
> -	 * if the seat has the touch capability.
> -	 *
> -	 * This prevents a race between the compositor sending new
> -	 * capabilities and the client trying to use the old ones.
> -	 */
>  	struct weston_touch *touch = seat->touch_state;
>  	struct wl_resource *cr;
>  
> -	if (!touch)
> -		return;
> -
> -        cr = wl_resource_create(client, &wl_touch_interface,
> -				wl_resource_get_version(resource), id);
> +	cr = wl_resource_create(client, &wl_touch_interface,
> +			wl_resource_get_version(resource), id);
>  	if (cr == NULL) {
>  		wl_client_post_no_memory(client);
>  		return;
>  	}
>  
> +	if (!touch) {
> +		/*weston_log("binding inert touch for seat %p\n", seat);*/
> +		wl_resource_set_implementation(cr, &inert_touch_interface, NULL, NULL);
> +		return;
> +	}
> +
> +
>  	if (touch->focus &&
>  	    wl_resource_get_client(touch->focus->surface->resource) == client) {
>  		wl_list_insert(&touch->focus_resource_list,
> @@ -2180,9 +2226,7 @@ weston_seat_init_keyboard(struct weston_seat *seat, struct xkb_keymap *keymap)
>  	struct weston_keyboard *keyboard;
>  
>  	if (seat->keyboard_state) {
> -		seat->keyboard_device_count += 1;
> -		if (seat->keyboard_device_count == 1)
> -			seat_send_updated_caps(seat);
> +		weston_log("seat %p already has a keyboard device\n", seat);
>  		return 0;
>  	}
>  
> @@ -2216,7 +2260,6 @@ weston_seat_init_keyboard(struct weston_seat *seat, struct xkb_keymap *keymap)
>  #endif
>  
>  	seat->keyboard_state = keyboard;
> -	seat->keyboard_device_count = 1;
>  	keyboard->seat = seat;
>  
>  	seat_send_updated_caps(seat);
> @@ -2257,12 +2300,12 @@ weston_keyboard_reset_state(struct weston_keyboard *keyboard)
>  WL_EXPORT void
>  weston_seat_release_keyboard(struct weston_seat *seat)
>  {
> -	seat->keyboard_device_count--;
> -	assert(seat->keyboard_device_count >= 0);
> -	if (seat->keyboard_device_count == 0) {
> +	if (seat->keyboard_state) {
>  		weston_keyboard_set_focus(seat->keyboard_state, NULL);
>  		weston_keyboard_cancel_grab(seat->keyboard_state);
>  		weston_keyboard_reset_state(seat->keyboard_state);
> +		seat->keyboard_state = NULL;
> +
>  		seat_send_updated_caps(seat);
>  	}
>  }
> @@ -2273,9 +2316,7 @@ weston_seat_init_pointer(struct weston_seat *seat)
>  	struct weston_pointer *pointer;
>  
>  	if (seat->pointer_state) {
> -		seat->pointer_device_count += 1;
> -		if (seat->pointer_device_count == 1)
> -			seat_send_updated_caps(seat);
> +		weston_log("seat %p already has a pointer device\n", seat);
>  		return;
>  	}
>  
> @@ -2284,7 +2325,6 @@ weston_seat_init_pointer(struct weston_seat *seat)
>  		return;
>  
>  	seat->pointer_state = pointer;
> -	seat->pointer_device_count = 1;
>  	pointer->seat = seat;
>  
>  	seat_send_updated_caps(seat);
> @@ -2295,8 +2335,7 @@ weston_seat_release_pointer(struct weston_seat *seat)
>  {
>  	struct weston_pointer *pointer = seat->pointer_state;
>  
> -	seat->pointer_device_count--;
> -	if (seat->pointer_device_count == 0) {
> +	if (seat->pointer_state) {
>  		weston_pointer_clear_focus(pointer);
>  		weston_pointer_cancel_grab(pointer);
>  
> @@ -2304,12 +2343,9 @@ weston_seat_release_pointer(struct weston_seat *seat)
>  			pointer_unmap_sprite(pointer);
>  
>  		weston_pointer_reset_state(pointer);
> -		seat_send_updated_caps(seat);
> +		seat->pointer_state = NULL;
>  
> -		/* seat->pointer is intentionally not destroyed so that
> -		 * a newly attached pointer on this seat will retain
> -		 * the previous cursor co-ordinates.
> -		 */
> +		seat_send_updated_caps(seat);
>  	}
>  }
>  
> @@ -2319,9 +2355,7 @@ weston_seat_init_touch(struct weston_seat *seat)
>  	struct weston_touch *touch;
>  
>  	if (seat->touch_state) {
> -		seat->touch_device_count += 1;
> -		if (seat->touch_device_count == 1)
> -			seat_send_updated_caps(seat);
> +		weston_log("seat %p already has a touch device\n", seat);
>  		return;
>  	}
>  
> @@ -2330,7 +2364,6 @@ weston_seat_init_touch(struct weston_seat *seat)
>  		return;
>  
>  	seat->touch_state = touch;
> -	seat->touch_device_count = 1;
>  	touch->seat = seat;
>  
>  	seat_send_updated_caps(seat);
> @@ -2339,11 +2372,12 @@ weston_seat_init_touch(struct weston_seat *seat)
>  WL_EXPORT void
>  weston_seat_release_touch(struct weston_seat *seat)
>  {
> -	seat->touch_device_count--;
> -	if (seat->touch_device_count == 0) {
> +	if (seat->touch_state) {
>  		weston_touch_set_focus(seat->touch_state, NULL);
>  		weston_touch_cancel_grab(seat->touch_state);
>  		weston_touch_reset_state(seat->touch_state);
> +		seat->touch_state = NULL;
> +
>  		seat_send_updated_caps(seat);
>  	}
>  }
> @@ -2413,10 +2447,7 @@ weston_seat_get_keyboard(struct weston_seat *seat)
>  	if (!seat)
>  		return NULL;
>  
> -	if (seat->keyboard_device_count)
> -		return seat->keyboard_state;
> -
> -	return NULL;
> +	return seat->keyboard_state;
>  }
>  
>  /** Get a seat's pointer pointer
> @@ -2435,10 +2466,7 @@ weston_seat_get_pointer(struct weston_seat *seat)
>  	if (!seat)
>  		return NULL;
>  
> -	if (seat->pointer_device_count)
> -		return seat->pointer_state;
> -
> -	return NULL;
> +	return seat->pointer_state;
>  }
>  
>  /** Get a seat's touch pointer
> @@ -2457,8 +2485,5 @@ weston_seat_get_touch(struct weston_seat *seat)
>  	if (!seat)
>  		return NULL;
>  
> -	if (seat->touch_device_count)
> -		return seat->touch_state;
> -
> -	return NULL;
> +	return seat->touch_state;
>  }
> diff --git a/src/libinput-device.c b/src/libinput-device.c
> index 2cbfb88..ddd8e2c 100644
> --- a/src/libinput-device.c
> +++ b/src/libinput-device.c
> @@ -547,7 +547,7 @@ evdev_notify_keyboard_focus(struct weston_seat *seat,
>  {
>  	struct wl_array keys;
>  
> -	if (seat->keyboard_device_count == 0)
> +	if (!seat->keyboard_state)
>  		return;
>  
>  	wl_array_init(&keys);
> diff --git a/src/screen-share.c b/src/screen-share.c
> index d961c89..e20aede 100644
> --- a/src/screen-share.c
> +++ b/src/screen-share.c
> @@ -283,6 +283,8 @@ ss_seat_handle_modifiers(void *data, struct wl_keyboard *wl_keyboard,
>  		serial_out = wl_display_next_serial(c->wl_display);
>  
>  	keyboard = weston_seat_get_keyboard(&seat->base);
> +	if (!keyboard)
> +		return;
>  	xkb_state_update_mask(keyboard->xkb_state.state,
>  			      mods_depressed, mods_latched,
>  			      mods_locked, 0, 0, group);
> diff --git a/src/text-backend.c b/src/text-backend.c
> index 8c9e30d..f3f30dc 100644
> --- a/src/text-backend.c
> +++ b/src/text-backend.c
> @@ -664,15 +664,17 @@ input_method_context_grab_keyboard(struct wl_client *client,
>  
>  	context->keyboard = cr;
>  
> -	wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
> -				keyboard->xkb_info->keymap_fd,
> -				keyboard->xkb_info->keymap_size);
> -
> -	if (keyboard->grab != &keyboard->default_grab) {
> -		weston_keyboard_end_grab(keyboard);
> +	if (keyboard) {
> +		wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
> +					keyboard->xkb_info->keymap_fd,
> +					keyboard->xkb_info->keymap_size);
> +
> +		if (keyboard->grab != &keyboard->default_grab) {
> +			weston_keyboard_end_grab(keyboard);
> +		}
> +		weston_keyboard_start_grab(keyboard, &keyboard->input_method_grab);
> +		keyboard->input_method_resource = cr;
>  	}
> -	weston_keyboard_start_grab(keyboard, &keyboard->input_method_grab);
> -	keyboard->input_method_resource = cr;
>  }
>  
>  static void
> @@ -686,10 +688,14 @@ input_method_context_key(struct wl_client *client,
>  	struct input_method_context *context =
>  		wl_resource_get_user_data(resource);
>  	struct weston_seat *seat = context->input_method->seat;
> -	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
> -	struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
> +	struct weston_keyboard *keyboard;
> +	struct weston_keyboard_grab *default_grab;
>  
> -	default_grab->interface->key(default_grab, time, key, state_w);
> +	keyboard = weston_seat_get_keyboard(seat);
> +	if (keyboard) {
> +		default_grab = &keyboard->default_grab;
> +		default_grab->interface->key(default_grab, time, key, state_w);
> +	}
>  }
>  
>  static void
> @@ -705,13 +711,17 @@ input_method_context_modifiers(struct wl_client *client,
>  		wl_resource_get_user_data(resource);
>  
>  	struct weston_seat *seat = context->input_method->seat;
> -	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
> -	struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
> +	struct weston_keyboard *keyboard;
> +	struct weston_keyboard_grab *default_grab;
>  
> -	default_grab->interface->modifiers(default_grab,
> -					   serial, mods_depressed,
> -					   mods_latched, mods_locked,
> -					   group);
> +	keyboard = weston_seat_get_keyboard(seat);
> +	if (keyboard) {
> +		default_grab = &keyboard->default_grab;
> +		default_grab->interface->modifiers(default_grab,
> +						   serial, mods_depressed,
> +						   mods_latched, mods_locked,
> +						   group);
> +	}
>  }
>  
>  static void
> diff --git a/src/zoom.c b/src/zoom.c
> index 08c0693..8658f08 100644
> --- a/src/zoom.c
> +++ b/src/zoom.c
> @@ -124,6 +124,8 @@ weston_output_update_zoom(struct weston_output *output)
>  	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>  
>  	assert(output->zoom.active);
> +	if (!pointer)
> +		return;
>  
>  	output->zoom.current.x = wl_fixed_to_double(pointer->x);
>  	output->zoom.current.y = wl_fixed_to_double(pointer->y);
> @@ -155,8 +157,9 @@ weston_output_activate_zoom(struct weston_output *output,
>  	output->zoom.active = true;
>  	output->zoom.seat = seat;
>  	output->disable_planes++;
> -	wl_signal_add(&pointer->motion_signal,
> -		      &output->zoom.motion_listener);
> +	if (pointer)
> +		wl_signal_add(&pointer->motion_signal,
> +				&output->zoom.motion_listener);
>  }
>  
>  WL_EXPORT void
> diff --git a/tests/devices-test.c b/tests/devices-test.c
> index 8f9feec..8851c17 100644
> --- a/tests/devices-test.c
> +++ b/tests/devices-test.c
> @@ -74,26 +74,6 @@ TEST(seat_capabilities_test)
>  	assert(cl->input->pointer);
>  	assert(cl->input->keyboard);
>  	assert(cl->input->touch);
> -
> -	/* add extra devices */
> -	weston_test_device_add(cl->test->weston_test, "keyboard");
> -	weston_test_device_add(cl->test->weston_test, "pointer");
> -	weston_test_device_add(cl->test->weston_test, "touch");
> -	client_roundtrip(cl);
> -
> -	/* remove extra devices */
> -	weston_test_device_release(cl->test->weston_test, "keyboard");
> -	weston_test_device_release(cl->test->weston_test, "pointer");
> -	weston_test_device_release(cl->test->weston_test, "touch");
> -	client_roundtrip(cl);
> -
> -	/* we still should have all the capabilities, since the devices
> -	 * were doubled */
> -	assert(cl->input->caps == WL_SEAT_CAPABILITY_ALL);
> -
> -	assert(cl->input->pointer);
> -	assert(cl->input->keyboard);
> -	assert(cl->input->touch);
>  }
>  
>  #define COUNT 15
> diff --git a/tests/weston-test.c b/tests/weston-test.c
> index b593f1e..28aefad 100644
> --- a/tests/weston-test.c
> +++ b/tests/weston-test.c
> @@ -85,7 +85,8 @@ notify_pointer_position(struct weston_test *test, struct wl_resource *resource)
>  	struct weston_seat *seat = get_seat(test);
>  	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>  
> -	weston_test_send_pointer_position(resource, pointer->x, pointer->y);
> +	if (pointer)
> +		weston_test_send_pointer_position(resource, pointer->x, pointer->y);
>  }
>  
>  static void
> @@ -146,9 +147,10 @@ move_pointer(struct wl_client *client, struct wl_resource *resource,
>  	struct weston_seat *seat = get_seat(test);
>  	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>  
> -	notify_motion(seat, 100,
> -		      wl_fixed_from_int(x) - pointer->x,
> -		      wl_fixed_from_int(y) - pointer->y);
> +	if (pointer)
> +		notify_motion(seat, 100,
> +				  wl_fixed_from_int(x) - pointer->x,
> +				  wl_fixed_from_int(y) - pointer->y);
>  
>  	notify_pointer_position(test, resource);
>  }
> @@ -177,11 +179,13 @@ activate_surface(struct wl_client *client, struct wl_resource *resource,
>  	keyboard = weston_seat_get_keyboard(seat);
>  	if (surface) {
>  		weston_surface_activate(surface, seat);
> -		notify_keyboard_focus_in(seat, &keyboard->keys,
> -					 STATE_UPDATE_AUTOMATIC);
> +		if (keyboard)
> +			notify_keyboard_focus_in(seat, &keyboard->keys,
> +					STATE_UPDATE_AUTOMATIC);
>  	}
>  	else {
> -		notify_keyboard_focus_out(seat);
> +		if (keyboard)
> +			notify_keyboard_focus_out(seat);
>  		weston_surface_activate(surface, seat);
>  	}
>  }
> diff --git a/xwayland/dnd.c b/xwayland/dnd.c
> index a036b30..94a9563 100644
> --- a/xwayland/dnd.c
> +++ b/xwayland/dnd.c
> @@ -214,7 +214,8 @@ handle_enter(struct weston_wm *wm, xcb_client_message_event_t *client_message)
>  	}
>  
>  	free(reply);
> -	weston_pointer_start_drag(pointer, &source->base, NULL, NULL);
> +	if (pointer)
> +		weston_pointer_start_drag(pointer, &source->base, NULL, NULL);
>  }
>  
>  int
> 


As Jonas noticed I have missed something with the refcounting of
keyboard/pointer/touch in my patch. I'm sending an updated version.

-- 
David FORT
website: http://www.hardening-consulting.com/



More information about the wayland-devel mailing list