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

Derek Foreman derekf at osg.samsung.com
Fri Jul 31 14:55:32 PDT 2015


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.

Reviewed-by: Jonas Ã…dahl <jadahl at gmail.com>
Signed-off-by: Derek Foreman <derekf at osg.samsung.com>
---

Removed an accidentally added newline

Added comments to the 3 functions that use *_state pointers
directly explaining why we're doing out of spec things to
avoid a race.

rebased (and fixed exposay and zoom conflicts)

 desktop-shell/exposay.c             |  34 ++---
 desktop-shell/input-panel.c         |   7 +-
 desktop-shell/shell.c               | 191 +++++++++++++++++-----------
 fullscreen-shell/fullscreen-shell.c |  18 ++-
 ivi-shell/hmi-controller.c          |  30 +++--
 ivi-shell/input-panel-ivi.c         |   7 +-
 src/compositor-drm.c                |  10 +-
 src/compositor-wayland.c            |   8 +-
 src/compositor-x11.c                |  18 ++-
 src/compositor.c                    |  27 ++--
 src/compositor.h                    |  15 ++-
 src/data-device.c                   |  41 +++---
 src/input.c                         | 246 +++++++++++++++++++++++++-----------
 src/libinput-seat.c                 |  15 ++-
 src/main.c                          |   7 +-
 src/text-backend.c                  |  19 +--
 src/zoom.c                          |   9 +-
 tests/surface-screenshot.c          |   7 +-
 tests/weston-test.c                 |   9 +-
 xwayland/dnd.c                      |   3 +-
 xwayland/window-manager.c           |  23 ++--
 21 files changed, 484 insertions(+), 260 deletions(-)

diff --git a/desktop-shell/exposay.c b/desktop-shell/exposay.c
index 3d5d0c3..109f8e3 100644
--- a/desktop-shell/exposay.c
+++ b/desktop-shell/exposay.c
@@ -525,14 +525,16 @@ 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);
 
-	if (seat->pointer_device_count)
-		weston_pointer_end_grab(seat->pointer);
+	if (pointer)
+		weston_pointer_end_grab(pointer);
 
-	if (seat->keyboard_device_count) {
-		weston_keyboard_end_grab(seat->keyboard);
-		if (seat->keyboard->input_method_resource)
-			seat->keyboard->grab = &seat->keyboard->input_method_grab;
+	if (keyboard) {
+		weston_keyboard_end_grab(keyboard);
+		if (keyboard->input_method_resource)
+			keyboard->grab = &keyboard->input_method_grab;
 	}
 
 	return EXPOSAY_LAYOUT_INACTIVE;
@@ -566,28 +568,30 @@ 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);
 	shell->exposay.clicked = NULL;
 	wl_list_init(&shell->exposay.surface_list);
 
 	lower_fullscreen_layer(shell, NULL);
 	shell->exposay.grab_kbd.interface = &exposay_kbd_grab;
-	weston_keyboard_start_grab(seat->keyboard,
+	weston_keyboard_start_grab(keyboard,
 	                           &shell->exposay.grab_kbd);
-	weston_keyboard_set_focus(seat->keyboard, NULL);
+	weston_keyboard_set_focus(keyboard, NULL);
 
 	shell->exposay.grab_ptr.interface = &exposay_ptr_grab;
-	if (seat->pointer_device_count) {
-		weston_pointer_start_grab(seat->pointer,
+	if (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 1028df1..251d044 100644
--- a/desktop-shell/input-panel.c
+++ b/desktop-shell/input-panel.c
@@ -68,9 +68,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);
+
+		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 009e671..487c3e7 100644
--- a/desktop-shell/shell.c
+++ b/desktop-shell/shell.c
@@ -378,10 +378,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;
@@ -546,10 +547,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;
@@ -900,27 +902,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);
+
 		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);
+
 		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);
 	}
 }
 
@@ -928,11 +936,12 @@ static void
 replace_focus_state(struct desktop_shell *shell, struct workspace *ws,
 		    struct weston_seat *seat)
 {
+	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
 	struct focus_state *state;
 
 	wl_list_for_each(state, &ws->focus_list, link) {
 		if (state->seat == seat) {
-			focus_state_set_focus(state, seat->keyboard->focus);
+			focus_state_set_focus(state, keyboard->focus);
 			return;
 		}
 	}
@@ -1431,12 +1440,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);
+
+		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);
@@ -1447,6 +1459,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;
@@ -1454,7 +1467,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 ||
@@ -1782,23 +1795,25 @@ 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->pointer, true) < 0))
+		    (surface_move(shsurf, pointer, true) < 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->touch) < 0))
+		    (surface_touch_move(shsurf, touch) < 0))
 			wl_resource_post_no_memory(resource);
 	}
 }
@@ -1986,20 +2001,21 @@ common_surface_resize(struct wl_resource *resource,
 		      uint32_t edges)
 {
 	struct weston_seat *seat = wl_resource_get_user_data(seat_resource);
+	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
 	struct shell_surface *shsurf = wl_resource_get_user_data(resource);
 	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;
 
-	if (surface_resize(shsurf, seat->pointer, edges) < 0)
+	if (surface_resize(shsurf, pointer, edges) < 0)
 		wl_resource_post_no_memory(resource);
 }
 
@@ -2096,10 +2112,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);
@@ -2121,15 +2139,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)
-			continue;
-		if (seat->pointer->focus->surface->resource == NULL)
+		struct weston_pointer *pointer = weston_seat_get_pointer(seat);
+
+		if (!pointer ||
+		    !pointer->focus ||
+		    !pointer->focus->surface->resource)
 			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;
@@ -2684,11 +2704,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);
+
+		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);
@@ -3020,17 +3043,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);
+
 		/* 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;
@@ -3061,7 +3089,7 @@ shell_interface_set_maximized(struct shell_surface *shsurf)
 static int
 shell_interface_move(struct shell_surface *shsurf, struct weston_seat *ws)
 {
-	return surface_move(shsurf, ws->pointer, true);
+	return surface_move(shsurf, weston_seat_get_pointer(ws), true);
 }
 
 static int
@@ -3069,7 +3097,7 @@ shell_interface_resize(struct shell_surface *shsurf,
 		       struct weston_seat *ws,
 		       uint32_t edges)
 {
-	return surface_resize(shsurf, ws->pointer, edges);
+	return surface_resize(shsurf, weston_seat_get_pointer(ws), edges);
 }
 
 static const struct weston_pointer_grab_interface popup_grab_interface;
@@ -3101,24 +3129,28 @@ destroy_shell_seat(struct wl_listener *listener, void *data)
 static void
 shell_seat_caps_changed(struct wl_listener *listener, void *data)
 {
+	struct weston_keyboard *keyboard;
+	struct weston_pointer *pointer;
 	struct shell_seat *seat;
 
 	seat = container_of(listener, struct shell_seat, caps_changed_listener);
+	keyboard = weston_seat_get_keyboard(seat->seat);
+	pointer = weston_seat_get_pointer(seat->seat);
 
-	if (seat->seat->keyboard_device_count &&
+	if (keyboard &&
 	    wl_list_empty(&seat->keyboard_focus_listener.link)) {
-		wl_signal_add(&seat->seat->keyboard->focus_signal,
+		wl_signal_add(&keyboard->focus_signal,
 			      &seat->keyboard_focus_listener);
-	} else if (!seat->seat->keyboard_device_count) {
+	} else if (!keyboard) {
 		wl_list_remove(&seat->keyboard_focus_listener.link);
 		wl_list_init(&seat->keyboard_focus_listener.link);
 	}
 
-	if (seat->seat->pointer_device_count &&
+	if (pointer &&
 	    wl_list_empty(&seat->pointer_focus_listener.link)) {
-		wl_signal_add(&seat->seat->pointer->focus_signal,
+		wl_signal_add(&pointer->focus_signal,
 			      &seat->pointer_focus_listener);
-	} else if (!seat->seat->pointer_device_count) {
+	} else if (!pointer) {
 		wl_list_remove(&seat->pointer_focus_listener.link);
 		wl_list_init(&seat->pointer_focus_listener.link);
 	}
@@ -3415,6 +3447,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);
@@ -3441,7 +3475,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 =
@@ -3452,10 +3486,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 {
@@ -3498,6 +3532,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;
@@ -3506,12 +3542,12 @@ 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 {
@@ -4776,18 +4812,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;
@@ -5168,10 +5205,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);
+
+		if (!keyboard)
 			continue;
 
-		weston_keyboard_set_focus(seat->keyboard, NULL);
+		weston_keyboard_set_focus(keyboard, NULL);
 	}
 }
 
@@ -5405,10 +5445,13 @@ 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);
@@ -5456,9 +5499,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;
 		}
 	}
diff --git a/fullscreen-shell/fullscreen-shell.c b/fullscreen-shell/fullscreen-shell.c
index cae6ed5..ef9302b 100644
--- a/fullscreen-shell/fullscreen-shell.c
+++ b/fullscreen-shell/fullscreen-shell.c
@@ -96,15 +96,17 @@ static void
 seat_caps_changed(struct wl_listener *l, void *data)
 {
 	struct weston_seat *seat = data;
+	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
+	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
 	struct pointer_focus_listener *listener;
 	struct fs_output *fsout;
 
 	listener = container_of(l, struct pointer_focus_listener, seat_caps);
 
 	/* no pointer */
-	if (seat->pointer_device_count) {
+	if (pointer) {
 		if (!listener->pointer_focus.link.prev) {
-			wl_signal_add(&seat->pointer->focus_signal,
+			wl_signal_add(&pointer->focus_signal,
 				      &listener->pointer_focus);
 		}
 	} else {
@@ -113,7 +115,7 @@ seat_caps_changed(struct wl_listener *l, void *data)
 		}
 	}
 
-	if (seat->keyboard_device_count && seat->keyboard->focus != NULL) {
+	if (keyboard && keyboard->focus != NULL) {
 		wl_list_for_each(fsout, &listener->shell->output_list, link) {
 			if (fsout->surface) {
 				weston_surface_activate(fsout->surface, seat);
@@ -681,7 +683,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);
+
+			if (keyboard && !keyboard->focus)
 				weston_surface_activate(surface, seat);
 		}
 	}
@@ -729,7 +734,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);
+
+		if (keyboard && !keyboard->focus)
 			weston_surface_activate(surface, seat);
 	}
 }
diff --git a/ivi-shell/hmi-controller.c b/ivi-shell/hmi-controller.c
index eae346a..760bf06 100644
--- a/ivi-shell/hmi-controller.c
+++ b/ivi-shell/hmi-controller.c
@@ -1469,15 +1469,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;
@@ -1568,6 +1571,9 @@ ivi_hmi_controller_workspace_control(struct wl_client *client,
 	struct pointer_move_grab *pnt_move_grab = NULL;
 	struct touch_move_grab *tch_move_grab = NULL;
 	struct weston_seat *seat = NULL;
+	struct weston_pointer *pointer;
+	struct weston_touch *touch;
+
 	enum HMI_GRAB_DEVICE device;
 
 	if (hmi_ctrl->workspace_count < 2)
@@ -1586,21 +1592,23 @@ ivi_hmi_controller_workspace_control(struct wl_client *client,
 
 	switch (device) {
 	case HMI_GRAB_DEVICE_POINTER:
-		pnt_move_grab = create_workspace_pointer_move(seat->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:
-		tch_move_grab = create_workspace_touch_move(seat->touch,
+		touch = weston_seat_get_touch(seat);
+		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:
diff --git a/ivi-shell/input-panel-ivi.c b/ivi-shell/input-panel-ivi.c
index c624ef3..ecd497e 100644
--- a/ivi-shell/input-panel-ivi.c
+++ b/ivi-shell/input-panel-ivi.c
@@ -70,9 +70,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);
+
+		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/compositor-drm.c b/src/compositor-drm.c
index 3cb6b84..2aab691 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -2075,6 +2075,7 @@ setup_output_seat_constraint(struct drm_backend *b,
 			     const char *s)
 {
 	if (strcmp(s, "") != 0) {
+		struct weston_pointer *pointer;
 		struct udev_seat *seat;
 
 		seat = udev_seat_get_named(&b->input, s);
@@ -2083,10 +2084,11 @@ setup_output_seat_constraint(struct drm_backend *b,
 
 		seat->base.output = output;
 
-		if (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 a8e63e1..1b40e46 100644
--- a/src/compositor-wayland.c
+++ b/src/compositor-wayland.c
@@ -1479,7 +1479,7 @@ input_handle_keymap(void *data, struct wl_keyboard *keyboard, uint32_t format,
 
 	close(fd);
 
-	if (input->base.keyboard)
+	if (weston_seat_get_keyboard(&input->base))
 		weston_seat_update_keymap(&input->base, keymap);
 	else
 		weston_seat_init_keyboard(&input->base, keymap);
@@ -1569,11 +1569,12 @@ input_handle_key(void *data, struct wl_keyboard *keyboard,
 }
 
 static void
-input_handle_modifiers(void *data, struct wl_keyboard *keyboard,
+input_handle_modifiers(void *data, struct wl_keyboard *wl_keyboard,
 		       uint32_t serial_in, uint32_t mods_depressed,
 		       uint32_t mods_latched, uint32_t mods_locked,
 		       uint32_t group)
 {
+	struct weston_keyboard *keyboard;
 	struct wayland_input *input = data;
 	struct wayland_backend *b = input->backend;
 	uint32_t serial_out;
@@ -1586,7 +1587,8 @@ input_handle_modifiers(void *data, struct wl_keyboard *keyboard,
 	else
 		serial_out = wl_display_next_serial(b->compositor->wl_display);
 
-	xkb_state_update_mask(input->base.keyboard->xkb_state.state,
+	keyboard = weston_seat_get_keyboard(&input->base);
+	xkb_state_update_mask(keyboard->xkb_state.state,
 			      mods_depressed, mods_latched,
 			      mods_locked, 0, 0, group);
 	notify_modifiers(&input->base, serial_out);
diff --git a/src/compositor-x11.c b/src/compositor-x11.c
index 55c85ed..73ba783 100644
--- a/src/compositor-x11.c
+++ b/src/compositor-x11.c
@@ -174,7 +174,9 @@ x11_backend_get_keymap(struct x11_backend *b)
 static uint32_t
 get_xkb_mod_mask(struct x11_backend *b, uint32_t in)
 {
-	struct weston_xkb_info *info = b->core_seat.keyboard->xkb_info;
+	struct weston_keyboard *keyboard =
+		weston_seat_get_keyboard(&b->core_seat);
+	struct weston_xkb_info *info = keyboard->xkb_info;
 	uint32_t ret = 0;
 
 	if ((in & ShiftMask) && info->shift_mod != XKB_MOD_INVALID)
@@ -206,6 +208,7 @@ x11_backend_setup_xkb(struct x11_backend *b)
 	b->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;
@@ -285,7 +288,8 @@ x11_backend_setup_xkb(struct x11_backend *b)
 		return;
 	}
 
-	xkb_state_update_mask(b->core_seat.keyboard->xkb_state.state,
+	keyboard = weston_seat_get_keyboard(&b->core_seat);
+	xkb_state_update_mask(keyboard->xkb_state.state,
 			      get_xkb_mod_mask(b, state_reply->baseMods),
 			      get_xkb_mod_mask(b, state_reply->latchedMods),
 			      get_xkb_mod_mask(b, state_reply->lockedMods),
@@ -975,7 +979,10 @@ static void delete_cb(void *data)
 static void
 update_xkb_state(struct x11_backend *b, xcb_xkb_state_notify_event_t *state)
 {
-	xkb_state_update_mask(b->core_seat.keyboard->xkb_state.state,
+	struct weston_keyboard *keyboard =
+		weston_seat_get_keyboard(&b->core_seat);
+
+	xkb_state_update_mask(keyboard->xkb_state.state,
 			      get_xkb_mod_mask(b, state->baseMods),
 			      get_xkb_mod_mask(b, state->latchedMods),
 			      get_xkb_mod_mask(b, state->lockedMods),
@@ -1003,9 +1010,10 @@ static void
 update_xkb_state_from_core(struct x11_backend *b, uint16_t x11_mask)
 {
 	uint32_t mask = get_xkb_mod_mask(b, x11_mask);
-	struct weston_keyboard *keyboard = b->core_seat.keyboard;
+	struct weston_keyboard *keyboard
+		= weston_seat_get_keyboard(&b->core_seat);
 
-	xkb_state_update_mask(b->core_seat.keyboard->xkb_state.state,
+	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 66c3eee..541829c 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -95,7 +95,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)
@@ -1752,15 +1752,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);
+
+		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);
 	}
 }
 
@@ -4587,10 +4592,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,
-							interface);
-		}
+		struct weston_pointer *pointer = weston_seat_get_pointer(seat);
+
+		if (pointer)
+			weston_pointer_set_default_grab(pointer, interface);
 	}
 }
 
diff --git a/src/compositor.h b/src/compositor.h
index b74f7e8..2654f8d 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -503,9 +503,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_state;
+	struct weston_keyboard *keyboard_state;
+	struct weston_touch *touch_state;
 	int pointer_device_count;
 	int keyboard_device_count;
 	int touch_device_count;
@@ -1587,6 +1587,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 825b734..9825bda 100644
--- a/src/data-device.c
+++ b/src/data-device.c
@@ -662,23 +662,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;
@@ -698,9 +700,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);
@@ -711,13 +713,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));
@@ -766,6 +769,7 @@ weston_seat_set_selection(struct weston_seat *seat,
 			  struct weston_data_source *source, uint32_t serial)
 {
 	struct weston_surface *focus = NULL;
+	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
 
 	if (seat->selection_data_source &&
 	    seat->selection_serial - serial < UINT32_MAX / 2)
@@ -780,8 +784,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));
 	}
@@ -939,11 +943,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 bbcaec5..8f24ccd 100644
--- a/src/input.c
+++ b/src/input.c
@@ -53,7 +53,7 @@ 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)
 		return;
@@ -391,7 +391,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);
 	struct wl_resource *resource;
 	struct wl_list *resource_list;
 
@@ -626,7 +627,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;
@@ -946,7 +947,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);
@@ -956,7 +957,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 {
@@ -993,7 +994,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);
@@ -1004,9 +1005,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);
 	}
 
@@ -1018,7 +1020,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);
@@ -1049,7 +1051,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;
 
@@ -1124,7 +1126,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;
@@ -1196,7 +1198,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 */
@@ -1240,7 +1242,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;
@@ -1319,7 +1321,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;
 
@@ -1376,8 +1378,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... */
@@ -1400,7 +1404,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;
 
@@ -1426,7 +1430,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);
@@ -1448,8 +1453,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
@@ -1507,7 +1512,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;
@@ -1586,7 +1591,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);
@@ -1706,9 +1711,18 @@ seat_get_pointer(struct wl_client *client, struct wl_resource *resource,
 		 uint32_t id)
 {
 	struct weston_seat *seat = wl_resource_get_user_data(resource);
+	/* We use the pointer_state directly, which means we'll
+	 * give a wl_pointer if the seat has ever had one - even though
+	 * the spec explicitly states that this request only takes effect
+	 * if the seat has the pointer capability.
+	 *
+	 * This prevents a race between the compositor sending new
+	 * capabilities and the client trying to use the old ones.
+	 */
+	struct weston_pointer *pointer = seat->pointer_state;
 	struct wl_resource *cr;
 
-	if (!seat->pointer)
+	if (!pointer)
 		return;
 
         cr = wl_resource_create(client, &wl_pointer_interface,
@@ -1721,25 +1735,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);
 	}
 }
@@ -1758,16 +1772,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;
@@ -1778,7 +1795,15 @@ 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_state directly, which means we'll
+	 * give a wl_keyboard if the seat has ever had one - even though
+	 * the spec explicitly states that this request only takes effect
+	 * if the seat has the keyboard capability.
+	 *
+	 * This prevents a race between the compositor sending new
+	 * capabilities and the client trying to use the old ones.
+	 */
+	struct weston_keyboard *keyboard = seat->keyboard_state;
 	struct wl_resource *cr;
 
 	if (!keyboard)
@@ -1858,9 +1883,18 @@ seat_get_touch(struct wl_client *client, struct wl_resource *resource,
 	       uint32_t id)
 {
 	struct weston_seat *seat = wl_resource_get_user_data(resource);
+	/* We use the touch_state directly, which means we'll
+	 * give a wl_touch if the seat has ever had one - even though
+	 * the spec explicitly states that this request only takes effect
+	 * if the seat has the touch capability.
+	 *
+	 * This prevents a race between the compositor sending new
+	 * capabilities and the client trying to use the old ones.
+	 */
+	struct weston_touch *touch = seat->touch_state;
 	struct wl_resource *cr;
 
-	if (!seat->touch)
+	if (!touch)
 		return;
 
         cr = wl_resource_create(client, &wl_touch_interface,
@@ -1870,12 +1904,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,
@@ -1901,11 +1935,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_device_count)
+	if (weston_seat_get_pointer(seat))
 		caps |= WL_SEAT_CAPABILITY_POINTER;
-	if (seat->keyboard_device_count)
+	if (weston_seat_get_keyboard(seat))
 		caps |= WL_SEAT_CAPABILITY_KEYBOARD;
-	if (seat->touch_device_count)
+	if (weston_seat_get_touch(seat))
 		caps |= WL_SEAT_CAPABILITY_TOUCH;
 
 	wl_seat_send_capabilities(resource, caps);
@@ -2095,17 +2129,19 @@ 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
 }
@@ -2115,7 +2151,7 @@ weston_seat_init_keyboard(struct weston_seat *seat, struct xkb_keymap *keymap)
 {
 	struct weston_keyboard *keyboard;
 
-	if (seat->keyboard) {
+	if (seat->keyboard_state) {
 		seat->keyboard_device_count += 1;
 		if (seat->keyboard_device_count == 1)
 			seat_send_updated_caps(seat);
@@ -2151,7 +2187,7 @@ weston_seat_init_keyboard(struct weston_seat *seat, struct xkb_keymap *keymap)
 	}
 #endif
 
-	seat->keyboard = keyboard;
+	seat->keyboard_state = keyboard;
 	seat->keyboard_device_count = 1;
 	keyboard->seat = seat;
 
@@ -2196,9 +2232,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_state, NULL);
+		weston_keyboard_cancel_grab(seat->keyboard_state);
+		weston_keyboard_reset_state(seat->keyboard_state);
 		seat_send_updated_caps(seat);
 	}
 }
@@ -2208,7 +2244,7 @@ weston_seat_init_pointer(struct weston_seat *seat)
 {
 	struct weston_pointer *pointer;
 
-	if (seat->pointer) {
+	if (seat->pointer_state) {
 		seat->pointer_device_count += 1;
 		if (seat->pointer_device_count == 1)
 			seat_send_updated_caps(seat);
@@ -2219,7 +2255,7 @@ weston_seat_init_pointer(struct weston_seat *seat)
 	if (pointer == NULL)
 		return;
 
-	seat->pointer = pointer;
+	seat->pointer_state = pointer;
 	seat->pointer_device_count = 1;
 	pointer->seat = seat;
 
@@ -2229,7 +2265,7 @@ 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_state;
 
 	seat->pointer_device_count--;
 	if (seat->pointer_device_count == 0) {
@@ -2256,7 +2292,7 @@ weston_seat_init_touch(struct weston_seat *seat)
 {
 	struct weston_touch *touch;
 
-	if (seat->touch) {
+	if (seat->touch_state) {
 		seat->touch_device_count += 1;
 		if (seat->touch_device_count == 1)
 			seat_send_updated_caps(seat);
@@ -2267,7 +2303,7 @@ weston_seat_init_touch(struct weston_seat *seat)
 	if (touch == NULL)
 		return;
 
-	seat->touch = touch;
+	seat->touch_state = touch;
 	seat->touch_device_count = 1;
 	touch->seat = seat;
 
@@ -2279,9 +2315,9 @@ weston_seat_release_touch(struct weston_seat *seat)
 {
 	seat->touch_device_count--;
 	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_state, NULL);
+		weston_touch_cancel_grab(seat->touch_state);
+		weston_touch_reset_state(seat->touch_state);
 		seat_send_updated_caps(seat);
 	}
 }
@@ -2321,12 +2357,12 @@ 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_state)
+		weston_pointer_destroy(seat->pointer_state);
+	if (seat->keyboard_state)
+		weston_keyboard_destroy(seat->keyboard_state);
+	if (seat->touch_state)
+		weston_touch_destroy(seat->touch_state);
 
 	free (seat->seat_name);
 
@@ -2334,3 +2370,69 @@ weston_seat_release(struct weston_seat *seat)
 
 	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 is present
+ *
+ * The keyboard pointer for a seat isn't freed when all keyboards are removed,
+ * so it 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_state;
+
+	return NULL;
+}
+
+/** Get a seat's pointer pointer
+ *
+ * \param seat The seat to query
+ * \return The seat's pointer pointer, or NULL if no pointer device is present
+ *
+ * The pointer pointer for a seat isn't freed when all mice are removed,
+ * so it 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_state;
+
+	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 is present
+ *
+ * The touch pointer for a seat isn't freed when all touch devices are removed,
+ * so it 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_state;
+
+	return NULL;
+}
diff --git a/src/libinput-seat.c b/src/libinput-seat.c
index 6353667..e6d44b0 100644
--- a/src/libinput-seat.c
+++ b/src/libinput-seat.c
@@ -60,6 +60,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);
@@ -77,10 +78,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) {
@@ -378,8 +380,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 =
+		weston_seat_get_keyboard(&seat->base);
+
 	udev_seat_remove_devices(seat);
-	if (seat->base.keyboard)
+	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/main.c b/src/main.c
index 0017ab5..4acb913 100644
--- a/src/main.c
+++ b/src/main.c
@@ -798,8 +798,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);
+
+			if (keyboard)
+				weston_keyboard_set_locks(keyboard,
 							  WESTON_NUM_LOCK,
 							  WESTON_NUM_LOCK);
 		}
diff --git a/src/text-backend.c b/src/text-backend.c
index 76e4e15..cd6c4d99 100644
--- a/src/text-backend.c
+++ b/src/text-backend.c
@@ -658,7 +658,7 @@ input_method_context_grab_keyboard(struct wl_client *client,
 		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);
@@ -687,7 +687,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);
@@ -706,7 +706,7 @@ input_method_context_modifiers(struct wl_client *client,
 		wl_resource_get_user_data(resource);
 
 	struct weston_seat *seat = context->input_method->seat;
-	struct weston_keyboard *keyboard = 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,
@@ -812,10 +812,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;
@@ -907,15 +908,17 @@ 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,
+		wl_signal_add(&keyboard->focus_signal,
 			      &seat->input_method->keyboard_focus_listener);
-		seat->keyboard->input_method_grab.interface =
+		keyboard->input_method_grab.interface =
 			&input_method_context_grab;
 	}
 
diff --git a/src/zoom.c b/src/zoom.c
index efc658c..8eb20fe 100644
--- a/src/zoom.c
+++ b/src/zoom.c
@@ -129,11 +129,12 @@ WL_EXPORT void
 weston_output_update_zoom(struct weston_output *output)
 {
 	struct weston_seat *seat = output->zoom.seat;
+	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
 
 	assert(output->zoom.active);
 
-	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);
@@ -154,13 +155,15 @@ WL_EXPORT void
 weston_output_activate_zoom(struct weston_output *output,
 			    struct weston_seat *seat)
 {
+	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
+
 	if (output->zoom.active)
 		return;
 
 	output->zoom.active = true;
 	output->zoom.seat = seat;
 	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 a54ae22..703d48b 100644
--- a/tests/surface-screenshot.c
+++ b/tests/surface-screenshot.c
@@ -139,6 +139,7 @@ trigger_binding(struct weston_keyboard *keyboard, uint32_t time, uint32_t key,
 	char fname[1024];
 	struct weston_surface *surface;
 	struct weston_seat *seat = keyboard->seat;
+	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
 	int width, height;
 	char desc[512];
 	void *pixels;
@@ -147,12 +148,10 @@ trigger_binding(struct weston_keyboard *keyboard, 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 df9a139..b593f1e 100644
--- a/tests/weston-test.c
+++ b/tests/weston-test.c
@@ -83,7 +83,7 @@ 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);
 
 	weston_test_send_pointer_position(resource, pointer->x, pointer->y);
 }
@@ -144,7 +144,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,
@@ -171,12 +171,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 eb9c5dd..a036b30 100644
--- a/xwayland/dnd.c
+++ b/xwayland/dnd.c
@@ -154,6 +154,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;
@@ -213,7 +214,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 c3a57c1..daebf47 100644
--- a/xwayland/window-manager.c
+++ b/xwayland/window-manager.c
@@ -1316,12 +1316,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 &&
-		    (seat == NULL ||
-		     s->pointer->grab_serial -
-		     seat->pointer->grab_serial < (1 << 30)))
+		struct weston_pointer *pointer = weston_seat_get_pointer(s);
+		struct weston_pointer *old_pointer =
+			weston_seat_get_pointer(seat);
+
+		if (pointer && pointer->focus &&
+		    pointer->focus->surface == window->surface &&
+		    pointer->button_count > 0 &&
+		    (!seat ||
+		     pointer->grab_serial -
+		     old_pointer->grab_serial < (1 << 30)))
 			seat = s;
 	}
 
@@ -1345,13 +1349,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.4.6



More information about the wayland-devel mailing list