[PATCH weston v5] input: Don't test keyboard/pointer/touch pointers

Derek Foreman derekf at osg.samsung.com
Fri May 22 11:47:37 PDT 2015


Thanks for the very comprehensive review!

On 20/05/15 10:47 PM, Jonas Ã…dahl wrote:
> On Mon, May 04, 2015 at 10:59:10AM -0500, Derek Foreman wrote:
>> Keyboards and pointers aren't freed when devices are removed,
>> so we should really be testing keyboard_device_count and
>> pointer_device_count in most cases, not the actual pointers.
>> Otherwise we end up with different behaviour after removing a
>> device than we had before it was inserted.
>>
>> This commit renames the touch/keyboard/pointer pointers and adds
>> helper functions to get them that hide this complexity and return
>> NULL when *_device_count is 0.
>>
>> Signed-off-by: Derek Foreman <derekf at osg.samsung.com>
>> ---
>>
>> Fixed a few bugs that turned up while running devices-test - now
>> seat_get_pointer, seat_get_touch and seat_get_keyboard use the resource
>> pointers directly.
>>
>> Added a couple of null pointer checks.
>>
>> Moved the helper functions to input.c
> 
> Hey, some issues and nits inlined below. Another general comment is, in
> various places, you use the helper and temporary variabes when it is
> guaranteed that it'll always return for example seat->pointer (in grabs,
> keybindings and the like). Are those changes really necessary? Being
> able to go directly from seat to pointer is awfully convenient and very
> often reliable (in grabs, keybindings etc).

I don't like adding a protective helper function to make it harder to
screw up access to touch/keyboard/pointer and then just randomly not
using it for convenience.  It'll make it very hard to understand for
someone new looking at the code.

Is there a reason the binding callbacks take a seat instead of a
touch/keyboard/pointer to begin with?
weston_pointer, _touch, _keyboard all have a seat pointer anyway.

I'll have a go at making all the callbacks take the appropriate pointer
in the first place - I think that'll make the code look nicer anyway...

>>
>>  desktop-shell/exposay.c             |  27 ++--
>>  desktop-shell/input-panel.c         |   7 +-
>>  desktop-shell/shell.c               | 266 +++++++++++++++++++-------------
>>  fullscreen-shell/fullscreen-shell.c |  21 ++-
>>  ivi-shell/hmi-controller.c          |  35 +++--
>>  ivi-shell/input-panel-ivi.c         |   7 +-
>>  src/bindings.c                      |  28 ++--
>>  src/compositor-drm.c                |  16 +-
>>  src/compositor-wayland.c            |   8 +-
>>  src/compositor-x11.c                |  20 ++-
>>  src/compositor.c                    |  32 ++--
>>  src/compositor.h                    |  15 +-
>>  src/data-device.c                   |  41 ++---
>>  src/input.c                         | 294 +++++++++++++++++++++++-------------
>>  src/libinput-device.c               |   3 +-
>>  src/libinput-seat.c                 |  15 +-
>>  src/screen-share.c                  |   3 +-
>>  src/screenshooter.c                 |   7 +-
>>  src/text-backend.c                  |  19 ++-
>>  src/zoom.c                          |   8 +-
>>  tests/surface-screenshot.c          |   7 +-
>>  tests/weston-test.c                 |  12 +-
>>  xwayland/dnd.c                      |   3 +-
>>  xwayland/window-manager.c           |  21 ++-
>>  24 files changed, 583 insertions(+), 332 deletions(-)
>>
>> diff --git a/desktop-shell/exposay.c b/desktop-shell/exposay.c
>> index 4b65cbd..e3b1c78 100644
>> --- a/desktop-shell/exposay.c
>> +++ b/desktop-shell/exposay.c
>> @@ -517,11 +517,13 @@ static enum exposay_layout_state
>>  exposay_set_inactive(struct desktop_shell *shell)
>>  {
>>  	struct weston_seat *seat = shell->exposay.seat;
>> +	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
>> +	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>>  
>> -	weston_keyboard_end_grab(seat->keyboard);
>> -	weston_pointer_end_grab(seat->pointer);
>> -	if (seat->keyboard->input_method_resource)
>> -		seat->keyboard->grab = &seat->keyboard->input_method_grab;
>> +	weston_keyboard_end_grab(keyboard);
>> +	weston_pointer_end_grab(pointer);
>> +	if (keyboard->input_method_resource)
>> +		keyboard->grab = &keyboard->input_method_grab;
> 
> This may introduce segfaults as seat->keyboard/seat->pointer would
> previously always be non-NULL, even when the last keyboard/pointer was
> disconnected.

Thanks, I think this code could already crash if there wasn't a pointer
in the seat that used the exposay keybind.  (easily confirmed - yup)

>>  
>>  	return EXPOSAY_LAYOUT_INACTIVE;
>>  }
>> @@ -554,26 +556,27 @@ static enum exposay_layout_state
>>  exposay_transition_active(struct desktop_shell *shell)
>>  {
>>  	struct weston_seat *seat = shell->exposay.seat;
>> +	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>> +	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
>>  	struct shell_output *shell_output;
>>  	bool animate = false;
>>  
>>  	shell->exposay.workspace = get_current_workspace(shell);
>> -	shell->exposay.focus_prev = get_default_view (seat->keyboard->focus);
>> -	shell->exposay.focus_current = get_default_view (seat->keyboard->focus);
>> +	shell->exposay.focus_prev = get_default_view(keyboard->focus);
>> +	shell->exposay.focus_current = get_default_view(keyboard->focus);
> 
> Same issue here regarding pointe/keyboard can now be NULL when before
> they couldn't.

Sure they could, as before - at least for the pointer.  exposay is
triggered by a keyboard binding, so I think the keyboard will always be
good.

I just sent a patch to fix the exposay crash present in git master,
hopefully we can get it in for the release...

>>  	shell->exposay.clicked = NULL;
>>  	wl_list_init(&shell->exposay.surface_list);
>>  
>>  	lower_fullscreen_layer(shell);
>>  	shell->exposay.grab_kbd.interface = &exposay_kbd_grab;
>> -	weston_keyboard_start_grab(seat->keyboard,
>> -	                           &shell->exposay.grab_kbd);
>> -	weston_keyboard_set_focus(seat->keyboard, NULL);
>> +	weston_keyboard_start_grab(keyboard, &shell->exposay.grab_kbd);
>> +	weston_keyboard_set_focus(keyboard, NULL);
>>  
>>  	shell->exposay.grab_ptr.interface = &exposay_ptr_grab;
>> -	weston_pointer_start_grab(seat->pointer,
>> +	weston_pointer_start_grab(pointer,
>>  	                          &shell->exposay.grab_ptr);
>> -	weston_pointer_set_focus(seat->pointer, NULL,
>> -			         seat->pointer->x, seat->pointer->y);
>> +	weston_pointer_set_focus(pointer, NULL,
>> +			         pointer->x, pointer->y);
>>  
>>  	wl_list_for_each(shell_output, &shell->output_list, link) {
>>  		enum exposay_layout_state state;
>> diff --git a/desktop-shell/input-panel.c b/desktop-shell/input-panel.c
>> index ffa3ade..1c2d08b 100644
>> --- a/desktop-shell/input-panel.c
>> +++ b/desktop-shell/input-panel.c
>> @@ -66,9 +66,12 @@ show_input_panel_surface(struct input_panel_surface *ipsurf)
>>  	float x, y;
>>  
>>  	wl_list_for_each(seat, &shell->compositor->seat_list, link) {
>> -		if (!seat->keyboard || !seat->keyboard->focus)
>> +		struct weston_keyboard *keyboard =
>> +						weston_seat_get_keyboard(seat);
> 
> nit: Indentation wrong. The overwhelming way of indenting \n after = is
> with one extra tab. Try "grep -r --include="*.c" -A1 -e ' =$' weston/".

Thanks, I'll update.

> nit2: What was the conclusion of the can-we-declare-in-sub-blocks? I
> remember it was discussed not too long ago, but don't remember the
> conclusion.

Wow, is there really an argument over that?  There are certainly
occurrences of it already, but I'll take these out if I have to.

>> +
>> +		if (!keyboard || !keyboard->focus)
>>  			continue;
>> -		focus = weston_surface_get_main_surface(seat->keyboard->focus);
>> +		focus = weston_surface_get_main_surface(keyboard->focus);
>>  		ipsurf->output = focus->output;
>>  		x = ipsurf->output->x + (ipsurf->output->width - ipsurf->surface->width) / 2;
>>  		y = ipsurf->output->y + ipsurf->output->height - ipsurf->surface->height;
>> diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
>> index 5f54dea..07068a8 100644
>> --- a/desktop-shell/shell.c
>> +++ b/desktop-shell/shell.c
>> @@ -360,10 +360,11 @@ shell_grab_start(struct shell_grab *grab,
>>  		 enum desktop_shell_cursor cursor)
>>  {
>>  	struct desktop_shell *shell = shsurf->shell;
>> +	struct weston_touch *touch = weston_seat_get_touch(pointer->seat);
>>  
>>  	popup_grab_end(pointer);
>> -	if (pointer->seat->touch)
>> -		touch_popup_grab_end(pointer->seat->touch);
>> +	if (touch)
>> +		touch_popup_grab_end(touch);
>>  
>>  	grab->grab.interface = interface;
>>  	grab->shsurf = shsurf;
>> @@ -527,10 +528,11 @@ shell_touch_grab_start(struct shell_touch_grab *grab,
>>  		       struct weston_touch *touch)
>>  {
>>  	struct desktop_shell *shell = shsurf->shell;
>> +	struct weston_pointer *pointer = weston_seat_get_pointer(touch->seat);
>>  
>>  	touch_popup_grab_end(touch);
>> -	if (touch->seat->pointer)
>> -		popup_grab_end(touch->seat->pointer);
>> +	if (pointer)
>> +		popup_grab_end(pointer);
>>  
>>  	grab->grab.interface = interface;
>>  	grab->shsurf = shsurf;
>> @@ -889,27 +891,33 @@ restore_focus_state(struct desktop_shell *shell, struct workspace *ws)
>>  	wl_list_init(&shell->compositor->seat_list);
>>  
>>  	wl_list_for_each_safe(state, next, &ws->focus_list, link) {
>> +		struct weston_keyboard *keyboard =
>> +					weston_seat_get_keyboard(state->seat);
> 
> nit: Same indentation inconsistency as above.
> 
>> +
>>  		wl_list_remove(&state->seat->link);
>>  		wl_list_insert(&shell->compositor->seat_list,
>>  			       &state->seat->link);
>>  
>> -		if (state->seat->keyboard == NULL)
>> +		if (!keyboard)
>>  			continue;
>>  
>>  		surface = state->keyboard_focus;
>>  
>> -		weston_keyboard_set_focus(state->seat->keyboard, surface);
>> +		weston_keyboard_set_focus(keyboard, surface);
>>  	}
>>  
>>  	/* For any remaining seats that we don't have a focus state
>>  	 * for we'll reset the keyboard focus to NULL */
>>  	wl_list_for_each_safe(seat, next_seat, &pending_seat_list, link) {
>> +		struct weston_keyboard *keyboard =
>> +						weston_seat_get_keyboard(seat);
> 
> nit: Same indentation inconsistency as above.
> 
>> +
>>  		wl_list_insert(&shell->compositor->seat_list, &seat->link);
>>  
>> -		if (seat->keyboard == NULL)
>> +		if (!keyboard)
>>  			continue;
>>  
>> -		weston_keyboard_set_focus(seat->keyboard, NULL);
>> +		weston_keyboard_set_focus(keyboard, NULL);
>>  	}
>>  }
>>  
>> @@ -921,7 +929,10 @@ replace_focus_state(struct desktop_shell *shell, struct workspace *ws,
>>  
>>  	wl_list_for_each(state, &ws->focus_list, link) {
>>  		if (state->seat == seat) {
>> -			focus_state_set_focus(state, seat->keyboard->focus);
>> +			struct weston_keyboard *keyboard =
>> +						weston_seat_get_keyboard(seat);
> 
> nit: Same indentation inconsistency as above.
> 
>> +
>> +			focus_state_set_focus(state, keyboard->focus);
>>  			return;
>>  		}
>>  	}
>> @@ -1420,12 +1431,15 @@ move_surface_to_workspace(struct desktop_shell *shell,
>>  
>>  	drop_focus_state(shell, from, view->surface);
>>  	wl_list_for_each(seat, &shell->compositor->seat_list, link) {
>> -		if (!seat->keyboard)
>> +		struct weston_keyboard *keyboard =
>> +						weston_seat_get_keyboard(seat);
> 
> nit: Same indentation inconsistency as above.
> 
>> +
>> +		if (!keyboard)
>>  			continue;
>>  
>> -		focus = weston_surface_get_main_surface(seat->keyboard->focus);
>> +		focus = weston_surface_get_main_surface(keyboard->focus);
>>  		if (focus == view->surface)
>> -			weston_keyboard_set_focus(seat->keyboard, NULL);
>> +			weston_keyboard_set_focus(keyboard, NULL);
>>  	}
>>  
>>  	weston_view_damage_below(view);
>> @@ -1436,6 +1450,7 @@ take_surface_to_workspace_by_seat(struct desktop_shell *shell,
>>  				  struct weston_seat *seat,
>>  				  unsigned int index)
>>  {
>> +	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
>>  	struct weston_surface *surface;
>>  	struct weston_view *view;
>>  	struct shell_surface *shsurf;
>> @@ -1443,7 +1458,7 @@ take_surface_to_workspace_by_seat(struct desktop_shell *shell,
>>  	struct workspace *to;
>>  	struct focus_state *state;
>>  
>> -	surface = weston_surface_get_main_surface(seat->keyboard->focus);
>> +	surface = weston_surface_get_main_surface(keyboard->focus);
>>  	view = get_default_view(surface);
>>  	if (view == NULL ||
>>  	    index == shell->workspaces.current ||
>> @@ -1624,6 +1639,7 @@ static int
>>  surface_touch_move(struct shell_surface *shsurf, struct weston_seat *seat)
>>  {
>>  	struct weston_touch_move_grab *move;
>> +	struct weston_touch *touch = weston_seat_get_touch(seat);
>>  
>>  	if (!shsurf)
>>  		return -1;
>> @@ -1637,12 +1653,12 @@ surface_touch_move(struct shell_surface *shsurf, struct weston_seat *seat)
>>  
>>  	move->active = 1;
>>  	move->dx = wl_fixed_from_double(shsurf->view->geometry.x) -
>> -			seat->touch->grab_x;
>> +					touch->grab_x;
>>  	move->dy = wl_fixed_from_double(shsurf->view->geometry.y) -
>> -			seat->touch->grab_y;
>> +					touch->grab_y;
>>  
>>  	shell_touch_grab_start(&move->base, &touch_move_grab_interface, shsurf,
>> -			       seat->touch);
>> +			       touch);
> 
> Same issue regarding potential NULL pointer reference here.

I can't follow the failure.  This is called from two paths, one through
a touch binding that will be fine, the other through
common_surface_move() which tests seat->touch before it gets here?

>>  
>>  	return 0;
>>  }
>> @@ -1738,6 +1754,7 @@ static int
>>  surface_move(struct shell_surface *shsurf, struct weston_seat *seat,
>>  	     int client_initiated)
>>  {
>> +	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>>  	struct weston_move_grab *move;
>>  
>>  	if (!shsurf)
>> @@ -1752,13 +1769,13 @@ surface_move(struct shell_surface *shsurf, struct weston_seat *seat,
>>  		return -1;
>>  
>>  	move->dx = wl_fixed_from_double(shsurf->view->geometry.x) -
>> -			seat->pointer->grab_x;
>> +					pointer->grab_x;
>>  	move->dy = wl_fixed_from_double(shsurf->view->geometry.y) -
>> -			seat->pointer->grab_y;
>> +					pointer->grab_y;
>>  	move->client_initiated = client_initiated;
>>  
>>  	shell_grab_start(&move->base, &move_grab_interface, shsurf,
>> -			 seat->pointer, DESKTOP_SHELL_CURSOR_MOVE);
>> +			 pointer, DESKTOP_SHELL_CURSOR_MOVE);
> 
> Potential NULL pointer dereference when the surface_move call originates
> from the Xwayland window manager.

As with exposay, I think this is a bug already?  Do we need to fix this
before the release?  I don't know how to get the xwm to move a window.

I tried using xdotool to move the window, but it's completely ignored.

If we don't need to fix this immediately, I'll just add a test for NULL
to the next revision of this patch.

>>  
>>  	return 0;
>>  }
>> @@ -1768,21 +1785,23 @@ common_surface_move(struct wl_resource *resource,
>>  		    struct wl_resource *seat_resource, uint32_t serial)
>>  {
>>  	struct weston_seat *seat = wl_resource_get_user_data(seat_resource);
>> +	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>> +	struct weston_touch *touch = weston_seat_get_touch(seat);
>>  	struct shell_surface *shsurf = wl_resource_get_user_data(resource);
>>  	struct weston_surface *surface;
>>  
>> -	if (seat->pointer &&
>> -	    seat->pointer->focus &&
>> -	    seat->pointer->button_count > 0 &&
>> -	    seat->pointer->grab_serial == serial) {
>> -		surface = weston_surface_get_main_surface(seat->pointer->focus->surface);
>> +	if (pointer &&
>> +	    pointer->focus &&
>> +	    pointer->button_count > 0 &&
>> +	    pointer->grab_serial == serial) {
>> +		surface = weston_surface_get_main_surface(pointer->focus->surface);
>>  		if ((surface == shsurf->surface) &&
>>  		    (surface_move(shsurf, seat, 1) < 0))
>>  			wl_resource_post_no_memory(resource);
>> -	} else if (seat->touch &&
>> -		   seat->touch->focus &&
>> -		   seat->touch->grab_serial == serial) {
>> -		surface = weston_surface_get_main_surface(seat->touch->focus->surface);
>> +	} else if (touch &&
>> +		   touch->focus &&
>> +		   touch->grab_serial == serial) {
>> +		surface = weston_surface_get_main_surface(touch->focus->surface);
>>  		if ((surface == shsurf->surface) &&
>>  		    (surface_touch_move(shsurf, seat) < 0))
>>  			wl_resource_post_no_memory(resource);
>> @@ -1932,6 +1951,7 @@ static int
>>  surface_resize(struct shell_surface *shsurf,
>>  	       struct weston_seat *seat, uint32_t edges)
>>  {
>> +	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>>  	struct weston_resize_grab *resize;
>>  	const unsigned resize_topbottom =
>>  		WL_SHELL_SURFACE_RESIZE_TOP | WL_SHELL_SURFACE_RESIZE_BOTTOM;
>> @@ -1961,7 +1981,7 @@ surface_resize(struct shell_surface *shsurf,
>>  	shsurf->resize_edges = edges;
>>  	shell_surface_state_changed(shsurf);
>>  	shell_grab_start(&resize->base, &resize_grab_interface, shsurf,
>> -			 seat->pointer, edges);
>> +			 pointer, edges);
> 
> Potential NULL pointer dereference. Same as for surface_move.
> 
>>  
>>  	return 0;
>>  }
>> @@ -1973,15 +1993,16 @@ common_surface_resize(struct wl_resource *resource,
>>  {
>>  	struct weston_seat *seat = wl_resource_get_user_data(seat_resource);
>>  	struct shell_surface *shsurf = wl_resource_get_user_data(resource);
>> +	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>>  	struct weston_surface *surface;
>>  
>> -	if (seat->pointer == NULL ||
>> -	    seat->pointer->button_count == 0 ||
>> -	    seat->pointer->grab_serial != serial ||
>> -	    seat->pointer->focus == NULL)
>> +	if (!pointer ||
>> +	    pointer->button_count == 0 ||
>> +	    pointer->grab_serial != serial ||
>> +	    pointer->focus == NULL)
>>  		return;
>>  
>> -	surface = weston_surface_get_main_surface(seat->pointer->focus->surface);
>> +	surface = weston_surface_get_main_surface(pointer->focus->surface);
>>  	if (surface != shsurf->surface)
>>  		return;
>>  
>> @@ -2081,10 +2102,12 @@ end_busy_cursor(struct weston_compositor *compositor, struct wl_client *client)
>>  	struct weston_seat *seat;
>>  
>>  	wl_list_for_each(seat, &compositor->seat_list, link) {
>> -		if (seat->pointer == NULL)
>> +		struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>> +
>> +		if (!pointer)
>>  			continue;
>>  
>> -		grab = (struct shell_grab *) seat->pointer->grab;
>> +		grab = (struct shell_grab *)pointer->grab;
>>  		if (grab->grab.interface == &busy_cursor_grab_interface &&
>>  		    wl_resource_get_client(grab->shsurf->resource) == client) {
>>  			shell_grab_end(grab);
>> @@ -2106,15 +2129,17 @@ xdg_ping_timeout_handler(void *data)
>>  	/* Client is not responding */
>>  	sc->unresponsive = 1;
>>  	wl_list_for_each(seat, &sc->shell->compositor->seat_list, link) {
>> -		if (seat->pointer == NULL || seat->pointer->focus == NULL)
>> +		struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>> +
>> +		if (!pointer || pointer->focus == NULL)
>>  			continue;
>> -		if (seat->pointer->focus->surface->resource == NULL)
>> +		if (pointer->focus->surface->resource == NULL)
>>  			continue;
>> -		
>> -		shsurf = get_shell_surface(seat->pointer->focus->surface);
>> +
>> +		shsurf = get_shell_surface(pointer->focus->surface);
>>  		if (shsurf &&
>>  		    wl_resource_get_client(shsurf->resource) == sc->client)
>> -			set_busy_cursor(shsurf, seat->pointer);
>> +			set_busy_cursor(shsurf, pointer);
>>  	}
>>  
>>  	return 1;
>> @@ -2669,11 +2694,14 @@ set_minimized(struct weston_surface *surface)
>>  
>>  	drop_focus_state(shsurf->shell, current_ws, view->surface);
>>  	wl_list_for_each(seat, &shsurf->shell->compositor->seat_list, link) {
>> -		if (!seat->keyboard)
>> +		struct weston_keyboard *keyboard =
>> +					weston_seat_get_keyboard(seat);
> 
> nit: Same indentation inconsistency as above.
> 
>> +
>> +		if (!keyboard)
>>  			continue;
>> -		focus = weston_surface_get_main_surface(seat->keyboard->focus);
>> +		focus = weston_surface_get_main_surface(keyboard->focus);
>>  		if (focus == view->surface)
>> -			weston_keyboard_set_focus(seat->keyboard, NULL);
>> +			weston_keyboard_set_focus(keyboard, NULL);
>>  	}
>>  
>>  	shell_surface_update_child_surface_layers(shsurf);
>> @@ -3004,17 +3032,22 @@ get_focused_output(struct weston_compositor *compositor)
>>  	struct weston_output *output = NULL;
>>  
>>  	wl_list_for_each(seat, &compositor->seat_list, link) {
>> +		struct weston_touch *touch = weston_seat_get_touch(seat);
>> +		struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>> +		struct weston_keyboard *keyboard =
>> +						weston_seat_get_keyboard(seat);
> 
> nit: Same indentation inconsistency as above.
> 
>> +
>>  		/* Priority has touch focus, then pointer and
>>  		 * then keyboard focus. We should probably have
>>  		 * three for loops and check frist for touch,
>>  		 * then for pointer, etc. but unless somebody has some
>>  		 * objections, I think this is sufficient. */
>> -		if (seat->touch && seat->touch->focus)
>> -			output = seat->touch->focus->output;
>> -		else if (seat->pointer && seat->pointer->focus)
>> -			output = seat->pointer->focus->output;
>> -		else if (seat->keyboard && seat->keyboard->focus)
>> -			output = seat->keyboard->focus->output;
>> +		if (touch && touch->focus)
>> +			output = touch->focus->output;
>> +		else if (pointer && pointer->focus)
>> +			output = pointer->focus->output;
>> +		else if (keyboard && keyboard->focus)
>> +			output = keyboard->focus->output;
>>  
>>  		if (output)
>>  			break;
>> @@ -3081,19 +3114,22 @@ shell_seat_caps_changed(struct wl_listener *listener, void *data)
>>  
>>  	seat = container_of(listener, struct shell_seat, caps_changed_listener);
>>  
>> -	if (seat->seat->keyboard &&
>> +	/* this is one of the few places where seat->keyboard_resource and
>> +	 * seat->pointer_resource should be tested directly, instead of
>> +	 * through weston_seat_get_* */
> 
> Should these maybe be a separate patch?
> 
>> +	if (seat->seat->keyboard_resource &&
>>  	    wl_list_empty(&seat->keyboard_focus_listener.link)) {
>> -		wl_signal_add(&seat->seat->keyboard->focus_signal,
>> +		wl_signal_add(&seat->seat->keyboard_resource->focus_signal,
>>  			      &seat->keyboard_focus_listener);
>> -	} else if (!seat->seat->keyboard) {
>> +	} else if (!seat->seat->keyboard_resource) {
>>  		wl_list_init(&seat->keyboard_focus_listener.link);
>>  	}
>>  
>> -	if (seat->seat->pointer &&
>> +	if (seat->seat->pointer_resource &&
>>  	    wl_list_empty(&seat->pointer_focus_listener.link)) {
>> -		wl_signal_add(&seat->seat->pointer->focus_signal,
>> +		wl_signal_add(&seat->seat->pointer_resource->focus_signal,
>>  			      &seat->pointer_focus_listener);
>> -	} else if (!seat->seat->pointer) {
>> +	} else if (!seat->seat->pointer_resource) {
>>  		wl_list_init(&seat->pointer_focus_listener.link);
>>  	}
>>  }
>> @@ -3197,6 +3233,7 @@ popup_grab_button(struct weston_pointer_grab *grab,
>>  	struct shell_seat *shseat =
>>  	    container_of(grab, struct shell_seat, popup_grab.grab);
>>  	struct wl_display *display = shseat->seat->compositor->wl_display;
>> +	struct weston_pointer *pointer = weston_seat_get_pointer(shseat->seat);
>>  	enum wl_pointer_button_state state = state_w;
>>  	uint32_t serial;
>>  	struct wl_list *resource_list;
>> @@ -3210,7 +3247,7 @@ popup_grab_button(struct weston_pointer_grab *grab,
>>  		}
>>  	} else if (state == WL_POINTER_BUTTON_STATE_RELEASED &&
>>  		   (shseat->popup_grab.initial_up ||
>> -		    time - shseat->seat->pointer->grab_time > 500)) {
>> +		    time - pointer->grab_time > 500)) {
>>  		popup_grab_end(grab->pointer);
>>  	}
>>  
>> @@ -3389,6 +3426,8 @@ add_popup_grab(struct shell_surface *shsurf,
>>  {
>>  	struct weston_seat *seat = shseat->seat;
>>  	struct shell_surface *parent, *top_surface;
>> +	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>> +	struct weston_touch *touch = weston_seat_get_touch(seat);
>>  
>>  	parent = get_shell_surface(shsurf->parent);
>>  	top_surface = get_top_popup(shseat);
>> @@ -3415,7 +3454,7 @@ add_popup_grab(struct shell_surface *shsurf,
>>  			/* We must make sure here that this popup was opened
>>  			 * after a mouse press, and not just by moving around
>>  			 * with other popups already open. */
>> -			if (shseat->seat->pointer->button_count > 0)
>> +			if (pointer->button_count > 0)
>>  				shseat->popup_grab.initial_up = 0;
>>  		} else if (type == TOUCH) {
>>  			shseat->popup_grab.touch_grab.interface =
>> @@ -3426,10 +3465,10 @@ add_popup_grab(struct shell_surface *shsurf,
>>  			       &shsurf->popup.grab_link);
>>  
>>  		if (type == POINTER) {
>> -			weston_pointer_start_grab(seat->pointer,
>> +			weston_pointer_start_grab(pointer,
>>  						  &shseat->popup_grab.grab);
>>  		} else if (type == TOUCH) {
>> -			weston_touch_start_grab(seat->touch,
>> +			weston_touch_start_grab(touch,
>>  						&shseat->popup_grab.touch_grab);
>>  		}
>>  	} else {
>> @@ -3472,6 +3511,8 @@ shell_map_popup(struct shell_surface *shsurf)
>>  {
>>  	struct shell_seat *shseat = shsurf->popup.shseat;
>>  	struct weston_view *parent_view = get_default_view(shsurf->parent);
>> +	struct weston_pointer *pointer = weston_seat_get_pointer(shseat->seat);
>> +	struct weston_touch *touch = weston_seat_get_touch(shseat->seat);
>>  
>>  	shsurf->surface->output = parent_view->output;
>>  	shsurf->view->output = parent_view->output;
>> @@ -3480,12 +3521,10 @@ shell_map_popup(struct shell_surface *shsurf)
>>  	weston_view_set_position(shsurf->view, shsurf->popup.x, shsurf->popup.y);
>>  	weston_view_update_transform(shsurf->view);
>>  
>> -	if (shseat->seat->pointer &&
>> -	    shseat->seat->pointer->grab_serial == shsurf->popup.serial) {
>> +	if (pointer && pointer->grab_serial == shsurf->popup.serial) {
>>  		if (add_popup_grab(shsurf, shseat, POINTER) != 0)
>>  			return -1;
>> -	} else if (shseat->seat->touch &&
>> -	           shseat->seat->touch->grab_serial == shsurf->popup.serial) {
>> +	} else if (touch && touch->grab_serial == shsurf->popup.serial) {
>>  		if (add_popup_grab(shsurf, shseat, TOUCH) != 0)
>>  			return -1;
>>  	} else {
>> @@ -4599,14 +4638,15 @@ get_shell_surface_type(struct weston_surface *surface)
>>  static void
>>  move_binding(struct weston_seat *seat, uint32_t time, uint32_t button, void *data)
>>  {
>> +	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>>  	struct weston_surface *focus;
>>  	struct weston_surface *surface;
>>  	struct shell_surface *shsurf;
>>  
>> -	if (seat->pointer->focus == NULL)
>> +	if (pointer->focus == NULL)
>>  		return;
>>  
>> -	focus = seat->pointer->focus->surface;
>> +	focus = pointer->focus->surface;
>>  
>>  	surface = weston_surface_get_main_surface(focus);
>>  	if (surface == NULL)
>> @@ -4623,7 +4663,8 @@ move_binding(struct weston_seat *seat, uint32_t time, uint32_t button, void *dat
>>  static void
>>  maximize_binding(struct weston_seat *seat, uint32_t time, uint32_t button, void *data)
>>  {
>> -	struct weston_surface *focus = seat->keyboard->focus;
>> +	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
>> +	struct weston_surface *focus = keyboard->focus;
>>  	struct weston_surface *surface;
>>  	struct shell_surface *shsurf;
>>  
>> @@ -4646,7 +4687,8 @@ maximize_binding(struct weston_seat *seat, uint32_t time, uint32_t button, void
>>  static void
>>  fullscreen_binding(struct weston_seat *seat, uint32_t time, uint32_t button, void *data)
>>  {
>> -	struct weston_surface *focus = seat->keyboard->focus;
>> +	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
>> +	struct weston_surface *focus = keyboard->focus;
>>  	struct weston_surface *surface;
>>  	struct shell_surface *shsurf;
>>  
>> @@ -4673,11 +4715,12 @@ touch_move_binding(struct weston_seat *seat, uint32_t time, void *data)
>>  	struct weston_surface *focus;
>>  	struct weston_surface *surface;
>>  	struct shell_surface *shsurf;
>> +	struct weston_touch *touch = weston_seat_get_touch(seat);
>>  
>> -	if (seat->touch->focus == NULL)
>> +	if (touch->focus == NULL)
>>  		return;
>>  
>> -	focus = seat->touch->focus->surface;
>> +	focus = touch->focus->surface;
>>  	surface = weston_surface_get_main_surface(focus);
>>  	if (surface == NULL)
>>  		return;
>> @@ -4695,14 +4738,15 @@ resize_binding(struct weston_seat *seat, uint32_t time, uint32_t button, void *d
>>  {
>>  	struct weston_surface *focus;
>>  	struct weston_surface *surface;
>> +	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>>  	uint32_t edges = 0;
>>  	int32_t x, y;
>>  	struct shell_surface *shsurf;
>>  
>> -	if (seat->pointer->focus == NULL)
>> +	if (pointer->focus == NULL)
>>  		return;
>>  
>> -	focus = seat->pointer->focus->surface;
>> +	focus = pointer->focus->surface;
>>  
>>  	surface = weston_surface_get_main_surface(focus);
>>  	if (surface == NULL)
>> @@ -4714,8 +4758,8 @@ resize_binding(struct weston_seat *seat, uint32_t time, uint32_t button, void *d
>>  		return;
>>  
>>  	weston_view_from_global(shsurf->view,
>> -				wl_fixed_to_int(seat->pointer->grab_x),
>> -				wl_fixed_to_int(seat->pointer->grab_y),
>> +				wl_fixed_to_int(pointer->grab_x),
>> +				wl_fixed_to_int(pointer->grab_y),
>>  				&x, &y);
>>  
>>  	if (x < shsurf->surface->width / 3)
>> @@ -4741,7 +4785,8 @@ surface_opacity_binding(struct weston_seat *seat, uint32_t time, uint32_t axis,
>>  {
>>  	float step = 0.005;
>>  	struct shell_surface *shsurf;
>> -	struct weston_surface *focus = seat->pointer->focus->surface;
>> +	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>> +	struct weston_surface *focus = pointer->focus->surface;
>>  	struct weston_surface *surface;
>>  
>>  	/* XXX: broken for windows containing sub-surfaces */
>> @@ -4769,18 +4814,19 @@ do_zoom(struct weston_seat *seat, uint32_t time, uint32_t key, uint32_t axis,
>>  	wl_fixed_t value)
>>  {
>>  	struct weston_compositor *compositor = seat->compositor;
>> +	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>>  	struct weston_output *output;
>>  	float increment;
>>  
>> -	if (!seat->pointer) {
>> +	if (!pointer) {
>>  		weston_log("Zoom hotkey pressed but seat '%s' contains no pointer.\n", seat->seat_name);
>>  		return;
>>  	}
>>  
>>  	wl_list_for_each(output, &compositor->output_list, link) {
>>  		if (pixman_region32_contains_point(&output->region,
>> -						   wl_fixed_to_double(seat->pointer->x),
>> -						   wl_fixed_to_double(seat->pointer->y),
>> +						   wl_fixed_to_double(pointer->x),
>> +						   wl_fixed_to_double(pointer->y),
>>  						   NULL)) {
>>  			if (key == KEY_PAGEUP)
>>  				increment = output->zoom.increment;
>> @@ -4938,6 +4984,7 @@ static const struct weston_pointer_grab_interface rotate_grab_interface = {
>>  static void
>>  surface_rotate(struct shell_surface *surface, struct weston_seat *seat)
>>  {
>> +	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>>  	struct rotate_grab *rotate;
>>  	float dx, dy;
>>  	float r;
>> @@ -4951,8 +4998,8 @@ surface_rotate(struct shell_surface *surface, struct weston_seat *seat)
>>  				    surface->surface->height * 0.5f,
>>  				    &rotate->center.x, &rotate->center.y);
>>  
>> -	dx = wl_fixed_to_double(seat->pointer->x) - rotate->center.x;
>> -	dy = wl_fixed_to_double(seat->pointer->y) - rotate->center.y;
>> +	dx = wl_fixed_to_double(pointer->x) - rotate->center.x;
>> +	dy = wl_fixed_to_double(pointer->y) - rotate->center.y;
>>  	r = sqrtf(dx * dx + dy * dy);
>>  	if (r > 20.0f) {
>>  		struct weston_matrix inverse;
>> @@ -4969,7 +5016,7 @@ surface_rotate(struct shell_surface *surface, struct weston_seat *seat)
>>  	}
>>  
>>  	shell_grab_start(&rotate->base, &rotate_grab_interface, surface,
>> -			 seat->pointer, DESKTOP_SHELL_CURSOR_ARROW);
>> +			 pointer, DESKTOP_SHELL_CURSOR_ARROW);
>>  }
>>  
>>  static void
>> @@ -4979,11 +5026,12 @@ rotate_binding(struct weston_seat *seat, uint32_t time, uint32_t button,
>>  	struct weston_surface *focus;
>>  	struct weston_surface *base_surface;
>>  	struct shell_surface *surface;
>> +	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>>  
>> -	if (seat->pointer->focus == NULL)
>> +	if (pointer->focus == NULL)
>>  		return;
>>  
>> -	focus = seat->pointer->focus->surface;
>> +	focus = pointer->focus->surface;
>>  
>>  	base_surface = weston_surface_get_main_surface(focus);
>>  	if (base_surface == NULL)
>> @@ -5121,23 +5169,27 @@ static void
>>  click_to_activate_binding(struct weston_seat *seat, uint32_t time, uint32_t button,
>>  			  void *data)
>>  {
>> -	if (seat->pointer->grab != &seat->pointer->default_grab)
>> +	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>> +
>> +	if (pointer->grab != &pointer->default_grab)
>>  		return;
>> -	if (seat->pointer->focus == NULL)
>> +	if (pointer->focus == NULL)
>>  		return;
>>  
>> -	activate_binding(seat, data, seat->pointer->focus->surface);
>> +	activate_binding(seat, data, pointer->focus->surface);
>>  }
>>  
>>  static void
>>  touch_to_activate_binding(struct weston_seat *seat, uint32_t time, void *data)
>>  {
>> -	if (seat->touch->grab != &seat->touch->default_grab)
>> +	struct weston_touch *touch = weston_seat_get_touch(seat);
>> +
>> +	if (touch->grab != &touch->default_grab)
>>  		return;
>> -	if (seat->touch->focus == NULL)
>> +	if (touch->focus == NULL)
>>  		return;
>>  
>> -	activate_binding(seat, data, seat->touch->focus->surface);
>> +	activate_binding(seat, data, touch->focus->surface);
>>  }
>>  
>>  static void
>> @@ -5146,10 +5198,13 @@ unfocus_all_seats(struct desktop_shell *shell)
>>  	struct weston_seat *seat, *next;
>>  
>>  	wl_list_for_each_safe(seat, next, &shell->compositor->seat_list, link) {
>> -		if (seat->keyboard == NULL)
>> +		struct weston_keyboard *keyboard =
>> +						weston_seat_get_keyboard(seat);
> 
> nit: Same indentation inconsistency as above.
> 
>> +
>> +		if (!keyboard)
>>  			continue;
>>  
>> -		weston_keyboard_set_focus(seat->keyboard, NULL);
>> +		weston_keyboard_set_focus(keyboard, NULL);
>>  	}
>>  }
>>  
>> @@ -5377,10 +5432,14 @@ idle_handler(struct wl_listener *listener, void *data)
>>  	struct weston_seat *seat;
>>  
>>  	wl_list_for_each(seat, &shell->compositor->seat_list, link) {
>> -		if (seat->pointer)
>> -			popup_grab_end(seat->pointer);
>> -		if (seat->touch)
>> -			touch_popup_grab_end(seat->touch);
>> +		struct weston_touch *touch = weston_seat_get_touch(seat);
>> +		struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>> +
>> +		if (pointer)
>> +			popup_grab_end(pointer);
>> +
>> +		if (touch)
>> +			touch_popup_grab_end(touch);
>>  	}
>>  
>>  	shell_fade(shell, FADE_OUT);
>> @@ -5428,9 +5487,11 @@ weston_view_set_initial_position(struct weston_view *view,
>>  	 * TODO: Do something clever for touch too?
>>  	 */
>>  	wl_list_for_each(seat, &compositor->seat_list, link) {
>> -		if (seat->pointer) {
>> -			ix = wl_fixed_to_int(seat->pointer->x);
>> -			iy = wl_fixed_to_int(seat->pointer->y);
>> +		struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>> +
>> +		if (pointer) {
>> +			ix = wl_fixed_to_int(pointer->x);
>> +			iy = wl_fixed_to_int(pointer->y);
>>  			break;
>>  		}
>>  	}
>> @@ -6112,6 +6173,7 @@ switcher_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
>>  {
>>  	struct desktop_shell *shell = data;
>>  	struct switcher *switcher;
>> +	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
>>  
>>  	switcher = malloc(sizeof *switcher);
>>  	switcher->shell = shell;
>> @@ -6123,8 +6185,8 @@ switcher_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
>>  	restore_all_output_modes(shell->compositor);
>>  	lower_fullscreen_layer(switcher->shell);
>>  	switcher->grab.interface = &switcher_grab;
>> -	weston_keyboard_start_grab(seat->keyboard, &switcher->grab);
>> -	weston_keyboard_set_focus(seat->keyboard, NULL);
>> +	weston_keyboard_start_grab(keyboard, &switcher->grab);
>> +	weston_keyboard_set_focus(keyboard, NULL);
>>  	switcher_next(switcher);
>>  }
>>  
>> @@ -6165,13 +6227,13 @@ static void
>>  force_kill_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
>>  		   void *data)
>>  {
>> -	struct weston_surface *focus_surface;
>> +	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
>> +	struct weston_surface *focus_surface = keyboard->focus;
>>  	struct wl_client *client;
>>  	struct desktop_shell *shell = data;
>>  	struct weston_compositor *compositor = shell->compositor;
>>  	pid_t pid;
>>  
>> -	focus_surface = seat->keyboard->focus;
>>  	if (!focus_surface)
>>  		return;
>>  
>> diff --git a/fullscreen-shell/fullscreen-shell.c b/fullscreen-shell/fullscreen-shell.c
>> index 35e6d8f..546daeb 100644
>> --- a/fullscreen-shell/fullscreen-shell.c
>> +++ b/fullscreen-shell/fullscreen-shell.c
>> @@ -95,12 +95,16 @@ seat_caps_changed(struct wl_listener *l, void *data)
>>  	struct pointer_focus_listener *listener;
>>  	struct fs_output *fsout;
>>  
>> +	/* This function is one of the few places where seat->pointer_resource
>> +	 * and seat->keyboard_resource should be tested directly instead of
>> +	 * seat->*_device_count.
>> +	 */
>>  	listener = container_of(l, struct pointer_focus_listener, seat_caps);
>>  
>>  	/* no pointer */
>> -	if (seat->pointer) {
>> +	if (seat->pointer_resource) {
>>  		if (!listener->pointer_focus.link.prev) {
>> -			wl_signal_add(&seat->pointer->focus_signal,
>> +			wl_signal_add(&seat->pointer_resource->focus_signal,
>>  				      &listener->pointer_focus);
>>  		}
>>  	} else {
>> @@ -109,7 +113,8 @@ seat_caps_changed(struct wl_listener *l, void *data)
>>  		}
>>  	}
>>  
>> -	if (seat->keyboard && seat->keyboard->focus != NULL) {
>> +	if (seat->keyboard_resource &&
>> +	    seat->keyboard_resource->focus != NULL) {
>>  		wl_list_for_each(fsout, &listener->shell->output_list, link) {
>>  			if (fsout->surface) {
>>  				weston_surface_activate(fsout->surface, seat);
>> @@ -677,7 +682,10 @@ fullscreen_shell_present_surface(struct wl_client *client,
>>  
>>  	if (surface) {
>>  		wl_list_for_each(seat, &shell->compositor->seat_list, link) {
>> -			if (seat->keyboard && seat->keyboard->focus == NULL)
>> +			struct weston_keyboard *keyboard =
>> +						weston_seat_get_keyboard(seat);
> 
> nit: Same indentation inconsistency as above.
> 
>> +
>> +			if (keyboard && keyboard->focus == NULL)
>>  				weston_surface_activate(surface, seat);
>>  		}
>>  	}
>> @@ -725,7 +733,10 @@ fullscreen_shell_present_surface_for_mode(struct wl_client *client,
>>  				       fsout, mode_feedback_destroyed);
>>  
>>  	wl_list_for_each(seat, &shell->compositor->seat_list, link) {
>> -		if (seat->keyboard && seat->keyboard->focus == NULL)
>> +		struct weston_keyboard *keyboard =
>> +						weston_seat_get_keyboard(seat);
> 
> nit: Same indentation inconsistency as above.
> 
>> +
>> +		if (keyboard && keyboard->focus == NULL)
>>  			weston_surface_activate(surface, seat);
>>  	}
>>  }
>> diff --git a/ivi-shell/hmi-controller.c b/ivi-shell/hmi-controller.c
>> index cd79c38..1f02cbf 100644
>> --- a/ivi-shell/hmi-controller.c
>> +++ b/ivi-shell/hmi-controller.c
>> @@ -1465,15 +1465,18 @@ enum HMI_GRAB_DEVICE {
>>  static enum HMI_GRAB_DEVICE
>>  get_hmi_grab_device(struct weston_seat *seat, uint32_t serial)
>>  {
>> -	if (seat->pointer &&
>> -	    seat->pointer->focus &&
>> -	    seat->pointer->button_count &&
>> -	    seat->pointer->grab_serial == serial)
>> +	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>> +	struct weston_touch *touch = weston_seat_get_touch(seat);
>> +
>> +	if (pointer &&
>> +	    pointer->focus &&
>> +	    pointer->button_count &&
>> +	    pointer->grab_serial == serial)
>>  		return HMI_GRAB_DEVICE_POINTER;
>>  
>> -	if (seat->touch &&
>> -	    seat->touch->focus &&
>> -	    seat->touch->grab_serial == serial)
>> +	if (touch &&
>> +	    touch->focus &&
>> +	    touch->grab_serial == serial)
>>  		return HMI_GRAB_DEVICE_TOUCH;
>>  
>>  	return HMI_GRAB_DEVICE_NONE;
>> @@ -1581,24 +1584,28 @@ ivi_hmi_controller_workspace_control(struct wl_client *client,
>>  	ivi_controller_interface->transition_move_layer_cancel(layer);
>>  
>>  	switch (device) {
>> -	case HMI_GRAB_DEVICE_POINTER:
>> -		pnt_move_grab = create_workspace_pointer_move(seat->pointer,
>> +	case HMI_GRAB_DEVICE_POINTER: {
>> +		struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>> +
>> +		pnt_move_grab = create_workspace_pointer_move(pointer,
>>  							      resource);
>>  
>>  		pointer_grab_start(&pnt_move_grab->base, layer,
>>  				   &pointer_move_grab_workspace_interface,
>> -				   seat->pointer);
>> +				   pointer);
>>  		break;
>> +	}
>> +	case HMI_GRAB_DEVICE_TOUCH: {
>> +		struct weston_touch *touch = weston_seat_get_touch(seat);
>>  
>> -	case HMI_GRAB_DEVICE_TOUCH:
>> -		tch_move_grab = create_workspace_touch_move(seat->touch,
>> +		tch_move_grab = create_workspace_touch_move(touch,
>>  							    resource);
>>  
>>  		touch_grab_start(&tch_move_grab->base, layer,
>>  				 &touch_move_grab_workspace_interface,
>> -				 seat->touch);
>> +				 touch);
>>  		break;
>> -
>> +	}
>>  	default:
>>  		break;
>>  	}
>> diff --git a/ivi-shell/input-panel-ivi.c b/ivi-shell/input-panel-ivi.c
>> index 6b89177..164408c 100644
>> --- a/ivi-shell/input-panel-ivi.c
>> +++ b/ivi-shell/input-panel-ivi.c
>> @@ -66,9 +66,12 @@ show_input_panel_surface(struct input_panel_surface *ipsurf)
>>  	float x, y;
>>  
>>  	wl_list_for_each(seat, &shell->compositor->seat_list, link) {
>> -		if (!seat->keyboard || !seat->keyboard->focus)
>> +		struct weston_keyboard *keyboard =
>> +						weston_seat_get_keyboard(seat);
> 
> nit: Same indentation inconsistency as above.
> 
>> +
>> +		if (!keyboard || !keyboard->focus)
>>  			continue;
>> -		focus = weston_surface_get_main_surface(seat->keyboard->focus);
>> +		focus = weston_surface_get_main_surface(keyboard->focus);
>>  		ipsurf->output = focus->output;
>>  		x = ipsurf->output->x + (ipsurf->output->width - ipsurf->surface->width) / 2;
>>  		y = ipsurf->output->y + ipsurf->output->height - ipsurf->surface->height;
>> diff --git a/src/bindings.c b/src/bindings.c
>> index 6aeed91..c0002fd 100644
>> --- a/src/bindings.c
>> +++ b/src/bindings.c
>> @@ -254,11 +254,12 @@ install_binding_grab(struct weston_seat *seat, uint32_t time, uint32_t key,
>>                       struct weston_surface *focus)
>>  {
>>  	struct binding_keyboard_grab *grab;
>> +	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
>>  
>>  	grab = malloc(sizeof *grab);
>>  	grab->key = key;
>>  	grab->grab.interface = &binding_grab;
>> -	weston_keyboard_start_grab(seat->keyboard, &grab->grab);
>> +	weston_keyboard_start_grab(keyboard, &grab->grab);
>>  
>>  	/* Notify the surface which had the focus before this binding
>>  	 * triggered that we stole a keypress from under it, by forcing
>> @@ -268,9 +269,9 @@ install_binding_grab(struct weston_seat *seat, uint32_t time, uint32_t key,
>>  	 * If the old focus surface is different than the new one it
>>  	 * means it was changed in the binding handler, so it received
>>  	 * the enter event already. */
>> -	if (focus && seat->keyboard->focus == focus) {
>> -		weston_keyboard_set_focus(seat->keyboard, NULL);
>> -		weston_keyboard_set_focus(seat->keyboard, focus);
>> +	if (focus && keyboard->focus == focus) {
>> +		weston_keyboard_set_focus(keyboard, NULL);
>> +		weston_keyboard_set_focus(keyboard, focus);
>>  	}
>>  }
>>  
>> @@ -280,6 +281,7 @@ weston_compositor_run_key_binding(struct weston_compositor *compositor,
>>  				  uint32_t time, uint32_t key,
>>  				  enum wl_keyboard_key_state state)
>>  {
>> +	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
>>  	struct weston_binding *b, *tmp;
>>  	struct weston_surface *focus;
>>  
>> @@ -293,14 +295,14 @@ weston_compositor_run_key_binding(struct weston_compositor *compositor,
>>  	wl_list_for_each_safe(b, tmp, &compositor->key_binding_list, link) {
>>  		if (b->key == key && b->modifier == seat->modifier_state) {
>>  			weston_key_binding_handler_t handler = b->handler;
>> -			focus = seat->keyboard->focus;
>> +			focus = keyboard->focus;
>>  			handler(seat, time, key, b->data);
>>  
>>  			/* If this was a key binding and it didn't
>>  			 * install a keyboard grab, install one now to
>>  			 * swallow the key press. */
>> -			if (seat->keyboard->grab ==
>> -			    &seat->keyboard->default_grab)
>> +			if (keyboard->grab ==
>> +			    &keyboard->default_grab)
>>  				install_binding_grab(seat, time, key, focus);
>>  		}
>>  	}
>> @@ -313,8 +315,9 @@ weston_compositor_run_modifier_binding(struct weston_compositor *compositor,
>>  				       enum wl_keyboard_key_state state)
>>  {
>>  	struct weston_binding *b, *tmp;
>> +	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
>>  
>> -	if (seat->keyboard->grab != &seat->keyboard->default_grab)
>> +	if (keyboard->grab != &keyboard->default_grab)
>>  		return;
>>  
>>  	wl_list_for_each_safe(b, tmp, &compositor->modifier_binding_list, link) {
>> @@ -366,8 +369,9 @@ weston_compositor_run_touch_binding(struct weston_compositor *compositor,
>>  				    int touch_type)
>>  {
>>  	struct weston_binding *b, *tmp;
>> +	struct weston_touch *touch = weston_seat_get_touch(seat);
>>  
>> -	if (seat->touch->num_tp != 1 || touch_type != WL_TOUCH_DOWN)
>> +	if (touch->num_tp != 1 || touch_type != WL_TOUCH_DOWN)
>>  		return;
>>  
>>  	wl_list_for_each_safe(b, tmp, &compositor->touch_binding_list, link) {
>> @@ -539,6 +543,10 @@ static void
>>  debug_binding(struct weston_seat *seat, uint32_t time, uint32_t key, void *data)
>>  {
>>  	struct debug_binding_grab *grab;
>> +	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
>> +
>> +	if (!keyboard)
>> +		return;
> 
> Why add this test here? We get here through a key binding, meaning we
> just received a key. I assume we won't loose the keyboard before we have
> already passed this path?

good point.  I can't see any reason to keep that test.

>>  
>>  	grab = calloc(1, sizeof *grab);
>>  	if (!grab)
>> @@ -547,7 +555,7 @@ debug_binding(struct weston_seat *seat, uint32_t time, uint32_t key, void *data)
>>  	grab->seat = seat;
>>  	grab->key[0] = key;
>>  	grab->grab.interface = &debug_binding_keyboard_grab;
>> -	weston_keyboard_start_grab(seat->keyboard, &grab->grab);
>> +	weston_keyboard_start_grab(keyboard, &grab->grab);
>>  }
>>  
>>  /** Install the trigger binding for debug bindings.
>> diff --git a/src/compositor-drm.c b/src/compositor-drm.c
>> index 43197a8..7b1442d 100644
>> --- a/src/compositor-drm.c
>> +++ b/src/compositor-drm.c
>> @@ -1893,16 +1893,20 @@ setup_output_seat_constraint(struct drm_compositor *ec,
>>  			     const char *s)
>>  {
>>  	if (strcmp(s, "") != 0) {
>> +		struct weston_pointer *pointer;
>>  		struct udev_seat *seat;
>>  
>>  		seat = udev_seat_get_named(&ec->input, s);
>> -		if (seat)
>> -			seat->base.output = output;
>> +		if (!seat)
>> +			return;
>> +
>> +		seat->base.output = output;
>>  
>> -		if (seat && seat->base.pointer)
>> -			weston_pointer_clamp(seat->base.pointer,
>> -					     &seat->base.pointer->x,
>> -					     &seat->base.pointer->y);
>> +		pointer = weston_seat_get_pointer(&seat->base);
>> +		if (pointer)
>> +			weston_pointer_clamp(pointer,
>> +					     &pointer->x,
>> +					     &pointer->y);
>>  	}
>>  }
>>  
>> diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c
>> index 6c33361..6a86250 100644
>> --- a/src/compositor-wayland.c
>> +++ b/src/compositor-wayland.c
>> @@ -1418,6 +1418,7 @@ input_handle_keymap(void *data, struct wl_keyboard *keyboard, uint32_t format,
>>  		    int fd, uint32_t size)
>>  {
>>  	struct wayland_input *input = data;
>> +	struct weston_keyboard *weston_keyboard;
>>  	struct xkb_keymap *keymap;
>>  	char *map_str;
>>  
>> @@ -1456,7 +1457,8 @@ input_handle_keymap(void *data, struct wl_keyboard *keyboard, uint32_t format,
>>  
>>  	close(fd);
>>  
>> -	if (input->base.keyboard)
>> +	weston_keyboard = weston_seat_get_keyboard(&input->base);
>> +	if (weston_keyboard)
> 
> This change will cause compositor-wayland not being able to update the
> keymap when the parent compositor does so.
> 
>>  		weston_seat_update_keymap(&input->base, keymap);
>>  	else
>>  		weston_seat_init_keyboard(&input->base, keymap);
>> @@ -1551,6 +1553,7 @@ input_handle_modifiers(void *data, struct wl_keyboard *keyboard,
>>  		       uint32_t mods_latched, uint32_t mods_locked,
>>  		       uint32_t group)
>>  {
>> +	struct weston_keyboard *weston_keyboard;
>>  	struct wayland_input *input = data;
>>  	struct wayland_compositor *c = input->compositor;
>>  	uint32_t serial_out;
>> @@ -1563,7 +1566,8 @@ input_handle_modifiers(void *data, struct wl_keyboard *keyboard,
>>  	else
>>  		serial_out = wl_display_next_serial(c->base.wl_display);
>>  
>> -	xkb_state_update_mask(input->base.keyboard->xkb_state.state,
>> +	weston_keyboard = weston_seat_get_keyboard(&input->base);
>> +	xkb_state_update_mask(weston_keyboard->xkb_state.state,
>>  			      mods_depressed, mods_latched,
>>  			      mods_locked, 0, 0, group);
>>  	notify_modifiers(&input->base, serial_out);
>> diff --git a/src/compositor-x11.c b/src/compositor-x11.c
>> index 9792ac6..1cbdbc4 100644
>> --- a/src/compositor-x11.c
>> +++ b/src/compositor-x11.c
>> @@ -169,9 +169,13 @@ x11_compositor_get_keymap(struct x11_compositor *c)
>>  static uint32_t
>>  get_xkb_mod_mask(struct x11_compositor *c, uint32_t in)
>>  {
>> -	struct weston_xkb_info *info = c->core_seat.keyboard->xkb_info;
>> +	struct weston_keyboard *keyboard;
>> +	struct weston_xkb_info *info;
>>  	uint32_t ret = 0;
>>  
>> +	keyboard = weston_seat_get_keyboard(&c->core_seat);
>> +	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)
>> @@ -201,6 +205,7 @@ x11_compositor_setup_xkb(struct x11_compositor *c)
>>  	c->xkb_event_base = 0;
>>  	return;
>>  #else
>> +	struct weston_keyboard *keyboard;
>>  	const xcb_query_extension_reply_t *ext;
>>  	xcb_generic_error_t *error;
>>  	xcb_void_cookie_t select;
>> @@ -280,7 +285,8 @@ x11_compositor_setup_xkb(struct x11_compositor *c)
>>  		return;
>>  	}
>>  
>> -	xkb_state_update_mask(c->core_seat.keyboard->xkb_state.state,
>> +	keyboard = weston_seat_get_keyboard(&c->core_seat);
>> +	xkb_state_update_mask(keyboard->xkb_state.state,
>>  			      get_xkb_mod_mask(c, state_reply->baseMods),
>>  			      get_xkb_mod_mask(c, state_reply->latchedMods),
>>  			      get_xkb_mod_mask(c, state_reply->lockedMods),
>> @@ -963,7 +969,10 @@ static void delete_cb(void *data)
>>  static void
>>  update_xkb_state(struct x11_compositor *c, xcb_xkb_state_notify_event_t *state)
>>  {
>> -	xkb_state_update_mask(c->core_seat.keyboard->xkb_state.state,
>> +	struct weston_keyboard *keyboard;
>> +
>> +	keyboard = weston_seat_get_keyboard(&c->core_seat);
>> +	xkb_state_update_mask(keyboard->xkb_state.state,
>>  			      get_xkb_mod_mask(c, state->baseMods),
>>  			      get_xkb_mod_mask(c, state->latchedMods),
>>  			      get_xkb_mod_mask(c, state->lockedMods),
>> @@ -991,9 +1000,10 @@ static void
>>  update_xkb_state_from_core(struct x11_compositor *c, uint16_t x11_mask)
>>  {
>>  	uint32_t mask = get_xkb_mod_mask(c, x11_mask);
>> -	struct weston_keyboard *keyboard = c->core_seat.keyboard;
>> +	struct weston_keyboard *keyboard;
>>  
>> -	xkb_state_update_mask(c->core_seat.keyboard->xkb_state.state,
>> +	keyboard = weston_seat_get_keyboard(&c->core_seat);
>> +	xkb_state_update_mask(keyboard->xkb_state.state,
>>  			      keyboard->modifiers.mods_depressed & mask,
>>  			      keyboard->modifiers.mods_latched & mask,
>>  			      keyboard->modifiers.mods_locked & mask,
>> diff --git a/src/compositor.c b/src/compositor.c
>> index 698ee52..6b744c5 100644
>> --- a/src/compositor.c
>> +++ b/src/compositor.c
>> @@ -146,7 +146,7 @@ static void weston_mode_switch_finish(struct weston_output *output,
>>  	/* If a pointer falls outside the outputs new geometry, move it to its
>>  	 * lower-right corner */
>>  	wl_list_for_each(seat, &output->compositor->seat_list, link) {
>> -		struct weston_pointer *pointer = seat->pointer;
>> +		struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>>  		int32_t x, y;
>>  
>>  		if (!pointer)
>> @@ -1806,15 +1806,20 @@ weston_view_unmap(struct weston_view *view)
>>  		return;
>>  
>>  	wl_list_for_each(seat, &view->surface->compositor->seat_list, link) {
>> -		if (seat->keyboard && seat->keyboard->focus == view->surface)
>> -			weston_keyboard_set_focus(seat->keyboard, NULL);
>> -		if (seat->pointer && seat->pointer->focus == view)
>> -			weston_pointer_set_focus(seat->pointer,
>> +		struct weston_touch *touch = weston_seat_get_touch(seat);
>> +		struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>> +		struct weston_keyboard *keyboard =
>> +						weston_seat_get_keyboard(seat);
> 
> nit: Same indentation inconsistency as above.
> 
>> +
>> +		if (keyboard && keyboard->focus == view->surface)
>> +			weston_keyboard_set_focus(keyboard, NULL);
>> +		if (pointer && pointer->focus == view)
>> +			weston_pointer_set_focus(pointer,
>>  						 NULL,
>>  						 wl_fixed_from_int(0),
>>  						 wl_fixed_from_int(0));
>> -		if (seat->touch && seat->touch->focus == view)
>> -			weston_touch_set_focus(seat->touch, NULL);
>> +		if (touch && touch->focus == view)
>> +			weston_touch_set_focus(touch, NULL);
>>  	}
>>  }
>>  
>> @@ -4646,8 +4651,10 @@ weston_compositor_set_default_pointer_grab(struct weston_compositor *ec,
>>  
>>  	ec->default_pointer_grab = interface;
>>  	wl_list_for_each(seat, &ec->seat_list, link) {
>> -		if (seat->pointer) {
>> -			weston_pointer_set_default_grab(seat->pointer,
>> +		struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>> +
>> +		if (pointer) {
>> +			weston_pointer_set_default_grab(pointer,
>>  							interface);
>>  		}
>>  	}
>> @@ -5414,8 +5421,11 @@ int main(int argc, char *argv[])
>>  	weston_config_section_get_bool(section, "numlock-on", &numlock_on, 0);
>>  	if (numlock_on) {
>>  		wl_list_for_each(seat, &ec->seat_list, link) {
>> -			if (seat->keyboard)
>> -				weston_keyboard_set_locks(seat->keyboard,
>> +			struct weston_keyboard *keyboard =
>> +						weston_seat_get_keyboard(seat);
> 
> nit: Same indentation inconsistency as above.
> 
>> +
>> +			if (keyboard)
>> +				weston_keyboard_set_locks(keyboard,
>>  							  WESTON_NUM_LOCK,
>>  							  WESTON_NUM_LOCK);
>>  		}
>> diff --git a/src/compositor.h b/src/compositor.h
>> index f9834ba..35c6a30 100644
>> --- a/src/compositor.h
>> +++ b/src/compositor.h
>> @@ -509,9 +509,9 @@ struct weston_seat {
>>  	struct wl_list base_resource_list;
>>  
>>  	struct wl_global *global;
>> -	struct weston_pointer *pointer;
>> -	struct weston_keyboard *keyboard;
>> -	struct weston_touch *touch;
>> +	struct weston_pointer *pointer_resource;
>> +	struct weston_keyboard *keyboard_resource;
>> +	struct weston_touch *touch_resource;
> 
> These names are misleading. It's not a wl_resource (which usually
> carries such names).

Fair enough.

> Maybe a better cleanup altogether would be to free the instances, set
> seat->pointer to NULL, but keep some relevant state around, i.e. have
> weston_pointer_state in weston_seat, that a weston_seat->pointer->state
> is set to. We could keep pointer position etc there, while seat->pointer
> would be NULL.

Can we really do that?  I thought there were other reasons we were stuck
holding onto those pointers forever?

What happens when a mouse is unplugged at the same time a client calls
wl_pointer_set_cursor()?  I don't think we have a way to gun down all
the wl_pointer resources that clients have, and when they try to use
them the compositor will dereference the old pointer pointer?

> But before doing that we really need to check places which previously
> relied on pointer/keyboard/touch never going away so they won't break.

And some of those places are already broken because they expect
pointer/keyboard/touch to always exist (even if no mouse has ever been
plugged in, for example.)

>>  	int pointer_device_count;
>>  	int keyboard_device_count;
>>  	int touch_device_count;
>> @@ -1572,6 +1572,15 @@ weston_parse_transform(const char *transform, uint32_t *out);
>>  const char *
>>  weston_transform_to_string(uint32_t output_transform);
>>  
>> +struct weston_keyboard *
>> +weston_seat_get_keyboard(struct weston_seat *seat);
>> +
>> +struct weston_pointer *
>> +weston_seat_get_pointer(struct weston_seat *seat);
>> +
>> +struct weston_touch *
>> +weston_seat_get_touch(struct weston_seat *seat);
>> +
>>  #ifdef  __cplusplus
>>  }
>>  #endif
>> diff --git a/src/data-device.c b/src/data-device.c
>> index 3e7baf9..d2699fd 100644
>> --- a/src/data-device.c
>> +++ b/src/data-device.c
>> @@ -658,23 +658,25 @@ data_device_start_drag(struct wl_client *client, struct wl_resource *resource,
>>  		       struct wl_resource *icon_resource, uint32_t serial)
>>  {
>>  	struct weston_seat *seat = wl_resource_get_user_data(resource);
>> +	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>> +	struct weston_touch *touch = weston_seat_get_touch(seat);
>>  	struct weston_surface *origin = wl_resource_get_user_data(origin_resource);
>>  	struct weston_data_source *source = NULL;
>>  	struct weston_surface *icon = NULL;
>>  	int is_pointer_grab, is_touch_grab;
>>  	int32_t ret = 0;
>>  
>> -	is_pointer_grab = seat->pointer &&
>> -			  seat->pointer->button_count == 1 &&
>> -			  seat->pointer->grab_serial == serial &&
>> -			  seat->pointer->focus &&
>> -			  seat->pointer->focus->surface == origin;
>> +	is_pointer_grab = pointer &&
>> +			  pointer->button_count == 1 &&
>> +			  pointer->grab_serial == serial &&
>> +			  pointer->focus &&
>> +			  pointer->focus->surface == origin;
>>  
>> -	is_touch_grab = seat->touch &&
>> -			seat->touch->num_tp == 1 &&
>> -			seat->touch->grab_serial == serial &&
>> -			seat->touch->focus &&
>> -			seat->touch->focus->surface == origin;
>> +	is_touch_grab = touch &&
>> +			touch->num_tp == 1 &&
>> +			touch->grab_serial == serial &&
>> +			touch->focus &&
>> +			touch->focus->surface == origin;
>>  
>>  	if (!is_pointer_grab && !is_touch_grab)
>>  		return;
>> @@ -694,9 +696,9 @@ data_device_start_drag(struct wl_client *client, struct wl_resource *resource,
>>  	}
>>  
>>  	if (is_pointer_grab)
>> -		ret = weston_pointer_start_drag(seat->pointer, source, icon, client);
>> +		ret = weston_pointer_start_drag(pointer, source, icon, client);
>>  	else if (is_touch_grab)
>> -		ret = weston_touch_start_drag(seat->touch, source, icon, client);
>> +		ret = weston_touch_start_drag(touch, source, icon, client);
>>  
>>  	if (ret < 0)
>>  		wl_resource_post_no_memory(resource);
>> @@ -707,13 +709,14 @@ destroy_selection_data_source(struct wl_listener *listener, void *data)
>>  {
>>  	struct weston_seat *seat = container_of(listener, struct weston_seat,
>>  						selection_data_source_listener);
>> +	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
>>  	struct wl_resource *data_device;
>>  	struct weston_surface *focus = NULL;
>>  
>>  	seat->selection_data_source = NULL;
>>  
>> -	if (seat->keyboard)
>> -		focus = seat->keyboard->focus;
>> +	if (keyboard)
>> +		focus = keyboard->focus;
>>  	if (focus && focus->resource) {
>>  		data_device = wl_resource_find_for_client(&seat->drag_resource_list,
>>  							  wl_resource_get_client(focus->resource));
>> @@ -761,6 +764,7 @@ WL_EXPORT void
>>  weston_seat_set_selection(struct weston_seat *seat,
>>  			  struct weston_data_source *source, uint32_t serial)
>>  {
>> +	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
>>  	struct weston_surface *focus = NULL;
>>  
>>  	if (seat->selection_data_source &&
>> @@ -776,8 +780,8 @@ weston_seat_set_selection(struct weston_seat *seat,
>>  	seat->selection_data_source = source;
>>  	seat->selection_serial = serial;
>>  
>> -	if (seat->keyboard)
>> -		focus = seat->keyboard->focus;
>> +	if (keyboard)
>> +		focus = keyboard->focus;
>>  	if (focus && focus->resource) {
>>  		weston_seat_send_selection(seat, wl_resource_get_client(focus->resource));
>>  	}
>> @@ -935,11 +939,12 @@ WL_EXPORT void
>>  wl_data_device_set_keyboard_focus(struct weston_seat *seat)
>>  {
>>  	struct weston_surface *focus;
>> +	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
>>  
>> -	if (!seat->keyboard)
>> +	if (!keyboard)
>>  		return;
>>  
>> -	focus = seat->keyboard->focus;
>> +	focus = keyboard->focus;
>>  	if (!focus || !focus->resource)
>>  		return;
>>  
>> diff --git a/src/input.c b/src/input.c
>> index 6604c5d..3f9e267 100644
>> --- a/src/input.c
>> +++ b/src/input.c
>> @@ -49,12 +49,12 @@ static void unbind_resource(struct wl_resource *resource)
>>  WL_EXPORT void
>>  weston_seat_repick(struct weston_seat *seat)
>>  {
>> -	const struct weston_pointer *pointer = seat->pointer;
>> +	const struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>>  
>> -	if (pointer == NULL)
>> +	if (!pointer)
>>  		return;
>>  
>> -	pointer->grab->interface->focus(seat->pointer->grab);
>> +	pointer->grab->interface->focus(pointer->grab);
>>  }
>>  
>>  static void
>> @@ -387,7 +387,8 @@ default_grab_keyboard_modifiers(struct weston_keyboard_grab *grab,
>>  				uint32_t mods_locked, uint32_t group)
>>  {
>>  	struct weston_keyboard *keyboard = grab->keyboard;
>> -	struct weston_pointer *pointer = grab->keyboard->seat->pointer;
>> +	struct weston_pointer *pointer =
>> +				weston_seat_get_pointer(grab->keyboard->seat);
> 
> nit: Same indentation inconsistency as above.
> 
>>  	struct wl_resource *resource;
>>  	struct wl_list *resource_list;
>>  
>> @@ -622,7 +623,7 @@ weston_pointer_set_focus(struct weston_pointer *pointer,
>>  			 struct weston_view *view,
>>  			 wl_fixed_t sx, wl_fixed_t sy)
>>  {
>> -	struct weston_keyboard *kbd = pointer->seat->keyboard;
>> +	struct weston_keyboard *kbd = weston_seat_get_keyboard(pointer->seat);
>>  	struct wl_resource *resource;
>>  	struct wl_display *display = pointer->seat->compositor->wl_display;
>>  	uint32_t serial;
>> @@ -942,7 +943,7 @@ notify_motion(struct weston_seat *seat,
>>  	      uint32_t time, wl_fixed_t dx, wl_fixed_t dy)
>>  {
>>  	struct weston_compositor *ec = seat->compositor;
>> -	struct weston_pointer *pointer = seat->pointer;
>> +	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);
>> @@ -952,7 +953,7 @@ static void
>>  run_modifier_bindings(struct weston_seat *seat, uint32_t old, uint32_t new)
>>  {
>>  	struct weston_compositor *compositor = seat->compositor;
>> -	struct weston_keyboard *keyboard = seat->keyboard;
>> +	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
>>  	uint32_t diff;
>>  	unsigned int i;
>>  	struct {
>> @@ -989,7 +990,7 @@ notify_motion_absolute(struct weston_seat *seat,
>>  		       uint32_t time, wl_fixed_t x, wl_fixed_t y)
>>  {
>>  	struct weston_compositor *ec = seat->compositor;
>> -	struct weston_pointer *pointer = seat->pointer;
>> +	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>>  
>>  	weston_compositor_wake(ec);
>>  	pointer->grab->interface->motion(pointer->grab, time, x, y);
>> @@ -1000,9 +1001,10 @@ weston_surface_activate(struct weston_surface *surface,
>>  			struct weston_seat *seat)
>>  {
>>  	struct weston_compositor *compositor = seat->compositor;
>> +	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
>>  
>> -	if (seat->keyboard) {
>> -		weston_keyboard_set_focus(seat->keyboard, surface);
>> +	if (keyboard) {
>> +		weston_keyboard_set_focus(keyboard, surface);
>>  		wl_data_device_set_keyboard_focus(seat);
>>  	}
>>  
>> @@ -1014,7 +1016,7 @@ notify_button(struct weston_seat *seat, uint32_t time, int32_t button,
>>  	      enum wl_pointer_button_state state)
>>  {
>>  	struct weston_compositor *compositor = seat->compositor;
>> -	struct weston_pointer *pointer = seat->pointer;
>> +	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>>  
>>  	if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
>>  		weston_compositor_idle_inhibit(compositor);
>> @@ -1045,7 +1047,7 @@ notify_axis(struct weston_seat *seat, uint32_t time, uint32_t axis,
>>  	    wl_fixed_t value)
>>  {
>>  	struct weston_compositor *compositor = seat->compositor;
>> -	struct weston_pointer *pointer = seat->pointer;
>> +	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>>  	struct wl_resource *resource;
>>  	struct wl_list *resource_list;
>>  
>> @@ -1120,7 +1122,7 @@ weston_keyboard_set_locks(struct weston_keyboard *keyboard,
>>  WL_EXPORT void
>>  notify_modifiers(struct weston_seat *seat, uint32_t serial)
>>  {
>> -	struct weston_keyboard *keyboard = seat->keyboard;
>> +	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
>>  	struct weston_keyboard_grab *grab = keyboard->grab;
>>  	uint32_t mods_depressed, mods_latched, mods_locked, group;
>>  	uint32_t mods_lookup;
>> @@ -1138,19 +1140,19 @@ notify_modifiers(struct weston_seat *seat, uint32_t serial)
>>  	group = xkb_state_serialize_layout(keyboard->xkb_state.state,
>>  					   XKB_STATE_LAYOUT_EFFECTIVE);
>>  
>> -	if (mods_depressed != seat->keyboard->modifiers.mods_depressed ||
>> -	    mods_latched != seat->keyboard->modifiers.mods_latched ||
>> -	    mods_locked != seat->keyboard->modifiers.mods_locked ||
>> -	    group != seat->keyboard->modifiers.group)
>> +	if (mods_depressed != keyboard->modifiers.mods_depressed ||
>> +	    mods_latched != keyboard->modifiers.mods_latched ||
>> +	    mods_locked != keyboard->modifiers.mods_locked ||
>> +	    group != keyboard->modifiers.group)
>>  		changed = 1;
>>  
>> -	run_modifier_bindings(seat, seat->keyboard->modifiers.mods_depressed,
>> +	run_modifier_bindings(seat, keyboard->modifiers.mods_depressed,
>>  	                      mods_depressed);
>>  
>> -	seat->keyboard->modifiers.mods_depressed = mods_depressed;
>> -	seat->keyboard->modifiers.mods_latched = mods_latched;
>> -	seat->keyboard->modifiers.mods_locked = mods_locked;
>> -	seat->keyboard->modifiers.group = group;
>> +	keyboard->modifiers.mods_depressed = mods_depressed;
>> +	keyboard->modifiers.mods_latched = mods_latched;
>> +	keyboard->modifiers.mods_locked = mods_locked;
>> +	keyboard->modifiers.group = group;
>>  
>>  	/* And update the modifier_state for bindings. */
>>  	mods_lookup = mods_depressed | mods_latched;
>> @@ -1192,7 +1194,7 @@ static void
>>  update_modifier_state(struct weston_seat *seat, uint32_t serial, uint32_t key,
>>  		      enum wl_keyboard_key_state state)
>>  {
>> -	struct weston_keyboard *keyboard = seat->keyboard;
>> +	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
>>  	enum xkb_key_direction direction;
>>  
>>  	/* Keyboard modifiers don't exist in raw keyboard mode */
>> @@ -1236,7 +1238,7 @@ weston_xkb_info_create(struct xkb_keymap *keymap);
>>  static void
>>  update_keymap(struct weston_seat *seat)
>>  {
>> -	struct weston_keyboard *keyboard = seat->keyboard;
>> +	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
>>  	struct wl_resource *resource;
>>  	struct weston_xkb_info *xkb_info;
>>  	struct xkb_state *state;
>> @@ -1276,9 +1278,9 @@ update_keymap(struct weston_seat *seat)
>>  	xkb_state_unref(keyboard->xkb_state.state);
>>  	keyboard->xkb_state.state = state;
>>  
>> -	wl_resource_for_each(resource, &seat->keyboard->resource_list)
>> +	wl_resource_for_each(resource, &keyboard->resource_list)
>>  		send_keymap(resource, xkb_info);
>> -	wl_resource_for_each(resource, &seat->keyboard->focus_resource_list)
>> +	wl_resource_for_each(resource, &keyboard->focus_resource_list)
>>  		send_keymap(resource, xkb_info);
>>  
>>  	notify_modifiers(seat, wl_display_next_serial(seat->compositor->wl_display));
>> @@ -1286,10 +1288,10 @@ update_keymap(struct weston_seat *seat)
>>  	if (!latched_mods && !locked_mods)
>>  		return;
>>  
>> -	wl_resource_for_each(resource, &seat->keyboard->resource_list)
>> -		send_modifiers(resource, wl_display_get_serial(seat->compositor->wl_display), seat->keyboard);
>> -	wl_resource_for_each(resource, &seat->keyboard->focus_resource_list)
>> -		send_modifiers(resource, wl_display_get_serial(seat->compositor->wl_display), seat->keyboard);
>> +	wl_resource_for_each(resource, &keyboard->resource_list)
>> +		send_modifiers(resource, wl_display_get_serial(seat->compositor->wl_display), keyboard);
>> +	wl_resource_for_each(resource, &keyboard->focus_resource_list)
>> +		send_modifiers(resource, wl_display_get_serial(seat->compositor->wl_display), keyboard);
>>  }
>>  #else
>>  WL_EXPORT void
>> @@ -1315,7 +1317,7 @@ 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 = seat->keyboard;
>> +	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
>>  	struct weston_keyboard_grab *grab = keyboard->grab;
>>  	uint32_t *k, *end;
>>  
>> @@ -1372,8 +1374,10 @@ WL_EXPORT void
>>  notify_pointer_focus(struct weston_seat *seat, struct weston_output *output,
>>  		     wl_fixed_t x, wl_fixed_t y)
>>  {
>> +	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>> +
>>  	if (output) {
>> -		weston_pointer_move(seat->pointer, x, y);
>> +		weston_pointer_move(pointer, x, y);
>>  	} else {
>>  		/* FIXME: We should call weston_pointer_set_focus(seat,
>>  		 * NULL) here, but somehow that breaks re-entry... */
>> @@ -1396,7 +1400,7 @@ notify_keyboard_focus_in(struct weston_seat *seat, struct wl_array *keys,
>>  			 enum weston_key_state_update update_state)
>>  {
>>  	struct weston_compositor *compositor = seat->compositor;
>> -	struct weston_keyboard *keyboard = seat->keyboard;
>> +	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
>>  	struct weston_surface *surface;
>>  	uint32_t *k, serial;
>>  
>> @@ -1422,7 +1426,8 @@ WL_EXPORT void
>>  notify_keyboard_focus_out(struct weston_seat *seat)
>>  {
>>  	struct weston_compositor *compositor = seat->compositor;
>> -	struct weston_keyboard *keyboard = seat->keyboard;
>> +	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
>> +	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>>  	uint32_t *k, serial;
>>  
>>  	serial = wl_display_next_serial(compositor->wl_display);
>> @@ -1444,8 +1449,8 @@ notify_keyboard_focus_out(struct weston_seat *seat)
>>  
>>  	weston_keyboard_set_focus(keyboard, NULL);
>>  	weston_keyboard_cancel_grab(keyboard);
>> -	if (seat->pointer)
>> -		weston_pointer_cancel_grab(seat->pointer);
>> +	if (pointer)
>> +		weston_pointer_cancel_grab(pointer);
>>  }
>>  
>>  WL_EXPORT void
>> @@ -1503,7 +1508,7 @@ notify_touch(struct weston_seat *seat, uint32_t time, int touch_id,
>>               wl_fixed_t x, wl_fixed_t y, int touch_type)
>>  {
>>  	struct weston_compositor *ec = seat->compositor;
>> -	struct weston_touch *touch = seat->touch;
>> +	struct weston_touch *touch = weston_seat_get_touch(seat);
>>  	struct weston_touch_grab *grab = touch->grab;
>>  	struct weston_view *ev;
>>  	wl_fixed_t sx, sy;
>> @@ -1582,7 +1587,7 @@ notify_touch(struct weston_seat *seat, uint32_t time, int touch_id,
>>  WL_EXPORT void
>>  notify_touch_frame(struct weston_seat *seat)
>>  {
>> -	struct weston_touch *touch = seat->touch;
>> +	struct weston_touch *touch = weston_seat_get_touch(seat);
>>  	struct weston_touch_grab *grab = touch->grab;
>>  
>>  	grab->interface->frame(grab);
>> @@ -1633,6 +1638,9 @@ pointer_set_cursor(struct wl_client *client, struct wl_resource *resource,
>>  	struct weston_pointer *pointer = wl_resource_get_user_data(resource);
>>  	struct weston_surface *surface = NULL;
>>  
>> +	if (!pointer)
>> +		return;
>> +
>>  	if (surface_resource)
>>  		surface = wl_resource_get_user_data(surface_resource);
>>  
>> @@ -1702,9 +1710,13 @@ 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_resource directly here because we only
>> +	 * want to fail if the seat never contained a pointer.
>> +	 */
>> +	struct weston_pointer *pointer = seat->pointer_resource;
>>  	struct wl_resource *cr;
>>  
>> -	if (!seat->pointer)
>> +	if (!pointer)
>>  		return;
>>  
>>          cr = wl_resource_create(client, &wl_pointer_interface,
>> @@ -1717,25 +1729,25 @@ seat_get_pointer(struct wl_client *client, struct wl_resource *resource,
>>  	/* May be moved to focused list later by either
>>  	 * weston_pointer_set_focus or directly if this client is already
>>  	 * focused */
>> -	wl_list_insert(&seat->pointer->resource_list, wl_resource_get_link(cr));
>> -	wl_resource_set_implementation(cr, &pointer_interface, seat->pointer,
>> +	wl_list_insert(&pointer->resource_list, wl_resource_get_link(cr));
>> +	wl_resource_set_implementation(cr, &pointer_interface, pointer,
>>  				       unbind_resource);
>>  
>> -	if (seat->pointer->focus && seat->pointer->focus->surface->resource &&
>> -	    wl_resource_get_client(seat->pointer->focus->surface->resource) == client) {
>> +	if (pointer->focus && pointer->focus->surface->resource &&
>> +	    wl_resource_get_client(pointer->focus->surface->resource) == client) {
>>  		wl_fixed_t sx, sy;
>>  
>> -		weston_view_from_global_fixed(seat->pointer->focus,
>> -					      seat->pointer->x,
>> -					      seat->pointer->y,
>> +		weston_view_from_global_fixed(pointer->focus,
>> +					      pointer->x,
>> +					      pointer->y,
>>  					      &sx, &sy);
>>  
>>  		wl_list_remove(wl_resource_get_link(cr));
>> -		wl_list_insert(&seat->pointer->focus_resource_list,
>> +		wl_list_insert(&pointer->focus_resource_list,
>>  			       wl_resource_get_link(cr));
>>  		wl_pointer_send_enter(cr,
>> -				      seat->pointer->focus_serial,
>> -				      seat->pointer->focus->surface->resource,
>> +				      pointer->focus_serial,
>> +				      pointer->focus->surface->resource,
>>  				      sx, sy);
>>  	}
>>  }
>> @@ -1754,16 +1766,19 @@ static bool
>>  should_send_modifiers_to_client(struct weston_seat *seat,
>>  				struct wl_client *client)
>>  {
>> -	if (seat->keyboard &&
>> -	    seat->keyboard->focus &&
>> -	    seat->keyboard->focus->resource &&
>> -	    wl_resource_get_client(seat->keyboard->focus->resource) == client)
>> +	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
>> +	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>> +
>> +	if (keyboard &&
>> +	    keyboard->focus &&
>> +	    keyboard->focus->resource &&
>> +	    wl_resource_get_client(keyboard->focus->resource) == client)
>>  		return true;
>>  
>> -	if (seat->pointer &&
>> -	    seat->pointer->focus &&
>> -	    seat->pointer->focus->surface->resource &&
>> -	    wl_resource_get_client(seat->pointer->focus->surface->resource) == client)
>> +	if (pointer &&
>> +	    pointer->focus &&
>> +	    pointer->focus->surface->resource &&
>> +	    wl_resource_get_client(pointer->focus->surface->resource) == client)
>>  		return true;
>>  
>>  	return false;
>> @@ -1774,10 +1789,13 @@ seat_get_keyboard(struct wl_client *client, struct wl_resource *resource,
>>  		  uint32_t id)
>>  {
>>  	struct weston_seat *seat = wl_resource_get_user_data(resource);
>> -	struct weston_keyboard *keyboard = seat->keyboard;
>> +	/* We use the keyboard_resource directly here because we only
>> +	 * want to fail if the seat never contained a keyboard.
>> +	 */
>> +	struct weston_keyboard *keyboard = seat->keyboard_resource;
>>  	struct wl_resource *cr;
>>  
>> -	if (!seat->keyboard)
>> +	if (!keyboard)
>>  		return;
>>  
>>          cr = wl_resource_create(client, &wl_keyboard_interface,
>> @@ -1790,7 +1808,7 @@ seat_get_keyboard(struct wl_client *client, struct wl_resource *resource,
>>  	/* May be moved to focused list later by either
>>  	 * weston_keyboard_set_focus or directly if this client is already
>>  	 * focused */
>> -	wl_list_insert(&seat->keyboard->resource_list, wl_resource_get_link(cr));
>> +	wl_list_insert(&keyboard->resource_list, wl_resource_get_link(cr));
>>  	wl_resource_set_implementation(cr, &keyboard_interface,
>>  				       seat, unbind_resource);
>>  
>> @@ -1813,27 +1831,26 @@ seat_get_keyboard(struct wl_client *client, struct wl_resource *resource,
>>  	}
>>  
>>  	if (should_send_modifiers_to_client(seat, client)) {
>> -		send_modifiers_to_resource(seat->keyboard,
>> +		send_modifiers_to_resource(keyboard,
>>  					   cr,
>> -					   seat->keyboard->focus_serial);
>> +					   keyboard->focus_serial);
>>  	}
>>  
>> -	if (seat->keyboard->focus && seat->keyboard->focus->resource &&
>> -	    wl_resource_get_client(seat->keyboard->focus->resource) == client) {
>> -		struct weston_surface *surface =
>> -			(struct weston_surface *) seat->keyboard->focus;
>> +	if (keyboard->focus && keyboard->focus->resource &&
>> +	    wl_resource_get_client(keyboard->focus->resource) == client) {
>> +		struct weston_surface *surface = keyboard->focus;
>>  
>>  		wl_list_remove(wl_resource_get_link(cr));
>> -		wl_list_insert(&seat->keyboard->focus_resource_list,
>> +		wl_list_insert(&keyboard->focus_resource_list,
>>  			       wl_resource_get_link(cr));
>>  		wl_keyboard_send_enter(cr,
>> -				       seat->keyboard->focus_serial,
>> +				       keyboard->focus_serial,
>>  				       surface->resource,
>> -				       &seat->keyboard->keys);
>> +				       &keyboard->keys);
>>  
>>  		/* If this is the first keyboard resource for this
>>  		 * client... */
>> -		if (seat->keyboard->focus_resource_list.prev ==
>> +		if (keyboard->focus_resource_list.prev ==
>>  		    wl_resource_get_link(cr))
>>  			wl_data_device_set_keyboard_focus(seat);
>>  	}
>> @@ -1854,9 +1871,13 @@ 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_resource directly here because we only
>> +	 * want to fail if the seat never contained a touch device.
>> +	 */
>> +	struct weston_touch *touch = seat->touch_resource;
>>  	struct wl_resource *cr;
>>  
>> -	if (!seat->touch)
>> +	if (!touch)
>>  		return;
>>  
>>          cr = wl_resource_create(client, &wl_touch_interface,
>> @@ -1866,12 +1887,12 @@ seat_get_touch(struct wl_client *client, struct wl_resource *resource,
>>  		return;
>>  	}
>>  
>> -	if (seat->touch->focus &&
>> -	    wl_resource_get_client(seat->touch->focus->surface->resource) == client) {
>> -		wl_list_insert(&seat->touch->resource_list,
>> +	if (touch->focus &&
>> +	    wl_resource_get_client(touch->focus->surface->resource) == client) {
>> +		wl_list_insert(&touch->resource_list,
>>  			       wl_resource_get_link(cr));
>>  	} else {
>> -		wl_list_insert(&seat->touch->focus_resource_list,
>> +		wl_list_insert(&touch->focus_resource_list,
>>  			       wl_resource_get_link(cr));
>>  	}
>>  	wl_resource_set_implementation(cr, &touch_interface,
>> @@ -1897,11 +1918,11 @@ bind_seat(struct wl_client *client, void *data, uint32_t version, uint32_t id)
>>  	wl_resource_set_implementation(resource, &seat_interface, data,
>>  				       unbind_resource);
>>  
>> -	if (seat->pointer)
>> +	if (seat->pointer_device_count)
>>  		caps |= WL_SEAT_CAPABILITY_POINTER;
>> -	if (seat->keyboard)
>> +	if (seat->keyboard_device_count)
>>  		caps |= WL_SEAT_CAPABILITY_KEYBOARD;
>> -	if (seat->touch)
>> +	if (seat->touch_device_count)
>>  		caps |= WL_SEAT_CAPABILITY_TOUCH;
>>  
>>  	wl_seat_send_capabilities(resource, caps);
>> @@ -2091,17 +2112,18 @@ weston_compositor_xkb_destroy(struct weston_compositor *ec)
>>  WL_EXPORT void
>>  weston_seat_update_keymap(struct weston_seat *seat, struct xkb_keymap *keymap)
>>  {
>> -	if (!seat->keyboard || !keymap)
>> +	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
>> +	if (!keyboard || !keymap)
>>  		return;
>>  
>>  #ifdef ENABLE_XKBCOMMON
>>  	if (!seat->compositor->use_xkbcommon)
>>  		return;
>>  
>> -	xkb_keymap_unref(seat->keyboard->pending_keymap);
>> -	seat->keyboard->pending_keymap = xkb_keymap_ref(keymap);
>> +	xkb_keymap_unref(keyboard->pending_keymap);
>> +	keyboard->pending_keymap = xkb_keymap_ref(keymap);
>>  
>> -	if (seat->keyboard->keys.size == 0)
>> +	if (keyboard->keys.size == 0)
>>  		update_keymap(seat);
>>  #endif
>>  }
>> @@ -2111,7 +2133,7 @@ weston_seat_init_keyboard(struct weston_seat *seat, struct xkb_keymap *keymap)
>>  {
>>  	struct weston_keyboard *keyboard;
>>  
>> -	if (seat->keyboard) {
>> +	if (seat->keyboard_resource) {
>>  		seat->keyboard_device_count += 1;
>>  		if (seat->keyboard_device_count == 1)
>>  			seat_send_updated_caps(seat);
>> @@ -2147,7 +2169,7 @@ weston_seat_init_keyboard(struct weston_seat *seat, struct xkb_keymap *keymap)
>>  	}
>>  #endif
>>  
>> -	seat->keyboard = keyboard;
>> +	seat->keyboard_resource = keyboard;
>>  	seat->keyboard_device_count = 1;
>>  	keyboard->seat = seat;
>>  
>> @@ -2192,9 +2214,9 @@ weston_seat_release_keyboard(struct weston_seat *seat)
>>  	seat->keyboard_device_count--;
>>  	assert(seat->keyboard_device_count >= 0);
>>  	if (seat->keyboard_device_count == 0) {
>> -		weston_keyboard_set_focus(seat->keyboard, NULL);
>> -		weston_keyboard_cancel_grab(seat->keyboard);
>> -		weston_keyboard_reset_state(seat->keyboard);
>> +		weston_keyboard_set_focus(seat->keyboard_resource, NULL);
>> +		weston_keyboard_cancel_grab(seat->keyboard_resource);
>> +		weston_keyboard_reset_state(seat->keyboard_resource);
>>  		seat_send_updated_caps(seat);
>>  	}
>>  }
>> @@ -2204,7 +2226,7 @@ weston_seat_init_pointer(struct weston_seat *seat)
>>  {
>>  	struct weston_pointer *pointer;
>>  
>> -	if (seat->pointer) {
>> +	if (seat->pointer_resource) {
>>  		seat->pointer_device_count += 1;
>>  		if (seat->pointer_device_count == 1)
>>  			seat_send_updated_caps(seat);
>> @@ -2215,7 +2237,7 @@ weston_seat_init_pointer(struct weston_seat *seat)
>>  	if (pointer == NULL)
>>  		return;
>>  
>> -	seat->pointer = pointer;
>> +	seat->pointer_resource = pointer;
>>  	seat->pointer_device_count = 1;
>>  	pointer->seat = seat;
>>  
>> @@ -2225,9 +2247,10 @@ weston_seat_init_pointer(struct weston_seat *seat)
>>  WL_EXPORT void
>>  weston_seat_release_pointer(struct weston_seat *seat)
>>  {
>> -	struct weston_pointer *pointer = seat->pointer;
>> +	struct weston_pointer *pointer = seat->pointer_resource;
>>  
>>  	seat->pointer_device_count--;
>> +	assert(seat->pointer_device_count >= 0);
>>  	if (seat->pointer_device_count == 0) {
>>  		weston_pointer_set_focus(pointer, NULL,
>>  					 wl_fixed_from_int(0),
>> @@ -2252,7 +2275,7 @@ weston_seat_init_touch(struct weston_seat *seat)
>>  {
>>  	struct weston_touch *touch;
>>  
>> -	if (seat->touch) {
>> +	if (seat->touch_resource) {
>>  		seat->touch_device_count += 1;
>>  		if (seat->touch_device_count == 1)
>>  			seat_send_updated_caps(seat);
>> @@ -2263,7 +2286,7 @@ weston_seat_init_touch(struct weston_seat *seat)
>>  	if (touch == NULL)
>>  		return;
>>  
>> -	seat->touch = touch;
>> +	seat->touch_resource = touch;
>>  	seat->touch_device_count = 1;
>>  	touch->seat = seat;
>>  
>> @@ -2274,10 +2297,11 @@ WL_EXPORT void
>>  weston_seat_release_touch(struct weston_seat *seat)
>>  {
>>  	seat->touch_device_count--;
>> +	assert(seat->touch_device_count >= 0);
>>  	if (seat->touch_device_count == 0) {
>> -		weston_touch_set_focus(seat->touch, NULL);
>> -		weston_touch_cancel_grab(seat->touch);
>> -		weston_touch_reset_state(seat->touch);
>> +		weston_touch_set_focus(seat->touch_resource, NULL);
>> +		weston_touch_cancel_grab(seat->touch_resource);
>> +		weston_touch_reset_state(seat->touch_resource);
>>  		seat_send_updated_caps(seat);
>>  	}
>>  }
>> @@ -2317,16 +2341,82 @@ weston_seat_release(struct weston_seat *seat)
>>  	if (seat->saved_kbd_focus)
>>  		wl_list_remove(&seat->saved_kbd_focus_listener.link);
>>  
>> -	if (seat->pointer)
>> -		weston_pointer_destroy(seat->pointer);
>> -	if (seat->keyboard)
>> -		weston_keyboard_destroy(seat->keyboard);
>> -	if (seat->touch)
>> -		weston_touch_destroy(seat->touch);
>> +	if (seat->pointer_resource)
>> +		weston_pointer_destroy(seat->pointer_resource);
>> +	if (seat->keyboard_resource)
>> +		weston_keyboard_destroy(seat->keyboard_resource);
>> +	if (seat->touch_resource)
>> +		weston_touch_destroy(seat->touch_resource);
>>  
>> -	free (seat->seat_name);
>> +	free(seat->seat_name);
>>  
>>  	wl_global_destroy(seat->global);
>>  
>>  	wl_signal_emit(&seat->destroy_signal, seat);
>>  }
>> +
>> +/** Get a seat's keyboard pointer
>> + *
>> + * \param seat The seat to query
>> + * \return The seat's keyboard pointer, or NULL if no keyboard present
>> + *
>> + * The keyboard pointer for a seat isn't freed when all keyboards are removed,
>> + * so should only be used when the seat's keyboard_device_count is greater
>> + * than zero.  This function does that test and only returns a pointer
>> + * when a keyboard is present.
>> + */
>> +WL_EXPORT struct weston_keyboard *
>> +weston_seat_get_keyboard(struct weston_seat *seat)
>> +{
>> +	if (!seat)
>> +		return NULL;
>> +
>> +	if (seat->keyboard_device_count)
>> +		return seat->keyboard_resource;
>> +
>> +	return NULL;
>> +}
>> +
>> +/** Get a seat's pointer pointer
>> + *
>> + * \param seat The seat to query
>> + * \return The seat's pointer pointer, or NULL if no pointing device present
>> + *
>> + * The pointer pointer for a seat isn't freed when all mice are removed,
>> + * so should only be used when the seat's pointer_device_count is greater
>> + * than zero.  This function does that test and only returns a pointer
>> + * when a pointing device is present.
>> + */
>> +WL_EXPORT struct weston_pointer *
>> +weston_seat_get_pointer(struct weston_seat *seat)
>> +{
>> +	if (!seat)
>> +		return NULL;
>> +
>> +	if (seat->pointer_device_count)
>> +		return seat->pointer_resource;
>> +
>> +	return NULL;
>> +}
>> +
>> +/** Get a seat's touch pointer
>> + *
>> + * \param seat The seat to query
>> + * \return The seat's touch pointer, or NULL if no touch device present
>> + *
>> + * The touch pointer for a seat isn't freed when all touch devices are removed,
>> + * so should only be used when the seat's touch_device_count is greater
>> + * than zero.  This function does that test and only returns a pointer
>> + * when a touch device is present.
>> + */
>> +WL_EXPORT struct weston_touch *
>> +weston_seat_get_touch(struct weston_seat *seat)
>> +{
>> +	if (!seat)
>> +		return NULL;
>> +
>> +	if (seat->touch_device_count)
>> +		return seat->touch_resource;
>> +
>> +	return NULL;
>> +}
>> diff --git a/src/libinput-device.c b/src/libinput-device.c
>> index 567e5ea..3fb507f 100644
>> --- a/src/libinput-device.c
>> +++ b/src/libinput-device.c
>> @@ -541,9 +541,10 @@ void
>>  evdev_notify_keyboard_focus(struct weston_seat *seat,
>>  			    struct wl_list *evdev_devices)
>>  {
>> +	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
>>  	struct wl_array keys;
>>  
>> -	if (seat->keyboard_device_count == 0)
>> +	if (!keyboard)
>>  		return;
>>  
>>  	wl_array_init(&keys);
>> diff --git a/src/libinput-seat.c b/src/libinput-seat.c
>> index c0a87ea..3ac0183 100644
>> --- a/src/libinput-seat.c
>> +++ b/src/libinput-seat.c
>> @@ -56,6 +56,7 @@ device_added(struct udev_input *input, struct libinput_device *libinput_device)
>>  	struct libinput_seat *libinput_seat;
>>  	struct weston_seat *seat;
>>  	struct udev_seat *udev_seat;
>> +	struct weston_pointer *pointer;
>>  
>>  	c = input->compositor;
>>  	libinput_seat = libinput_device_get_seat(libinput_device);
>> @@ -73,10 +74,11 @@ device_added(struct udev_input *input, struct libinput_device *libinput_device)
>>  	udev_seat = (struct udev_seat *) seat;
>>  	wl_list_insert(udev_seat->devices_list.prev, &device->link);
>>  
>> -	if (seat->output && seat->pointer)
>> -		weston_pointer_clamp(seat->pointer,
>> -				     &seat->pointer->x,
>> -				     &seat->pointer->y);
>> +	pointer = weston_seat_get_pointer(seat);
>> +	if (seat->output && pointer)
>> +		weston_pointer_clamp(pointer,
>> +				     &pointer->x,
>> +				     &pointer->y);
>>  
>>  	output_name = libinput_device_get_output_name(libinput_device);
>>  	if (output_name) {
>> @@ -368,8 +370,11 @@ udev_seat_create(struct udev_input *input, const char *seat_name)
>>  static void
>>  udev_seat_destroy(struct udev_seat *seat)
>>  {
>> +	struct weston_keyboard *keyboard;
>> +
>>  	udev_seat_remove_devices(seat);
>> -	if (seat->base.keyboard)
>> +	keyboard = weston_seat_get_keyboard(&seat->base);
>> +	if (keyboard)
>>  		notify_keyboard_focus_out(&seat->base);
>>  	weston_seat_release(&seat->base);
>>  	wl_list_remove(&seat->output_create_listener.link);
>> diff --git a/src/screen-share.c b/src/screen-share.c
>> index 524a0ca..49b8416 100644
>> --- a/src/screen-share.c
>> +++ b/src/screen-share.c
>> @@ -1067,8 +1067,9 @@ share_output_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
>>  {
>>  	struct weston_output *output;
>>  	struct screen_share *ss = data;
>> +	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>>  
>> -	if (!seat->pointer) {
>> +	if (!pointer) {
>>  		weston_log("Cannot pick output: Seat does not have pointer\n");
>>  		return;
>>  	}
>> diff --git a/src/screenshooter.c b/src/screenshooter.c
>> index 4e32db5..af66af3 100644
>> --- a/src/screenshooter.c
>> +++ b/src/screenshooter.c
>> @@ -559,6 +559,7 @@ static void
>>  recorder_binding(struct weston_seat *seat, uint32_t time, uint32_t key, void *data)
>>  {
>>  	struct weston_compositor *ec = seat->compositor;
>> +	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
>>  	struct weston_output *output;
>>  	struct wl_listener *listener = NULL;
>>  	struct weston_recorder *recorder;
>> @@ -582,9 +583,9 @@ recorder_binding(struct weston_seat *seat, uint32_t time, uint32_t key, void *da
>>  		recorder->destroying = 1;
>>  		weston_output_schedule_repaint(recorder->output);
>>  	} else {
>> -		if (seat->keyboard && seat->keyboard->focus &&
>> -		    seat->keyboard->focus->output)
>> -			output = seat->keyboard->focus->output;
>> +		if (keyboard && keyboard->focus &&
>> +		    keyboard->focus->output)
>> +			output = keyboard->focus->output;
>>  		else
>>  			output = container_of(ec->output_list.next,
>>  					      struct weston_output, link);
>> diff --git a/src/text-backend.c b/src/text-backend.c
>> index 4dc7179..e5a3acb 100644
>> --- a/src/text-backend.c
>> +++ b/src/text-backend.c
>> @@ -611,7 +611,7 @@ input_method_context_grab_keyboard(struct wl_client *client,
>>  	struct input_method_context *context = wl_resource_get_user_data(resource);
>>  	struct wl_resource *cr;
>>  	struct weston_seat *seat = context->input_method->seat;
>> -	struct weston_keyboard *keyboard = seat->keyboard;
>> +	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
>>  
>>  	cr = wl_resource_create(client, &wl_keyboard_interface, 1, id);
>>  	wl_resource_set_implementation(cr, NULL, context, unbind_keyboard);
>> @@ -639,7 +639,7 @@ 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 = seat->keyboard;
>> +	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
>>  	struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
>>  
>>  	default_grab->interface->key(default_grab, time, key, state_w);
>> @@ -657,7 +657,7 @@ input_method_context_modifiers(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 = seat->keyboard;
>> +	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
>>  	struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
>>  
>>  	default_grab->interface->modifiers(default_grab,
>> @@ -758,10 +758,11 @@ input_method_context_end_keyboard_grab(struct input_method_context *context)
>>  	struct weston_keyboard_grab *grab;
>>  	struct weston_keyboard *keyboard;
>>  
>> -	if (!context->input_method->seat->keyboard)
>> +	keyboard = weston_seat_get_keyboard(context->input_method->seat);
>> +	if (!keyboard)
>>  		return;
>>  
>> -	grab = &context->input_method->seat->keyboard->input_method_grab;
>> +	grab = &keyboard->input_method_grab;
>>  	keyboard = grab->keyboard;
>>  	if (!keyboard)
>>  		return;
>> @@ -850,13 +851,15 @@ handle_keyboard_focus(struct wl_listener *listener, void *data)
>>  static void
>>  input_method_init_seat(struct weston_seat *seat)
>>  {
>> +	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
>> +
>>  	if (seat->input_method->focus_listener_initialized)
>>  		return;
>>  
>> -	if (seat->keyboard) {
>> +	if (keyboard) {
>>  		seat->input_method->keyboard_focus_listener.notify = handle_keyboard_focus;
>> -		wl_signal_add(&seat->keyboard->focus_signal, &seat->input_method->keyboard_focus_listener);
>> -		seat->keyboard->input_method_grab.interface = &input_method_context_grab;
>> +		wl_signal_add(&keyboard->focus_signal, &seat->input_method->keyboard_focus_listener);
>> +		keyboard->input_method_grab.interface = &input_method_context_grab;
>>  	}
>>  
>>  	seat->input_method->focus_listener_initialized = 1;
>> diff --git a/src/zoom.c b/src/zoom.c
>> index bee038b..38624e0 100644
>> --- a/src/zoom.c
>> +++ b/src/zoom.c
>> @@ -129,9 +129,10 @@ WL_EXPORT void
>>  weston_output_update_zoom(struct weston_output *output)
>>  {
>>  	struct weston_seat *seat = weston_zoom_pick_seat(output->compositor);
>> +	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>>  
>> -	output->zoom.current.x = seat->pointer->x;
>> -	output->zoom.current.y = seat->pointer->y;
>> +	output->zoom.current.x = pointer->x;
>> +	output->zoom.current.y = pointer->y;
>>  
>>  	weston_zoom_transition(output);
>>  	weston_output_update_zoom_transform(output);
>> @@ -152,13 +153,14 @@ WL_EXPORT void
>>  weston_output_activate_zoom(struct weston_output *output)
>>  {
>>  	struct weston_seat *seat = weston_zoom_pick_seat(output->compositor);
>> +	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>>  
>>  	if (output->zoom.active)
>>  		return;
>>  
>>  	output->zoom.active = 1;
>>  	output->disable_planes++;
>> -	wl_signal_add(&seat->pointer->motion_signal,
>> +	wl_signal_add(&pointer->motion_signal,
>>  		      &output->zoom.motion_listener);
>>  }
>>  
>> diff --git a/tests/surface-screenshot.c b/tests/surface-screenshot.c
>> index 57ec925..c0b4bd2 100644
>> --- a/tests/surface-screenshot.c
>> +++ b/tests/surface-screenshot.c
>> @@ -131,6 +131,7 @@ static void
>>  trigger_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
>>  		void *data)
>>  {
>> +	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>>  	const char *prefix = "surfaceshot-";
>>  	const char *suffix = ".pam";
>>  	char fname[1024];
>> @@ -143,12 +144,10 @@ trigger_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
>>  	int ret;
>>  	FILE *fp;
>>  
>> -	if (seat->pointer_device_count == 0 ||
>> -	    !seat->pointer ||
>> -	    !seat->pointer->focus)
>> +	if (!pointer || !pointer->focus)
>>  		return;
>>  
>> -	surface = seat->pointer->focus->surface;
>> +	surface = pointer->focus->surface;
>>  
>>  	weston_surface_get_content_size(surface, &width, &height);
>>  
>> diff --git a/tests/weston-test.c b/tests/weston-test.c
>> index 9f1f49b..284705a 100644
>> --- a/tests/weston-test.c
>> +++ b/tests/weston-test.c
>> @@ -78,7 +78,10 @@ static void
>>  notify_pointer_position(struct weston_test *test, struct wl_resource *resource)
>>  {
>>  	struct weston_seat *seat = get_seat(test);
>> -	struct weston_pointer *pointer = seat->pointer;
>> +	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>> +
>> +	if (!pointer)
>> +		return;
>>  
>>  	weston_test_send_pointer_position(resource, pointer->x, pointer->y);
>>  }
>> @@ -139,7 +142,7 @@ move_pointer(struct wl_client *client, struct wl_resource *resource,
>>  {
>>  	struct weston_test *test = wl_resource_get_user_data(resource);
>>  	struct weston_seat *seat = get_seat(test);
>> -	struct weston_pointer *pointer = seat->pointer;
>> +	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>>  
>>  	notify_motion(seat, 100,
>>  		      wl_fixed_from_int(x) - pointer->x,
>> @@ -166,12 +169,13 @@ activate_surface(struct wl_client *client, struct wl_resource *resource,
>>  		wl_resource_get_user_data(surface_resource) : NULL;
>>  	struct weston_test *test = wl_resource_get_user_data(resource);
>>  	struct weston_seat *seat;
>> +	struct weston_keyboard *keyboard;
>>  
>>  	seat = get_seat(test);
>> -
>> +	keyboard = weston_seat_get_keyboard(seat);
>>  	if (surface) {
>>  		weston_surface_activate(surface, seat);
>> -		notify_keyboard_focus_in(seat, &seat->keyboard->keys,
>> +		notify_keyboard_focus_in(seat, &keyboard->keys,
>>  					 STATE_UPDATE_AUTOMATIC);
>>  	}
>>  	else {
>> diff --git a/xwayland/dnd.c b/xwayland/dnd.c
>> index f0f2457..944c220 100644
>> --- a/xwayland/dnd.c
>> +++ b/xwayland/dnd.c
>> @@ -151,6 +151,7 @@ handle_enter(struct weston_wm *wm, xcb_client_message_event_t *client_message)
>>  {
>>  	struct dnd_data_source *source;
>>  	struct weston_seat *seat = weston_wm_pick_seat(wm);
>> +	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>>  	char **p;
>>  	const char *name;
>>  	uint32_t *types;
>> @@ -210,7 +211,7 @@ handle_enter(struct weston_wm *wm, xcb_client_message_event_t *client_message)
>>  	}
>>  
>>  	free(reply);
>> -	weston_pointer_start_drag(seat->pointer, &source->base, NULL, NULL);
>> +	weston_pointer_start_drag(pointer, &source->base, NULL, NULL);
>>  }
>>  
>>  int
>> diff --git a/xwayland/window-manager.c b/xwayland/window-manager.c
>> index cab7e20..44fe51d 100644
>> --- a/xwayland/window-manager.c
>> +++ b/xwayland/window-manager.c
>> @@ -1302,12 +1302,16 @@ weston_wm_pick_seat_for_window(struct weston_wm_window *window)
>>  
>>  	seat = NULL;
>>  	wl_list_for_each(s, &wm->server->compositor->seat_list, link) {
>> -		if (s->pointer != NULL && s->pointer->focus &&
>> -		    s->pointer->focus->surface == window->surface &&
>> -		    s->pointer->button_count > 0 &&
>> +		struct weston_pointer *pointer = weston_seat_get_pointer(s);
>> +		struct weston_pointer *old_pointer =
>> +						weston_seat_get_pointer(seat);
> 
> nit: Same indentation inconsistency as above.
> 
> 
> Jonas
> 
>> +
>> +		if (pointer && pointer->focus &&
>> +		    pointer->focus->surface == window->surface &&
>> +		    pointer->button_count > 0 &&
>>  		    (seat == NULL ||
>> -		     s->pointer->grab_serial -
>> -		     seat->pointer->grab_serial < (1 << 30)))
>> +		     pointer->grab_serial -
>> +		     old_pointer->grab_serial < (1 << 30)))
>>  			seat = s;
>>  	}
>>  
>> @@ -1331,13 +1335,14 @@ weston_wm_window_handle_moveresize(struct weston_wm_window *window,
>>  
>>  	struct weston_wm *wm = window->wm;
>>  	struct weston_seat *seat = weston_wm_pick_seat_for_window(window);
>> +	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
>>  	int detail;
>>  	struct weston_shell_interface *shell_interface =
>>  		&wm->server->compositor->shell_interface;
>>  
>> -	if (seat == NULL || seat->pointer->button_count != 1
>> -	    || !seat->pointer->focus
>> -	    || seat->pointer->focus->surface != window->surface)
>> +	if (!pointer || pointer->button_count != 1
>> +	    || !pointer->focus
>> +	    || pointer->focus->surface != window->surface)
>>  		return;
>>  
>>  	detail = client_message->data.data32[2];
>> -- 
>> 2.1.4
>>
>> _______________________________________________
>> 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