e_comp_wl_input: implement tizen_pointergrab protocol sandbox/duna/pointergrab
authorduna.oh <duna.oh@samsung.com>
Thu, 25 May 2023 04:42:27 +0000 (13:42 +0900)
committerduna.oh <duna.oh@samsung.com>
Thu, 15 Jun 2023 09:40:15 +0000 (18:40 +0900)
configure.ac
packaging/enlightenment.spec
src/bin/e_comp_wl.c
src/bin/e_comp_wl.h
src/bin/e_comp_wl_input.c
src/bin/e_comp_wl_input.h
src/bin/e_input.c
src/bin/e_input.h
src/bin/e_input_evdev.c

index 423b81fb3b74deda080f9d24644a1b3b31837048..043bd62fcd0212f962425ae8ef36fbc361141905 100755 (executable)
@@ -370,7 +370,7 @@ AC_MSG_RESULT([${have_shm_open}])
 AC_SUBST(SHM_OPEN_LIBS)
 
 if test "x${e_cv_want_wayland_only}" != "xno" || test "x${e_cv_want_wayland_clients}" != "xno";then
-  PKG_CHECK_MODULES([WAYLAND], [wayland-server >= 1.8.0 xkbcommon uuid xdg-shell-unstable-v5-server xdg-shell-unstable-v6-server tizen-remote-surface-server scaler-server screenshooter-server tizen-extension-server tizen-launch-server tizen-surface-server tizen-dpms-server eom-server presentation-time-server tizen-hwc-server linux-explicit-synchronization-unstable-v1-server wtz-foreign-server relative-pointer-unstable-v1-server pointer-constraints-unstable-v1-server wtz-screen-server wtz-shell-server],
+  PKG_CHECK_MODULES([WAYLAND], [wayland-server >= 1.8.0 xkbcommon uuid xdg-shell-unstable-v5-server xdg-shell-unstable-v6-server tizen-remote-surface-server scaler-server screenshooter-server tizen-extension-server tizen-launch-server tizen-surface-server tizen-dpms-server eom-server presentation-time-server tizen-hwc-server linux-explicit-synchronization-unstable-v1-server wtz-foreign-server relative-pointer-unstable-v1-server pointer-constraints-unstable-v1-server wtz-screen-server wtz-shell-server tizen-pointergrab-ext-server],
     [
       have_wayland=yes
       AC_DEFINE_UNQUOTED([HAVE_WAYLAND],[1],[enable wayland support])
index 0e530c98406826bf042494b3ddcb50afb330cd8e..16a833b1e364b2ebce65a9654002e1f72710bdd5 100644 (file)
@@ -65,6 +65,7 @@ BuildRequires:  pkgconfig(pointer-constraints-unstable-v1-server)
 BuildRequires:  pkgconfig(relative-pointer-unstable-v1-server)
 BuildRequires:  pkgconfig(wtz-screen-server)
 BuildRequires:  pkgconfig(wtz-shell-server)
+BuildRequires:  pkgconfig(tizen-pointergrab-ext-server)
 Requires:       libwayland-extension-server
 
 # for gtest/gmock
index 29d0c7d3e75e6dab59d685324afd25a1a7b97e3f..82fb5d263ddf62c41a512d65989e2adea29efa4a 100644 (file)
@@ -5,6 +5,7 @@
 
 #include <relative-pointer-unstable-v1-server-protocol.h>
 #include <pointer-constraints-unstable-v1-server-protocol.h>
+#include <tizen-pointergrab-ext-server-protocol.h>
 
 #include <wayland-tbm-server.h>
 #include <gbm.h>
@@ -4488,9 +4489,10 @@ _e_comp_wl_cb_mouse_move_preventer(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore
 
    E_Client *focus = e_client_focused_get();
 
-   if ((!e_comp_wl->ptr_constraints.activated) ||
+   if ((!e_comp_wl->pointergrab.client || !e_comp_wl->pointergrab.locked) &&
+       ((!e_comp_wl->ptr_constraints.activated) ||
        (!focus) ||
-       (e_comp_wl->ptr_constraints.ec != focus))
+       (e_comp_wl->ptr_constraints.ec != focus)))
      {
         if (saved_x != -1 || saved_y != -1)
           {
@@ -5727,6 +5729,57 @@ e_comp_wl_mouse_relative_motion_send(E_Client *ec,
    return EINA_TRUE;
 }
 
+EINTERN Eina_Bool
+e_comp_wl_mouse_pointergrab_relative_motion_send(struct wl_client *wc,
+                                     int dx, int dy, int dx_unaccel, int dy_unaccel,
+                                     uint64_t time)
+{
+   struct wl_resource *res;
+   Eina_List *l;
+
+   ERR("e_comp_wl_mouse_pointergrab_relative_motion_send()");
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(wc, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl, EINA_FALSE);
+
+   EINA_LIST_FOREACH(e_comp_wl->relative_ptr.resources, l, res)
+     {
+        if (!e_comp_wl_input_relative_pointer_check(res)) continue;
+        if (wl_resource_get_client(res) != wc) continue;
+        zwp_relative_pointer_v1_send_relative_motion(res,
+                                                     (uint32_t)(time >> 32),
+                                                     (uint32_t)(time),
+                                                     wl_fixed_from_int(dx),
+                                                     wl_fixed_from_int(dy),
+                                                     wl_fixed_from_int(dx_unaccel),
+                                                     wl_fixed_from_int(dy_unaccel));
+     }
+
+   return EINA_TRUE;
+}
+
+EINTERN Eina_Bool
+e_comp_wl_mouse_pointergrab_motion_send(struct wl_client *wc, int x, int y, uint32_t time)
+{
+   struct wl_resource *res;
+   Eina_List *l;
+
+   ERR("e_comp_wl_mouse_pointergrab_motion_send() x:%d, y:%d", x, y);
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(wc, EINA_FALSE);
+
+   EINA_LIST_FOREACH(e_comp_wl->pointergrab.resources, l, res)
+     {
+        if (!e_comp_wl_input_pointergrab_check(res)) continue;
+        if (wl_resource_get_client(res) != wc) continue;
+        tizen_pointergrab_send_motion(res, time,
+                                      wl_fixed_from_int(x),
+                                      wl_fixed_from_int(y));
+     }
+
+   return EINA_TRUE;
+}
+
 EINTERN Eina_Bool
 e_comp_wl_mouse_move_send(E_Client *ec, int x, int y, Ecore_Device *dev, uint32_t time)
 {
index d0611f664227737dc72acb195e3c61ace431f92e..5eb941a69f438b9ac4263cfa143507dadbfccbf6 100644 (file)
@@ -261,6 +261,15 @@ struct _E_Comp_Wl_Data
         struct wl_global *global;
      } ptr_constraints;
 
+   struct
+     {
+      struct wl_global *global;
+      Eina_List *resources;
+      struct wl_client *client;
+      Eina_Bool locked: 1;
+      struct wl_listener client_destroy_listener;
+     } pointergrab;
+
    struct
      {
         Eina_List *resources;
@@ -627,6 +636,8 @@ EINTERN Eina_Bool e_comp_wl_mouse_wheel_send(E_Client *ec, int direction, int z,
 EINTERN Eina_Bool e_comp_wl_mouse_in_send(E_Client *ec, int x, int y, Ecore_Device *dev, uint32_t time);
 EINTERN Eina_Bool e_comp_wl_mouse_out_send(E_Client *ec, Ecore_Device *dev, uint32_t time);
 EINTERN Eina_Bool e_comp_wl_mouse_relative_motion_send(E_Client *ec, int dx, int dy, int dx_unaccel, int dy_unaccel, uint64_t time);
+EINTERN Eina_Bool e_comp_wl_mouse_pointergrab_relative_motion_send(struct wl_client *wc, int dx, int dy, int dx_unaccel, int dy_unaccel, uint64_t time);
+EINTERN Eina_Bool e_comp_wl_mouse_pointergrab_motion_send(struct wl_client *wc, int dx, int dy, uint32_t time);
 EINTERN void e_comp_wl_mouse_in_renew(E_Client *ec, int buttons, int x, int y, void *data, Evas_Modifier *modifiers, Evas_Lock *locks, unsigned int timestamp, Evas_Event_Flags event_flags, Evas_Device *dev, Evas_Object *event_src);
 EINTERN void e_comp_wl_mouse_out_renew(E_Client *ec, int buttons, int x, int y, void *data, Evas_Modifier *modifiers, Evas_Lock *locks, unsigned int timestamp, Evas_Event_Flags event_flags, Evas_Device *dev, Evas_Object *event_src);
 EINTERN Eina_Bool e_comp_wl_key_process(Ecore_Event_Key *ev, int type);
index 7c0f49c53ba52864dbcab4cf01e6a0de390cda5f..3893d637c2f7a1f52c56f00fdabd517c3d52cf2d 100644 (file)
@@ -5,6 +5,19 @@
 
 #include <relative-pointer-unstable-v1-server-protocol.h>
 #include <pointer-constraints-unstable-v1-server-protocol.h>
+#include <tizen-pointergrab-ext-server-protocol.h>
+
+#ifdef HAVE_CYNARA
+# include <cynara-session.h>
+# include <cynara-client.h>
+# include <cynara-creds-socket.h>
+# include <sys/smack.h>
+#endif
+
+#ifdef HAVE_CYNARA
+static cynara *pointergrab_cynara = NULL;
+static Eina_Bool pointergrab_cynara_initialized;
+#endif
 
 typedef struct _E_Comp_Wl_Pointer_Constraint E_Comp_Wl_Pointer_Constraint;
 
@@ -60,6 +73,10 @@ static char *_env_e_default_xkb_layout  = NULL;
 static char *_env_e_default_xkb_variant = NULL;
 static char *_env_e_default_xkb_opts    = NULL;
 
+static void
+_e_comp_wl_input_pointergrab_unlock_pointer(struct wl_client *client,
+                                            struct wl_resource *resource);
+
 static void
 _e_comp_wl_input_update_seat_caps(struct wl_client *wc)
 {
@@ -562,8 +579,19 @@ void
 _e_comp_wl_input_relative_motion_handler(double dx[2], double dy[2], uint64_t time_us)
 {
    Eina_Bool res;
-   res = e_comp_wl_mouse_relative_motion_send(e_comp_wl->ptr_constraints.ec,
-                                              (int)dx[0], (int)dy[0], (int)dx[1], (int)dy[1], time_us);
+
+   ERR("_e_comp_wl_input_relative_motion_handler()");
+
+   if (e_comp_wl->ptr_constraints.ec)
+     {
+        res = e_comp_wl_mouse_relative_motion_send(e_comp_wl->ptr_constraints.ec,
+                                                   (int)dx[0], (int)dy[0], (int)dx[1], (int)dy[1], time_us);
+     }
+   else
+     {
+        res = e_comp_wl_mouse_pointergrab_relative_motion_send(e_comp_wl->pointergrab.client,
+                                                   (int)dx[0], (int)dy[0], (int)dx[1], (int)dy[1], time_us);
+     }
 
    if (!res)
      {
@@ -571,6 +599,20 @@ _e_comp_wl_input_relative_motion_handler(double dx[2], double dy[2], uint64_t ti
      }
 }
 
+void
+_e_comp_wl_input_pointergrab_motion_handler(double x, double y, uint32_t timestamp)
+{
+   Eina_Bool res;
+   ERR("_e_comp_wl_input_pointergrab_motion_handler()");
+   res = e_comp_wl_mouse_pointergrab_motion_send(e_comp_wl->pointergrab.client,
+                                                 (int)x, (int)y, timestamp);
+
+   if (!res)
+     {
+        ERR("Could not send pointergrab_motion to client(%p)", e_comp_wl->pointergrab.client);
+     }
+}
+
 static void
 _e_comp_wl_input_convert_eina_tiler_to_pixman_region32(const Eina_Tiler *tiler,
                                                        pixman_region32_t *region)
@@ -916,8 +958,16 @@ static void
 _e_comp_wl_input_cb_unbind_locked_pointer(struct wl_resource *resource)
 {
    E_Comp_Wl_Pointer_Constraint *constraint;
-   constraint = wl_resource_get_user_data(resource);
+   ERR("_e_comp_wl_input_cb_unbind_locked_pointer()");
+
+   if (e_comp_wl->pointergrab.client)
+     {
+        struct wl_client *wc = wl_resource_get_client(resource);
+        if (e_comp_wl->pointergrab.client == wc)
+          _e_comp_wl_input_pointergrab_unlock_pointer(wc, resource);
+     }
 
+   constraint = wl_resource_get_user_data(resource);
    if (!constraint)
      return;
 
@@ -929,6 +979,7 @@ _e_comp_wl_input_cb_locked_pointer_destroy(struct wl_client *client,
                                            struct wl_resource *resource)
 {
    E_Comp_Wl_Pointer_Constraint *constraint;
+   ERR("_e_comp_wl_input_cb_locked_pointer_destroy()");
    constraint = wl_resource_get_user_data(resource);
 
    if (constraint &&
@@ -1013,6 +1064,52 @@ static const struct zwp_locked_pointer_v1_interface _e_comp_wl_locked_pointer_in
    _e_comp_wl_input_cb_locked_pointer_set_region,
 };
 
+static void
+_e_comp_wl_input_pointergrab_lock_pointer(struct wl_client *client,
+                                          struct wl_resource *resource,
+                                          uint32_t id,
+                                          struct wl_resource *pointer,
+                                          uint32_t lifetime)
+{
+   ERR("_e_comp_wl_input_pointergrab_lock_pointer()");
+
+   struct wl_resource *res;
+   res = wl_resource_create(client, &zwp_locked_pointer_v1_interface, 1, id);
+
+   if (!res)
+     {
+        ERR("Could not create a resource for zwp_locked_pointer_v1: %m");
+        wl_client_post_no_memory(client);
+        return;
+     }
+
+   wl_resource_set_implementation(res, &_e_comp_wl_locked_pointer_interface,
+                                  NULL, _e_comp_wl_input_cb_unbind_locked_pointer);
+
+   if (!e_input_pointergrab_motion_handler_set(NULL))
+     ERR("ERROR! Could not set pointergrab motion handler !");
+   if (!e_input_relative_motion_handler_set(_e_comp_wl_input_relative_motion_handler))
+     ERR("ERROR! Could not set relative motion handler !");
+   zwp_locked_pointer_v1_send_locked(res);
+
+   e_comp_wl->pointergrab.locked = EINA_TRUE;
+}
+
+static void
+_e_comp_wl_input_pointergrab_unlock_pointer(struct wl_client *client,
+                                            struct wl_resource *resource)
+{
+   ERR("_e_comp_wl_input_pointergrab_unlock_pointer()");
+
+   if (!e_input_pointergrab_motion_handler_set(_e_comp_wl_input_pointergrab_motion_handler))
+     ERR("ERROR! Could not set pointergrab motion handler !");
+   if (!e_input_relative_motion_handler_set(NULL))
+     ERR("ERROR! Could not set relative motion handler !");
+   zwp_locked_pointer_v1_send_unlocked(resource);
+
+   e_comp_wl->pointergrab.locked = EINA_FALSE;
+}
+
 static void
 _e_comp_wl_input_cb_pointer_constraints_lock_pointer(struct wl_client *client,
                                                      struct wl_resource *resource,
@@ -1022,6 +1119,13 @@ _e_comp_wl_input_cb_pointer_constraints_lock_pointer(struct wl_client *client,
                                                      struct wl_resource *region,
                                                      uint32_t lifetime)
 {
+   ERR("_e_comp_wl_input_cb_pointer_constraints_lock_pointer()");
+
+   if (e_comp_wl->pointergrab.client)
+     {
+        _e_comp_wl_input_pointergrab_lock_pointer(client, resource, id, pointer, lifetime);
+     }
+
    if (!pointer || !surface)
      {
         ERR("Pointer resource or surface resource is invalid !");
@@ -1138,6 +1242,213 @@ _e_comp_wl_input_cb_surface_commit(void *data EINA_UNUSED, E_Client *ec)
    wl_signal_emit(&e_comp_wl->ptr_constraints.surface_commit_signal, ec);
 }
 
+#ifdef HAVE_CYNARA
+#define E_POINTERGRAB_CYNARA_ERROR_CHECK_GOTO(func_name, ret, label) \
+  do \
+    { \
+       if (EINA_UNLIKELY(CYNARA_API_SUCCESS != ret)) \
+          { \
+             _e_pointergrab_util_cynara_log(func_name, ret); \
+             goto label; \
+          } \
+    } \
+  while (0)
+
+static void
+_e_pointergrab_util_cynara_log(const char *func_name, int err)
+{
+#define CYNARA_BUFSIZE 128
+   char buf[CYNARA_BUFSIZE] = "\0";
+   int ret;
+
+   ret = cynara_strerror(err, buf, CYNARA_BUFSIZE);
+   if (ret != CYNARA_API_SUCCESS)
+     {
+        DBG("Failed to cynara_strerror: %d (error log about %s: %d)\n", ret, func_name, err);
+        return;
+     }
+   DBG("%s is failed: %s\n", func_name, buf);
+}
+
+static Eina_Bool
+_e_pointergrab_util_do_privilege_check(struct wl_client *client, int socket_fd, const char *rule)
+{
+   int ret, pid;
+   char *clientSmack=NULL, *uid=NULL, *client_session=NULL;
+   Eina_Bool res = EINA_FALSE;
+
+   /* If initialization of cynara has been failed, let's not to do further permission checks. */
+   if (pointergrab_cynara == NULL && pointergrab_cynara_initialized) return EINA_TRUE;
+   if (socket_fd < 0) return EINA_FALSE;
+
+   ret = cynara_creds_socket_get_client(socket_fd, CLIENT_METHOD_SMACK, &clientSmack);
+   E_POINTERGRAB_CYNARA_ERROR_CHECK_GOTO("cynara_creds_socket_get_client", ret, finish);
+
+   ret = cynara_creds_socket_get_user(socket_fd, USER_METHOD_UID, &uid);
+   E_POINTERGRAB_CYNARA_ERROR_CHECK_GOTO("cynara_creds_socket_get_user", ret, finish);
+
+   ret = cynara_creds_socket_get_pid(socket_fd, &pid);
+   E_POINTERGRAB_CYNARA_ERROR_CHECK_GOTO("cynara_creds_socket_get_pid", ret, finish);
+
+   client_session = cynara_session_from_pid(pid);
+
+   ret = cynara_check(pointergrab_cynara, clientSmack, client_session, uid, rule);
+
+   if (CYNARA_API_ACCESS_ALLOWED == ret)
+        res = EINA_TRUE;
+
+finish:
+   E_FREE(client_session);
+   E_FREE(clientSmack);
+   E_FREE(uid);
+
+   return res;
+}
+#endif
+
+static void
+_e_comp_wl_input_cb_pointergrab_destroy(struct wl_client *client,
+                                        struct wl_resource *resource)
+{
+   wl_resource_destroy(resource);
+}
+
+static void
+_e_pointergrab_cb_client_destroy(struct wl_listener *listener, void *data)
+{
+   ERR("_e_pointergrab_cb_client_destroy()");
+
+   e_comp_wl->pointergrab.client = NULL;
+   e_input_pointergrab_motion_handler_set(NULL);
+   e_input_relative_motion_handler_set(NULL);
+
+   if (e_comp_wl->pointergrab.client_destroy_listener.notify)
+     wl_list_remove(&e_comp_wl->pointergrab.client_destroy_listener.link);
+   e_comp_wl->pointergrab.client_destroy_listener.notify = NULL;
+}
+static int
+e_pointergrab_enabled_set(struct wl_client *client, struct wl_resource *resource, Eina_Bool enable)
+{
+   if (enable)
+     {
+        ERR("e_pointergrab_enabled_set() enabled:TRUE");
+        if (e_comp_wl->pointergrab.client && e_comp_wl->pointergrab.client != client)
+          return TIZEN_POINTERGRAB_ERROR_GRABBED_ALREADY;
+
+        e_comp_wl->pointergrab.client = client;
+        e_comp_wl->pointergrab.locked = EINA_FALSE;
+        if (!e_input_pointergrab_motion_handler_set(_e_comp_wl_input_pointergrab_motion_handler))
+          {
+             ERR("ERROR! Could not set pointergrab motion handler !");
+             return TIZEN_POINTERGRAB_ERROR_NO_SYSTEM_RESOURCES;
+          }
+        e_input_relative_motion_handler_set(NULL);
+
+        e_comp_wl->pointergrab.client_destroy_listener.notify = _e_pointergrab_cb_client_destroy;
+        wl_client_add_destroy_listener(client, &e_comp_wl->pointergrab.client_destroy_listener);
+     }
+   else
+     {
+        ERR("e_pointergrab_enabled_set() enabled:FALSE");
+        if (e_comp_wl->pointergrab.client && e_comp_wl->pointergrab.client != client)
+          return TIZEN_POINTERGRAB_ERROR_GRABBED_ALREADY;
+
+        e_comp_wl->pointergrab.client = NULL;
+        e_comp_wl->pointergrab.locked = EINA_FALSE;
+        e_input_pointergrab_motion_handler_set(NULL);
+        e_input_relative_motion_handler_set(NULL);
+
+        if (e_comp_wl->pointergrab.client_destroy_listener.notify)
+          wl_list_remove(&e_comp_wl->pointergrab.client_destroy_listener.link);
+        e_comp_wl->pointergrab.client_destroy_listener.notify = NULL;
+     }
+
+   return TIZEN_POINTERGRAB_ERROR_NONE;
+}
+
+static void
+_e_comp_wl_input_cb_pointergrab_enable(struct wl_client *client,
+                                       struct wl_resource *resource)
+{
+   int ret = TIZEN_POINTERGRAB_ERROR_NONE;
+
+   ERR("pointergrab_enable");
+
+// #ifdef HAVE_CYNARA
+//    if (EINA_FALSE == _e_pointergrab_util_do_privilege_check(client, wl_client_get_fd(client),
+//                                                           "http://tizen.org/privilege/pointergrab"))
+//      {
+//         ERR("pointergrab request:priv check failed");
+//         tizen_pointergrab_send_notify(resource, TIZEN_POINTERGRAB_ERROR_NO_PERMISSION);
+//         return;
+//      }
+// #endif
+
+   ret = e_pointergrab_enabled_set(client, resource, EINA_TRUE);
+   tizen_pointergrab_send_notify(resource, ret);
+}
+
+static void
+_e_comp_wl_input_cb_pointergrab_disable(struct wl_client *client,
+                                        struct wl_resource *resource)
+{
+   int ret = TIZEN_POINTERGRAB_ERROR_NONE;
+
+   ERR("pointergrab_disable");
+
+// #ifdef HAVE_CYNARA
+//    if (EINA_FALSE == _e_pointergrab_util_do_privilege_check(client, wl_client_get_fd(client),
+//                                                           "http://tizen.org/privilege/pointergrab"))
+//      {
+//         ERR("pointergrab request:priv check failed");
+//         tizen_pointergrab_send_notify(resource, TIZEN_POINTERGRAB_ERROR_NO_PERMISSION);
+//         return;
+//      }
+// #endif
+
+   ret = e_pointergrab_enabled_set(client, resource, EINA_FALSE);
+   tizen_pointergrab_send_notify(resource, ret);
+}
+
+static const struct tizen_pointergrab_interface _e_pointergrab_interface = {
+       _e_comp_wl_input_cb_pointergrab_destroy,
+       _e_comp_wl_input_cb_pointergrab_enable,
+       _e_comp_wl_input_cb_pointergrab_disable,
+};
+
+static void
+_e_comp_wl_input_cb_unbind_pointergrab(struct wl_resource *resource)
+{
+   ERR("unbind_pointergrab");
+
+   e_comp_wl->pointergrab.resources =
+              eina_list_remove(e_comp_wl->pointergrab.resources, resource);
+}
+
+static void
+_e_comp_wl_input_cb_bind_pointergrab(struct wl_client *client,
+                                     void *data EINA_UNUSED,
+                                     uint32_t version, uint32_t id)
+{
+   struct wl_resource *resource;
+
+   ERR("bind_pointergrab");
+
+   resource = wl_resource_create(client, &tizen_pointergrab_interface, version, id);
+
+   if (!resource)
+     {
+        ERR("Could not create pointergrab resource: %m");
+        return;
+     }
+
+   e_comp_wl->pointergrab.resources =
+              eina_list_append(e_comp_wl->pointergrab.resources, resource);
+
+   wl_resource_set_implementation(resource, &_e_pointergrab_interface,
+                                  NULL, _e_comp_wl_input_cb_unbind_pointergrab);
+}
+
 static void
 _e_comp_wl_input_keymap_cache_create(const char *keymap_path, char *keymap_data)
 {
@@ -1395,6 +1706,16 @@ e_comp_wl_input_init(void)
                                              _e_comp_wl_input_cb_surface_commit,
                                              NULL);
 
+  e_comp_wl->pointergrab.global =
+    wl_global_create(e_comp_wl->wl.disp,
+                      &tizen_pointergrab_interface, 1,
+                      e_comp->wl_comp_data,
+                      _e_comp_wl_input_cb_bind_pointergrab);
+  if (!e_comp_wl->pointergrab.global)
+     {
+        ERR("Could not create global for pointergrab: %m");
+        return EINA_FALSE;
+     }
 
    wl_array_init(&e_comp_wl->kbd.keys);
    wl_array_init(&e_comp_wl->kbd.routed_keys);
@@ -1509,6 +1830,13 @@ e_comp_wl_input_relative_pointer_check(struct wl_resource *res)
                                   &_e_relative_pointer_interface);
 }
 
+EINTERN Eina_Bool
+e_comp_wl_input_pointergrab_check(struct wl_resource *res)
+{
+   return wl_resource_instance_of(res, &tizen_pointergrab_interface,
+                                  &_e_pointergrab_interface);
+}
+
 EINTERN Eina_Bool
 e_comp_wl_input_keyboard_check(struct wl_resource *res)
 {
index 1e9149881a9e9a61dbff48650bc5d7ddbc236128..428ad1d4767d4e39a6eb2e43484c550f91dea10b 100644 (file)
@@ -16,6 +16,7 @@ EINTERN Eina_Bool e_comp_wl_input_init(void);
 EINTERN void e_comp_wl_input_shutdown(void);
 EINTERN Eina_Bool e_comp_wl_input_pointer_check(struct wl_resource *res);
 EINTERN Eina_Bool e_comp_wl_input_relative_pointer_check(struct wl_resource *res);
+EINTERN Eina_Bool e_comp_wl_input_pointergrab_check(struct wl_resource *res);
 EINTERN Eina_Bool e_comp_wl_input_keyboard_check(struct wl_resource *res);
 EINTERN Eina_Bool e_comp_wl_input_touch_check(struct wl_resource *res);
 
index f55d814bb88541c49f6c3ce9192518d64a3c258b..d2dd687dbaa8cd57bb21210781aa0c93329e6dba 100644 (file)
@@ -279,3 +279,22 @@ e_input_relative_motion_handler_get(void)
 
    return NULL;
 }
+
+EINTERN Eina_Bool
+e_input_pointergrab_motion_handler_set(e_input_pointergrab_motion_cb handler)
+{
+   if (!e_input)
+     return EINA_FALSE;
+
+   e_input->pointergrab_motion_handler = handler;
+   return EINA_TRUE;
+}
+
+EINTERN e_input_pointergrab_motion_cb
+e_input_pointergrab_motion_handler_get(void)
+{
+   if (e_input)
+     return e_input->pointergrab_motion_handler;
+
+   return NULL;
+}
index 77238cef6b138ad5ca7256ef358cc67d6f88fdc6..ef36e57ddce82a2b94efae69c4b2a5cfe46a24ec 100644 (file)
@@ -37,6 +37,7 @@ typedef struct _E_Input_Seat E_Input_Seat;
 typedef struct _E_Input_Coord E_Input_Coord;
 
 typedef void (*e_input_relative_motion_cb)(double dx[2], double dy[2], uint64_t time_us);
+typedef void (*e_input_pointergrab_motion_cb)(double seat_x, double seat_y, uint32_t timestamp);
 
 struct _E_Input
 {
@@ -51,6 +52,7 @@ struct _E_Input
    unsigned int touch_device_count;
 
    e_input_relative_motion_cb relative_motion_handler;
+   e_input_pointergrab_motion_cb pointergrab_motion_handler;
 };
 
 struct _E_Input_Device
@@ -128,5 +130,8 @@ EINTERN Eina_Bool e_input_device_seat_name_set(E_Input_Device *dev, const char *
 
 EINTERN Eina_Bool e_input_relative_motion_handler_set(e_input_relative_motion_cb handler);
 EINTERN e_input_relative_motion_cb e_input_relative_motion_handler_get(void);
+
+EINTERN Eina_Bool e_input_pointergrab_motion_handler_set(e_input_pointergrab_motion_cb handler);
+EINTERN e_input_pointergrab_motion_cb e_input_pointergrab_motion_handler_get(void);
 #endif
 #endif
index 438e7afd0d88b27320b4964f629e02b2516338af..6b7d7350b09f60225fbc9c852be706e683ee1339 100644 (file)
@@ -778,6 +778,13 @@ _device_pointer_relative_motion_send(double dx[2], double dy[2], uint64_t time_u
    if (func) func(dx, dy, time_us);
 }
 
+static void
+_device_pointer_pointergrab_motion_send(double x, double y, uint32_t timestamp)
+{
+   e_input_pointergrab_motion_cb func = e_input_pointergrab_motion_handler_get();
+   if (func) func(x, y, timestamp);
+}
+
 static void
 _device_handle_pointer_motion(struct libinput_device *device, struct libinput_event_pointer *event)
 {
@@ -839,9 +846,11 @@ _device_handle_pointer_motion(struct libinput_device *device, struct libinput_ev
         return;
      }
 
-  _device_pointer_relative_motion_send(&delta_x[0], &delta_y[0],
+   _device_pointer_relative_motion_send(&delta_x[0], &delta_y[0],
                                        libinput_event_pointer_get_time_usec(event));
-  _device_pointer_motion(edev, event);
+   _device_pointer_pointergrab_motion_send(edev->seat->ptr.dx, edev->seat->ptr.dy,
+                                           libinput_event_pointer_get_time(event));
+   _device_pointer_motion(edev, event);
 }
 
 static void