[PATCH weston 14/19] tablet: Add support for moving windows around using the stylus
Stephen Chandler Paul
thatslyude at gmail.com
Wed Aug 6 16:08:04 PDT 2014
Changing the pointer to the appropriate image while moving the stylus
around isn't supported yet.
Signed-off-by: Stephen Chandler Paul <thatslyude at gmail.com>
---
clients/window.c | 27 +++++
desktop-shell/shell.c | 268 ++++++++++++++++++++++++++++++++++++++++++++++++++
src/compositor.h | 5 +
src/input.c | 23 +++++
4 files changed, 323 insertions(+)
diff --git a/clients/window.c b/clients/window.c
index 83459eb..7b844f8 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -2483,6 +2483,31 @@ frame_tablet_motion_handler(struct widget *widget, struct tablet *tablet,
return frame_get_pointer_image_for_location(data, location);
}
+static void
+frame_tablet_down_handler(struct widget *widget, struct tablet *tablet,
+ uint32_t time, void *data)
+{
+ struct window_frame *frame = data;
+ enum theme_location location;
+
+ /* Map a stylus touch to the left mouse button */
+ location = frame_pointer_button(frame->frame, tablet, BTN_LEFT, 1);
+ frame_handle_status(frame, tablet->input, time, location);
+}
+
+static void
+frame_tablet_up_handler(struct widget *widget, struct tablet *tablet,
+ uint32_t time, void *data)
+{
+ struct window_frame *frame = data;
+ enum theme_location location;
+
+ /* Map the stylus leaving contact with the tablet as releasing the left
+ * mouse button */
+ location = frame_pointer_button(frame->frame, tablet, BTN_LEFT, 0);
+ frame_handle_status(frame, tablet->input, time, location);
+}
+
struct widget *
window_frame_create(struct window *window, void *data)
{
@@ -2511,6 +2536,8 @@ window_frame_create(struct window *window, void *data)
widget_set_touch_down_handler(frame->widget, frame_touch_down_handler);
widget_set_touch_up_handler(frame->widget, frame_touch_up_handler);
widget_set_tablet_motion_handler(frame->widget, frame_tablet_motion_handler);
+ widget_set_tablet_down_handler(frame->widget, frame_tablet_down_handler);
+ widget_set_tablet_up_handler(frame->widget, frame_tablet_up_handler);
window->frame = frame;
diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
index 3c3649c..679d011 100644
--- a/desktop-shell/shell.c
+++ b/desktop-shell/shell.c
@@ -191,6 +191,13 @@ struct shell_touch_grab {
struct weston_touch *touch;
};
+struct shell_tablet_grab {
+ struct weston_tablet_grab grab;
+ struct shell_surface *shsurf;
+ struct wl_listener shsurf_destroy_listener;
+ struct weston_tablet *tablet;
+};
+
struct weston_move_grab {
struct shell_grab base;
wl_fixed_t dx, dy;
@@ -203,6 +210,11 @@ struct weston_touch_move_grab {
wl_fixed_t dx, dy;
};
+struct weston_tablet_move_grab {
+ struct shell_tablet_grab base;
+ wl_fixed_t dx, dy;
+};
+
struct rotate_grab {
struct shell_grab base;
struct weston_matrix rotation;
@@ -220,6 +232,7 @@ 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_added_listener;
struct {
struct weston_pointer_grab grab;
@@ -229,6 +242,11 @@ struct shell_seat {
} popup_grab;
};
+struct tablet_listener {
+ struct wl_listener base;
+ struct wl_listener removed_listener;
+};
+
struct shell_client {
struct wl_resource *resource;
struct wl_client *client;
@@ -465,6 +483,43 @@ shell_touch_grab_end(struct shell_touch_grab *grab)
}
static void
+shell_tablet_grab_start(struct shell_tablet_grab *grab,
+ const struct weston_tablet_grab_interface *interface,
+ struct shell_surface *shsurf,
+ struct weston_tablet *tablet)
+{
+ struct desktop_shell *shell = shsurf->shell;
+
+ if (tablet->seat->pointer)
+ popup_grab_end(tablet->seat->pointer);
+
+ 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->tablet = tablet;
+ shsurf->grabbed = 1;
+
+ weston_tablet_start_grab(tablet, &grab->grab);
+ if (shell->child.desktop_shell)
+ weston_tablet_set_focus(tablet,
+ get_default_view(shell->grab_surface),
+ 0);
+}
+
+static void
+shell_tablet_grab_end(struct shell_tablet_grab *grab)
+{
+ if (grab->shsurf) {
+ wl_list_remove(&grab->shsurf_destroy_listener.link);
+ grab->shsurf->grabbed = 0;
+ }
+
+ weston_tablet_end_grab(grab->tablet);
+}
+
+static void
center_on_output(struct weston_view *view,
struct weston_output *output);
@@ -1649,6 +1704,135 @@ surface_move(struct shell_surface *shsurf, struct weston_seat *seat,
}
static void
+tablet_noop_grab_proximity_in(struct weston_tablet_grab *grab,
+ uint32_t time,
+ struct weston_tablet_tool *tool)
+{
+}
+
+static void
+tablet_move_grab_proximity_out(struct weston_tablet_grab *grab, uint32_t time)
+{
+ struct weston_tablet_move_grab *move =
+ (struct weston_tablet_move_grab *)grab;
+
+ shell_tablet_grab_end(&move->base);
+ free(grab);
+}
+
+static void
+tablet_move_grab_up(struct weston_tablet_grab *grab, uint32_t time)
+{
+ struct weston_tablet_move_grab *move =
+ (struct weston_tablet_move_grab *)grab;
+
+ shell_tablet_grab_end(&move->base);
+ free(grab);
+}
+
+static void
+tablet_noop_grab_down(struct weston_tablet_grab *grab, uint32_t time)
+{
+}
+
+static void
+tablet_move_grab_motion(struct weston_tablet_grab *grab, uint32_t time,
+ wl_fixed_t x, wl_fixed_t y)
+{
+ struct weston_tablet_move_grab *move =
+ (struct weston_tablet_move_grab *)grab;
+ struct shell_surface *shsurf = move->base.shsurf;
+
+ if (!shsurf)
+ return;
+
+ weston_tablet_cursor_move(grab->tablet, 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_noop_grab_pressure(struct weston_tablet_grab *grab, uint32_t time,
+ wl_fixed_t pressure)
+{
+}
+
+static void
+tablet_noop_grab_distance(struct weston_tablet_grab *grab, uint32_t time,
+ wl_fixed_t distance)
+{
+}
+
+static void
+tablet_noop_grab_tilt(struct weston_tablet_grab *grab, uint32_t time,
+ wl_fixed_t tilt_x, wl_fixed_t tilt_y)
+{
+}
+
+static void tablet_noop_grab_button(struct weston_tablet_grab *grab,
+ uint32_t time, uint32_t button,
+ enum wl_tablet_button_state state)
+{
+}
+
+static void
+tablet_noop_grab_frame(struct weston_tablet_grab *grab)
+{
+}
+
+static void
+tablet_move_grab_cancel(struct weston_tablet_grab *grab)
+{
+ struct weston_tablet_move_grab *move =
+ (struct weston_tablet_move_grab *)grab;
+
+ shell_tablet_grab_end(&move->base);
+ free(grab);
+}
+
+static struct weston_tablet_grab_interface tablet_move_grab_interface = {
+ tablet_noop_grab_proximity_in,
+ tablet_move_grab_proximity_out,
+ tablet_move_grab_motion,
+ tablet_noop_grab_down,
+ tablet_move_grab_up,
+ tablet_noop_grab_pressure,
+ tablet_noop_grab_distance,
+ tablet_noop_grab_tilt,
+ tablet_noop_grab_button,
+ tablet_noop_grab_frame,
+ tablet_move_grab_cancel,
+};
+
+static int
+surface_tablet_move(struct shell_surface *shsurf, struct weston_tablet *tablet)
+{
+ struct weston_tablet_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) -
+ tablet->grab_x;
+ move->dy = wl_fixed_from_double(shsurf->view->geometry.y) -
+ tablet->grab_y;
+
+ shell_tablet_grab_start(&move->base, &tablet_move_grab_interface,
+ shsurf, tablet);
+
+ return 0;
+}
+
+static void
common_surface_move(struct wl_resource *resource,
struct wl_resource *seat_resource, uint32_t serial)
{
@@ -1671,6 +1855,20 @@ common_surface_move(struct wl_resource *resource,
if ((surface == shsurf->surface) &&
(surface_touch_move(shsurf, seat) < 0))
wl_resource_post_no_memory(resource);
+ } else if (!wl_list_empty(&seat->tablet_list)) {
+ struct weston_tablet *tablet;
+
+ wl_list_for_each(tablet, &seat->tablet_list, link) {
+ if (tablet->focus &&
+ tablet->grab_serial == serial) {
+ surface = weston_surface_get_main_surface(
+ tablet->focus->surface);
+
+ if ((surface == shsurf->surface) &&
+ (surface_tablet_move(shsurf, tablet) < 0))
+ wl_resource_post_no_memory(resource);
+ }
+ }
}
}
@@ -2057,6 +2255,22 @@ handle_pointer_focus(struct wl_listener *listener, void *data)
}
static void
+handle_tablet_focus(struct wl_listener *listener, void *data)
+{
+ struct weston_tablet *tablet = data;
+ struct weston_view *view = tablet->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)
@@ -2854,6 +3068,38 @@ shell_interface_move(struct shell_surface *shsurf, struct weston_seat *ws)
static const struct weston_pointer_grab_interface popup_grab_interface;
static void
+destroy_tablet_listener(struct wl_listener *listener, void *data)
+{
+ struct tablet_listener *tablet_listener =
+ container_of(listener, struct tablet_listener, removed_listener);
+
+ wl_list_remove(&tablet_listener->removed_listener.link);
+ wl_list_remove(&tablet_listener->base.link);
+ free(tablet_listener);
+}
+
+static void
+handle_tablet_added(struct wl_listener *listener, void *data)
+{
+ struct weston_tablet *tablet = data;
+ struct tablet_listener *tablet_listener;
+
+ tablet_listener = malloc(sizeof *tablet_listener);
+ if (!tablet_listener) {
+ weston_log("no memory to allocate to shell seat tablet "
+ "listener\n");
+ return;
+ }
+
+ tablet_listener->removed_listener.notify = destroy_tablet_listener;
+ wl_signal_add(&tablet->removed_signal,
+ &tablet_listener->removed_listener);
+
+ tablet_listener->base.notify = handle_tablet_focus;
+ wl_signal_add(&tablet->focus_signal, &tablet_listener->base);
+}
+
+static void
destroy_shell_seat(struct wl_listener *listener, void *data)
{
struct shell_seat *shseat =
@@ -2876,6 +3122,7 @@ destroy_shell_seat(struct wl_listener *listener, void *data)
}
wl_list_remove(&shseat->seat_destroy_listener.link);
+ wl_list_remove(&shseat->tablet_added_listener.link);
free(shseat);
}
@@ -2907,6 +3154,7 @@ static struct shell_seat *
create_shell_seat(struct weston_seat *seat)
{
struct shell_seat *shseat;
+ struct weston_tablet *tablet;
shseat = calloc(1, sizeof *shseat);
if (!shseat) {
@@ -2927,6 +3175,26 @@ 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_added_listener.notify = handle_tablet_added;
+ wl_list_init(&shseat->tablet_added_listener.link);
+
+ wl_list_for_each(tablet, &seat->tablet_list, link) {
+ struct tablet_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_listener;
+ wl_signal_add(&tablet->removed_signal,
+ &listener->removed_listener);
+
+ listener->base.notify = handle_tablet_focus;
+ wl_signal_add(&tablet->focus_signal, &listener->base);
+ }
+
shseat->caps_changed_listener.notify = shell_seat_caps_changed;
wl_signal_add(&seat->updated_caps_signal,
&shseat->caps_changed_listener);
diff --git a/src/compositor.h b/src/compositor.h
index 91ce7b7..081be57 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -420,6 +420,9 @@ struct weston_tablet {
uint32_t focus_serial;
uint32_t grab_serial;
+ struct wl_signal focus_signal;
+ struct wl_signal removed_signal;
+
struct weston_tablet_tool *current_tool;
int32_t hotspot_x, hotspot_y;
@@ -436,6 +439,7 @@ struct weston_tablet {
struct weston_tablet_grab *grab;
struct weston_tablet_grab default_grab;
+ wl_fixed_t grab_x, grab_y;
struct wl_list link;
@@ -623,6 +627,7 @@ struct weston_seat {
struct wl_global *tablet_manager;
struct wl_list tablet_manager_resource_list;
+ struct wl_signal tablet_added_signal;
void (*led_update)(struct weston_seat *ws, enum weston_led leds);
diff --git a/src/input.c b/src/input.c
index 62b49ed..baafd70 100644
--- a/src/input.c
+++ b/src/input.c
@@ -750,6 +750,8 @@ weston_tablet_create(void)
tablet->default_grab.interface = &default_tablet_grab_interface;
tablet->default_grab.tablet = tablet;
tablet->grab = &tablet->default_grab;
+ wl_signal_init(&tablet->focus_signal);
+ wl_signal_init(&tablet->removed_signal);
return tablet;
}
@@ -873,6 +875,8 @@ weston_tablet_set_focus(struct weston_tablet *tablet, struct weston_view *view,
tablet->focus = view;
tablet->focus_view_listener.notify = tablet_focus_view_destroyed;
+
+ wl_signal_emit(&tablet->focus_signal, tablet);
}
WL_EXPORT void
@@ -1136,6 +1140,19 @@ weston_touch_cancel_grab(struct weston_touch *touch)
touch->grab->interface->cancel(touch->grab);
}
+WL_EXPORT void
+weston_tablet_start_grab(struct weston_tablet *tablet, struct weston_tablet_grab *grab)
+{
+ tablet->grab = grab;
+ grab->tablet = tablet;
+}
+
+WL_EXPORT void
+weston_tablet_end_grab(struct weston_tablet *tablet)
+{
+ tablet->grab = &tablet->default_grab;
+}
+
static void
weston_pointer_clamp_for_output(struct weston_pointer *pointer,
struct weston_output *output,
@@ -1946,6 +1963,9 @@ notify_tablet_down(struct weston_tablet *tablet, uint32_t time)
weston_compositor_idle_inhibit(compositor);
tablet->tool_contact_status = WESTON_TOOL_DOWN;
+ tablet->grab_serial = wl_display_get_serial(compositor->wl_display);
+ tablet->grab_x = tablet->x;
+ tablet->grab_y = tablet->y;
grab->interface->down(grab, time);
}
@@ -2786,6 +2806,7 @@ weston_seat_add_tablet(struct weston_seat *seat)
if (tablet == NULL)
return NULL;
+ wl_signal_emit(&seat->tablet_added_signal, tablet);
tablet->seat = seat;
return tablet;
@@ -2796,6 +2817,7 @@ weston_seat_release_tablet(struct weston_tablet *tablet)
{
struct wl_resource *resource;
+ wl_signal_emit(&tablet->removed_signal, tablet);
weston_tablet_set_focus(tablet, NULL, 0);
wl_resource_for_each(resource, &tablet->resource_list)
wl_tablet_send_removed(resource);
@@ -2836,6 +2858,7 @@ weston_seat_init(struct weston_seat *seat, struct weston_compositor *ec,
wl_list_init(&seat->tablet_list);
wl_list_init(&seat->tablet_manager_resource_list);
wl_list_init(&seat->tablet_tool_list);
+ wl_signal_init(&seat->tablet_added_signal);
seat->global = wl_global_create(ec->wl_display, &wl_seat_interface, 4,
seat, bind_seat);
--
1.8.5.5
More information about the wayland-devel
mailing list