pepper: Touch API implementation
authorTaekyun Kim <tkq.kim@samsung.com>
Fri, 16 Oct 2015 07:51:06 +0000 (16:51 +0900)
committerTaekyun Kim <tkq.kim@samsung.com>
Fri, 16 Oct 2015 09:13:47 +0000 (18:13 +0900)
Basic usage scenario.

1. Add a touch point when detecting touch down event.
2. Pick a view and set the focus for the point.
3. Move the touch point when detecting touch motion event.
4. Remove the touch point when detecting touch up event.

Send protocol events using pepper_touch_send_XXX APIs when desired.

Change-Id: Ie230ead5a438c835d8330d2bba57f2b6fd9fb358

src/lib/pepper/pepper-internal.h
src/lib/pepper/pepper.h
src/lib/pepper/touch.c

index 1b2e36fc7db080d9a14f158e30c08d64a83de9bd..50c313ffe885a7b81926012b74b0e505b575a0dd 100644 (file)
@@ -17,6 +17,7 @@ typedef struct pepper_data_source   pepper_data_source_t;
 typedef struct pepper_data_device   pepper_data_device_t;
 typedef struct pepper_data_offer    pepper_data_offer_t;
 typedef struct pepper_input         pepper_input_t;
+typedef struct pepper_touch_point   pepper_touch_point_t;
 
 typedef void (*pepper_callback_t)(pepper_object_t *object, void *data);
 
@@ -290,14 +291,30 @@ pepper_keyboard_bind_resource(struct wl_client *client, struct wl_resource *reso
 void
 pepper_keyboard_handle_event(pepper_keyboard_t *keyboard, uint32_t id, pepper_input_event_t *event);
 
+struct pepper_touch_point
+{
+    pepper_touch_t             *touch;
+
+    uint32_t                    id;
+    double                      x, y;
+
+    pepper_view_t              *focus;
+    uint32_t                    focus_serial;
+    pepper_event_listener_t    *focus_destroy_listener;
+
+    pepper_list_t               link;
+};
+
 struct pepper_touch
 {
-    pepper_object_t                 base;
-    pepper_seat_t                  *seat;
-    struct wl_list                  resource_list;
+    pepper_object_t             base;
+    pepper_seat_t              *seat;
+    struct wl_list              resource_list;
 
-    const pepper_touch_grab_t      *grab;
-    void                           *data;
+    pepper_list_t               point_list;
+
+    const pepper_touch_grab_t  *grab;
+    void                       *data;
 };
 
 pepper_touch_t *
index fcd7014794c5c4cb63eea51a6426cba449446755..4200cc8cefba9e967893581def5a46fdf4c9390e 100644 (file)
@@ -441,10 +441,19 @@ PEPPER_API pepper_seat_t *
 pepper_touch_get_seat(pepper_touch_t *touch);
 
 PEPPER_API void
-pepper_touch_set_focus(pepper_touch_t *touch, pepper_view_t *focus);
+pepper_touch_add_point(pepper_touch_t *touch, uint32_t id, double x, double y);
+
+PEPPER_API void
+pepper_touch_remove_point(pepper_touch_t *touch, uint32_t id);
+
+PEPPER_API void
+pepper_touch_point_set_focus(pepper_touch_t *touch, uint32_t id, pepper_view_t *focus);
 
 PEPPER_API pepper_view_t *
-pepper_touch_get_focus(pepper_touch_t *touch);
+pepper_touch_point_get_focus(pepper_touch_t *touch, uint32_t id);
+
+PEPPER_API void
+pepper_touch_point_get_position(pepper_touch_t *touch, uint32_t id, double *x, double *y);
 
 PEPPER_API void
 pepper_touch_send_down(pepper_touch_t *touch, uint32_t time, uint32_t id, double x, double y);
index 579b11e3dd5b2da721852ee11320d9f3c653faa3..2f9441e8f389d695eade8df62cc23877cb39c5e5 100644 (file)
@@ -11,6 +11,59 @@ static const struct wl_touch_interface touch_impl =
     touch_release,
 };
 
+static pepper_touch_point_t *
+get_touch_point(pepper_touch_t *touch, uint32_t id)
+{
+    pepper_touch_point_t *point;
+
+    pepper_list_for_each(point, &touch->point_list, link)
+    {
+        if (point->id == id)
+            return point;
+    }
+
+    return NULL;
+}
+
+static void
+touch_point_set_focus(pepper_touch_point_t *point, pepper_view_t *focus);
+
+static void
+touch_point_handle_focus_destroy(pepper_event_listener_t *listener, pepper_object_t *surface,
+                                 uint32_t id, void *info, void *data)
+{
+    pepper_touch_point_t *point = data;
+    touch_point_set_focus(point, NULL);
+}
+
+static void
+touch_point_set_focus(pepper_touch_point_t *point, pepper_view_t *focus)
+{
+    if (point->focus == focus)
+        return;
+
+    if (point->focus)
+    {
+        pepper_event_listener_remove(point->focus_destroy_listener);
+        pepper_object_emit_event(&point->touch->base, PEPPER_EVENT_FOCUS_LEAVE, point->focus);
+        pepper_object_emit_event(&point->focus->base, PEPPER_EVENT_FOCUS_LEAVE, point->focus);
+    }
+
+    point->focus = focus;
+
+    if (focus)
+    {
+        point->focus_serial = wl_display_next_serial(point->touch->seat->compositor->display);
+
+        point->focus_destroy_listener =
+            pepper_object_add_event_listener(&focus->base, PEPPER_EVENT_OBJECT_DESTROY, 0,
+                                            touch_point_handle_focus_destroy, point);
+
+        pepper_object_emit_event(&point->touch->base, PEPPER_EVENT_FOCUS_ENTER, focus);
+        pepper_object_emit_event(&focus->base, PEPPER_EVENT_FOCUS_ENTER, focus);
+    }
+}
+
 void
 pepper_touch_handle_event(pepper_touch_t *touch, uint32_t id, pepper_input_event_t *event)
 {
@@ -30,6 +83,11 @@ pepper_touch_handle_event(pepper_touch_t *touch, uint32_t id, pepper_input_event
         break;
     case PEPPER_EVENT_TOUCH_MOTION:
         {
+            pepper_touch_point_t *point = get_touch_point(touch, id);
+
+            point->x = event->x;
+            point->y = event->y;
+
             if (touch->grab)
                 touch->grab->motion(touch, touch->data, event->time, event->id, event->x, event->y);
         }
@@ -61,6 +119,7 @@ pepper_touch_create(pepper_seat_t *seat)
 
     touch->seat = seat;
     wl_list_init(&touch->resource_list);
+    pepper_list_init(&touch->point_list);
 
     return touch;
 }
@@ -68,6 +127,16 @@ pepper_touch_create(pepper_seat_t *seat)
 void
 pepper_touch_destroy(pepper_touch_t *touch)
 {
+    pepper_touch_point_t *point, *tmp;
+
+    pepper_list_for_each_safe(point, tmp, &touch->point_list, link)
+    {
+        if (point->focus)
+            pepper_event_listener_remove(point->focus_destroy_listener);
+
+        free(point);
+    }
+
     if (touch->grab)
         touch->grab->cancel(touch, touch->data);
 
@@ -122,46 +191,141 @@ pepper_touch_get_seat(pepper_touch_t *touch)
 }
 
 PEPPER_API void
-pepper_touch_set_focus(pepper_touch_t *touch, pepper_view_t *focus)
+pepper_touch_add_point(pepper_touch_t *touch, uint32_t id, double x, double y)
+{
+    pepper_touch_point_t *point = get_touch_point(touch, id);
+    PEPPER_CHECK(point, return, "Touch point %d already exist.\n", id);
+
+    point = calloc(1, sizeof(pepper_touch_point_t));
+    PEPPER_CHECK(point, return, "malloc() failed.\n");
+
+    point->touch = touch;
+    point->id = id;
+    point->x = x;
+    point->y = y;
+
+    pepper_list_insert(touch->point_list.prev, &point->link);
+}
+
+PEPPER_API void
+pepper_touch_remove_point(pepper_touch_t *touch, uint32_t id)
+{
+    pepper_touch_point_t *point = get_touch_point(touch, id);
+    PEPPER_CHECK(point, return, "Touch point %d does not exist.\n", id);
+
+    touch_point_set_focus(point, NULL);
+    pepper_list_remove(&point->link);
+    free(point);
+}
+
+PEPPER_API void
+pepper_touch_point_set_focus(pepper_touch_t *touch, uint32_t id, pepper_view_t *focus)
 {
-    /* TODO: */
+    pepper_touch_point_t *point = get_touch_point(touch, id);
+    PEPPER_CHECK(point, return, "Touch point %d does not exist.\n", id);
+    touch_point_set_focus(point, focus);
 }
 
 PEPPER_API pepper_view_t *
-pepper_touch_get_focus(pepper_touch_t *touch)
+pepper_touch_point_get_focus(pepper_touch_t *touch, uint32_t id)
 {
-    /* TODO: */
-    return NULL;
+    pepper_touch_point_t *point = get_touch_point(touch, id);
+    PEPPER_CHECK(point, return NULL, "Touch point %d does not exist.\n", id);
+
+    return point->focus;
+}
+
+PEPPER_API void
+pepper_touch_point_get_position(pepper_touch_t *touch, uint32_t id, double *x, double *y)
+{
+    pepper_touch_point_t *point = get_touch_point(touch, id);
+    PEPPER_CHECK(point, return, "Touch point %d does not exist.\n", id);
+
+    if (x)
+        *x = point->x;
+
+    if (y)
+        *y = point->y;
 }
 
-    PEPPER_API void
+PEPPER_API void
 pepper_touch_send_down(pepper_touch_t *touch, uint32_t time, uint32_t id, double x, double y)
 {
-    /* TODO: wl_touch_send_down(resource, serial, time, touch->focus->surface->resource, x, y); */
+    struct wl_resource     *resource;
+    wl_fixed_t              fx = wl_fixed_from_double(x);
+    wl_fixed_t              fy = wl_fixed_from_double(y);
+    pepper_touch_point_t   *point = get_touch_point(touch, id);
+
+    PEPPER_CHECK(!point || !point->focus || !point->focus->surface ||
+                 !point->focus->surface->resource, return, "No targets to send touch down.\n");
+
+    wl_resource_for_each(resource, &touch->resource_list)
+    {
+        struct wl_resource *surface_resource = point->focus->surface->resource;
+
+        if (wl_resource_get_client(resource) == wl_resource_get_client(surface_resource))
+            wl_touch_send_down(resource, point->focus_serial, time, surface_resource, id, fx, fy);
+    }
 }
 
-    PEPPER_API void
+PEPPER_API void
 pepper_touch_send_up(pepper_touch_t *touch, uint32_t time, uint32_t id)
 {
-    /* TODO: wl_touch_send_up(resource, serial, time, id); */
+    struct wl_resource     *resource;
+    uint32_t                serial;
+    pepper_touch_point_t   *point = get_touch_point(touch, id);
+
+    PEPPER_CHECK(!point || !point->focus || !point->focus->surface ||
+                 !point->focus->surface->resource, return, "No targets to send touch down.\n");
+
+    serial = wl_display_next_serial(touch->seat->compositor->display);
+
+    wl_resource_for_each(resource, &touch->resource_list)
+    {
+        struct wl_resource *surface_resource = point->focus->surface->resource;
+
+        if (wl_resource_get_client(resource) == wl_resource_get_client(surface_resource))
+            wl_touch_send_up(resource, serial, time, id);
+    }
 }
 
-    PEPPER_API void
+PEPPER_API void
 pepper_touch_send_motion(pepper_touch_t *touch, uint32_t time, uint32_t id, double x, double y)
 {
-    /* TODO: wl_touch_send_motion(resource, time, id, x, y); */
+
+    struct wl_resource     *resource;
+    wl_fixed_t              fx = wl_fixed_from_double(x);
+    wl_fixed_t              fy = wl_fixed_from_double(y);
+    pepper_touch_point_t   *point = get_touch_point(touch, id);
+
+    PEPPER_CHECK(!point || !point->focus || !point->focus->surface ||
+                 !point->focus->surface->resource, return, "No targets to send touch down.\n");
+
+    wl_resource_for_each(resource, &touch->resource_list)
+    {
+        struct wl_resource *surface_resource = point->focus->surface->resource;
+
+        if (wl_resource_get_client(resource) == wl_resource_get_client(surface_resource))
+            wl_touch_send_motion(resource, time, id, fx, fy);
+    }
 }
 
-    PEPPER_API void
+PEPPER_API void
 pepper_touch_send_frame(pepper_touch_t *touch)
 {
-    /* TODO: wl_touch_send_frame(resource); */
+    struct wl_resource     *resource;
+
+    wl_resource_for_each(resource, &touch->resource_list)
+        wl_touch_send_frame(resource);
 }
 
-    PEPPER_API void
+PEPPER_API void
 pepper_touch_send_cancel(pepper_touch_t *touch)
 {
-    /* TODO: wl_touch_send_cancel(resource); */
+    struct wl_resource     *resource;
+
+    wl_resource_for_each(resource, &touch->resource_list)
+        wl_touch_send_cancel(resource);
 }
 
 PEPPER_API void
@@ -182,4 +346,3 @@ pepper_touch_get_grab_data(pepper_touch_t *touch)
 {
     return touch->data;
 }
-