#include "e.h"
+#include "e_devicemgr_intern.h"
+#include "e_input_intern.h"
#include "e_input_private.h"
-#include "e_input_event.h"
+#include "e_input_event_intern.h"
+#include "e_keyrouter_intern.h"
+#include "e_comp_wl_intern.h"
#include <glib.h>
static gboolean input_thread_prepare(GSource *source, gint *time);
static E_Input_Event_Source *g_input_event_source = NULL;
+static GList *_key_event_list = NULL;
GSourceFuncs input_event_funcs = {
.prepare = input_thread_prepare,
if (!edev || !edev->path) return EINA_FALSE;
- ecore_thread_main_loop_begin();
-
dev_list = ecore_device_list();
if (dev_list)
{
if (!identifier) continue;
if ((ecore_device_class_get(dev) == clas) && (!strcmp(identifier, edev->path)))
{
- ecore_thread_main_loop_end();
+ ERR("Found same device in device list");
return EINA_FALSE;
}
}
dev = ecore_device_add();
if (!dev)
{
+ ERR("Failed to create ecore device");
edev->ecore_dev = NULL;
- ecore_thread_main_loop_end();
return EINA_FALSE;
}
edev->ecore_dev_list = eina_list_append(edev->ecore_dev_list, ecore_device_ref(dev));
}
- // create E_Device info
- e_dev = e_device_new();
+ const GList *device_list = e_device_list_get();
+ const gchar *device_identifier;
+ for (GList *list = g_list_first((GList *)device_list); list; list = list->next)
+ {
+ E_Device *device = (E_Device *)list->data;
+ if (!device) continue;
+ device_identifier = e_device_identifier_get(device);
+ if (!device_identifier) continue;
+
+ if ((e_device_class_get(device) == clas) && (!strcmp(device_identifier, edev->path)))
+ {
+ e_dev = device;
+ break;
+ }
+ }
+
if (!e_dev)
{
- edev->e_dev = NULL;
- ecore_thread_main_loop_end();
- return EINA_FALSE;
+ // create E_Device info
+ e_dev = e_device_new();
+ if (!e_dev)
+ {
+ ERR("Failed to add e device");
+ edev->e_dev = NULL;
+ return EINA_FALSE;
+ }
}
e_device_name_set(e_dev, libinput_device_get_name(edev->device));
_e_input_ecore_device_event(dev, edev->seat ? edev->seat->name : NULL, EINA_TRUE);
- ecore_thread_main_loop_end();
+ INF("[Add Device] device name(%s), identifier(%s), class(%s)", e_device_name_get(e_dev), edev->path, _e_input_ecore_device_class_to_string(clas));
+
return EINA_TRUE;
}
static Eina_Bool
_e_input_remove_ecore_device(E_Input_Evdev *edev, Ecore_Device_Class clas)
{
+ Eina_Bool ret = EINA_FALSE;
const Eina_List *dev_list = NULL, *l;
+ const GList *e_dev_list = NULL;
Eina_List *ll, *ll_next;
Ecore_Device *dev = NULL, *data;
const char *identifier;
+ const gchar *device_identifier;
+ const char *device_remove_log = NULL;
if (!edev->path) return EINA_FALSE;
dev_list = ecore_device_list();
if (!dev_list) return EINA_FALSE;
- ecore_thread_main_loop_begin();
EINA_LIST_FOREACH(dev_list, l, dev)
{
if (!dev) continue;
}
_e_input_ecore_device_event(dev, edev->seat ? edev->seat->name : NULL, EINA_FALSE);
ecore_device_del(dev);
- ecore_thread_main_loop_end();
- return EINA_TRUE;
+ ret = EINA_TRUE;
}
}
- ecore_thread_main_loop_end();
- return EINA_FALSE;
+
+ e_dev_list = e_device_list_get();
+ if (!e_dev_list)
+ {
+ ERR("Failed to get e device list");
+ return EINA_FALSE;
+ }
+
+ for (GList *list = g_list_first((GList *)e_dev_list); list; list = list->next)
+ {
+ E_Device *device = (E_Device *)list->data;
+ if (!device) continue;
+ device_identifier = e_device_identifier_get(device);
+ if (!device_identifier) continue;
+
+ if ((e_device_class_get(device) == clas) && (!strcmp(device_identifier, edev->path)))
+ {
+ device_remove_log = eina_stringshare_printf("[Remove Device] device name(%s), identifier(%s), class(%s)",
+ e_device_name_get(device),
+ device_identifier,
+ _e_input_ecore_device_class_to_string(clas));
+
+ if (edev->e_dev)
+ {
+ g_object_unref(device);
+ edev->e_dev = NULL;
+ }
+ else if (edev->e_dev_list)
+ {
+ GList *del_list = g_list_find(edev->e_dev_list, device);
+ if (del_list)
+ {
+ edev->e_dev_list = g_list_delete_link(edev->e_dev_list, del_list);
+ }
+ }
+ ret = EINA_TRUE;
+ }
+ }
+
+ if (device_remove_log)
+ {
+ INF("%s", device_remove_log);
+ eina_stringshare_del(device_remove_log);
+ }
+
+ return ret;
}
Eina_Bool
{
if (eina_list_count(edev->ecore_dev_list) > 0)
{
- ecore_thread_main_loop_begin();
EINA_LIST_FREE(edev->ecore_dev_list, data)
{
-
WRN("Invalid device is left. name: %s, identifier: %s, clas: %s\n",
ecore_device_name_get(data), ecore_device_identifier_get(data),
_e_input_ecore_device_class_to_string(ecore_device_class_get(data)));
ecore_device_unref(data);
ecore_device_del(data);
-
}
- ecore_thread_main_loop_end();
}
edev->ecore_dev_list = NULL;
}
E_Input_Seat *seat;
E_Input_Evdev *edev;
+ ecore_thread_main_loop_begin();
libinput_seat = libinput_device_get_seat(device);
seat_name = libinput_seat_get_logical_name(libinput_seat);
if (!(seat = _seat_get(input, seat_name)))
{
ERR("Could not get matching seat: %s", seat_name);
+ ecore_thread_main_loop_end();
return;
}
if (!(edev = _e_input_evdev_device_create(seat, device)))
{
ERR("Failed to create new evdev device");
+ ecore_thread_main_loop_end();
return;
}
if (EINA_FALSE == _e_input_device_add(edev))
{
ERR("Failed to create evas device !\n");
+ ecore_thread_main_loop_end();
return;
}
+
+ ecore_thread_main_loop_end();
}
static void
{
E_Input_Evdev *edev;
+ ecore_thread_main_loop_begin();
+
/* try to get the evdev structure */
if (!(edev = libinput_device_get_user_data(device)))
{
+ ecore_thread_main_loop_end();
return;
}
/* destroy this evdev */
_e_input_evdev_device_destroy(edev);
+
+ ecore_thread_main_loop_end();
}
static int
switch (libinput_event_get_type(event))
{
case LIBINPUT_EVENT_DEVICE_ADDED:
+ if (e_config->key_input_ttrace_enable)
+ {
+ TRACE_INPUT_BEGIN(_device_added);
+ ELOGF("INPUT", "_device_added|B|", NULL);
+ }
+
_device_added(input, device);
+
+ if (e_config->key_input_ttrace_enable)
+ {
+ TRACE_INPUT_END();
+ ELOGF("INPUT", "_device_added|E|", NULL);
+ }
break;
case LIBINPUT_EVENT_DEVICE_REMOVED:
+ if (e_config->key_input_ttrace_enable)
+ {
+ TRACE_INPUT_BEGIN(_device_removed);
+ ELOGF("INPUT", "_device_removed|B|", NULL);
+ }
+
_device_removed(input, device);
+
+ if (e_config->key_input_ttrace_enable)
+ {
+ TRACE_INPUT_END();
+ ELOGF("INPUT", "_device_removed|E|", NULL);
+ }
break;
default:
ret = EINA_FALSE;
_input_events_process(E_Input_Backend *input)
{
struct libinput_event *event;
-
while ((event = libinput_get_event(input->libinput)))
{
_input_event_process(event);
if (!(input = data)) return EINA_TRUE;
+ if (e_config->key_input_ttrace_enable)
+ {
+ TRACE_INPUT_BEGIN(_cb_input_dispatch);
+ ELOGF("INPUT", "_cb_input_dispatch|B|", NULL);
+ }
+
if (libinput_dispatch(input->libinput) != 0)
ERR("Failed to dispatch libinput events: %m");
/* process pending events */
_input_events_process(input);
+ if (e_config->key_input_ttrace_enable)
+ {
+ TRACE_INPUT_END();
+ ELOGF("INPUT", "_cb_input_dispatch|E|", NULL);
+ }
+
return EINA_TRUE;
}
+static void
+_e_input_delayed_key_events_print()
+{
+ struct timespec tp;
+ unsigned int time;
+
+ clock_gettime(CLOCK_MONOTONIC, &tp);
+ time = (tp.tv_sec * 1000) + (tp.tv_nsec / 1000000L);
+
+ GList *key_list = g_list_first(_key_event_list);
+ while (key_list)
+ {
+ Ecore_Event_Key *key = (Ecore_Event_Key *)key_list->data;
+ if (!key) continue;
+
+ if (e_config->key_input_time_limit <= (time - key->timestamp))
+ ERR("Delayed key event : keyname(%s), keycode(%u), timestamp(%u), elapsed_time(%u ms)", key->keyname, key->keycode, key->timestamp, time - key->timestamp);
+
+ if (key->keyname)
+ eina_stringshare_del(key->keyname);
+ E_FREE(key);
+
+ GList *next = key_list->next;
+ _key_event_list = g_list_delete_link(_key_event_list, key_list);
+ key_list = next;
+ }
+
+ _key_event_list = NULL;
+}
+
static gboolean
input_thread_prepare(GSource *source, gint *time)
{
- /* flush pending client events */
- e_comp_wl_display_flush();
+ if (e_config->key_input_ttrace_enable)
+ {
+ TRACE_INPUT_BEGIN(e_comp_wl_focused_client_flush);
+ ELOGF("INPUT", "e_comp_wl_focused_client_flush|B|", NULL);
+ }
+
+ /* flush only focused client events */
+ e_comp_wl_focused_client_flush();
+
+ if (_key_event_list)
+ _e_input_delayed_key_events_print();
+
+ if (e_config->key_input_ttrace_enable)
+ {
+ TRACE_INPUT_END();
+ ELOGF("INPUT", "e_comp_wl_focused_client_flush|E|", NULL);
+ }
if (time)
*time = -1;
if (!src) return G_SOURCE_REMOVE;
if (!input) return G_SOURCE_REMOVE;
+ if (e_config->key_input_ttrace_enable)
+ {
+ TRACE_INPUT_BEGIN(input_dispatch);
+ ELOGF("INPUT", "input_dispatch|B|", NULL);
+ }
+
GIOCondition cond;
cond = g_source_query_unix_fd(source, src->tag);
return G_SOURCE_CONTINUE;
}
+ if (!input->libinput)
+ return G_SOURCE_REMOVE;
+
+ if (e_config->key_input_ttrace_enable)
+ {
+ TRACE_INPUT_BEGIN(libinput_dispatch);
+ ELOGF("INPUT", "libinput_dispatch|B|", NULL);
+ }
+
if (libinput_dispatch(input->libinput) != 0)
ERR("Failed to dispatch libinput events: %m");
+ if (e_config->key_input_ttrace_enable)
+ {
+ TRACE_INPUT_END();
+ ELOGF("INPUT", "libinput_dispatch|E|", NULL);
+ }
+
+ if (e_config->key_input_ttrace_enable)
+ {
+ TRACE_INPUT_BEGIN(_input_events_process);
+ ELOGF("INPUT", "_input_events_process|B|", NULL);
+ }
+
/* process pending events */
_input_events_process(input);
+ if (e_config->key_input_ttrace_enable)
+ {
+ TRACE_INPUT_END();
+ ELOGF("INPUT", "_input_events_process|E|", NULL);
+
+ TRACE_INPUT_END();
+ ELOGF("INPUT", "input_dispatch|E|", NULL);
+ }
+
e_input_event_process((GSource *)input->event_source);
return G_SOURCE_CONTINUE;
static void
input_thread_start(void *data, Ecore_Thread *th)
{
+ E_Input_Device *dev;
E_Input_Backend *input;
GMainContext *context = NULL;
InputEventSource *input_event_source = NULL;
- INF("input thread start");
-
if (!(input = data)) return;
eina_thread_name_set(eina_thread_self(), "input-thread");
+ e_input_libinput_context_create(input);
+
+ /* enable this input */
+ if (!e_input_enable_input(input))
+ {
+ ERR("Failed to enable input");
+ return;
+ }
+
+ /* append this input */
+ dev = input->dev;
+ dev->inputs = eina_list_append(dev->inputs, input);
+
//create a context
context = g_main_context_new();
g_main_context_push_thread_default(context);
//create main loop
input->input_thread_loop = g_main_loop_new(context, FALSE);
+ g_source_attach((GSource *)input->event_source, context);
+
//set the callback for this source
g_source_set_callback(&input_event_source->gsource, NULL, input, NULL);
g_source_attach(&input_event_source->gsource, context);
+ e_keyrouter_input_handler_add();
+
+ e_input_thread_id_set(gettid());
+ e_input_main_thread_id_set(getpid());
+
+ _e_input_hook_call(E_INPUT_HOOK_INPUT_THREAD_START, NULL);
+
+ INF("input thread start tid(%d) pid(%d)", e_input_thread_id_get(), e_input_main_thread_id_get());
+
g_main_loop_run(input->input_thread_loop);
}
input->input_thread = NULL;
}
+void
+_e_input_key_event_list_add(Ecore_Event_Key *key)
+{
+ Ecore_Event_Key *clone = NULL;
+
+ if (!key) return;
+
+ clone = E_NEW(Ecore_Event_Key, 1);
+ if (!clone) return;
+
+ if (key->keyname)
+ clone->keyname = (char *)eina_stringshare_add(key->keyname);
+
+ clone->keycode = key->keycode;
+ clone->timestamp = key->timestamp;
+
+ _key_event_list = g_list_append(_key_event_list, clone);
+}
+
EINTERN Eina_Bool
e_input_enable_input(E_Input_Backend *input)
{
ecore_main_fd_handler_add(input->fd, ECORE_FD_READ,
_cb_input_dispatch, input, NULL, NULL);
}
+ }
- if (input->suspended)
- {
- if (libinput_resume(input->libinput) != 0)
- goto err;
+ if (input->suspended)
+ {
+ if (libinput_resume(input->libinput) != 0)
+ goto err;
- input->suspended = EINA_FALSE;
+ input->suspended = EINA_FALSE;
- /* process pending events */
- _input_events_process(input);
- }
+ /* process pending events */
+ _input_events_process(input);
}
input->enabled = EINA_TRUE;
input->suspended = EINA_FALSE;
- if (e_input_thread_mode_get())
- {
- input->input_thread = ecore_thread_feedback_run(input_thread_start, input_thread_feedback, input_thread_end, input_thread_cancel, input, EINA_FALSE);
- }
-
return EINA_TRUE;
err:
input->event_source = e_input_event_source_create();
g_input_event_source = input->event_source;
-}
\ No newline at end of file
+}
+
+EINTERN void e_input_thread_run(E_Input_Backend *input)
+{
+ input->input_thread = ecore_thread_feedback_run(input_thread_start, input_thread_feedback, input_thread_end, input_thread_cancel, input, EINA_FALSE);
+}