diff options
author | Ji-Youn Park <jy0703.park@samsung.com> | 2015-05-30 02:42:12 +0900 |
---|---|---|
committer | Ji-Youn Park <jy0703.park@samsung.com> | 2015-06-01 16:30:23 +0900 |
commit | ce6c0787986f37ccfeb20bcba345ac0fe137520e (patch) | |
tree | 6ffbb68af10e5c5a603b059738d01790ded29cfc | |
parent | 35bff0942d5fa7121dbc8609c45f3d39985b93c1 (diff) | |
download | efl-ce6c0787986f37ccfeb20bcba345ac0fe137520e.tar.gz |
:wecore_wayland: Add key router feature related with client side.
this feature is not freezed, so it can be changed.
Change-Id: I1255d995d805cd296f7c455bbd0609a311bccbe6
-rw-r--r-- | src/Makefile_Ecore_Wayland.am | 2 | ||||
-rw-r--r-- | src/lib/ecore_wayland/Ecore_Wayland.h | 26 | ||||
-rw-r--r-- | src/lib/ecore_wayland/ecore_wl.c | 150 | ||||
-rw-r--r-- | src/lib/ecore_wayland/ecore_wl_private.h | 3 | ||||
-rw-r--r-- | src/lib/ecore_wayland/keyrouter-client-protocol.h | 141 | ||||
-rw-r--r-- | src/lib/ecore_wayland/keyrouter-protocol.c | 37 |
6 files changed, 357 insertions, 2 deletions
diff --git a/src/Makefile_Ecore_Wayland.am b/src/Makefile_Ecore_Wayland.am index 1b2730d58c..6e48711fba 100644 --- a/src/Makefile_Ecore_Wayland.am +++ b/src/Makefile_Ecore_Wayland.am @@ -22,6 +22,8 @@ lib/ecore_wayland/ivi-application-protocol.c \ lib/ecore_wayland/ivi-application-client-protocol.h \ lib/ecore_wayland/xdg-shell-client-protocol.h \ lib/ecore_wayland/xdg-shell-protocol.c \ +lib/ecore_wayland/keyrouter-client-protocol.h \ +lib/ecore_wayland/keyrouter-protocol.c \ lib/ecore_wayland/tizen-policy-client-protocol.h \ lib/ecore_wayland/tizen-policy-protocol.c \ lib/ecore_wayland/tizen-extension-client-protocol.h \ diff --git a/src/lib/ecore_wayland/Ecore_Wayland.h b/src/lib/ecore_wayland/Ecore_Wayland.h index c878d8ff2d..3425199435 100644 --- a/src/lib/ecore_wayland/Ecore_Wayland.h +++ b/src/lib/ecore_wayland/Ecore_Wayland.h @@ -89,8 +89,20 @@ enum _Ecore_Wl_Window_Buffer_Type ECORE_WL_WINDOW_BUFFER_TYPE_SHM }; +//this enum for keyrouter and client window side +//keycode (8~255) +enum _Ecore_Wl_Window_Keygrab_Mode +{ + ECORE_WL_WINDOW_KEYGRAB_UNKNOWN = 0, /**< Unknown keygrab mode */ + ECORE_WL_WINDOW_KEYGRAB_SHARED = 1, /**< Getting the grabbed-key together with the other client windows */ + ECORE_WL_WINDOW_KEYGRAB_TOPMOST = 2, /**< Getting the grabbed-key only when window is top of the stack */ + ECORE_WL_WINDOW_KEYGRAB_EXCLUSIVE = 3, /**< Getting the grabbed-key exclusively regardless of window's position */ + ECORE_WL_WINDOW_KEYGRAB_OVERRIDE_EXCLUSIVE = 4 /**< Getting the grabbed-key exclusively regardless of window's position. Being overrided the grab by the other client window */ +}; + typedef enum _Ecore_Wl_Window_Type Ecore_Wl_Window_Type; typedef enum _Ecore_Wl_Window_Buffer_Type Ecore_Wl_Window_Buffer_Type; +typedef enum _Ecore_Wl_Window_Keygrab_Mode Ecore_Wl_Window_Keygrab_Mode; /** @since 1.7.6 */ struct _Ecore_Wl_Global @@ -909,6 +921,20 @@ EAPI void ecore_wl_subsurf_sync_set(Ecore_Wl_Subsurf *ess, Eina_Bool val); * @since 1.8 */ EAPI void ecore_wl_subsurf_opaque_region_set(Ecore_Wl_Subsurf *ess, int x, int y, int w, int h); + +/** + * Set keygrab value of the window. + * + * @ingroup Ecore_Wl_Window + */ +EAPI Eina_Bool ecore_wl_window_keygrab_set(Ecore_Wl_Window *win, const char *key, int mod, int not_mod, int priority, Ecore_Wl_Window_Keygrab_Mode grab_mode); + +/** + * Unset keygrab value of the window. + * + * @ingroup Ecore_Wl_Window + */ +EAPI Eina_Bool ecore_wl_window_keygrab_unset(Ecore_Wl_Window *win, const char *key, int mod, int any_mod); #ifdef __cplusplus } #endif diff --git a/src/lib/ecore_wayland/ecore_wl.c b/src/lib/ecore_wayland/ecore_wl.c index 6491a6436e..15a5d871fe 100644 --- a/src/lib/ecore_wayland/ecore_wl.c +++ b/src/lib/ecore_wayland/ecore_wl.c @@ -18,6 +18,7 @@ #include "xdg-shell-client-protocol.h" #define XDG_VERSION 4 +#include "keyrouter-client-protocol.h" /* local function prototypes */ static int _ecore_wl_shutdown(Eina_Bool close); @@ -36,12 +37,14 @@ static Eina_Bool _ecore_wl_animator_window_add(const Eina_Hash *hash EINA_UNUSED static void _ecore_wl_signal_exit(void); static void _ecore_wl_signal_exit_free(void *data EINA_UNUSED, void *event); static void _ecore_wl_init_callback(void *data, struct wl_callback *callback, uint32_t serial EINA_UNUSED); +static void _ecore_wl_cb_keygrab_notify(void *data, struct wl_keyrouter *wl_keyrouter, struct wl_surface *surface, uint32_t key, uint32_t mode, uint32_t error); /* local variables */ static int _ecore_wl_init_count = 0; static Eina_Bool _ecore_wl_animator_busy = EINA_FALSE; static Eina_Bool _ecore_wl_fatal_error = EINA_FALSE; static Eina_Bool _ecore_wl_server_mode = EINA_FALSE; +static int _ecore_wl_keygrab_error = -1; static const struct wl_registry_listener _ecore_wl_registry_listener = { @@ -64,6 +67,11 @@ static const struct wl_callback_listener _ecore_wl_anim_listener = _ecore_wl_animator_callback }; +static const struct wl_keyrouter_listener _ecore_wl_keyrouter_listener = +{ + _ecore_wl_cb_keygrab_notify +}; + static void xdg_shell_ping(void *data EINA_UNUSED, struct xdg_shell *shell, uint32_t serial) { @@ -524,6 +532,8 @@ _ecore_wl_shutdown(Eina_Bool close) wl_compositor_destroy(_ecore_wl_disp->wl.compositor); if (_ecore_wl_disp->wl.subcompositor) wl_subcompositor_destroy(_ecore_wl_disp->wl.subcompositor); + if (_ecore_wl_disp->wl.keyrouter) + wl_keyrouter_destroy(_ecore_wl_disp->wl.keyrouter); if (_ecore_wl_disp->wl.display) { wl_registry_destroy(_ecore_wl_disp->wl.registry); @@ -708,8 +718,15 @@ _ecore_wl_cb_handle_global(void *data, struct wl_registry *registry, unsigned in ewd->wl.tz_surf_ext = wl_registry_bind(registry, id, &tizen_surface_extension_interface, 1); } + else if (!strcmp(interface, "wl_keyrouter")) + { + ewd->wl.keyrouter = + wl_registry_bind(registry, id, &wl_keyrouter_interface, 1); + if (ewd->wl.keyrouter) + wl_keyrouter_add_listener(_ecore_wl_disp->wl.keyrouter, &_ecore_wl_keyrouter_listener, ewd->wl.display); + } - if ((ewd->wl.compositor) && (ewd->wl.shm) && + if ((ewd->wl.compositor) && (ewd->wl.shm) && ((ewd->wl.shell) || (ewd->wl.xdg_shell))) { Ecore_Wl_Event_Interfaces_Bound *ev; @@ -744,7 +761,7 @@ _ecore_wl_cb_handle_global_remove(void *data, struct wl_registry *registry EINA_ EINA_INLIST_FOREACH_SAFE(ewd->globals, tmp, global) { if (global->id != id) continue; - ewd->globals = + ewd->globals = eina_inlist_remove(ewd->globals, EINA_INLIST_GET(global)); free(global->interface); free(global); @@ -863,3 +880,132 @@ _ecore_wl_signal_exit_free(void *data EINA_UNUSED, void *event) { free(event); } + +//Currently we cannot change keyname to keycode. +//we need wl function like XStringToKeysym and XKeysymToKeycode function. + +static unsigned int +_ecore_wl_keystring_to_keycode(const char *key) +{ + unsigned int keycode; + + /* xkb rules reflect X broken keycodes, so offset by 8 */ + keycode = (unsigned)atoi(key) + 8; + return keycode; +} + +//Currently this function is only used in sink call, so use global value(_ecore_wl_keygrab_error) and just check the error is ok. +static void +_ecore_wl_cb_keygrab_notify(void *data EINA_UNUSED, struct wl_keyrouter *wl_keyrouter EINA_UNUSED, struct wl_surface *surface EINA_UNUSED, uint32_t key, uint32_t mode, uint32_t error) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + _ecore_wl_keygrab_error = error; + INF("[PID:%d] key=%d, mode=%d, error=%d", getpid(), key, mode, error); +} + +//I'm not sure that keygrab function should be changed to Ecore_evas_XXX. +//In the future, keyrouter feature can be added upstream or finish stabilizing. +//After that time, we maybe change API name or other thing. +//So do not use this API if you have trouble catch keyrouter feature or rule changes. + +//Keyrouter support the situation when wl_win is not exist. +//But keyrouter also can be meet situation when there are several surfaces. +//So I decided to add keygrab feature into ecore_wl_window side like x system. + +//Mod, not_mod, priority will be used future. +//But now we are not support, so just use 0 for this parameter. +//win can be NULL + +EAPI Eina_Bool +ecore_wl_window_keygrab_set(Ecore_Wl_Window *win, const char *key, int mod EINA_UNUSED, int not_mod EINA_UNUSED, int priority EINA_UNUSED, Ecore_Wl_Window_Keygrab_Mode grab_mode) +{ + Eina_Bool ret = EINA_FALSE; + unsigned int keycode = 0; + struct wl_surface *surface = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!key) return EINA_FALSE; + if ((grab_mode < ECORE_WL_WINDOW_KEYGRAB_UNKNOWN) || (grab_mode > ECORE_WL_WINDOW_KEYGRAB_OVERRIDE_EXCLUSIVE)) + return EINA_FALSE; + + INF("win=%p key=%s mod=%d", win, key, grab_mode); + + keycode = _ecore_wl_keystring_to_keycode(key); + if (keycode == 0) + { + WRN("Keycode of key(\"%s\") doesn't exist", key); + return EINA_FALSE; + } + + /* Request to grab a key */ + if (win) + surface = ecore_wl_window_surface_get(win); + + INF("Before keygrab _ecore_wl_keygrab_error = %d", _ecore_wl_keygrab_error); + wl_keyrouter_set_keygrab(_ecore_wl_disp->wl.keyrouter, surface, keycode, grab_mode); + + /* Send sync to wayland compositor and register sync callback to exit while dispatch loop below */ + ecore_wl_sync(); + + INF("After keygrab _ecore_wl_keygrab_error = %d", _ecore_wl_keygrab_error); + if (!_ecore_wl_keygrab_error) + { + INF("[PID:%d]Succeed to get return value !", getpid()); + ret = EINA_TRUE; + } + else + { + WRN("[PID:%d]Failed to get return value ! ret=%d)", getpid(), _ecore_wl_keygrab_error); + ret = EINA_FALSE; + } + _ecore_wl_keygrab_error = -1; + return ret; +} + +EAPI Eina_Bool +ecore_wl_window_keygrab_unset(Ecore_Wl_Window *win, const char *key, int mod EINA_UNUSED, int any_mod EINA_UNUSED) +{ + Eina_Bool ret = EINA_FALSE; + unsigned int keycode = 0; + struct wl_surface *surface = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!key) return EINA_FALSE; + INF("win=%p key=%s ", win, key); + + keycode = _ecore_wl_keystring_to_keycode(key); + if (keycode == 0) + { + WRN("Keycode of key(\"%s\") doesn't exist", key); + return EINA_FALSE; + } + + /* Request to ungrab a key */ + if (win) + surface = ecore_wl_window_surface_get(win); + + INF("Before keyungrab _ecore_wl_keygrab_error = %d", _ecore_wl_keygrab_error); + + wl_keyrouter_unset_keygrab(_ecore_wl_disp->wl.keyrouter, surface, keycode); + + /* Send sync to wayland compositor and register sync callback to exit while dispatch loop below */ + ecore_wl_sync(); + + INF("After keygrab _ecore_wl_keygrab_error = %d", _ecore_wl_keygrab_error); + if (!_ecore_wl_keygrab_error) + { + ret = EINA_TRUE; + INF("[PID:%d] Succeed to get return value ! ", getpid()); + } + else + { + ret = EINA_FALSE; + WRN("[PID:%d] Failed to get return value ! (ret=%d)", getpid(), _ecore_wl_keygrab_error); + } + _ecore_wl_keygrab_error = -1; + return ret; +} + diff --git a/src/lib/ecore_wayland/ecore_wl_private.h b/src/lib/ecore_wayland/ecore_wl_private.h index af4f1cb68f..f74aade991 100644 --- a/src/lib/ecore_wayland/ecore_wl_private.h +++ b/src/lib/ecore_wayland/ecore_wl_private.h @@ -15,6 +15,8 @@ # include "tizen-policy-client-protocol.h" # include "tizen-extension-client-protocol.h" +# include "keyrouter-client-protocol.h" + //# define LOGFNS 1 # ifdef LOGFNS @@ -81,6 +83,7 @@ struct _Ecore_Wl_Display struct wl_data_device_manager *data_device_manager; struct tizen_policy *tz_policy; struct tizen_surface_extension *tz_surf_ext; + struct wl_keyrouter *keyrouter; } wl; int fd; diff --git a/src/lib/ecore_wayland/keyrouter-client-protocol.h b/src/lib/ecore_wayland/keyrouter-client-protocol.h new file mode 100644 index 0000000000..6e410174bf --- /dev/null +++ b/src/lib/ecore_wayland/keyrouter-client-protocol.h @@ -0,0 +1,141 @@ + +#ifndef KEYROUTER_CLIENT_PROTOCOL_H +#define KEYROUTER_CLIENT_PROTOCOL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> +#include <stddef.h> +#include "wayland-client.h" + +struct wl_client; +struct wl_resource; + +struct wl_keyrouter; + +extern const struct wl_interface wl_keyrouter_interface; + +#ifndef WL_KEYROUTER_ERROR_ENUM +#define WL_KEYROUTER_ERROR_ENUM +enum wl_keyrouter_error { + WL_KEYROUTER_ERROR_NONE = 0, + WL_KEYROUTER_ERROR_INVALID_SURFACE = 1, + WL_KEYROUTER_ERROR_INVALID_KEY = 2, + WL_KEYROUTER_ERROR_INVALID_MODE = 3, + WL_KEYROUTER_ERROR_GRABBED_ALREADY = 4, + WL_KEYROUTER_ERROR_NO_PERMISSION = 5, + WL_KEYROUTER_ERROR_NO_SYSTEM_RESOURCES = 6, +}; +#endif /* WL_KEYROUTER_ERROR_ENUM */ + +#ifndef WL_KEYROUTER_MODE_ENUM +#define WL_KEYROUTER_MODE_ENUM +/** + * wl_keyrouter_mode - mode for a key grab + * @WL_KEYROUTER_MODE_NONE: none + * @WL_KEYROUTER_MODE_SHARED: mode to get a key grab with the other + * client surfaces when the focused client surface gets the key + * @WL_KEYROUTER_MODE_TOPMOST: mode to get a key grab when the client + * surface is the top most surface + * @WL_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE: mode to get a key grab + * exclusively, overridably regardless of the order in the surface stack + * @WL_KEYROUTER_MODE_EXCLUSIVE: mode to get a key grab exclusively + * regardless of the order in surface stack + * + * This value is used to set a mode for a key grab. With this mode and + * the order of the surface between surfaces' stack, the compositor will + * determine the destination client surface. + */ +enum wl_keyrouter_mode { + WL_KEYROUTER_MODE_NONE = 0, + WL_KEYROUTER_MODE_SHARED = 1, + WL_KEYROUTER_MODE_TOPMOST = 2, + WL_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE = 3, + WL_KEYROUTER_MODE_EXCLUSIVE = 4, +}; +#endif /* WL_KEYROUTER_MODE_ENUM */ + +/** + * wl_keyrouter - an interface to set each focus for each key + * @keygrab_notify: (none) + * + * In tradition, all the keys in a keyboard and a device on which some + * keys are attached will be sent to focus surface by default. Currently + * it's possible to set up each focus for each key in a keyboard and a + * device. Therefore, by setting a key grab for a surface, the owner of the + * surface will get the key event when it has the key grab for the key. + */ +struct wl_keyrouter_listener { + /** + * keygrab_notify - (none) + * @surface: (none) + * @key: (none) + * @mode: (none) + * @error: (none) + */ + void (*keygrab_notify)(void *data, + struct wl_keyrouter *wl_keyrouter, + struct wl_surface *surface, + uint32_t key, + uint32_t mode, + uint32_t error); +}; + +static inline int +wl_keyrouter_add_listener(struct wl_keyrouter *wl_keyrouter, + const struct wl_keyrouter_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) wl_keyrouter, + (void (**)(void)) listener, data); +} + +#define WL_KEYROUTER_SET_KEYGRAB 0 +#define WL_KEYROUTER_UNSET_KEYGRAB 1 +#define WL_KEYROUTER_GET_KEYGRAB_STATUS 2 + +static inline void +wl_keyrouter_set_user_data(struct wl_keyrouter *wl_keyrouter, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) wl_keyrouter, user_data); +} + +static inline void * +wl_keyrouter_get_user_data(struct wl_keyrouter *wl_keyrouter) +{ + return wl_proxy_get_user_data((struct wl_proxy *) wl_keyrouter); +} + +static inline void +wl_keyrouter_destroy(struct wl_keyrouter *wl_keyrouter) +{ + wl_proxy_destroy((struct wl_proxy *) wl_keyrouter); +} + +static inline void +wl_keyrouter_set_keygrab(struct wl_keyrouter *wl_keyrouter, struct wl_surface *surface, uint32_t key, uint32_t mode) +{ + wl_proxy_marshal((struct wl_proxy *) wl_keyrouter, + WL_KEYROUTER_SET_KEYGRAB, surface, key, mode); +} + +static inline void +wl_keyrouter_unset_keygrab(struct wl_keyrouter *wl_keyrouter, struct wl_surface *surface, uint32_t key) +{ + wl_proxy_marshal((struct wl_proxy *) wl_keyrouter, + WL_KEYROUTER_UNSET_KEYGRAB, surface, key); +} + +static inline void +wl_keyrouter_get_keygrab_status(struct wl_keyrouter *wl_keyrouter, struct wl_surface *surface, uint32_t key) +{ + wl_proxy_marshal((struct wl_proxy *) wl_keyrouter, + WL_KEYROUTER_GET_KEYGRAB_STATUS, surface, key); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/lib/ecore_wayland/keyrouter-protocol.c b/src/lib/ecore_wayland/keyrouter-protocol.c new file mode 100644 index 0000000000..4ff03c7e7f --- /dev/null +++ b/src/lib/ecore_wayland/keyrouter-protocol.c @@ -0,0 +1,37 @@ + +#include <stdlib.h> +#include <stdint.h> +#include "wayland-util.h" + +extern const struct wl_interface wl_surface_interface; + +static const struct wl_interface *types[] = { + &wl_surface_interface, + NULL, + NULL, + &wl_surface_interface, + NULL, + &wl_surface_interface, + NULL, + &wl_surface_interface, + NULL, + NULL, + NULL, +}; + +static const struct wl_message wl_keyrouter_requests[] = { + { "set_keygrab", "?ouu", types + 0 }, + { "unset_keygrab", "?ou", types + 3 }, + { "get_keygrab_status", "?ou", types + 5 }, +}; + +static const struct wl_message wl_keyrouter_events[] = { + { "keygrab_notify", "?ouuu", types + 7 }, +}; + +WL_EXPORT const struct wl_interface wl_keyrouter_interface = { + "wl_keyrouter", 1, + 3, wl_keyrouter_requests, + 1, wl_keyrouter_events, +}; + |