From 1084da506e663840612bdd39c3c44258d41a454d Mon Sep 17 00:00:00 2001 From: Rusty Lynch Date: Thu, 15 Aug 2013 09:10:08 -0700 Subject: [PATCH] Add touch support for wl_shell_surface_move --- clients/calibrator.c | 4 +- clients/desktop-shell.c | 9 +-- clients/flower.c | 11 ++++ clients/fullscreen.c | 12 ++++ clients/simple-egl.c | 50 ++++++++++++++++ clients/smoke.c | 4 +- clients/transformed.c | 12 ++++ clients/window.c | 52 ++++++++++++---- clients/window.h | 11 +++- src/shell.c | 128 +++++++++++++++++++++++++++++++++++++--- 10 files changed, 263 insertions(+), 30 deletions(-) diff --git a/clients/calibrator.c b/clients/calibrator.c index 781475e8..783cdecc 100644 --- a/clients/calibrator.c +++ b/clients/calibrator.c @@ -163,8 +163,8 @@ button_handler(struct widget *widget, } static void -touch_handler(struct widget *widget, uint32_t serial, uint32_t time, - int32_t id, float x, float y, void *data) +touch_handler(struct widget *widget, struct input *input, uint32_t serial, + uint32_t time, int32_t id, float x, float y, void *data) { struct calibrator *calibrator = data; diff --git a/clients/desktop-shell.c b/clients/desktop-shell.c index 40c27818..319382db 100644 --- a/clients/desktop-shell.c +++ b/clients/desktop-shell.c @@ -322,8 +322,8 @@ panel_launcher_button_handler(struct widget *widget, } static void -panel_launcher_touch_down_handler(struct widget *widget, uint32_t serial, - uint32_t time, int32_t id, +panel_launcher_touch_down_handler(struct widget *widget, struct input *input, + uint32_t serial, uint32_t time, int32_t id, float x, float y, void *data) { struct panel_launcher *launcher; @@ -334,8 +334,9 @@ panel_launcher_touch_down_handler(struct widget *widget, uint32_t serial, } static void -panel_launcher_touch_up_handler(struct widget *widget, uint32_t serial, - uint32_t time, int32_t id, void *data) +panel_launcher_touch_up_handler(struct widget *widget, struct input *input, + uint32_t serial, uint32_t time, int32_t id, + void *data) { struct panel_launcher *launcher; diff --git a/clients/flower.c b/clients/flower.c index b31d5138..825c833e 100644 --- a/clients/flower.c +++ b/clients/flower.c @@ -152,6 +152,16 @@ button_handler(struct widget *widget, } } +static void +touch_down_handler(struct widget *widget, struct input *input, + uint32_t serial, uint32_t time, int32_t id, + float x, float y, void *data) +{ + struct flower *flower = data; + window_touch_move(flower->window, input, + display_get_serial(flower->display)); +} + int main(int argc, char *argv[]) { struct flower flower; @@ -178,6 +188,7 @@ int main(int argc, char *argv[]) widget_set_redraw_handler(flower.widget, redraw_handler); widget_set_button_handler(flower.widget, button_handler); widget_set_default_cursor(flower.widget, CURSOR_HAND1); + widget_set_touch_down_handler(flower.widget, touch_down_handler); window_schedule_resize(flower.window, flower.width, flower.height); diff --git a/clients/fullscreen.c b/clients/fullscreen.c index bea1a15f..72e2c81f 100644 --- a/clients/fullscreen.c +++ b/clients/fullscreen.c @@ -277,6 +277,16 @@ button_handler(struct widget *widget, } } +static void +touch_handler(struct widget *widget, struct input *input, + uint32_t serial, uint32_t time, int32_t id, + float x, float y, void *data) +{ + struct fullscreen *fullscreen = data; + window_touch_move(fullscreen->window, input, + display_get_serial(fullscreen->display)); +} + static void usage(int error_code) { @@ -340,6 +350,8 @@ int main(int argc, char *argv[]) widget_set_button_handler(fullscreen.widget, button_handler); widget_set_motion_handler(fullscreen.widget, motion_handler); + widget_set_touch_down_handler(fullscreen.widget, touch_handler); + window_set_key_handler(fullscreen.window, key_handler); window_set_fullscreen_handler(fullscreen.window, fullscreen_handler); diff --git a/clients/simple-egl.c b/clients/simple-egl.c index 4eeba021..a557fca5 100644 --- a/clients/simple-egl.c +++ b/clients/simple-egl.c @@ -55,6 +55,7 @@ struct display { struct wl_shell *shell; struct wl_seat *seat; struct wl_pointer *pointer; + struct wl_touch *touch; struct wl_keyboard *keyboard; struct wl_shm *shm; struct wl_cursor_theme *cursor_theme; @@ -528,6 +529,46 @@ static const struct wl_pointer_listener pointer_listener = { pointer_handle_axis, }; +static void +touch_handle_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_w, wl_fixed_t y_w) +{ + struct display *d = (struct display *)data; + + wl_shell_surface_move(d->window->shell_surface, d->seat, serial); +} + +static void +touch_handle_up(void *data, struct wl_touch *wl_touch, + uint32_t serial, uint32_t time, int32_t id) +{ +} + +static void +touch_handle_motion(void *data, struct wl_touch *wl_touch, + uint32_t time, int32_t id, wl_fixed_t x_w, wl_fixed_t y_w) +{ +} + +static void +touch_handle_frame(void *data, struct wl_touch *wl_touch) +{ +} + +static void +touch_handle_cancel(void *data, struct wl_touch *wl_touch) +{ +} + +static const struct wl_touch_listener touch_listener = { + touch_handle_down, + touch_handle_up, + touch_handle_motion, + touch_handle_frame, + touch_handle_cancel, +}; + static void keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard, uint32_t format, int fd, uint32_t size) @@ -597,6 +638,15 @@ seat_handle_capabilities(void *data, struct wl_seat *seat, wl_keyboard_destroy(d->keyboard); d->keyboard = NULL; } + + if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !d->touch) { + d->touch = wl_seat_get_touch(seat); + wl_touch_set_user_data(d->touch, d); + wl_touch_add_listener(d->touch, &touch_listener, d); + } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && d->touch) { + wl_touch_destroy(d->touch); + d->touch = NULL; + } } static const struct wl_seat_listener seat_listener = { diff --git a/clients/smoke.c b/clients/smoke.c index 6b557974..dd5f4bd4 100644 --- a/clients/smoke.c +++ b/clients/smoke.c @@ -267,8 +267,8 @@ mouse_motion_handler(struct widget *widget, struct input *input, } static void -touch_motion_handler(struct widget *widget, uint32_t time, - int32_t id, float x, float y, void *data) +touch_motion_handler(struct widget *widget, struct input *input, + uint32_t time, int32_t id, float x, float y, void *data) { smoke_motion_handler(data, x, y); } diff --git a/clients/transformed.c b/clients/transformed.c index e8d817dc..54212dd4 100644 --- a/clients/transformed.c +++ b/clients/transformed.c @@ -221,6 +221,16 @@ button_handler(struct widget *widget, } } +static void +touch_handler(struct widget *widget, struct input *input, + uint32_t serial, uint32_t time, int32_t id, + float x, float y, void *data) +{ + struct transformed *transformed = data; + window_touch_move(transformed->window, input, + display_get_serial(transformed->display)); +} + static void usage(int error_code) { @@ -287,6 +297,8 @@ int main(int argc, char *argv[]) widget_set_redraw_handler(transformed.widget, redraw_handler); widget_set_button_handler(transformed.widget, button_handler); + widget_set_touch_down_handler(transformed.widget, touch_handler); + window_set_key_handler(transformed.window, key_handler); window_set_fullscreen_handler(transformed.window, fullscreen_handler); window_set_output_handler(transformed.window, output_handler); diff --git a/clients/window.c b/clients/window.c index 84d3e739..cee436c6 100644 --- a/clients/window.c +++ b/clients/window.c @@ -1552,7 +1552,9 @@ window_destroy(struct window *window) wl_list_remove(&window->redraw_task.link); - wl_list_for_each(input, &display->input_list, link) { + wl_list_for_each(input, &display->input_list, link) { + if (input->touch_focus == window) + input->touch_focus = NULL; if (input->pointer_focus == window) input->pointer_focus = NULL; if (input->keyboard_focus == window) @@ -2353,8 +2355,8 @@ frame_button_button_handler(struct widget *widget, } static void -frame_button_touch_down_handler(struct widget *widget, uint32_t serial, - uint32_t time, int32_t id, +frame_button_touch_down_handler(struct widget *widget, struct input *input, + uint32_t serial, uint32_t time, int32_t id, float x, float y, void *data) { struct frame_button *frame_button = data; @@ -2692,6 +2694,19 @@ frame_button_handler(struct widget *widget, } } +static void +frame_touch_down_handler(struct widget *widget, struct input *input, + uint32_t serial, uint32_t time, int32_t id, + float x, float y, void *data) +{ + struct window *window = widget->window; + struct display *display = window->display; + + wl_shell_surface_move(window->shell_surface, + input_get_seat(input), + display->serial); +} + struct widget * frame_create(struct window *window, void *data) { @@ -2706,6 +2721,7 @@ frame_create(struct window *window, void *data) widget_set_enter_handler(frame->widget, frame_enter_handler); widget_set_motion_handler(frame->widget, frame_motion_handler); widget_set_button_handler(frame->widget, frame_button_handler); + widget_set_touch_down_handler(frame->widget, frame_touch_down_handler); /* Create empty list for frame buttons */ wl_list_init(&frame->buttons_list); @@ -3207,8 +3223,7 @@ touch_handle_down(void *data, struct wl_touch *wl_touch, float sx = wl_fixed_to_double(x_w); float sy = wl_fixed_to_double(y_w); - DBG("touch_handle_down: %i %i\n", id, wl_list_length(&input->touch_point_list)); - + input->display->serial = serial; input->touch_focus = wl_surface_get_user_data(surface); if (!input->touch_focus) { DBG("Failed to find to touch focus for surface %p\n", surface); @@ -3226,8 +3241,8 @@ touch_handle_down(void *data, struct wl_touch *wl_touch, wl_list_insert(&input->touch_point_list, &tp->link); if (widget->touch_down_handler) - (*widget->touch_down_handler)(widget, serial, - time, id, + (*widget->touch_down_handler)(widget, input, + serial, time, id, sx, sy, widget->user_data); } @@ -3241,8 +3256,6 @@ touch_handle_up(void *data, struct wl_touch *wl_touch, struct input *input = data; struct touch_point *tp, *tmp; - DBG("touch_handle_up: %i %i\n", id, wl_list_length(&input->touch_point_list)); - if (!input->touch_focus) { DBG("No touch focus found for touch up event!\n"); return; @@ -3253,7 +3266,7 @@ touch_handle_up(void *data, struct wl_touch *wl_touch, continue; if (tp->widget->touch_up_handler) - (*tp->widget->touch_up_handler)(tp->widget, serial, + (*tp->widget->touch_up_handler)(tp->widget, input, serial, time, id, tp->widget->user_data); @@ -3285,7 +3298,7 @@ touch_handle_motion(void *data, struct wl_touch *wl_touch, continue; if (tp->widget->touch_motion_handler) - (*tp->widget->touch_motion_handler)(tp->widget, time, + (*tp->widget->touch_motion_handler)(tp->widget, input, time, id, sx, sy, tp->widget->user_data); return; @@ -3307,7 +3320,8 @@ touch_handle_frame(void *data, struct wl_touch *wl_touch) wl_list_for_each_safe(tp, tmp, &input->touch_point_list, link) { if (tp->widget->touch_frame_handler) - (*tp->widget->touch_frame_handler)(tp->widget, tp->widget->user_data); + (*tp->widget->touch_frame_handler)(tp->widget, input, + tp->widget->user_data); wl_list_remove(&tp->link); free(tp); @@ -3329,7 +3343,8 @@ touch_handle_cancel(void *data, struct wl_touch *wl_touch) wl_list_for_each_safe(tp, tmp, &input->touch_point_list, link) { if (tp->widget->touch_cancel_handler) - (*tp->widget->touch_cancel_handler)(tp->widget, tp->widget->user_data); + (*tp->widget->touch_cancel_handler)(tp->widget, input, + tp->widget->user_data); wl_list_remove(&tp->link); free(tp); @@ -3813,6 +3828,16 @@ window_move(struct window *window, struct input *input, uint32_t serial) wl_shell_surface_move(window->shell_surface, input->seat, serial); } +void +window_touch_move(struct window *window, struct input *input, uint32_t serial) +{ + if (!window->shell_surface) + return; + + wl_shell_surface_move(window->shell_surface, input->seat, + window->display->serial); +} + static void surface_set_synchronized(struct surface *surface) { @@ -4920,6 +4945,7 @@ display_add_input(struct display *d, uint32_t id) input = xzalloc(sizeof *input); input->display = d; input->seat = wl_registry_bind(d->registry, id, &wl_seat_interface, 1); + input->touch_focus = NULL; input->pointer_focus = NULL; input->keyboard_focus = NULL; wl_list_init(&input->touch_point_list); diff --git a/clients/window.h b/clients/window.h index 1646d5a8..a2bab90f 100644 --- a/clients/window.h +++ b/clients/window.h @@ -236,6 +236,7 @@ typedef void (*widget_button_handler_t)(struct widget *widget, enum wl_pointer_button_state state, void *data); typedef void (*widget_touch_down_handler_t)(struct widget *widget, + struct input *input, uint32_t serial, uint32_t time, int32_t id, @@ -243,18 +244,22 @@ typedef void (*widget_touch_down_handler_t)(struct widget *widget, float y, void *data); typedef void (*widget_touch_up_handler_t)(struct widget *widget, + struct input *input, uint32_t serial, uint32_t time, int32_t id, void *data); typedef void (*widget_touch_motion_handler_t)(struct widget *widget, + struct input *input, uint32_t time, int32_t id, float x, float y, void *data); -typedef void (*widget_touch_frame_handler_t)(struct widget *widget,void *data); -typedef void (*widget_touch_cancel_handler_t)(struct widget *widget, void *data); +typedef void (*widget_touch_frame_handler_t)(struct widget *widget, + struct input *input, void *data); +typedef void (*widget_touch_cancel_handler_t)(struct widget *widget, + struct input *input, void *data); typedef void (*widget_axis_handler_t)(struct widget *widget, struct input *input, uint32_t time, uint32_t axis, @@ -324,6 +329,8 @@ window_get_display(struct window *window); void window_move(struct window *window, struct input *input, uint32_t time); void +window_touch_move(struct window *window, struct input *input, uint32_t time); +void window_get_allocation(struct window *window, struct rectangle *allocation); void window_schedule_redraw(struct window *window); diff --git a/src/shell.c b/src/shell.c index 8f2be78b..564d5be0 100644 --- a/src/shell.c +++ b/src/shell.c @@ -237,11 +237,23 @@ struct shell_grab { struct wl_listener shsurf_destroy_listener; }; +struct shell_touch_grab { + struct weston_touch_grab grab; + struct shell_surface *shsurf; + struct wl_listener shsurf_destroy_listener; + struct weston_touch *touch; +}; + struct weston_move_grab { struct shell_grab base; wl_fixed_t dx, dy; }; +struct weston_touch_move_grab { + struct shell_touch_grab base; + wl_fixed_t dx, dy; +}; + struct rotate_grab { struct shell_grab base; struct weston_matrix rotation; @@ -349,6 +361,36 @@ shell_grab_end(struct shell_grab *grab) weston_pointer_end_grab(grab->grab.pointer); } +static void +shell_touch_grab_start(struct shell_touch_grab *grab, + const struct weston_touch_grab_interface *interface, + struct shell_surface *shsurf, + struct weston_touch *touch) +{ + struct desktop_shell *shell = shsurf->shell; + + 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->touch = touch; + + weston_touch_start_grab(touch, &grab->grab); + if (shell->child.desktop_shell) + weston_touch_set_focus(touch->seat, shell->grab_surface); +} + +static void +shell_touch_grab_end(struct shell_touch_grab *grab) +{ + if (grab->shsurf) + wl_list_remove(&grab->shsurf_destroy_listener.link); + + weston_touch_end_grab(grab->touch); +} + static void center_on_output(struct weston_surface *surface, struct weston_output *output); @@ -1034,6 +1076,74 @@ bind_workspace_manager(struct wl_client *client, shell->workspaces.num); } +static void +touch_move_grab_down(struct weston_touch_grab *grab, uint32_t time, + int touch_id, wl_fixed_t sx, wl_fixed_t sy) +{ +} + +static void +touch_move_grab_up(struct weston_touch_grab *grab, uint32_t time, int touch_id) +{ + struct shell_touch_grab *shell_grab = container_of(grab, + struct shell_touch_grab, + grab); + shell_touch_grab_end(shell_grab); +} + +static void +touch_move_grab_motion(struct weston_touch_grab *grab, uint32_t time, + int touch_id, wl_fixed_t sx, wl_fixed_t sy) +{ + struct weston_touch_move_grab *move = (struct weston_touch_move_grab *) grab; + struct shell_surface *shsurf = move->base.shsurf; + struct weston_surface *es; + int dx = wl_fixed_to_int(grab->touch->grab_x + move->dx); + int dy = wl_fixed_to_int(grab->touch->grab_y + move->dy); + + if (!shsurf) + return; + + es = shsurf->surface; + + weston_surface_configure(es, dx, dy, + es->geometry.width, es->geometry.height); + + weston_compositor_schedule_repaint(es->compositor); +} + +static const struct weston_touch_grab_interface touch_move_grab_interface = { + touch_move_grab_down, + touch_move_grab_up, + touch_move_grab_motion, +}; + +static int +surface_touch_move(struct shell_surface *shsurf, struct weston_seat *seat) +{ + struct weston_touch_move_grab *move; + + if (!shsurf) + return -1; + + if (shsurf->type == SHELL_SURFACE_FULLSCREEN) + return 0; + + move = malloc(sizeof *move); + if (!move) + return -1; + + move->dx = wl_fixed_from_double(shsurf->surface->geometry.x) - + seat->touch->grab_x; + move->dy = wl_fixed_from_double(shsurf->surface->geometry.y) - + seat->touch->grab_y; + + shell_touch_grab_start(&move->base, &touch_move_grab_interface, shsurf, + seat->touch); + + return 0; +} + static void noop_grab_focus(struct weston_pointer_grab *grab) { @@ -1117,13 +1227,17 @@ shell_surface_move(struct wl_client *client, struct wl_resource *resource, struct weston_surface *surface; surface = weston_surface_get_main_surface(seat->pointer->focus); - if (seat->pointer->button_count == 0 || - seat->pointer->grab_serial != serial || - surface != shsurf->surface) - return; - - if (surface_move(shsurf, seat) < 0) - wl_resource_post_no_memory(resource); + if (seat->pointer->button_count > 0 && seat->pointer->grab_serial == serial) { + surface = weston_surface_get_main_surface(seat->pointer->focus); + if ((surface == shsurf->surface) && + (surface_move(shsurf, seat) < 0)) + wl_resource_post_no_memory(resource); + } else if (seat->touch->grab_serial == serial) { + surface = weston_surface_get_main_surface(seat->touch->focus); + if ((surface == shsurf->surface) && + (surface_touch_move(shsurf, seat) < 0)) + wl_resource_post_no_memory(resource); + } } struct weston_resize_grab {