devilhorns pushed a commit to branch master. http://git.enlightenment.org/core/efl.git/commit/?id=ba10e3547cffacaee92d10779703824dd2fc1460
commit ba10e3547cffacaee92d10779703824dd2fc1460 Author: Chris Michael <cp.mich...@samsung.com> Date: Sun Nov 22 16:13:36 2015 -0500 ecore-wl2: Start on implementing support for multi-seat Signed-off-by: Chris Michael <cp.mich...@samsung.com> --- src/Makefile_Ecore_Wl2.am | 1 + src/lib/ecore_wl2/Ecore_Wl2.h | 15 +++ src/lib/ecore_wl2/ecore_wl2_display.c | 2 +- src/lib/ecore_wl2/ecore_wl2_input.c | 29 +++-- src/lib/ecore_wl2/ecore_wl2_private.h | 100 ++++++++++++++- src/lib/ecore_wl2/ecore_wl2_seat.c | 233 ++++++++++++++++++++++++++++++++++ 6 files changed, 368 insertions(+), 12 deletions(-) diff --git a/src/Makefile_Ecore_Wl2.am b/src/Makefile_Ecore_Wl2.am index 0dc3dec..d08414b 100644 --- a/src/Makefile_Ecore_Wl2.am +++ b/src/Makefile_Ecore_Wl2.am @@ -12,6 +12,7 @@ lib/ecore_wl2/subsurface-client-protocol.h \ lib/ecore_wl2/subsurface-protocol.c \ lib/ecore_wl2/xdg-shell-client-protocol.h \ lib/ecore_wl2/xdg-shell-protocol.c \ +lib/ecore_wl2/ecore_wl2_seat.c \ lib/ecore_wl2/ecore_wl2_subsurf.c \ lib/ecore_wl2/ecore_wl2_dnd.c \ lib/ecore_wl2/ecore_wl2_window.c \ diff --git a/src/lib/ecore_wl2/Ecore_Wl2.h b/src/lib/ecore_wl2/Ecore_Wl2.h index 018365c..42875a6 100644 --- a/src/lib/ecore_wl2/Ecore_Wl2.h +++ b/src/lib/ecore_wl2/Ecore_Wl2.h @@ -37,6 +37,10 @@ typedef struct _Ecore_Wl2_Window Ecore_Wl2_Window; typedef struct _Ecore_Wl2_Display Ecore_Wl2_Display; typedef struct _Ecore_Wl2_Output Ecore_Wl2_Output; typedef struct _Ecore_Wl2_Input Ecore_Wl2_Input; +typedef struct _Ecore_Wl2_Seat Ecore_Wl2_Seat; +typedef struct _Ecore_Wl2_Pointer Ecore_Wl2_Pointer; +typedef struct _Ecore_Wl2_Keyboard Ecore_Wl2_Keyboard; +typedef struct _Ecore_Wl2_Touch Ecore_Wl2_Touch; typedef struct _Ecore_Wl2_Global { @@ -135,6 +139,9 @@ typedef enum _Ecore_Wl2_Window_Type ECORE_WL2_WINDOW_TYPE_LAST } Ecore_Wl2_Window_Type; +typedef void (*Ecore_Wl2_Bind_Cb)(struct wl_client *client, void *data, uint32_t version, uint32_t id); +typedef void (*Ecore_Wl2_Unbind_Cb)(struct wl_resource *resource); + EAPI extern int ECORE_WL2_EVENT_GLOBAL_ADDED; EAPI extern int ECORE_WL2_EVENT_GLOBAL_REMOVED; EAPI extern int ECORE_WL2_EVENT_FOCUS_IN; @@ -983,6 +990,14 @@ EAPI void ecore_wl2_subsurface_opaque_region_set(Ecore_Wl2_Subsurface *subsurfac */ EAPI int ecore_wl2_output_dpi_get(Ecore_Wl2_Output *output); +EAPI Ecore_Wl2_Seat *ecore_wl2_seat_create(Ecore_Wl2_Display *display, const char *name, const struct wl_seat_interface *implementation, int version, Ecore_Wl2_Bind_Cb bind_cb, Ecore_Wl2_Unbind_Cb unbind_cb); +EAPI void ecore_wl2_seat_destroy(Ecore_Wl2_Seat *seat); +EAPI void ecore_wl2_seat_capabilities_send(Ecore_Wl2_Seat *seat, enum wl_seat_capability caps); +EAPI void ecore_wl2_seat_pointer_release(Ecore_Wl2_Seat *seat); + +EAPI Ecore_Wl2_Pointer *ecore_wl2_pointer_get(Ecore_Wl2_Seat *seat); +EAPI Eina_Bool ecore_wl2_pointer_resource_create(Ecore_Wl2_Pointer *ptr, struct wl_client *client, const struct wl_pointer_interface *implementation, int version, uint32_t id); + /* # ifdef __cplusplus */ /* } */ /* # endif */ diff --git a/src/lib/ecore_wl2/ecore_wl2_display.c b/src/lib/ecore_wl2/ecore_wl2_display.c index 22b76b7..b0c387f 100644 --- a/src/lib/ecore_wl2/ecore_wl2_display.c +++ b/src/lib/ecore_wl2/ecore_wl2_display.c @@ -108,7 +108,7 @@ _cb_global_add(void *data, struct wl_registry *registry, unsigned int id, const else if (!strcmp(interface, "wl_output")) _ecore_wl2_output_add(ewd, id); else if (!strcmp(interface, "wl_seat")) - _ecore_wl2_input_add(ewd, id); + _ecore_wl2_input_add(ewd, id, version); event: /* allocate space for event structure */ diff --git a/src/lib/ecore_wl2/ecore_wl2_input.c b/src/lib/ecore_wl2/ecore_wl2_input.c index dccb184..7ccf1d1 100644 --- a/src/lib/ecore_wl2/ecore_wl2_input.c +++ b/src/lib/ecore_wl2/ecore_wl2_input.c @@ -1087,18 +1087,21 @@ _seat_cb_capabilities(void *data, struct wl_seat *seat, enum wl_seat_capability wl_pointer_set_user_data(input->wl.pointer, input); wl_pointer_add_listener(input->wl.pointer, &_pointer_listener, input); - if (!input->cursor.surface) - { - input->cursor.surface = - wl_compositor_create_surface(input->display->wl.compositor); - } + /* if (!input->cursor.surface) */ + /* { */ + /* input->cursor.surface = */ + /* wl_compositor_create_surface(input->display->wl.compositor); */ + /* } */ } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && (input->wl.pointer)) { if (input->cursor.surface) wl_surface_destroy(input->cursor.surface); input->cursor.surface = NULL; - wl_pointer_destroy(input->wl.pointer); + if (input->seat_version >= WL_POINTER_RELEASE_SINCE_VERSION) + wl_pointer_release(input->wl.pointer); + else + wl_pointer_destroy(input->wl.pointer); input->wl.pointer = NULL; } @@ -1110,7 +1113,10 @@ _seat_cb_capabilities(void *data, struct wl_seat *seat, enum wl_seat_capability } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && (input->wl.keyboard)) { - wl_keyboard_destroy(input->wl.keyboard); + if (input->seat_version >= WL_KEYBOARD_RELEASE_SINCE_VERSION) + wl_keyboard_release(input->wl.keyboard); + else + wl_keyboard_destroy(input->wl.keyboard); input->wl.keyboard = NULL; } @@ -1122,7 +1128,10 @@ _seat_cb_capabilities(void *data, struct wl_seat *seat, enum wl_seat_capability } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && (input->wl.touch)) { - wl_touch_destroy(input->wl.touch); + if (input->seat_version >= WL_TOUCH_RELEASE_SINCE_VERSION) + wl_touch_release(input->wl.touch); + else + wl_touch_destroy(input->wl.touch); input->wl.touch = NULL; } } @@ -1208,7 +1217,7 @@ _ecore_wl2_input_cursor_update(void *data) } void -_ecore_wl2_input_add(Ecore_Wl2_Display *display, unsigned int id) +_ecore_wl2_input_add(Ecore_Wl2_Display *display, unsigned int id, unsigned int version) { Ecore_Wl2_Input *input; @@ -1216,7 +1225,7 @@ _ecore_wl2_input_add(Ecore_Wl2_Display *display, unsigned int id) if (!input) return; input->display = display; - + input->seat_version = MIN(version, 4); input->repeat.rate = 0.025; input->repeat.delay = 0.4; input->repeat.enabled = EINA_TRUE; diff --git a/src/lib/ecore_wl2/ecore_wl2_private.h b/src/lib/ecore_wl2/ecore_wl2_private.h index 26a15ca..c428993 100644 --- a/src/lib/ecore_wl2/ecore_wl2_private.h +++ b/src/lib/ecore_wl2/ecore_wl2_private.h @@ -5,6 +5,10 @@ # include "Ecore_Wl2.h" # include "Ecore_Input.h" +# ifndef MIN +# define MIN(x, y) (((x) < (y)) ? (x) : (y)) +# endif + /* NB: Test if subsurface protocol is part of wayland code, if not then * include our own copy */ # ifndef WL_SUBSURFACE_ERROR_ENUM @@ -76,6 +80,7 @@ struct _Ecore_Wl2_Display Eina_Inlist *windows; Eina_Inlist *outputs; Eina_Inlist *inputs; + Eina_Inlist *seats; Eina_Bool sync_done : 1; }; @@ -157,6 +162,97 @@ typedef struct _Ecore_Wl2_Dnd_Source struct wl_array types; } Ecore_Wl2_Dnd_Source; + +/** TODO: Refactor ALL Input code :( + * + * wl_seat is a GROUP of Input Devices (such as): + * keyboards, pointers, touch devices + */ +struct _Ecore_Wl2_Pointer +{ + EINA_INLIST; + + Ecore_Wl2_Seat *seat; + + double sx, sy; + unsigned int button; + unsigned int enter_serial; + + struct + { + const char *name, *theme_name; + unsigned int index, size; + struct wl_cursor *wl_cursor; + struct wl_cursor_theme *theme; + struct wl_surface *surface; + struct wl_callback *frame_cb; + Ecore_Timer *timer; + } cursor; + + struct + { + unsigned int button, count, timestamp; + Ecore_Wl2_Window *window; + } grab; + + Ecore_Wl2_Window *focus; + + Eina_List *resources; +}; + +struct _Ecore_Wl2_Keyboard +{ + EINA_INLIST; + + struct + { + unsigned int button, count, timestamp; + Ecore_Wl2_Window *window; + } grab; +}; + +struct _Ecore_Wl2_Touch +{ + EINA_INLIST; + + struct + { + unsigned int button, count, timestamp; + Ecore_Wl2_Window *window; + } grab; +}; + +struct _Ecore_Wl2_Seat +{ + EINA_INLIST; + + uint32_t id; + uint32_t version; + const char *name; + struct wl_global *global; + const struct wl_seat_interface *implementation; + + struct + { + struct wl_global *global; + struct wl_resource *resource; + } im; + + Ecore_Wl2_Bind_Cb bind_cb; + Ecore_Wl2_Unbind_Cb unbind_cb; + + Ecore_Wl2_Pointer *pointer; + int pointer_count; + + Ecore_Wl2_Keyboard *keyboard; + int keyboard_count; + + Ecore_Wl2_Touch *touch; + int touch_count; + + Eina_List *resources; +}; + struct _Ecore_Wl2_Input { EINA_INLIST; @@ -246,6 +342,8 @@ struct _Ecore_Wl2_Input { Ecore_Wl2_Dnd_Source *source; } drag, selection; + + unsigned int seat_version; }; Ecore_Wl2_Window *_ecore_wl2_display_window_surface_find(Ecore_Wl2_Display *display, struct wl_surface *wl_surface); @@ -253,7 +351,7 @@ Ecore_Wl2_Window *_ecore_wl2_display_window_surface_find(Ecore_Wl2_Display *disp void _ecore_wl2_output_add(Ecore_Wl2_Display *display, unsigned int id); void _ecore_wl2_output_del(Ecore_Wl2_Output *output); -void _ecore_wl2_input_add(Ecore_Wl2_Display *display, unsigned int id); +void _ecore_wl2_input_add(Ecore_Wl2_Display *display, unsigned int id, unsigned int version); void _ecore_wl2_input_del(Ecore_Wl2_Input *input); void _ecore_wl2_input_ungrab(Ecore_Wl2_Input *input); diff --git a/src/lib/ecore_wl2/ecore_wl2_seat.c b/src/lib/ecore_wl2/ecore_wl2_seat.c new file mode 100644 index 0000000..5d7dcdf --- /dev/null +++ b/src/lib/ecore_wl2/ecore_wl2_seat.c @@ -0,0 +1,233 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "ecore_wl2_private.h" + +static void +_seat_cb_unbind(struct wl_resource *resource) +{ + Ecore_Wl2_Seat *seat; + + DBG("Seat Unbind"); + + seat = wl_resource_get_user_data(resource); + if (!seat) return; + + seat->resources = eina_list_remove(seat->resources, resource); + + if (seat->unbind_cb) seat->unbind_cb(resource); +} + +static void +_seat_cb_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id) +{ + Ecore_Wl2_Seat *seat; + struct wl_resource *res; + + seat = data; + seat->id = id; + + DBG("Seat Bind"); + + res = wl_resource_create(client, &wl_seat_interface, MIN(version, 4), id); + if (!res) + { + ERR("Failed to create seat resource: %m"); + return; + } + + seat->resources = eina_list_append(seat->resources, res); + + wl_resource_set_implementation(res, seat->implementation, seat, + _seat_cb_unbind); + + if (version >= WL_SEAT_NAME_SINCE_VERSION) + wl_seat_send_name(res, seat->name); + + if (seat->bind_cb) seat->bind_cb(client, seat, version, id); +} + +static void +_pointer_cb_unbind(struct wl_resource *resource) +{ + Ecore_Wl2_Pointer *ptr; + + DBG("Pointer Unbind"); + + ptr = wl_resource_get_user_data(resource); + if (!ptr) return; + + ptr->resources = eina_list_remove(ptr->resources, resource); + + /* wl_pointer_release(); */ +} + +static Ecore_Wl2_Pointer * +_ecore_wl2_seat_pointer_create(Ecore_Wl2_Seat *seat) +{ + Ecore_Wl2_Pointer *ptr; + + ptr = calloc(1, sizeof(Ecore_Wl2_Pointer)); + if (!ptr) return NULL; + + /* FIXME: Init pointer fields */ + + ptr->seat = seat; + + return ptr; +} + +static void +_ecore_wl2_seat_pointer_destroy(Ecore_Wl2_Pointer *ptr) +{ + /* FIXME: Free pointer fields */ + free(ptr); +} + +EAPI Ecore_Wl2_Seat * +ecore_wl2_seat_create(Ecore_Wl2_Display *display, const char *name, const struct wl_seat_interface *implementation, int version, Ecore_Wl2_Bind_Cb bind_cb, Ecore_Wl2_Unbind_Cb unbind_cb) +{ + Ecore_Wl2_Seat *seat; + + EINA_SAFETY_ON_NULL_RETURN_VAL(display, NULL); + + if (!name) name = "default"; + + EINA_INLIST_FOREACH(display->seats, seat) + { + if (!strcmp(seat->name, name)) + return seat; + } + + seat = calloc(1, sizeof(Ecore_Wl2_Seat)); + if (!seat) return NULL; + + seat->version = version; + seat->implementation = implementation; + seat->bind_cb = bind_cb; + seat->unbind_cb = unbind_cb; + + eina_stringshare_replace(&seat->name, name); + + seat->global = + wl_global_create(display->wl.display, &wl_seat_interface, seat->version, + seat, _seat_cb_bind); + if (!seat->global) + { + ERR("Could not create seat global: %m"); + free(seat); + return NULL; + } + + return seat; +} + +EAPI void +ecore_wl2_seat_destroy(Ecore_Wl2_Seat *seat) +{ + EINA_SAFETY_ON_NULL_RETURN(seat); + + eina_stringshare_del(seat->name); + + if (seat->pointer) _ecore_wl2_seat_pointer_destroy(seat->pointer); + + /* NB: Hmmm, should we iterate and free resources here ?? */ + + wl_global_destroy(seat->global); + + free(seat); +} + +EAPI void +ecore_wl2_seat_capabilities_send(Ecore_Wl2_Seat *seat, enum wl_seat_capability caps) +{ + Eina_List *l; + struct wl_resource *res; + + EINA_SAFETY_ON_NULL_RETURN(seat); + + EINA_LIST_FOREACH(seat->resources, l, res) + wl_seat_send_capabilities(res, caps); +} + +EAPI void +ecore_wl2_seat_pointer_release(Ecore_Wl2_Seat *seat) +{ + enum wl_seat_capability caps = 0; + + EINA_SAFETY_ON_NULL_RETURN(seat); + + seat->pointer_count--; + if (seat->pointer_count == 0) + { + if (seat->pointer_count > 0) + caps |= WL_SEAT_CAPABILITY_POINTER; + if (seat->keyboard_count > 0) + caps |= WL_SEAT_CAPABILITY_KEYBOARD; + if (seat->touch_count > 0) + caps |= WL_SEAT_CAPABILITY_TOUCH; + + ecore_wl2_seat_capabilities_send(seat, 0); + } +} + +EAPI Ecore_Wl2_Pointer * +ecore_wl2_pointer_get(Ecore_Wl2_Seat *seat) +{ + enum wl_seat_capability caps = 0; + + EINA_SAFETY_ON_NULL_RETURN_VAL(seat, NULL); + + if (seat->pointer_count > 0) + caps |= WL_SEAT_CAPABILITY_POINTER; + if (seat->keyboard_count > 0) + caps |= WL_SEAT_CAPABILITY_KEYBOARD; + if (seat->touch_count > 0) + caps |= WL_SEAT_CAPABILITY_TOUCH; + + if (seat->pointer) + { + seat->pointer_count += 1; + if (seat->pointer_count == 1) + { + caps |= WL_SEAT_CAPABILITY_POINTER; + ecore_wl2_seat_capabilities_send(seat, caps); + } + + return seat->pointer; + } + + seat->pointer = _ecore_wl2_seat_pointer_create(seat); + seat->pointer_count = 1; + + caps |= WL_SEAT_CAPABILITY_POINTER; + ecore_wl2_seat_capabilities_send(seat, caps); + + return seat->pointer; +} + +EAPI Eina_Bool +ecore_wl2_pointer_resource_create(Ecore_Wl2_Pointer *ptr, struct wl_client *client, const struct wl_pointer_interface *implementation, int version, uint32_t id) +{ + struct wl_resource *res; + + EINA_SAFETY_ON_NULL_RETURN_VAL(ptr, EINA_FALSE); + + res = wl_resource_create(client, &wl_pointer_interface, version, id); + if (!res) + { + ERR("Could not create pointer resource: %m"); + wl_client_post_no_memory(client); + return EINA_FALSE; + } + + wl_resource_set_implementation(res, implementation, ptr, _pointer_cb_unbind); + + ptr->resources = eina_list_append(ptr->resources, res); + + /* FIXME: Hmmm, should we sent a pointer_enter to ptr->focus'd surface + * here like weston does ? */ + + return EINA_TRUE; +} --