summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJi-Youn Park <jy0703.park@samsung.com>2015-05-30 02:42:12 +0900
committerJi-Youn Park <jy0703.park@samsung.com>2015-06-01 16:30:23 +0900
commitce6c0787986f37ccfeb20bcba345ac0fe137520e (patch)
tree6ffbb68af10e5c5a603b059738d01790ded29cfc
parent35bff0942d5fa7121dbc8609c45f3d39985b93c1 (diff)
downloadefl-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.am2
-rw-r--r--src/lib/ecore_wayland/Ecore_Wayland.h26
-rw-r--r--src/lib/ecore_wayland/ecore_wl.c150
-rw-r--r--src/lib/ecore_wayland/ecore_wl_private.h3
-rw-r--r--src/lib/ecore_wayland/keyrouter-client-protocol.h141
-rw-r--r--src/lib/ecore_wayland/keyrouter-protocol.c37
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,
+};
+