diff --git a/src/lib/ecore_wl2/Ecore_Wl2.h b/src/lib/ecore_wl2/Ecore_Wl2.h index be9f68f67f..402206cc70 100644 --- a/src/lib/ecore_wl2/Ecore_Wl2.h +++ b/src/lib/ecore_wl2/Ecore_Wl2.h @@ -153,6 +153,22 @@ typedef struct _Ecore_Wl2_Event_Seat_Capabilities Eina_Bool touch_enabled : 1; } 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, @@ -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 diff --git a/src/lib/ecore_wl2/ecore_wl2.c b/src/lib/ecore_wl2/ecore_wl2.c index 1855a96999..bbae13fc6b 100644 --- a/src/lib/ecore_wl2/ecore_wl2.c +++ b/src/lib/ecore_wl2/ecore_wl2.c @@ -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(); diff --git a/src/lib/ecore_wl2/ecore_wl2_input.c b/src/lib/ecore_wl2/ecore_wl2_input.c index 3ce69e4377..830c6adbeb 100644 --- a/src/lib/ecore_wl2/ecore_wl2_input.c +++ b/src/lib/ecore_wl2/ecore_wl2_input.c @@ -18,6 +18,14 @@ #include #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) { diff --git a/src/lib/ecore_wl2/ecore_wl2_private.h b/src/lib/ecore_wl2/ecore_wl2_private.h index 30f9d88473..dc1bcf739c 100644 --- a/src/lib/ecore_wl2/ecore_wl2_private.h +++ b/src/lib/ecore_wl2/ecore_wl2_private.h @@ -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); diff --git a/src/lib/ecore_wl2/ecore_wl2_window.c b/src/lib/ecore_wl2/ecore_wl2_window.c index 21225342f8..c2be35d04e 100644 --- a/src/lib/ecore_wl2/ecore_wl2_window.c +++ b/src/lib/ecore_wl2/ecore_wl2_window.c @@ -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); diff --git a/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_common.c b/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_common.c index 697909cb1e..48f03172d3 100644 --- a/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_common.c +++ b/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_common.c @@ -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; }