ecore_wl2: associate evas devices to input ecore events
authorBruno Dilly <bdilly@profusion.mobi>
Thu, 6 Oct 2016 20:43:12 +0000 (17:43 -0300)
committerBruno Dilly <bdilly@profusion.mobi>
Tue, 1 Nov 2016 18:06:19 +0000 (16:06 -0200)
So users would be able to differentiate between source
seats.

src/lib/ecore_wl2/Ecore_Wl2.h
src/lib/ecore_wl2/ecore_wl2.c
src/lib/ecore_wl2/ecore_wl2_input.c
src/lib/ecore_wl2/ecore_wl2_private.h
src/lib/ecore_wl2/ecore_wl2_window.c
src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_common.c

index be9f68f..402206c 100644 (file)
@@ -155,6 +155,22 @@ typedef struct _Ecore_Wl2_Event_Seat_Capabilities
 
 typedef enum
 {
+   ECORE_WL2_DEVICE_TYPE_SEAT,
+   ECORE_WL2_DEVICE_TYPE_POINTER,
+   ECORE_WL2_DEVICE_TYPE_KEYBOARD,
+   ECORE_WL2_DEVICE_TYPE_TOUCH
+} Ecore_Wl2_Device_Type;
+
+typedef struct _Ecore_Wl2_Event_Device
+{
+   Eo *dev;
+   int window_id;
+   unsigned int seat_id;
+   Ecore_Wl2_Device_Type type;
+} Ecore_Wl2_Event_Device;
+
+typedef enum
+{
    ECORE_WL2_SELECTION_CNP,
    ECORE_WL2_SELECTION_DND
 } Ecore_Wl2_Selection_Type;
@@ -219,6 +235,8 @@ EAPI extern int ECORE_WL2_EVENT_SYNC_DONE; /** @since 1.17 */
 EAPI extern int ECORE_WL2_EVENT_OFFER_DATA_READY; /** @since 1.19 */
 EAPI extern int ECORE_WL2_EVENT_SEAT_NAME_CHANGED; /** @since 1.19 */
 EAPI extern int ECORE_WL2_EVENT_SEAT_CAPABILITIES_CHANGED; /** @since 1.19 */
+EAPI extern int ECORE_WL2_EVENT_DEVICE_ADDED; /** @since 1.19 */
+EAPI extern int ECORE_WL2_EVENT_DEVICE_REMOVED; /** @since 1.19 */
 /**
  * @file
  * @brief Ecore functions for dealing with the Wayland display protocol
index 1855a96..bbae13f 100644 (file)
@@ -33,6 +33,8 @@ EAPI int ECORE_WL2_EVENT_SYNC_DONE = 0;
 EAPI int ECORE_WL2_EVENT_OFFER_DATA_READY = 0;
 EAPI int ECORE_WL2_EVENT_SEAT_NAME_CHANGED = 0;
 EAPI int ECORE_WL2_EVENT_SEAT_CAPABILITIES_CHANGED = 0;
+EAPI int ECORE_WL2_EVENT_DEVICE_ADDED = 0;
+EAPI int ECORE_WL2_EVENT_DEVICE_REMOVED = 0;
 
 EAPI int _ecore_wl2_event_window_www = -1;
 EAPI int _ecore_wl2_event_window_www_drag = -1;
@@ -93,6 +95,8 @@ ecore_wl2_init(void)
         ECORE_WL2_EVENT_OFFER_DATA_READY = ecore_event_type_new();
         ECORE_WL2_EVENT_SEAT_NAME_CHANGED = ecore_event_type_new();
         ECORE_WL2_EVENT_SEAT_CAPABILITIES_CHANGED = ecore_event_type_new();
+        ECORE_WL2_EVENT_DEVICE_ADDED = ecore_event_type_new();
+        ECORE_WL2_EVENT_DEVICE_REMOVED = ecore_event_type_new();
         _ecore_wl2_event_window_www = ecore_event_type_new();
         _ecore_wl2_event_window_www_drag = ecore_event_type_new();
      }
@@ -146,6 +150,8 @@ ecore_wl2_shutdown(void)
    ECORE_WL2_EVENT_OFFER_DATA_READY = 0;
    ECORE_WL2_EVENT_SEAT_NAME_CHANGED = 0;
    ECORE_WL2_EVENT_SEAT_CAPABILITIES_CHANGED = 0;
+   ECORE_WL2_EVENT_DEVICE_ADDED = 0;
+   ECORE_WL2_EVENT_DEVICE_REMOVED = 0;
 
    /* shutdown Ecore_Event */
    ecore_event_shutdown();
index 3ce69e4..830c6ad 100644 (file)
 #include <sys/mman.h>
 #include "ecore_wl2_private.h"
 
+typedef struct _Ecore_Wl2_Input_Devices
+{
+   Eo *pointer_dev;
+   Eo *keyboard_dev;
+   Eo *touch_dev;
+   int window_id;
+} Ecore_Wl2_Input_Devices;
+
 typedef struct _Ecore_Wl2_Mouse_Down_Info
 {
    EINA_INLIST;
@@ -57,6 +65,33 @@ _ecore_wl2_input_mouse_down_info_get(int device)
    return info;
 }
 
+static Ecore_Wl2_Input_Devices *
+_ecore_wl2_devices_get(Ecore_Wl2_Input *input, int window_id)
+{
+   Ecore_Wl2_Input_Devices *devices;
+   Eina_List *l;
+
+   EINA_LIST_FOREACH(input->devices_list, l, devices)
+     {
+        if (devices->window_id == window_id)
+          return devices;
+     }
+
+   return NULL;
+}
+
+static Eo *
+_ecore_wl2_mouse_dev_get(Ecore_Wl2_Input *input, int window_id)
+{
+   Ecore_Wl2_Input_Devices *devices;
+
+   devices = _ecore_wl2_devices_get(input, window_id);
+   if (devices)
+     return devices->pointer_dev;
+
+   return NULL;
+}
+
 static void
 _ecore_wl2_input_mouse_in_send(Ecore_Wl2_Input *input, Ecore_Wl2_Window *window)
 {
@@ -71,6 +106,7 @@ _ecore_wl2_input_mouse_in_send(Ecore_Wl2_Input *input, Ecore_Wl2_Window *window)
    ev->event_window = window->id;
    ev->timestamp = input->timestamp;
    ev->modifiers = input->keyboard.modifiers;
+   ev->dev = _ecore_wl2_mouse_dev_get(input, window->id);
 
    ecore_event_add(ECORE_EVENT_MOUSE_IN, ev, NULL, NULL);
 }
@@ -89,6 +125,7 @@ _ecore_wl2_input_mouse_out_send(Ecore_Wl2_Input *input, Ecore_Wl2_Window *window
    ev->event_window = window->id;
    ev->timestamp = input->timestamp;
    ev->modifiers = input->keyboard.modifiers;
+   ev->dev = _ecore_wl2_mouse_dev_get(input, window->id);
 
    ecore_event_add(ECORE_EVENT_MOUSE_OUT, ev, NULL, NULL);
 }
@@ -120,6 +157,7 @@ _ecore_wl2_input_mouse_move_send(Ecore_Wl2_Input *input, Ecore_Wl2_Window *windo
    ev->multi.y = input->pointer.sy;
    ev->multi.root.x = input->pointer.sx;
    ev->multi.root.y = input->pointer.sy;
+   ev->dev = _ecore_wl2_mouse_dev_get(input, window->id);
 
    info = _ecore_wl2_input_mouse_down_info_get(device);
    if (info)
@@ -165,6 +203,7 @@ _ecore_wl2_input_mouse_wheel_send(Ecore_Wl2_Input *input, unsigned int axis, int
         ev->window = input->focus.pointer->id;
         ev->event_window = input->focus.pointer->id;
      }
+   ev->dev = _ecore_wl2_mouse_dev_get(input, ev->window);
 
    ecore_event_add(ECORE_EVENT_MOUSE_WHEEL, ev, NULL, NULL);
 }
@@ -254,6 +293,7 @@ _ecore_wl2_input_mouse_down_send(Ecore_Wl2_Input *input, Ecore_Wl2_Window *windo
      {
         ev->window = window->id;
         ev->event_window = window->id;
+        ev->dev = _ecore_wl2_mouse_dev_get(input, window->id);
      }
 
    ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, ev, NULL, NULL);
@@ -324,6 +364,7 @@ _ecore_wl2_input_mouse_up_send(Ecore_Wl2_Input *input, Ecore_Wl2_Window *window,
 
    ev->window = window->id;
    ev->event_window = window->id;
+   ev->dev = _ecore_wl2_mouse_dev_get(input, window->id);
 
    ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_UP, ev, NULL, NULL);
 }
@@ -432,6 +473,18 @@ _ecore_wl2_input_symbol_rep_find(xkb_keysym_t keysym, char *buffer, int size, un
     snprintf(buffer, size, "Keycode-%u", code);
 }
 
+static Eo *
+_ecore_wl2_keyboard_dev_get(Ecore_Wl2_Input *input, int window_id)
+{
+   Ecore_Wl2_Input_Devices *devices;
+
+   devices = _ecore_wl2_devices_get(input, window_id);
+   if (devices)
+     return devices->keyboard_dev;
+
+   return NULL;
+}
+
 static void
 _ecore_wl2_input_key_send(Ecore_Wl2_Input *input, Ecore_Wl2_Window *window, xkb_keysym_t sym, xkb_keysym_t sym_name, unsigned int code, unsigned int state, unsigned int timestamp)
 {
@@ -466,6 +519,7 @@ _ecore_wl2_input_key_send(Ecore_Wl2_Input *input, Ecore_Wl2_Window *window, xkb_
    ev->timestamp = timestamp;
    ev->modifiers = input->keyboard.modifiers;
    ev->keycode = code;
+   ev->dev = _ecore_wl2_keyboard_dev_get(input, window->id);
 
    /* DBG("Emitting Key event (%s,%s,%s,%s)\n", ev->keyname, ev->key, ev->compose, ev->string); */
 
@@ -1264,6 +1318,90 @@ _ecore_wl2_input_cursor_update(void *data)
    return ECORE_CALLBACK_RENEW;
 }
 
+static void
+_ecore_wl2_devices_free(Ecore_Wl2_Input_Devices *devices)
+{
+   if (devices->pointer_dev)
+     efl_unref(devices->pointer_dev);
+   if (devices->keyboard_dev)
+     efl_unref(devices->keyboard_dev);
+   if (devices->touch_dev)
+     efl_unref(devices->touch_dev);
+
+   free(devices);
+}
+
+static Eina_Bool
+_ecore_evas_wl_common_cb_device_event(void *data, int type, void *event)
+{
+   Ecore_Wl2_Input_Devices *devs, *devices = NULL;;
+   Ecore_Wl2_Event_Device *ev = event;
+   Ecore_Wl2_Input *input = data;
+   Eina_List *l;
+
+   if (input->id != ev->seat_id)
+     return ECORE_CALLBACK_PASS_ON;
+
+   EINA_LIST_FOREACH(input->devices_list, l, devs)
+     {
+        if (devs->window_id == ev->window_id)
+          {
+             devices = devs;
+             break;
+          }
+     }
+
+   if (type == ECORE_WL2_EVENT_DEVICE_ADDED)
+     {
+        if (!devices)
+          {
+             devices = calloc(1, sizeof(Ecore_Wl2_Input_Devices));
+             EINA_SAFETY_ON_NULL_RETURN_VAL(devices, ECORE_CALLBACK_PASS_ON);
+             input->devices_list = eina_list_append(input->devices_list,
+                                                    devices);
+             devices->window_id = ev->window_id;
+          }
+
+        if (ev->type == ECORE_WL2_DEVICE_TYPE_POINTER)
+          devices->pointer_dev = efl_ref(ev->dev);
+        else if (ev->type == ECORE_WL2_DEVICE_TYPE_KEYBOARD)
+          devices->keyboard_dev = efl_ref(ev->dev);
+        else if (ev->type == ECORE_WL2_DEVICE_TYPE_TOUCH)
+          devices->touch_dev = efl_ref(ev->dev);
+
+        return ECORE_CALLBACK_PASS_ON;
+     }
+
+   if (!devices)
+     return ECORE_CALLBACK_PASS_ON;
+
+   if (ev->type == ECORE_WL2_DEVICE_TYPE_SEAT)
+     {
+        input->devices_list = eina_list_remove(input->devices_list,
+                                               devices);
+        _ecore_wl2_devices_free(devices);
+        return ECORE_CALLBACK_PASS_ON;
+     }
+
+   if (ev->type == ECORE_WL2_DEVICE_TYPE_POINTER && devices->pointer_dev)
+     {
+        efl_unref(devices->pointer_dev);
+        devices->pointer_dev = NULL;
+     }
+   else if (ev->type == ECORE_WL2_DEVICE_TYPE_KEYBOARD && devices->keyboard_dev)
+     {
+        efl_unref(devices->keyboard_dev);
+        devices->keyboard_dev = NULL;
+     }
+   else if (ev->type == ECORE_WL2_DEVICE_TYPE_TOUCH && devices->touch_dev)
+     {
+        efl_unref(devices->touch_dev);
+        devices->touch_dev = NULL;
+     }
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
 void
 _ecore_wl2_input_add(Ecore_Wl2_Display *display, unsigned int id, unsigned int version)
 {
@@ -1299,11 +1437,19 @@ _ecore_wl2_input_add(Ecore_Wl2_Display *display, unsigned int id, unsigned int v
      wl_data_device_manager_get_data_device(display->wl.data_device_manager,
                                             input->wl.seat);
    wl_data_device_add_listener(input->data.device, &_data_listener, input);
+
+   input->dev_add_handler = ecore_event_handler_add(
+      ECORE_WL2_EVENT_DEVICE_ADDED, _ecore_evas_wl_common_cb_device_event,
+      input);
+   input->dev_remove_handler = ecore_event_handler_add(
+      ECORE_WL2_EVENT_DEVICE_REMOVED, _ecore_evas_wl_common_cb_device_event,
+      input);
 }
 
 void
 _ecore_wl2_input_del(Ecore_Wl2_Input *input)
 {
+   Ecore_Wl2_Input_Devices *devices;
    Ecore_Wl2_Display *display;
    Eina_Inlist *l = NULL;
    Ecore_Wl2_Mouse_Down_Info *info = NULL;
@@ -1348,6 +1494,11 @@ _ecore_wl2_input_del(Ecore_Wl2_Input *input)
 
    if (input->wl.seat) wl_seat_destroy(input->wl.seat);
 
+   ecore_event_handler_del(input->dev_add_handler);
+   ecore_event_handler_del(input->dev_remove_handler);
+   EINA_LIST_FREE(input->devices_list, devices)
+      _ecore_wl2_devices_free(devices);
+
    display->inputs =
      eina_inlist_remove(display->inputs, EINA_INLIST_GET(input));
 
@@ -1373,6 +1524,31 @@ _ecore_wl2_input_cursor_update_stop(Ecore_Wl2_Input *input)
      }
 }
 
+void
+_ecore_wl2_input_window_remove(Ecore_Wl2_Input *input, Ecore_Wl2_Window *window)
+{
+   Ecore_Wl2_Input_Devices *devices;
+   Eina_List *l, *l_next;
+
+   if ((input->focus.pointer) &&
+       (input->focus.pointer == window))
+     input->focus.pointer = NULL;
+   if ((input->focus.keyboard) &&
+       (input->focus.keyboard == window))
+     {
+        input->focus.keyboard = NULL;
+        ecore_timer_del(input->repeat.timer);
+        input->repeat.timer = NULL;
+     }
+
+   EINA_LIST_FOREACH_SAFE(input->devices_list, l, l_next, devices)
+      if (devices->window_id == window->id)
+        {
+           _ecore_wl2_devices_free(devices);
+           input->devices_list = eina_list_remove_list(input->devices_list, l);
+        }
+}
+
 EAPI void
 ecore_wl2_input_grab(Ecore_Wl2_Input *input, Ecore_Wl2_Window *window, unsigned int button)
 {
index 30f9d88..dc1bcf7 100644 (file)
@@ -406,6 +406,10 @@ struct _Ecore_Wl2_Input
 
    unsigned int seat_version;
    unsigned int id;
+
+   Ecore_Event_Handler *dev_add_handler;
+   Ecore_Event_Handler *dev_remove_handler;
+   Eina_List *devices_list;
 };
 
 typedef struct Ecore_Wl2_Event_Window_WWW
@@ -436,6 +440,7 @@ void _ecore_wl2_input_grab(Ecore_Wl2_Input *input, Ecore_Wl2_Window *window, uns
 void _ecore_wl2_input_cursor_set(Ecore_Wl2_Input *input, const char *cursor);
 Eina_Bool _ecore_wl2_input_cursor_update(void *data);
 void _ecore_wl2_input_cursor_update_stop(Ecore_Wl2_Input *input);
+void _ecore_wl2_input_window_remove(Ecore_Wl2_Input *input, Ecore_Wl2_Window *window);
 
 void _ecore_wl2_dnd_add(Ecore_Wl2_Input *input, struct wl_data_offer *offer);
 void _ecore_wl2_dnd_enter(Ecore_Wl2_Input *input, struct wl_data_offer *offer, struct wl_surface *surface, int x, int y, uint32_t serial);
index 2122534..c2be35d 100644 (file)
@@ -488,18 +488,7 @@ ecore_wl2_window_free(Ecore_Wl2_Window *window)
    display = window->display;
 
    EINA_INLIST_FOREACH(display->inputs, input)
-     {
-        if ((input->focus.pointer) &&
-            (input->focus.pointer == window))
-          input->focus.pointer = NULL;
-        if ((input->focus.keyboard) &&
-            (input->focus.keyboard == window))
-          {
-             input->focus.keyboard = NULL;
-             ecore_timer_del(input->repeat.timer);
-             input->repeat.timer = NULL;
-          }
-     }
+      _ecore_wl2_input_window_remove(input, window);
 
    EINA_INLIST_FOREACH_SAFE(window->subsurfs, tmp, subsurf)
      _ecore_wl2_subsurf_free(subsurf);
index 697909c..48f0317 100644 (file)
@@ -449,6 +449,30 @@ _ecore_evas_wl_common_cb_www(void *d EINA_UNUSED, int t EINA_UNUSED, void *event
    return ECORE_CALLBACK_RENEW;
 }
 
+static void
+_ecore_evas_wl_common_cb_device_event_free(void *user_data, void *func_data)
+{
+   efl_unref(user_data);
+   free(func_data);
+}
+
+static void
+_ecore_evas_wl_common_device_event_add(int event_type, Ecore_Wl2_Device_Type device_type, unsigned int id, Evas_Device *dev, Ecore_Evas *ee)
+{
+   Ecore_Wl2_Event_Device *ev;
+
+   ev = calloc(1, sizeof(Ecore_Wl2_Event_Device));
+   EINA_SAFETY_ON_NULL_RETURN(ev);
+
+   ev->dev = efl_ref(dev);
+   ev->type = device_type;
+   ev->seat_id = id;
+   ev->window_id = ee->prop.window;
+
+   ecore_event_add(event_type, ev, _ecore_evas_wl_common_cb_device_event_free,
+                   dev);
+}
+
 static Eina_Bool
 _ecore_evas_wl_common_cb_global_added(void *d EINA_UNUSED, int t EINA_UNUSED, void *event)
 {
@@ -482,6 +506,10 @@ _ecore_evas_wl_common_cb_global_added(void *d EINA_UNUSED, int t EINA_UNUSED, vo
 
         wdata = ee->engine.data;
         wdata->devices_list = eina_list_append(wdata->devices_list, device);
+
+        _ecore_evas_wl_common_device_event_add(ECORE_WL2_EVENT_DEVICE_ADDED,
+                                               ECORE_WL2_DEVICE_TYPE_SEAT,
+                                               ev->id, dev, ee);
      }
 
    return ECORE_CALLBACK_PASS_ON;
@@ -535,6 +563,9 @@ _ecore_evas_wl_common_cb_global_removed(void *d EINA_UNUSED, int t EINA_UNUSED,
 
         if (found)
           {
+             _ecore_evas_wl_common_device_event_add(
+                ECORE_WL2_EVENT_DEVICE_REMOVED, ECORE_WL2_DEVICE_TYPE_SEAT,
+                ev->id, device->seat, ee);
              wdata->devices_list = eina_list_remove(wdata->devices_list,
                                                     device);
              _ecore_evas_wl_common_device_free(device);
@@ -597,9 +628,17 @@ _ecore_evas_wl_common_cb_seat_capabilities_changed(void *d EINA_UNUSED, int t EI
                           device->seat, NULL,
                           EVAS_DEVICE_CLASS_MOUSE,
                           EVAS_DEVICE_SUBCLASS_NONE);
+                       _ecore_evas_wl_common_device_event_add(
+                          ECORE_WL2_EVENT_DEVICE_ADDED,
+                          ECORE_WL2_DEVICE_TYPE_POINTER,
+                          ev->id, device->pointer, ee);
                     }
                   else if (!ev->pointer_enabled && device->pointer)
                     {
+                       _ecore_evas_wl_common_device_event_add(
+                          ECORE_WL2_EVENT_DEVICE_REMOVED,
+                          ECORE_WL2_DEVICE_TYPE_POINTER,
+                          ev->id, NULL, ee);
                        evas_device_del(device->pointer);
                        device->pointer = NULL;
                     }
@@ -612,9 +651,17 @@ _ecore_evas_wl_common_cb_seat_capabilities_changed(void *d EINA_UNUSED, int t EI
                           device->seat, NULL,
                           EVAS_DEVICE_CLASS_KEYBOARD,
                           EVAS_DEVICE_SUBCLASS_NONE);
+                       _ecore_evas_wl_common_device_event_add(
+                          ECORE_WL2_EVENT_DEVICE_ADDED,
+                          ECORE_WL2_DEVICE_TYPE_KEYBOARD,
+                          ev->id, device->keyboard, ee);
                     }
                   else if (!ev->keyboard_enabled && device->keyboard)
                     {
+                       _ecore_evas_wl_common_device_event_add(
+                          ECORE_WL2_EVENT_DEVICE_REMOVED,
+                          ECORE_WL2_DEVICE_TYPE_KEYBOARD,
+                          ev->id, NULL, ee);
                        evas_device_del(device->keyboard);
                        device->keyboard = NULL;
                     }
@@ -627,9 +674,17 @@ _ecore_evas_wl_common_cb_seat_capabilities_changed(void *d EINA_UNUSED, int t EI
                           device->seat, NULL,
                           EVAS_DEVICE_CLASS_TOUCH,
                           EVAS_DEVICE_SUBCLASS_NONE);
+                       _ecore_evas_wl_common_device_event_add(
+                          ECORE_WL2_EVENT_DEVICE_ADDED,
+                          ECORE_WL2_DEVICE_TYPE_TOUCH,
+                          ev->id, device->touch, ee);
                     }
                   else if (!ev->touch_enabled && device->touch)
                     {
+                       _ecore_evas_wl_common_device_event_add(
+                          ECORE_WL2_EVENT_DEVICE_REMOVED,
+                          ECORE_WL2_DEVICE_TYPE_TOUCH,
+                          ev->id, NULL, ee);
                        evas_device_del(device->touch);
                        device->touch = NULL;
                     }