summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDerek Foreman <derekf@osg.samsung.com>2015-11-06 15:56:10 -0600
committerDerek Foreman <derekf@osg.samsung.com>2015-12-08 13:04:50 -0600
commit748c695ef9ed191afd2b8726e474b7d4eb3917a3 (patch)
tree46a7cceeb9c0b8ea0c4847b2359cb0aa5efb9813
parent3cc004a65051b107e34c72852c229e32d9683706 (diff)
downloadweston-748c695ef9ed191afd2b8726e474b7d4eb3917a3.tar.gz
compositor-wayland: Add touch support
Adds support for touch devices to the wayland backend. Signed-off-by: Derek Foreman <derekf@osg.samsung.com> Reviewed-by: Daniel Stone <daniels@collabora.com>
-rw-r--r--src/compositor-wayland.c160
1 files changed, 160 insertions, 0 deletions
diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c
index 6f88ffab..4ea0b7d1 100644
--- a/src/compositor-wayland.c
+++ b/src/compositor-wayland.c
@@ -177,10 +177,13 @@ struct wayland_input {
enum weston_key_state_update keyboard_state_update;
uint32_t key_serial;
uint32_t enter_serial;
+ uint32_t touch_points;
+ bool touch_active;
bool has_focus;
int seat_version;
struct wayland_output *output;
+ struct wayland_output *touch_focus;
struct wayland_output *keyboard_focus;
};
@@ -1619,6 +1622,148 @@ static const struct wl_keyboard_listener keyboard_listener = {
};
static void
+input_handle_touch_down(void *data, struct wl_touch *wl_touch,
+ uint32_t serial, uint32_t time,
+ struct wl_surface *surface, int32_t id, wl_fixed_t x,
+ wl_fixed_t y)
+{
+ struct wayland_input *input = data;
+ struct wayland_output *output;
+ enum theme_location location;
+ bool first_touch;
+ int32_t fx, fy;
+
+ first_touch = (input->touch_points == 0);
+ input->touch_points++;
+
+ input->touch_focus = wl_surface_get_user_data(surface);
+ output = input->touch_focus;
+ if (!first_touch && !input->touch_active)
+ return;
+
+ if (output->frame) {
+ location = frame_touch_down(output->frame, input, id,
+ wl_fixed_to_int(x),
+ wl_fixed_to_int(y));
+
+ frame_interior(output->frame, &fx, &fy, NULL, NULL);
+ x -= wl_fixed_from_int(fx);
+ y -= wl_fixed_from_int(fy);
+
+ if (frame_status(output->frame) & FRAME_STATUS_REPAINT)
+ weston_output_schedule_repaint(&output->base);
+
+ if (first_touch && (frame_status(output->frame) & FRAME_STATUS_MOVE)) {
+ input->touch_points--;
+ wl_shell_surface_move(output->parent.shell_surface,
+ input->parent.seat, serial);
+ frame_status_clear(output->frame,
+ FRAME_STATUS_MOVE);
+ return;
+ }
+
+ if (first_touch && location != THEME_LOCATION_CLIENT_AREA)
+ return;
+ }
+
+ weston_output_transform_coordinate(&output->base, x, y, &x, &y);
+
+ notify_touch(&input->base, time, id, x, y, WL_TOUCH_DOWN);
+ input->touch_active = true;
+}
+
+static void
+input_handle_touch_up(void *data, struct wl_touch *wl_touch,
+ uint32_t serial, uint32_t time, int32_t id)
+{
+ struct wayland_input *input = data;
+ struct wayland_output *output = input->touch_focus;
+ bool active = input->touch_active;
+
+ input->touch_points--;
+ if (input->touch_points == 0) {
+ input->touch_focus = NULL;
+ input->touch_active = false;
+ }
+
+ if (!output)
+ return;
+
+ if (output->frame) {
+ frame_touch_up(output->frame, input, id);
+
+ if (frame_status(output->frame) & FRAME_STATUS_CLOSE) {
+ wayland_output_destroy(&output->base);
+ input->touch_focus = NULL;
+ input->keyboard_focus = NULL;
+ if (wl_list_empty(&input->backend->compositor->output_list))
+ weston_compositor_exit(input->backend->compositor);
+
+ return;
+ }
+ if (frame_status(output->frame) & FRAME_STATUS_REPAINT)
+ weston_output_schedule_repaint(&output->base);
+ }
+
+ if (active)
+ notify_touch(&input->base, time, id, 0, 0, WL_TOUCH_UP);
+}
+
+static void
+input_handle_touch_motion(void *data, struct wl_touch *wl_touch,
+ uint32_t time, int32_t id, wl_fixed_t x,
+ wl_fixed_t y)
+{
+ struct wayland_input *input = data;
+ struct wayland_output *output = input->touch_focus;
+ int32_t fx, fy;
+
+ if (!output || !input->touch_active)
+ return;
+
+ if (output->frame) {
+ frame_interior(output->frame, &fx, &fy, NULL, NULL);
+ x -= wl_fixed_from_int(fx);
+ y -= wl_fixed_from_int(fy);
+ }
+
+ weston_output_transform_coordinate(&output->base, x, y, &x, &y);
+
+ notify_touch(&input->base, time, id, x, y, WL_TOUCH_MOTION);
+}
+
+static void
+input_handle_touch_frame(void *data, struct wl_touch *wl_touch)
+{
+ struct wayland_input *input = data;
+
+ if (!input->touch_focus || !input->touch_active)
+ return;
+
+ notify_touch_frame(&input->base);
+}
+
+static void
+input_handle_touch_cancel(void *data, struct wl_touch *wl_touch)
+{
+ struct wayland_input *input = data;
+
+ if (!input->touch_focus || !input->touch_active)
+ return;
+
+ notify_touch_cancel(&input->base);
+}
+
+static const struct wl_touch_listener touch_listener = {
+ input_handle_touch_down,
+ input_handle_touch_up,
+ input_handle_touch_motion,
+ input_handle_touch_frame,
+ input_handle_touch_cancel,
+};
+
+
+static void
input_handle_capabilities(void *data, struct wl_seat *seat,
enum wl_seat_capability caps)
{
@@ -1652,6 +1797,21 @@ input_handle_capabilities(void *data, struct wl_seat *seat,
input->parent.keyboard = NULL;
weston_seat_release_keyboard(&input->base);
}
+
+ if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !input->parent.touch) {
+ input->parent.touch = wl_seat_get_touch(seat);
+ wl_touch_set_user_data(input->parent.touch, input);
+ wl_touch_add_listener(input->parent.touch,
+ &touch_listener, input);
+ weston_seat_init_touch(&input->base);
+ } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && input->parent.touch) {
+ if (input->seat_version >= WL_TOUCH_RELEASE_SINCE_VERSION)
+ wl_touch_release(input->parent.touch);
+ else
+ wl_touch_destroy(input->parent.touch);
+ input->parent.touch = NULL;
+ weston_seat_release_touch(&input->base);
+ }
}
static void