summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonny Lamb <jonny.lamb@collabora.co.uk>2014-08-20 11:27:10 +0200
committerPekka Paalanen <pekka.paalanen@collabora.co.uk>2014-09-04 13:34:57 +0300
commit76cf1feb3ba4142c137404f6ebe5c3c7545e154c (patch)
tree832d06f6cce46f4b1c9d5f0e35990b9468e2a727
parent389d205b58af5a716b4fcae1733b5a9db1d6e4c7 (diff)
downloadweston-76cf1feb3ba4142c137404f6ebe5c3c7545e154c.tar.gz
desktop-shell: implement touch popup grabs
Acked-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
-rw-r--r--desktop-shell/shell.c155
1 files changed, 143 insertions, 12 deletions
diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
index 26f13cc7..bf52b93c 100644
--- a/desktop-shell/shell.c
+++ b/desktop-shell/shell.c
@@ -223,9 +223,11 @@ struct shell_seat {
struct {
struct weston_pointer_grab grab;
+ struct weston_touch_grab touch_grab;
struct wl_list surfaces_list;
struct wl_client *client;
int32_t initial_up;
+ enum { POINTER, TOUCH } type;
} popup_grab;
};
@@ -322,6 +324,8 @@ get_default_view(struct weston_surface *surface)
static void
popup_grab_end(struct weston_pointer *pointer);
+static void
+touch_popup_grab_end(struct weston_touch *touch);
static void
shell_grab_start(struct shell_grab *grab,
@@ -333,6 +337,8 @@ shell_grab_start(struct shell_grab *grab,
struct desktop_shell *shell = shsurf->shell;
popup_grab_end(pointer);
+ if (pointer->seat->touch)
+ touch_popup_grab_end(pointer->seat->touch);
grab->grab.interface = interface;
grab->shsurf = shsurf;
@@ -497,6 +503,7 @@ shell_touch_grab_start(struct shell_touch_grab *grab,
{
struct desktop_shell *shell = shsurf->shell;
+ touch_popup_grab_end(touch);
if (touch->seat->pointer)
popup_grab_end(touch->seat->pointer);
@@ -3117,6 +3124,81 @@ static const struct weston_pointer_grab_interface popup_grab_interface = {
};
static void
+touch_popup_grab_down(struct weston_touch_grab *grab, uint32_t time,
+ int touch_id, wl_fixed_t sx, wl_fixed_t sy)
+{
+ struct wl_resource *resource;
+ struct shell_seat *shseat =
+ container_of(grab, struct shell_seat, popup_grab.touch_grab);
+ struct wl_display *display = shseat->seat->compositor->wl_display;
+ uint32_t serial;
+ struct wl_list *resource_list;
+
+ resource_list = &grab->touch->focus_resource_list;
+ if (!wl_list_empty(resource_list)) {
+ serial = wl_display_get_serial(display);
+ wl_resource_for_each(resource, resource_list) {
+ wl_touch_send_down(resource, serial, time,
+ grab->touch->focus->surface->resource,
+ touch_id, sx, sy);
+ }
+ }
+}
+
+static void
+touch_popup_grab_up(struct weston_touch_grab *grab, uint32_t time, int touch_id)
+{
+ struct wl_resource *resource;
+ struct shell_seat *shseat =
+ container_of(grab, struct shell_seat, popup_grab.touch_grab);
+ struct wl_display *display = shseat->seat->compositor->wl_display;
+ uint32_t serial;
+ struct wl_list *resource_list;
+
+ resource_list = &grab->touch->focus_resource_list;
+ if (!wl_list_empty(resource_list)) {
+ serial = wl_display_get_serial(display);
+ wl_resource_for_each(resource, resource_list) {
+ wl_touch_send_up(resource, serial, time, touch_id);
+ }
+ }
+}
+
+static void
+touch_popup_grab_motion(struct weston_touch_grab *grab, uint32_t time,
+ int touch_id, wl_fixed_t sx, wl_fixed_t sy)
+{
+ struct wl_resource *resource;
+ struct wl_list *resource_list;
+
+ resource_list = &grab->touch->focus_resource_list;
+ if (!wl_list_empty(resource_list)) {
+ wl_resource_for_each(resource, resource_list) {
+ wl_touch_send_motion(resource, time, touch_id, sx, sy);
+ }
+ }
+}
+
+static void
+touch_popup_grab_frame(struct weston_touch_grab *grab)
+{
+}
+
+static void
+touch_popup_grab_cancel(struct weston_touch_grab *grab)
+{
+ touch_popup_grab_end(grab->touch);
+}
+
+static const struct weston_touch_grab_interface touch_popup_grab_interface = {
+ touch_popup_grab_down,
+ touch_popup_grab_up,
+ touch_popup_grab_motion,
+ touch_popup_grab_frame,
+ touch_popup_grab_cancel,
+};
+
+static void
shell_surface_send_popup_done(struct shell_surface *shsurf)
{
if (shell_surface_is_wl_shell_surface(shsurf))
@@ -3155,21 +3237,59 @@ popup_grab_end(struct weston_pointer *pointer)
}
static void
-add_popup_grab(struct shell_surface *shsurf, struct shell_seat *shseat)
+touch_popup_grab_end(struct weston_touch *touch)
+{
+ struct weston_touch_grab *grab = touch->grab;
+ struct shell_seat *shseat =
+ container_of(grab, struct shell_seat, popup_grab.touch_grab);
+ struct shell_surface *shsurf;
+ struct shell_surface *prev = NULL;
+
+ if (touch->grab->interface == &touch_popup_grab_interface) {
+ weston_touch_end_grab(grab->touch);
+ shseat->popup_grab.client = NULL;
+ shseat->popup_grab.touch_grab.interface = NULL;
+ assert(!wl_list_empty(&shseat->popup_grab.surfaces_list));
+ /* Send the popup_done event to all the popups open */
+ wl_list_for_each(shsurf, &shseat->popup_grab.surfaces_list, popup.grab_link) {
+ shell_surface_send_popup_done(shsurf);
+ shsurf->popup.shseat = NULL;
+ if (prev) {
+ wl_list_init(&prev->popup.grab_link);
+ }
+ prev = shsurf;
+ }
+ wl_list_init(&prev->popup.grab_link);
+ wl_list_init(&shseat->popup_grab.surfaces_list);
+ }
+}
+
+static void
+add_popup_grab(struct shell_surface *shsurf, struct shell_seat *shseat, int32_t type)
{
struct weston_seat *seat = shseat->seat;
if (wl_list_empty(&shseat->popup_grab.surfaces_list)) {
+ shseat->popup_grab.type = type;
shseat->popup_grab.client = wl_resource_get_client(shsurf->resource);
- shseat->popup_grab.grab.interface = &popup_grab_interface;
- /* We must make sure here that this popup was opened after
- * a mouse press, and not just by moving around with other
- * popups already open. */
- if (shseat->seat->pointer->button_count > 0)
- shseat->popup_grab.initial_up = 0;
+
+ if (type == POINTER) {
+ shseat->popup_grab.grab.interface = &popup_grab_interface;
+ /* We must make sure here that this popup was opened after
+ * a mouse press, and not just by moving around with other
+ * popups already open. */
+ if (shseat->seat->pointer->button_count > 0)
+ shseat->popup_grab.initial_up = 0;
+ } else if (type == TOUCH) {
+ shseat->popup_grab.touch_grab.interface = &touch_popup_grab_interface;
+ }
wl_list_insert(&shseat->popup_grab.surfaces_list, &shsurf->popup.grab_link);
- weston_pointer_start_grab(seat->pointer, &shseat->popup_grab.grab);
+
+ if (type == POINTER)
+ weston_pointer_start_grab(seat->pointer, &shseat->popup_grab.grab);
+ else if (type == TOUCH)
+ weston_touch_start_grab(seat->touch, &shseat->popup_grab.touch_grab);
} else {
wl_list_insert(&shseat->popup_grab.surfaces_list, &shsurf->popup.grab_link);
}
@@ -3183,8 +3303,13 @@ remove_popup_grab(struct shell_surface *shsurf)
wl_list_remove(&shsurf->popup.grab_link);
wl_list_init(&shsurf->popup.grab_link);
if (wl_list_empty(&shseat->popup_grab.surfaces_list)) {
- weston_pointer_end_grab(shseat->popup_grab.grab.pointer);
- shseat->popup_grab.grab.interface = NULL;
+ if (shseat->popup_grab.type == POINTER) {
+ weston_pointer_end_grab(shseat->popup_grab.grab.pointer);
+ shseat->popup_grab.grab.interface = NULL;
+ } else if (shseat->popup_grab.type == TOUCH) {
+ weston_touch_end_grab(shseat->popup_grab.touch_grab.touch);
+ shseat->popup_grab.touch_grab.interface = NULL;
+ }
}
}
@@ -3203,7 +3328,10 @@ shell_map_popup(struct shell_surface *shsurf)
if (shseat->seat->pointer &&
shseat->seat->pointer->grab_serial == shsurf->popup.serial) {
- add_popup_grab(shsurf, shseat);
+ add_popup_grab(shsurf, shseat, POINTER);
+ } else if (shseat->seat->touch &&
+ shseat->seat->touch->grab_serial == shsurf->popup.serial) {
+ add_popup_grab(shsurf, shseat, TOUCH);
} else {
shell_surface_send_popup_done(shsurf);
shseat->popup_grab.client = NULL;
@@ -5014,9 +5142,12 @@ idle_handler(struct wl_listener *listener, void *data)
container_of(listener, struct desktop_shell, idle_listener);
struct weston_seat *seat;
- wl_list_for_each(seat, &shell->compositor->seat_list, link)
+ wl_list_for_each(seat, &shell->compositor->seat_list, link) {
if (seat->pointer)
popup_grab_end(seat->pointer);
+ if (seat->touch)
+ touch_popup_grab_end(seat->touch);
+ }
shell_fade(shell, FADE_OUT);
/* lock() is called from shell_fade_done() */