From: duna.oh Date: Thu, 25 May 2023 04:42:27 +0000 (+0900) Subject: e_comp_wl_input: implement tizen_pointergrab protocol X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fheads%2Fsandbox%2Fduna%2Fpointergrab;p=platform%2Fupstream%2Fenlightenment.git e_comp_wl_input: implement tizen_pointergrab protocol --- diff --git a/configure.ac b/configure.ac index 423b81fb3b..043bd62fcd 100755 --- a/configure.ac +++ b/configure.ac @@ -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]) diff --git a/packaging/enlightenment.spec b/packaging/enlightenment.spec index 0e530c9840..16a833b1e3 100644 --- a/packaging/enlightenment.spec +++ b/packaging/enlightenment.spec @@ -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 diff --git a/src/bin/e_comp_wl.c b/src/bin/e_comp_wl.c index 29d0c7d3e7..82fb5d263d 100644 --- a/src/bin/e_comp_wl.c +++ b/src/bin/e_comp_wl.c @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -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) { diff --git a/src/bin/e_comp_wl.h b/src/bin/e_comp_wl.h index d0611f6642..5eb941a69f 100644 --- a/src/bin/e_comp_wl.h +++ b/src/bin/e_comp_wl.h @@ -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); diff --git a/src/bin/e_comp_wl_input.c b/src/bin/e_comp_wl_input.c index 7c0f49c53b..3893d637c2 100644 --- a/src/bin/e_comp_wl_input.c +++ b/src/bin/e_comp_wl_input.c @@ -5,6 +5,19 @@ #include #include +#include + +#ifdef HAVE_CYNARA +# include +# include +# include +# include +#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) { diff --git a/src/bin/e_comp_wl_input.h b/src/bin/e_comp_wl_input.h index 1e9149881a..428ad1d476 100644 --- a/src/bin/e_comp_wl_input.h +++ b/src/bin/e_comp_wl_input.h @@ -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); diff --git a/src/bin/e_input.c b/src/bin/e_input.c index f55d814bb8..d2dd687dba 100644 --- a/src/bin/e_input.c +++ b/src/bin/e_input.c @@ -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; +} diff --git a/src/bin/e_input.h b/src/bin/e_input.h index 77238cef6b..ef36e57ddc 100644 --- a/src/bin/e_input.h +++ b/src/bin/e_input.h @@ -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 diff --git a/src/bin/e_input_evdev.c b/src/bin/e_input_evdev.c index 438e7afd0d..6b7d7350b0 100644 --- a/src/bin/e_input_evdev.c +++ b/src/bin/e_input_evdev.c @@ -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