e_devicemgr: handle keyboard_grab/ungrab requests 38/297738/2 accepted/tizen/unified/20230825.182737 accepted/tizen/unified/20230828.102403
authorduna.oh <duna.oh@samsung.com>
Wed, 23 Aug 2023 02:40:40 +0000 (11:40 +0900)
committerDuna Oh <duna.oh@samsung.com>
Wed, 23 Aug 2023 23:19:42 +0000 (23:19 +0000)
keyboard_grab/ungrab are available since tizen_input_device_manager v.6
key events can be grabbed according to the requested device subtype.
(Remocon/None)

Change-Id: I373a2f037bb3d6ffce68b5469544d267f9da6190

src/bin/Makefile.mk
src/bin/e_devicemgr.h
src/bin/e_devicemgr_keyboard_grab.c [new file with mode: 0644]
src/bin/e_devicemgr_private.h
src/bin/e_devicemgr_wl.c
src/bin/e_input.c
src/bin/e_input.h
src/bin/e_input_evdev.c

index fd3915d..579b8f2 100644 (file)
@@ -284,7 +284,8 @@ src/bin/e_input_event.c \
 src/bin/e_single_pixel_buffer.c \
 src/bin/e_comp_wl_buffer.c \
 src/bin/e_compositor.c \
-src/bin/e_blender.c
+src/bin/e_blender.c \
+src/bin/e_devicemgr_keyboard_grab.c
 
 src_bin_enlightenment_CPPFLAGS = $(E_CPPFLAGS) -DEFL_BETA_API_SUPPORT -DEFL_EO_API_SUPPORT -DE_LOGGING=2 @WAYLAND_CFLAGS@ $(TTRACE_CFLAGS) $(DLOG_CFLAGS) $(PIXMAN_CFLAGS) $(POLICY_CFLAGS) $(EGL_CFLAGS)
 if HAVE_LIBGOMP
index 9108350..8806c01 100644 (file)
@@ -88,6 +88,13 @@ struct _E_Devicemgr
    int max_touch_count;
    GMutex device_list_mutex;
    GMutex last_device_kbd_mutex;
+
+   struct
+   {
+      struct wl_client *client;
+      E_Client *ec;
+      unsigned int subtype;
+   } keyboard_grab;
 };
 
 struct _E_Devicemgr_Intercept_Hook
@@ -115,6 +122,8 @@ EINTERN Eina_Bool e_devicemgr_block_internal_remove(E_Devicemgr_Block_Expire_Cb
 
 E_API Eina_Bool e_devicemgr_block_reset(void);
 
+EINTERN Eina_Bool e_devicemgr_keyboard_grab_subtype_is_grabbed(Ecore_Device_Subclass subclas);
+
 #endif
 #endif
 
diff --git a/src/bin/e_devicemgr_keyboard_grab.c b/src/bin/e_devicemgr_keyboard_grab.c
new file mode 100644 (file)
index 0000000..a144ed5
--- /dev/null
@@ -0,0 +1,160 @@
+#include "e_devicemgr_private.h"
+
+static void _e_devicemgr_keyboard_grab_client_cb_destroy(struct wl_listener *l, void *data);
+
+EINTERN Eina_Bool
+e_devicemgr_keyboard_grab_subtype_is_grabbed(Ecore_Device_Subclass subclas)
+{
+   if ((subclas == ECORE_DEVICE_SUBCLASS_NONE) &&
+       (e_devicemgr->keyboard_grab.subtype & TIZEN_INPUT_DEVICE_MANAGER_SUBCLAS_NONE))
+       return EINA_TRUE;
+
+   if ((subclas == ECORE_DEVICE_SUBCLASS_REMOCON) &&
+       (e_devicemgr->keyboard_grab.subtype & TIZEN_INPUT_DEVICE_MANAGER_SUBCLAS_REMOCON))
+       return EINA_TRUE;
+
+   if ((subclas == ECORE_DEVICE_SUBCLASS_VIRTUAL_KEYBOARD) &&
+       (e_devicemgr->keyboard_grab.subtype & TIZEN_INPUT_DEVICE_MANAGER_SUBCLAS_VIRTUAL_KEYBOARD))
+       return EINA_TRUE;
+
+   DMWRN("Keyboard Grab. device subclas(%d) is not grabbed", subclas);
+   return EINA_FALSE;
+}
+
+static void
+_e_devicemgr_keyboard_grab_key_handler(uint32_t keycode, uint32_t state,
+                                           uint32_t timestamp)
+{
+    DMINF("key(%d-%s) event is delivered to grab ec(%p)",
+          keycode, state ? "Pressed" : "Released", e_devicemgr->keyboard_grab.ec);
+
+   if (!e_comp_wl_key_send(e_devicemgr->keyboard_grab.ec, keycode, state ? EINA_TRUE : EINA_FALSE,
+                      NULL, timestamp))
+      {
+         DMERR("Could not send keyboard_grab_key to client(%p)", e_devicemgr->keyboard_grab.client);
+      }
+}
+
+static Eina_Bool
+_e_devicemgr_keyboard_grab_client_remove(struct wl_client *client)
+{
+   struct wl_listener *destroy_listener = NULL;
+
+   if (client != e_devicemgr->keyboard_grab.client)
+     return EINA_FALSE;
+
+   e_devicemgr->keyboard_grab.subtype = 0x0;
+   e_devicemgr->keyboard_grab.client = NULL;
+   e_devicemgr->keyboard_grab.ec = NULL;
+
+   if (!e_input_keyboard_grab_key_handler_set(NULL))
+     {
+        DMERR("ERROR! Could not set keyboard_grab key handler to NULL!");
+        return EINA_FALSE;
+     }
+
+   destroy_listener = wl_client_get_destroy_listener(client, _e_devicemgr_keyboard_grab_client_cb_destroy);
+   if (destroy_listener)
+     {
+        wl_list_remove(&destroy_listener->link);
+        E_FREE(destroy_listener);
+     }
+
+   return EINA_TRUE;
+}
+
+static void
+_e_devicemgr_keyboard_grab_client_cb_destroy(struct wl_listener *l, void *data)
+{
+   struct wl_client *client = (struct wl_client *)data;
+
+   if (!e_devicemgr->keyboard_grab.client) return;
+
+   wl_list_remove(&l->link);
+   E_FREE(l);
+
+   _e_devicemgr_keyboard_grab_client_remove(client);
+}
+
+static Eina_Bool
+_e_devicemgr_keyboard_grab_client_add(struct wl_client *client, E_Client *ec, uint32_t subclas)
+{
+   struct wl_listener *destroy_listener = NULL;
+
+   e_devicemgr->keyboard_grab.subtype |= subclas;
+
+   if (e_devicemgr->keyboard_grab.client == client)
+     return EINA_TRUE;
+
+   e_devicemgr->keyboard_grab.client = client;
+   e_devicemgr->keyboard_grab.ec = ec;
+
+   if (!e_input_keyboard_grab_key_handler_set(_e_devicemgr_keyboard_grab_key_handler))
+     {
+        DMERR("ERROR! Could not set keyboard_grab key handler to func!");
+        return EINA_FALSE;
+     }
+
+   destroy_listener = E_NEW(struct wl_listener, 1);
+   EINA_SAFETY_ON_NULL_GOTO(destroy_listener, failed);
+   destroy_listener->notify = _e_devicemgr_keyboard_grab_client_cb_destroy;
+   wl_client_add_destroy_listener(client, destroy_listener);
+
+   return EINA_TRUE;
+
+failed:
+   e_devicemgr->keyboard_grab.client = NULL;
+   e_devicemgr->keyboard_grab.ec = NULL;
+   e_devicemgr->keyboard_grab.subtype = 0x0;
+
+   return EINA_FALSE;
+}
+
+int
+e_devicemgr_keyboard_grab(struct wl_client *client, struct wl_resource *surface, uint32_t subclas)
+{
+   int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+   E_Client *ec;
+   uint32_t all_subclass = TIZEN_INPUT_DEVICE_MANAGER_SUBCLAS_NONE |
+                        TIZEN_INPUT_DEVICE_MANAGER_SUBCLAS_REMOCON |
+                        TIZEN_INPUT_DEVICE_MANAGER_SUBCLAS_VIRTUAL_KEYBOARD;
+
+   if ((e_devicemgr->keyboard_grab.client) && (e_devicemgr->keyboard_grab.client != client))
+     {
+        return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NOT_ALLOWED;
+     }
+   if (!(subclas & all_subclass))
+     {
+        return TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_CLASS;
+     }
+
+   ec = e_client_from_surface_resource(surface);
+   if (!ec)
+     return TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_SURFACE;
+
+   if (!_e_devicemgr_keyboard_grab_client_add(client, ec, subclas))
+     ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NOT_ALLOWED;
+
+   return ret;
+}
+
+int
+e_devicemgr_keyboard_ungrab(struct wl_client *client, struct wl_resource *surface)
+{
+   int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+   E_Client *ec;
+
+   if ((e_devicemgr->keyboard_grab.client) && (e_devicemgr->keyboard_grab.client != client))
+    {
+       return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NOT_ALLOWED;
+    }
+
+   ec = e_client_from_surface_resource(surface);
+   if (!ec)
+     return TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_SURFACE;
+
+   if (!_e_devicemgr_keyboard_grab_client_remove(client))
+     ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NOT_ALLOWED;
+
+   return ret;
+}
\ No newline at end of file
index 0acd77a..6cf0418 100644 (file)
@@ -192,3 +192,6 @@ void e_devicemgr_wl_touch_max_count_send(int slot, struct wl_resource *res, stru
 void e_devicemgr_wl_generator_with_sync_send_event(struct wl_resource *resource, int error);
 void e_devicemgr_inputgen_device_ready_send(E_Devicemgr_Input_Device *dev);
 
+int e_devicemgr_keyboard_ungrab(struct wl_client *client, struct wl_resource *surface);
+int e_devicemgr_keyboard_grab(struct wl_client *client, struct wl_resource *surface, uint32_t subclas);
+
index cfe4cac..7f6bc3b 100644 (file)
@@ -562,6 +562,46 @@ _e_devicemgr_wl_cb_set_touch_count(struct wl_client *client, struct wl_resource
    tizen_input_device_manager_send_error(resource, ret);
 }
 
+static void
+_e_devicemgr_wl_cb_keyboard_grab(struct wl_client *client, struct wl_resource *resource,
+                                 struct wl_resource *surface, uint32_t subclas)
+{
+   int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+
+#ifdef HAVE_CYNARA
+   if (EINA_FALSE == _e_devicemgr_util_do_privilege_check(client, wl_client_get_fd(client),
+                                                          E_PRIVILEGE_INTERNAL_DEFAULT_PLATFORM))
+     {
+        DMERR("keyboard_grab request:priv check failed");
+        tizen_input_device_manager_send_error(resource, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION);
+        return;
+     }
+#endif
+
+   ret = e_devicemgr_keyboard_grab(client, surface, subclas);
+   tizen_input_device_manager_send_error(resource, ret);
+}
+
+static void
+_e_devicemgr_wl_cb_keyboard_ungrab(struct wl_client *client, struct wl_resource *resource,
+                                   struct wl_resource *surface)
+{
+   int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+
+#ifdef HAVE_CYNARA
+   if (EINA_FALSE == _e_devicemgr_util_do_privilege_check(client, wl_client_get_fd(client),
+                                                          E_PRIVILEGE_INTERNAL_DEFAULT_PLATFORM))
+     {
+        DMERR("keyboard_ungrab request:priv check failed");
+        tizen_input_device_manager_send_error(resource, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION);
+        return;
+     }
+#endif
+
+   ret = e_devicemgr_keyboard_ungrab(client, surface);
+   tizen_input_device_manager_send_error(resource, ret);
+}
+
 
 static const struct tizen_input_device_manager_interface _e_devicemgr_wl_implementation = {
    _e_devicemgr_wl_cb_block_events,
@@ -577,6 +617,8 @@ static const struct tizen_input_device_manager_interface _e_devicemgr_wl_impleme
    _e_devicemgr_wl_cb_generate_axis,
    _e_devicemgr_wl_cb_set_touch_count,
    _e_devicemgr_wl_cb_init_generator_with_sync,
+   _e_devicemgr_wl_cb_keyboard_grab,
+   _e_devicemgr_wl_cb_keyboard_ungrab
 };
 
 static void
@@ -716,7 +758,7 @@ e_devicemgr_wl_init(void)
 
    /* try to add tizen_input_device_manager to wayland globals */
    e_devicemgr->wl_data->global = wl_global_create(e_comp_wl->wl.disp,
-                                                   &tizen_input_device_manager_interface, 5,
+                                                   &tizen_input_device_manager_interface, 6,
                                                    NULL, _e_devicemgr_wl_cb_bind);
    if (!e_devicemgr->wl_data->global)
      {
index 74e01e2..85d641d 100644 (file)
@@ -353,3 +353,22 @@ e_input_relative_motion_handler_get(void)
    return NULL;
 }
 
+EINTERN Eina_Bool
+e_input_keyboard_grab_key_handler_set(e_input_keyboard_grab_key_cb handler)
+{
+   if (!e_input)
+     return EINA_FALSE;
+
+   e_input->keyboard_grab_key_handler = handler;
+   return EINA_TRUE;
+}
+
+EINTERN e_input_keyboard_grab_key_cb
+e_input_keyboard_grab_key_handler_get(void)
+{
+   if (e_input)
+     return e_input->keyboard_grab_key_handler;
+
+   return NULL;
+}
+
index beffdcb..8249884 100644 (file)
@@ -57,6 +57,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_keyboard_grab_key_cb)(uint32_t keycode, uint32_t state, uint32_t timestamp);
 
 struct _E_Input
 {
@@ -71,6 +72,7 @@ struct _E_Input
    unsigned int touch_device_count;
 
    e_input_relative_motion_cb relative_motion_handler;
+   e_input_keyboard_grab_key_cb keyboard_grab_key_handler;
 };
 
 struct _E_Input_Device
@@ -157,6 +159,9 @@ EINTERN void e_input_create_event_source(E_Input_Backend *input);
 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_keyboard_grab_key_handler_set(e_input_keyboard_grab_key_cb handler);
+EINTERN e_input_keyboard_grab_key_cb e_input_keyboard_grab_key_handler_get(void);
+
 EINTERN Eina_Bool e_input_device_subtype_set(E_Input_Device *dev, const char *input, const char *subtype);
 
 #endif
index 360bb4b..e9ef0d2 100644 (file)
@@ -3,6 +3,7 @@
 #include "e_device.h"
 #include "e_keyrouter_private.h"
 #include "e_input_event.h"
+#include "e_devicemgr.h"
 
 #include <glib.h>
 
@@ -532,6 +533,7 @@ _device_handle_key(struct libinput_device *device, struct libinput_event_keyboar
    int *pressed_keycode = NULL, *idata = NULL;
    Eina_Bool dup_found = EINA_FALSE;
    const char* device_name = NULL;
+   Ecore_Device_Subclass device_subclas = ECORE_DEVICE_SUBCLASS_NONE;
 
    if (!(edev = libinput_device_get_user_data(device)))
      {
@@ -570,6 +572,7 @@ _device_handle_key(struct libinput_device *device, struct libinput_event_keyboar
           }
 
         device_name = ecore_device_name_get(ecore_dev);
+        device_subclas = ecore_device_subclass_get(ecore_dev);
      }
    else
      {
@@ -602,6 +605,7 @@ _device_handle_key(struct libinput_device *device, struct libinput_event_keyboar
           }
 
         device_name = e_device_name_get(e_dev);
+        device_subclas = e_device_subclass_get(e_dev);
      }
 
    timestamp = libinput_event_keyboard_get_time(event);
@@ -671,6 +675,16 @@ _device_handle_key(struct libinput_device *device, struct libinput_event_keyboar
         return;
      }
 
+   e_input_keyboard_grab_key_cb func = e_input_keyboard_grab_key_handler_get();
+   if (func)
+     {
+        if (e_devicemgr_keyboard_grab_subtype_is_grabbed(device_subclas))
+          {
+             func(code, state, timestamp);
+             return;
+          }
+     }
+
    g_mutex_lock(&edev->xkb.state_mutex);
    xkb_state_update_key(edev->xkb.state, code,
                         (state ? XKB_KEY_DOWN : XKB_KEY_UP));