input: Don't test keyboard/pointer/touch pointers

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@osg.samsung.com>
Reviewed-by: Jonas Ã…dahl <jadahl@gmail.com>
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 @@
 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 @@
 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 @@
 	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 @@
 		 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 @@
 		       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 @@
 	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 @@
 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 @@
 
 	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 @@
 				  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 @@
 	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 @@
 		    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 @@
 		      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 @@
 	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 @@
 	/* 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 @@
 
 	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 @@
 	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 @@
 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 @@
 		       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 @@
 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 @@
 {
 	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 @@
 			/* 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 @@
 			       &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 @@
 {
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	 * 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;
 		}
 	}