[weston,v3,09/17] tablet: Add support for moving windows around using the stylus

Submitted by Maniraj Devadoss on Dec. 19, 2017, 8:33 a.m.

Details

Message ID 1513672422-6010-10-git-send-email-Maniraj.Devadoss@in.bosch.com
State New
Headers show
Series "Tablet device support for weston" ( rev: 3 ) in Wayland

Not browsing as part of any series.

Commit Message

Maniraj Devadoss Dec. 19, 2017, 8:33 a.m.
From: Lyude Paul <thatslyude@gmail.com>

Changing the pointer to the appropriate image while moving the stylus
around isn't supported yet.

Co-authored-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Lyude Paul <thatslyude@gmail.com>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Bastian Farkas <bfarkas@de.adit-jv.com>
---
 clients/window.c       |  33 ++++++
 desktop-shell/shell.c  | 267 +++++++++++++++++++++++++++++++++++++++++++++++++
 libweston/compositor.h |   6 ++
 libweston/input.c      |  12 +++
 4 files changed, 318 insertions(+)

Patch hide | download patch | download mbox

diff --git a/clients/window.c b/clients/window.c
index ac4004b..2d3d09f 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -2666,6 +2666,36 @@  frame_tablet_tool_motion_handler(struct widget *widget,
 	return CURSOR_LEFT_PTR;
 }
 
+static void
+frame_tablet_tool_down_handler(struct widget *widget,
+			       struct tablet_tool *tool,
+			       void *data)
+{
+	struct window_frame *frame = data;
+	enum theme_location location;
+	uint32_t time = 0; /* FIXME: we should be doing this in the frame
+			      handler where we have the timestamp  */
+
+	/* Map a stylus touch to the left mouse button */
+	location = frame_pointer_button(frame->frame, tool, BTN_LEFT, 1);
+	frame_handle_status(frame, tool->input, time, location);
+}
+
+static void
+frame_tablet_tool_up_handler(struct widget *widget, struct tablet_tool *tool,
+			     void *data)
+{
+	struct window_frame *frame = data;
+	enum theme_location location;
+	uint32_t time = 0; /* FIXME: we should be doing this in the frame
+			      handler where we have the timestamp  */
+
+	/* Map the stylus leaving contact with the tablet as releasing the left
+	 * mouse button */
+	location = frame_pointer_button(frame->frame, tool, BTN_LEFT, 0);
+	frame_handle_status(frame, tool->input, time, location);
+}
+
 struct widget *
 window_frame_create(struct window *window, void *data)
 {
@@ -2697,6 +2727,9 @@  window_frame_create(struct window *window, void *data)
 					     frame_tablet_tool_motion_handler,
 					     NULL, NULL, NULL,
 					     NULL, NULL, NULL);
+	widget_set_tablet_tool_down_handler(frame->widget, frame_tablet_tool_down_handler);
+	widget_set_tablet_tool_up_handler(frame->widget, frame_tablet_tool_up_handler);
+
 	window->frame = frame;
 
 	return frame->child;
diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
index f80088f..c34dd9e 100644
--- a/desktop-shell/shell.c
+++ b/desktop-shell/shell.c
@@ -158,6 +158,13 @@  struct shell_touch_grab {
 	struct weston_touch *touch;
 };
 
+struct shell_tablet_tool_grab {
+	struct weston_tablet_tool_grab grab;
+	struct shell_surface *shsurf;
+	struct wl_listener shsurf_destroy_listener;
+	struct weston_tablet_tool *tool;
+};
+
 struct weston_move_grab {
 	struct shell_grab base;
 	wl_fixed_t dx, dy;
@@ -170,6 +177,11 @@  struct weston_touch_move_grab {
 	wl_fixed_t dx, dy;
 };
 
+struct weston_tablet_tool_move_grab {
+	struct shell_tablet_tool_grab base;
+	wl_fixed_t dx, dy;
+};
+
 struct rotate_grab {
 	struct shell_grab base;
 	struct weston_matrix rotation;
@@ -187,8 +199,14 @@  struct shell_seat {
 	struct wl_listener caps_changed_listener;
 	struct wl_listener pointer_focus_listener;
 	struct wl_listener keyboard_focus_listener;
+	struct wl_listener tablet_tool_added_listener;
 };
 
+struct tablet_tool_listener {
+	struct wl_listener base;
+	struct wl_listener removed_listener;
+};
+ 
 
 static struct desktop_shell *
 shell_surface_get_shell(struct shell_surface *shsurf);
@@ -410,6 +428,43 @@  shell_touch_grab_end(struct shell_touch_grab *grab)
 }
 
 static void
+shell_tablet_tool_grab_start(struct shell_tablet_tool_grab *grab,
+			     const struct weston_tablet_tool_grab_interface *interface,
+			     struct shell_surface *shsurf,
+			     struct weston_tablet_tool *tool)
+{
+	struct desktop_shell *shell = shsurf->shell;
+
+	if (tool->seat->pointer_state)
+		popup_grab_end(tool->seat->pointer_state);
+
+	grab->grab.interface = interface;
+	grab->shsurf = shsurf;
+	grab->shsurf_destroy_listener.notify = destroy_shell_grab_shsurf;
+	wl_signal_add(&shsurf->destroy_signal, &grab->shsurf_destroy_listener);
+
+	grab->tool = tool;
+	shsurf->grabbed = 1;
+
+	weston_tablet_tool_start_grab(tool, &grab->grab);
+	if (shell->child.desktop_shell)
+		weston_tablet_tool_set_focus(tool,
+					     get_default_view(shell->grab_surface),
+					     0);
+}
+
+static void
+shell_tablet_tool_grab_end(struct shell_tablet_tool_grab *grab)
+{
+	if (grab->shsurf) {
+		wl_list_remove(&grab->shsurf_destroy_listener.link);
+		grab->shsurf->grabbed = 0;
+	}
+
+	weston_tablet_tool_end_grab(grab->tool);
+}
+
+static void
 center_on_output(struct weston_view *view,
 		 struct weston_output *output);
 
@@ -1570,6 +1625,138 @@  struct weston_resize_grab {
 };
 
 static void
+tablet_tool_noop_grab_proximity_in(struct weston_tablet_tool_grab *grab,
+				   uint32_t time,
+				   struct weston_tablet *tablet)
+{
+}
+
+static void
+tablet_tool_move_grab_proximity_out(struct weston_tablet_tool_grab *grab, uint32_t time)
+{
+	struct weston_tablet_tool_move_grab *move =
+		(struct weston_tablet_tool_move_grab *)grab;
+
+	shell_tablet_tool_grab_end(&move->base);
+	free(grab);
+}
+
+static void
+tablet_tool_move_grab_up(struct weston_tablet_tool_grab *grab, uint32_t time)
+{
+	struct weston_tablet_tool_move_grab *move =
+		(struct weston_tablet_tool_move_grab *)grab;
+
+	shell_tablet_tool_grab_end(&move->base);
+	free(grab);
+}
+
+static void
+tablet_tool_noop_grab_down(struct weston_tablet_tool_grab *grab, uint32_t time)
+{
+}
+
+static void
+tablet_tool_move_grab_motion(struct weston_tablet_tool_grab *grab, uint32_t time,
+			wl_fixed_t x, wl_fixed_t y)
+{
+	struct weston_tablet_tool_move_grab *move =
+		(struct weston_tablet_tool_move_grab *)grab;
+	struct shell_surface *shsurf = move->base.shsurf;
+
+	if (!shsurf)
+		return;
+
+	weston_tablet_tool_cursor_move(grab->tool, x, y);
+	weston_view_set_position(shsurf->view,
+				 wl_fixed_to_double(x + move->dx),
+				 wl_fixed_to_double(y + move->dy));
+	weston_compositor_schedule_repaint(shsurf->surface->compositor);
+}
+
+static void
+tablet_tool_noop_grab_pressure(struct weston_tablet_tool_grab *grab,
+			       uint32_t time,
+			       uint32_t pressure)
+{
+}
+
+static void
+tablet_tool_noop_grab_distance(struct weston_tablet_tool_grab *grab,
+			       uint32_t time,
+			       uint32_t distance)
+{
+}
+
+static void
+tablet_tool_noop_grab_tilt(struct weston_tablet_tool_grab *grab,
+			   uint32_t time,
+			   int32_t tilt_x, int32_t tilt_y)
+{
+}
+
+static void tablet_tool_noop_grab_button(struct weston_tablet_tool_grab *grab,
+					 uint32_t time, uint32_t button,
+					 enum zwp_tablet_tool_v1_button_state state)
+{
+}
+
+static void
+tablet_tool_noop_grab_frame(struct weston_tablet_tool_grab *grab,
+			    uint32_t time)
+{
+}
+
+static void
+tablet_tool_move_grab_cancel(struct weston_tablet_tool_grab *grab)
+{
+	struct weston_tablet_tool_move_grab *move =
+		(struct weston_tablet_tool_move_grab *)grab;
+
+	shell_tablet_tool_grab_end(&move->base);
+	free(grab);
+}
+
+static struct weston_tablet_tool_grab_interface tablet_tool_move_grab_interface = {
+	tablet_tool_noop_grab_proximity_in,
+	tablet_tool_move_grab_proximity_out,
+	tablet_tool_move_grab_motion,
+	tablet_tool_noop_grab_down,
+	tablet_tool_move_grab_up,
+	tablet_tool_noop_grab_pressure,
+	tablet_tool_noop_grab_distance,
+	tablet_tool_noop_grab_tilt,
+	tablet_tool_noop_grab_button,
+	tablet_tool_noop_grab_frame,
+	tablet_tool_move_grab_cancel,
+};
+
+static int
+surface_tablet_tool_move(struct shell_surface *shsurf, struct weston_tablet_tool *tool)
+{
+	struct weston_tablet_tool_move_grab *move;
+
+	if (!shsurf)
+		return -1;
+
+	if (shsurf->state.fullscreen || shsurf->state.maximized)
+		return 0;
+
+	move = malloc(sizeof(*move));
+	if (!move)
+		return -1;
+
+	move->dx = wl_fixed_from_double(shsurf->view->geometry.x) - tool->grab_x;
+	move->dy = wl_fixed_from_double(shsurf->view->geometry.y) - tool->grab_y;
+
+	shell_tablet_tool_grab_start(&move->base, &tablet_tool_move_grab_interface,
+				     shsurf, tool);
+
+	return 0;
+}
+
+
+static void
 resize_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
 		   struct weston_pointer_motion_event *event)
 {
@@ -1822,6 +2009,22 @@  handle_pointer_focus(struct wl_listener *listener, void *data)
 }
 
 static void
+handle_tablet_tool_focus(struct wl_listener *listener, void *data)
+{
+	struct weston_tablet_tool *tool = data;
+	struct weston_view *view = tool->focus;
+	struct weston_compositor *compositor;
+	uint32_t serial;
+
+	if (!view)
+		return;
+
+	compositor = view->surface->compositor;
+	serial = wl_display_next_serial(compositor->wl_display);
+	ping_handler(view->surface, serial);
+}
+
+static void
 shell_surface_lose_keyboard_focus(struct shell_surface *shsurf)
 {
 	if (--shsurf->focus_count == 0)
@@ -2167,6 +2370,37 @@  get_focused_output(struct weston_compositor *compositor)
 }
 
 static void
+destroy_tablet_tool_listener(struct wl_listener *listener, void *data)
+{
+	struct tablet_tool_listener *tool_listener =
+		container_of(listener, struct tablet_tool_listener, removed_listener);
+
+	wl_list_remove(&tool_listener->removed_listener.link);
+	wl_list_remove(&tool_listener->base.link);
+	free(tool_listener);
+}
+
+static void
+handle_tablet_tool_added(struct wl_listener *listener, void *data)
+{
+	struct weston_tablet_tool *tool = data;
+	struct tablet_tool_listener *tool_listener;
+
+	tool_listener = malloc(sizeof *tool_listener);
+	if (!tool_listener) {
+		weston_log("no memory to allocate to shell seat tablet listener\n");
+		return;
+	}
+
+	tool_listener->removed_listener.notify = destroy_tablet_tool_listener;
+	wl_signal_add(&tool->removed_signal,
+		      &tool_listener->removed_listener);
+
+	tool_listener->base.notify = handle_tablet_tool_focus;
+	wl_signal_add(&tool->focus_signal, &tool_listener->base);
+}
+
+static void
 destroy_shell_seat(struct wl_listener *listener, void *data)
 {
 	struct shell_seat *shseat =
@@ -2174,6 +2408,7 @@  destroy_shell_seat(struct wl_listener *listener, void *data)
 			     struct shell_seat, seat_destroy_listener);
 
 	wl_list_remove(&shseat->seat_destroy_listener.link);
+	wl_list_remove(&shseat->tablet_tool_added_listener.link);
 	free(shseat);
 }
 
@@ -2211,6 +2446,7 @@  static struct shell_seat *
 create_shell_seat(struct weston_seat *seat)
 {
 	struct shell_seat *shseat;
+	struct weston_tablet_tool *tool;
 
 	shseat = calloc(1, sizeof *shseat);
 	if (!shseat) {
@@ -2230,6 +2466,25 @@  create_shell_seat(struct weston_seat *seat)
 	shseat->pointer_focus_listener.notify = handle_pointer_focus;
 	wl_list_init(&shseat->pointer_focus_listener.link);
 
+	shseat->tablet_tool_added_listener.notify = handle_tablet_tool_added;
+	wl_list_init(&shseat->tablet_tool_added_listener.link);
+
+	wl_list_for_each(tool, &seat->tablet_tool_list, link) {
+		struct tablet_tool_listener *listener = malloc(sizeof *listener);
+
+		if (!listener) {
+			weston_log("no memory to allocate to shell seat tablet listener\n");
+			break;
+		}
+
+		listener->removed_listener.notify = destroy_tablet_tool_listener;
+		wl_signal_add(&tool->removed_signal,
+			      &listener->removed_listener);
+
+		listener->base.notify = handle_tablet_tool_focus;
+		wl_signal_add(&tool->focus_signal, &listener->base);
+	}
+
 	shseat->caps_changed_listener.notify = shell_seat_caps_changed;
 	wl_signal_add(&seat->updated_caps_signal,
 		      &shseat->caps_changed_listener);
@@ -2615,6 +2870,18 @@  desktop_surface_move(struct weston_desktop_surface *desktop_surface,
 		if ((focus == surface) &&
 		    (surface_touch_move(shsurf, touch) < 0))
 			wl_resource_post_no_memory(resource);
+	} else if (!wl_list_empty(&seat->tablet_tool_list)) {
+		struct weston_tablet_tool *tool;
+
+		wl_list_for_each(tool, &seat->tablet_tool_list, link) {
+			if (tool->focus && tool->grab_serial == serial) {
+				surface = weston_surface_get_main_surface(
+							  tool->focus->surface);
+				if (surface == shsurf->surface &&
+				    surface_tablet_tool_move(shsurf, tool) < 0)
+					wl_resource_post_no_memory(resource);
+			}
+		}
 	}
 }
 
diff --git a/libweston/compositor.h b/libweston/compositor.h
index 95c2a2d..1d58293 100644
--- a/libweston/compositor.h
+++ b/libweston/compositor.h
@@ -470,6 +470,11 @@  struct weston_tablet_tool {
 	struct wl_listener sprite_destroy_listener;
 
 	wl_fixed_t x, y;
+
+	struct wl_signal focus_signal;
+	struct wl_signal removed_signal;
+
+	wl_fixed_t grab_x, grab_y;
 };
 
 struct weston_tablet {
@@ -737,6 +742,7 @@  struct weston_seat {
 	char *seat_name;
 
 	struct wl_list tablet_seat_resource_list;
+	struct wl_signal tablet_tool_added_signal;
 };
 
 enum {
diff --git a/libweston/input.c b/libweston/input.c
index 7565ea0..e1741a7 100644
--- a/libweston/input.c
+++ b/libweston/input.c
@@ -1292,6 +1292,8 @@  weston_tablet_tool_set_focus(struct weston_tablet_tool *tool,
 						 &tool->focus_resource_listener);
 	tool->focus = view;
 	tool->focus_view_listener.notify = tablet_tool_focus_view_destroyed;
+
+	wl_signal_emit(&tool->focus_signal, tool);
 }
 
 WL_EXPORT void
@@ -1530,6 +1532,9 @@  weston_tablet_tool_create(void)
 	tool->default_grab.tool = tool;
 	tool->grab = &tool->default_grab;
 
+	wl_signal_init(&tool->focus_signal);
+	wl_signal_init(&tool->removed_signal);
+
 	return tool;
 }
 
@@ -3014,6 +3019,8 @@  notify_tablet_tool_down(struct weston_tablet_tool *tool,
 
 	 tool->tip_is_down = true;
 	 tool->grab_serial = wl_display_get_serial(compositor->wl_display);
+	 tool->grab_x = tool->x;
+	 tool->grab_y = tool->y;
 
 	 grab->interface->down(grab, time);
 }
@@ -3810,6 +3817,8 @@  weston_seat_release_tablet_tool(struct weston_tablet_tool *tool)
 {
 	/* FIXME: nothing is calling this function yet, tools are only
 	   released on shutdown when the seat goes away */
+	wl_signal_emit(&tool->removed_signal, tool);
+
 	weston_tablet_tool_destroy(tool);
 }
 
@@ -3869,6 +3878,8 @@  weston_seat_add_tablet_tool(struct weston_seat *seat)
 	if (tool == NULL)
 		return NULL;
 
+	wl_signal_emit(&seat->tablet_tool_added_signal, tool);
+
 	wl_list_init(&tool->resource_list);
 	tool->seat = seat;
 
@@ -3902,6 +3913,7 @@  weston_seat_init(struct weston_seat *seat, struct weston_compositor *ec,
 	wl_list_init(&seat->tablet_seat_resource_list);
 	wl_list_init(&seat->tablet_list);
 	wl_list_init(&seat->tablet_tool_list);
+	wl_signal_init(&seat->tablet_tool_added_signal);
 
 	seat->global = wl_global_create(ec->wl_display, &wl_seat_interface, 5,
 					seat, bind_seat);