E-mod can dispatch key events via dbus method call.
This approach enables synchronous dispatching key ecore events.
Change-Id: I7fb11d4eb93ed1bec71da6dd38dfb427ffcafc3d
e_dispatch_gesture_event.c \
e_dispatch_rotation_event.c \
e_universal_switch.c \
- e_mod_utils.c
+ e_mod_utils.c \
+ e_dispatch_key_event.c
module_la_LIBADD =
module_la_CFLAGS = @ENLIGHTENMENT_CFLAGS@
static Eina_Bool _on_gesture_sequence_timer(void *data);
static void _on_terminate_gesture_sequence(GestureCommand *cmd);
-static Ecore_Device * _get_device()
-{
- const Eina_List *dev_list = NULL;
- const Eina_List *l;
- Ecore_Device *dev = NULL;
- const char *identifier;
-
- dev_list = ecore_device_list();
- if (!dev_list) return NULL;
- EINA_LIST_FOREACH(dev_list, l, dev)
- {
- if (!dev) continue;
- identifier = ecore_device_identifier_get(dev);
- if (!identifier) continue;
-
- //FIXME: Find right way to get device class
- if (ecore_device_class_get(dev) == ECORE_DEVICE_CLASS_TOUCH)
- return dev;
- }
- return NULL;
-}
-
static void _dispatch_mouse_move_event(int x, int y, int device)
{
Ecore_Event_Mouse_Move *ev;
--- /dev/null
+#include "e_dispatch_key_event.h"
+
+#include "e.h"
+#include "e_mod_utils.h"
+#include "e_screen_reader_private.h"
+
+static Eina_Bool during_event = EINA_FALSE;
+static double time_between_presses = 0.01;
+
+typedef struct _KeyEventData {
+ KeyEventInfo info;
+ int keycode;
+ Eldbus_Message *reply;
+ Eldbus_Connection *conn;
+} KeyEventData;
+
+static Ecore_Event_Key *
+_create_key_event(KeyEventData *ked)
+{
+ Ecore_Event_Key *ev = calloc(1, sizeof(Ecore_Event_Key));
+ if (!ev)
+ {
+ ERROR("Malloc error");
+ eldbus_connection_send(ked->conn, ked->reply, NULL, NULL, -1);
+ return NULL;
+ }
+
+ ev->keyname = strdup(ked->info.keyname);
+ ev->key = strdup(ked->info.keyname);
+ ev->string = strdup(ked->info.keyname);
+ ev->compose = strdup(ked->info.keyname);
+ ev->window = e_comp->ee_win;
+ ev->event_window = e_comp->ee_win;
+ ev->root_window = e_comp->ee_win;
+ ev->same_screen = 1;
+ ev->dev = _get_device();
+ ev->keycode = ked->keycode;
+
+ return ev;
+}
+
+static void _ecore_deleter(void *data, void *func_data)
+{
+ Ecore_Event_Key *ev = func_data;
+
+ free((char *)ev->keyname);
+ free((char *)ev->key);
+ free((char *)ev->string);
+ free((char *)ev->compose);
+ free(ev);
+}
+
+static Eina_Bool _finalize_event(KeyEventData *ked)
+{
+ eldbus_connection_send(ked->conn, ked->reply, NULL, NULL, -1);
+ free(ked->info.keyname);
+ free(ked);
+ during_event = EINA_FALSE;
+
+ return EINA_FALSE;
+}
+
+static Eina_Bool _generate_key_up_event(void *data);
+
+static Eina_Bool _generate_key_down_event(void *data)
+{
+ KeyEventData *ked = data;
+
+ if (ked->info.multiplicity == 0)
+ return _finalize_event(ked);
+
+ --ked->info.multiplicity;
+
+ Ecore_Event_Key *ev = _create_key_event(ked);
+ ecore_event_add(ECORE_EVENT_KEY_DOWN, ev, _ecore_deleter, NULL);
+ ecore_timer_add(ked->info.hold_time, _generate_key_up_event, ked);
+
+ return EINA_FALSE;
+}
+
+static Eina_Bool _generate_key_up_event(void *data)
+{
+ KeyEventData *ked = data;
+
+ Ecore_Event_Key *ev = _create_key_event(ked);
+ ecore_event_add(ECORE_EVENT_KEY_UP, ev, _ecore_deleter, NULL);
+ ecore_timer_add(time_between_presses, _generate_key_down_event, ked);
+
+ return EINA_FALSE;
+}
+
+static Eldbus_Message *
+_check_event_data(KeyEventInfo *kei, const Eldbus_Message *msg)
+{
+ if (kei->multiplicity < 1)
+ return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Invalid multiplicity value, expected: > 1");
+
+ if (kei->hold_time < 0.0)
+ return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Invalid hold_time value, expected: >= 0.0");
+
+ return NULL;
+}
+
+Eldbus_Message *
+_e_dispatch_key_event(KeyEventInfo kei, Eldbus_Connection *conn, const Eldbus_Message *msg)
+{
+ if (during_event)
+ return eldbus_message_error_new(msg, "org.freedesktop.DBus.Error.Failed", "Previous call is being processed.");
+
+ Eldbus_Message *error_msg = _check_event_data(&kei, msg);
+ if (error_msg)
+ return error_msg;
+
+ KeyEventData *ked = (KeyEventData *)malloc(sizeof(KeyEventData));
+ ked->info.keyname = strdup(kei.keyname);
+ ked->info.multiplicity = kei.multiplicity;
+ ked->info.hold_time = kei.hold_time;
+ ked->keycode = _get_keycode_from_string(kei.keyname);
+ ked->reply = eldbus_message_method_return_new(msg);
+ ked->conn = conn;
+
+ during_event = EINA_TRUE;
+ _generate_key_down_event(ked);
+
+ return NULL;
+}
--- /dev/null
+#ifndef E_DISPATCH_KEY_EVENT_H
+#define E_DISPATCH_KEY_EVENT_H
+
+#include "e.h"
+
+typedef struct _KeyEventInfo {
+ char *keyname;
+ int multiplicity;
+ double hold_time;
+} KeyEventInfo;
+
+Eldbus_Message *_e_dispatch_key_event(KeyEventInfo kei, Eldbus_Connection *conn, const Eldbus_Message *msg);
+
+#endif
#include <vconf.h>
#include <e_dispatch_gesture_event.h>
#include <e_dispatch_rotation_event.h>
+#include <e_dispatch_key_event.h>
#include "e_universal_switch.h"
#define E_A11Y_SERVICE_BUS_NAME "org.enlightenment.wm-screen-reader"
static Eldbus_Message *_dispatch_drag_event(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg);
static Eldbus_Message *_dispatch_pinch_event(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg);
static Eldbus_Message *_dispatch_rotation_event(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg);
+static Eldbus_Message *_dispatch_key_event(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg);
static const Eldbus_Method methods[] = {
{ "ScreenReaderEnabled", ELDBUS_ARGS({"b", "bool"}), ELDBUS_ARGS({"b", "bool"}),
{ "DispatchRotationEvent", ELDBUS_ARGS({"i", "int"}), NULL,
_dispatch_rotation_event
},
+ { "DispatchKeyEvent", ELDBUS_ARGS({"s", "string"}, {"i", "int"}, {"d", "double"}), NULL,
+ _dispatch_key_event
+ },
{ }
};
return eldbus_message_method_return_new(msg);
}
+static Eldbus_Message *
+_dispatch_key_event(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
+{
+ KeyEventInfo kei;
+ if (eldbus_message_arguments_get(msg, "sid", &kei.keyname, &kei.multiplicity, &kei.hold_time))
+ {
+ return _e_dispatch_key_event(kei, conn, msg);
+ }
+ else
+ ERROR("eldbus_message_arguments_get() error\n");
+
+ return eldbus_message_method_return_new(msg);
+}
+
static int
_fetch_a11y_bus_address(void)
{
ERROR("Invalid angle");
}
}
+
+Ecore_Device * _get_device()
+{
+ const Eina_List *dev_list = ecore_device_list();
+ if (!dev_list) return NULL;
+
+ const Eina_List *l;
+ Ecore_Device *dev = NULL;
+ EINA_LIST_FOREACH(dev_list, l, dev)
+ {
+ if (!dev) continue;
+ const char *identifier = ecore_device_identifier_get(dev);
+ if (!identifier) continue;
+
+ //FIXME: Find right way to get device class (there could be more than one touch device in the future)
+ if (ecore_device_class_get(dev) == ECORE_DEVICE_CLASS_TOUCH)
+ return dev;
+ }
+ return NULL;
+}
+
+typedef struct _keycode_map_entry{
+ xkb_keysym_t keysym;
+ xkb_keycode_t keycode;
+} keycode_map_entry;
+
+static void
+_find_keycode(struct xkb_keymap *keymap, xkb_keycode_t key, void *data)
+{
+ keycode_map_entry* pair = (keycode_map_entry *)data;
+ const xkb_keysym_t *syms_out = NULL;
+ int nsyms = xkb_keymap_key_get_syms_by_level(keymap, key, 0, 0, &syms_out);
+
+ if (nsyms && syms_out && *syms_out == pair->keysym)
+ {
+ pair->keycode = key;
+ }
+}
+
+int _get_keycode_from_string(const char *key)
+{
+ xkb_keysym_t keysym = xkb_keysym_from_name(key, XKB_KEYSYM_NO_FLAGS);
+ struct xkb_keymap *keymap = e_comp_wl->xkb.keymap;
+ keycode_map_entry pair = {keysym, 0};
+ xkb_keymap_key_for_each(keymap, _find_keycode, &pair);
+
+ return pair.keycode;
+}
#ifndef E_MOD_UTILS_H
#define E_MOD_UTILS_H
+#include "e.h"
+
int _get_window_angle(void);
void _transform_coordinates(int *ax, int *ay);
+Ecore_Device * _get_device();
+int _get_keycode_from_string(const char *key);
#endif