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>
dev
Derek Foreman 9 years ago
parent 3cc004a650
commit 748c695ef9
  1. 160
      src/compositor-wayland.c

@ -177,10 +177,13 @@ struct wayland_input {
enum weston_key_state_update keyboard_state_update; enum weston_key_state_update keyboard_state_update;
uint32_t key_serial; uint32_t key_serial;
uint32_t enter_serial; uint32_t enter_serial;
uint32_t touch_points;
bool touch_active;
bool has_focus; bool has_focus;
int seat_version; int seat_version;
struct wayland_output *output; struct wayland_output *output;
struct wayland_output *touch_focus;
struct wayland_output *keyboard_focus; struct wayland_output *keyboard_focus;
}; };
@ -1618,6 +1621,148 @@ static const struct wl_keyboard_listener keyboard_listener = {
input_handle_repeat_info, input_handle_repeat_info,
}; };
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 static void
input_handle_capabilities(void *data, struct wl_seat *seat, input_handle_capabilities(void *data, struct wl_seat *seat,
enum wl_seat_capability caps) enum wl_seat_capability caps)
@ -1652,6 +1797,21 @@ input_handle_capabilities(void *data, struct wl_seat *seat,
input->parent.keyboard = NULL; input->parent.keyboard = NULL;
weston_seat_release_keyboard(&input->base); 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 static void

Loading…
Cancel
Save