From adf559a8501aaf6db686693f6c63de4eba2dcb90 Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Fri, 9 May 2014 10:28:47 +0100 Subject: [PATCH] Add wayland compositor data & input files to build order Signed-off-by: Chris Michael --- src/bin/Makefile.mk | 4 + src/bin/e_comp_wl_data.c | 116 +++++++++ src/bin/e_comp_wl_data.h | 10 + src/bin/e_comp_wl_input.c | 480 ++++++++++++++++++++++++++++++++++++++ src/bin/e_comp_wl_input.h | 20 ++ 5 files changed, 630 insertions(+) create mode 100644 src/bin/e_comp_wl_data.c create mode 100644 src/bin/e_comp_wl_data.h create mode 100644 src/bin/e_comp_wl_input.c create mode 100644 src/bin/e_comp_wl_input.h diff --git a/src/bin/Makefile.mk b/src/bin/Makefile.mk index 1678001ba..1f9ec6788 100644 --- a/src/bin/Makefile.mk +++ b/src/bin/Makefile.mk @@ -205,6 +205,8 @@ src/bin/e_zone.h if HAVE_WAYLAND_CLIENTS ENLIGHTENMENTHEADERS += \ src/bin/e_uuid_store.h \ +src/bin/e_comp_wl_data.h \ +src/bin/e_comp_wl_input.h \ src/bin/e_comp_wl.h endif @@ -378,6 +380,8 @@ endif if HAVE_WAYLAND_CLIENTS enlightenment_src += \ src/bin/e_uuid_store.c \ +src/bin/e_comp_wl_data.c \ +src/bin/e_comp_wl_input.c \ src/bin/e_comp_wl.c endif diff --git a/src/bin/e_comp_wl_data.c b/src/bin/e_comp_wl_data.c new file mode 100644 index 000000000..e6a57a330 --- /dev/null +++ b/src/bin/e_comp_wl_data.c @@ -0,0 +1,116 @@ +#include "e.h" +#include "e_comp_wl.h" +#include "e_comp_wl_data.h" + +static void +_e_comp_wl_data_device_cb_drag_start(struct wl_client *client, struct wl_resource *resource, struct wl_resource *source_resource, struct wl_resource *origin_resource, struct wl_resource *icon_resource, uint32_t serial) +{ + +} + +static void +_e_comp_wl_data_device_cb_selection_set(struct wl_client *client, struct wl_resource *resource, struct wl_resource *source_resource, uint32_t serial) +{ + +} + +static const struct wl_data_device_interface _e_data_device_interface = +{ + _e_comp_wl_data_device_cb_drag_start, + _e_comp_wl_data_device_cb_selection_set, +}; + +static void +_e_comp_wl_data_manager_cb_source_create(struct wl_client *client, struct wl_resource *resource, uint32_t id) +{ + /* NB: New resource */ +} + +static void +_e_comp_wl_data_manager_cb_device_get(struct wl_client *client EINA_UNUSED, struct wl_resource *manager_resource, uint32_t id, struct wl_resource *seat_resource) +{ + E_Comp_Data *cdata; + struct wl_resource *res; + + DBG("Comp_Wl_Data: Get Data Device"); + + /* try to get the compositor data */ + if (!(cdata = wl_resource_get_user_data(seat_resource))) return; + + /* try to create the data device resource */ + res = wl_resource_create(client, &wl_data_device_interface, 1, id); + if (!res) + { + ERR("Could not create data device resource: %m"); + wl_resource_post_no_memory(manager_resource); + return; + } + + wl_resource_set_implementation(res, &_e_data_device_interface, cdata, NULL); +} + +static const struct wl_data_device_manager_interface _e_manager_interface = +{ + _e_comp_wl_data_manager_cb_source_create, + _e_comp_wl_data_manager_cb_device_get +}; + +/* static void */ +/* _e_comp_wl_data_cb_unbind_manager(struct wl_resource *resource) */ +/* { */ +/* E_Comp_Data *cdata; */ + +/* DBG("Comp_Wl_Data: Unbind Manager"); */ + +/* if (!(cdata = wl_resource_get_user_data(resource))) return; */ + +/* cdata->mgr.resource = NULL; */ +/* } */ + +static void +_e_comp_wl_data_cb_bind_manager(struct wl_client *client, void *data, uint32_t version EINA_UNUSED, uint32_t id) +{ + E_Comp_Data *cdata; + struct wl_resource *res; + + if (!(cdata = data)) return; + + DBG("Comp_Wl_Data: Bind Manager"); + + /* try to create data manager resource */ + res = wl_resource_create(client, &wl_data_device_manager_interface, 1, id); + if (!res) + { + ERR("Could not create data device manager: %m"); + wl_client_post_no_memory(client); + return; + } + + wl_resource_set_implementation(res, &_e_manager_interface, cdata, NULL); +} + +EINTERN Eina_Bool +e_comp_wl_data_manager_init(E_Comp_Data *cdata) +{ + /* check for valid compositor data */ + if (!cdata) return EINA_FALSE; + + /* try to create global data manager */ + cdata->mgr.global = + wl_global_create(cdata->wl.disp, &wl_data_device_manager_interface, 1, + cdata, _e_comp_wl_data_cb_bind_manager); + if (!cdata->mgr.global) + { + ERR("Could not create global for data device manager: %m"); + return EINA_FALSE; + } + + return EINA_TRUE; +} + +EINTERN void +e_comp_wl_data_manager_shutdown(E_Comp_Data *cdata) +{ + /* destroy the global manager resource */ + if (cdata->mgr.global) wl_global_destroy(cdata->mgr.global); +} diff --git a/src/bin/e_comp_wl_data.h b/src/bin/e_comp_wl_data.h new file mode 100644 index 000000000..61bacfb85 --- /dev/null +++ b/src/bin/e_comp_wl_data.h @@ -0,0 +1,10 @@ +#ifdef E_TYPEDEFS +#else +# ifndef E_COMP_WL_DATA_H +# define E_COMP_WL_DATA_H + +EINTERN Eina_Bool e_comp_wl_data_manager_init(E_Comp_Data *cdata); +EINTERN void e_comp_wl_data_manager_shutdown(E_Comp_Data *cdata); + +# endif +#endif diff --git a/src/bin/e_comp_wl_input.c b/src/bin/e_comp_wl_input.c new file mode 100644 index 000000000..4d6eb7b5b --- /dev/null +++ b/src/bin/e_comp_wl_input.c @@ -0,0 +1,480 @@ +#include "e.h" +#include "e_comp_wl.h" +#include "e_comp_wl_input.h" +#include + +static void +_e_comp_wl_input_update_seat_caps(E_Comp_Data *cdata) +{ + Eina_List *l; + struct wl_resource *res; + enum wl_seat_capability caps = 0; + + if (!cdata) return; + + if (cdata->ptr.enabled) + caps |= WL_SEAT_CAPABILITY_POINTER; + if (cdata->kbd.enabled) + caps |= WL_SEAT_CAPABILITY_KEYBOARD; + if (cdata->touch.enabled) + caps |= WL_SEAT_CAPABILITY_TOUCH; + + EINA_LIST_FOREACH(cdata->seat.resources, l, res) + wl_seat_send_capabilities(res, caps); +} + +static void +_e_comp_wl_input_cb_resource_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource) +{ + wl_resource_destroy(resource); +} + +static void +_e_comp_wl_input_pointer_cb_cursor_set(struct wl_client *client, struct wl_resource *resource, uint32_t serial, struct wl_resource *surface_resource, int32_t x, int32_t y) +{ + E_Comp_Data *cdata; + + /* get compositor data */ + if (!(cdata = wl_resource_get_user_data(resource))) return; +} + +static const struct wl_pointer_interface _e_pointer_interface = +{ + _e_comp_wl_input_pointer_cb_cursor_set, + _e_comp_wl_input_cb_resource_destroy +}; + +static const struct wl_keyboard_interface _e_keyboard_interface = +{ + _e_comp_wl_input_cb_resource_destroy +}; + +static void +_e_comp_wl_input_cb_pointer_unbind(struct wl_resource *resource) +{ + E_Comp_Data *cdata; + + /* get compositor data */ + if (!(cdata = wl_resource_get_user_data(resource))) return; + + cdata->ptr.resources = eina_list_remove(cdata->ptr.resources, resource); +} + +static void +_e_comp_wl_input_cb_pointer_get(struct wl_client *client, struct wl_resource *resource, uint32_t id) +{ + E_Comp_Data *cdata; + struct wl_resource *res; + + /* get compositor data */ + if (!(cdata = wl_resource_get_user_data(resource))) return; + + /* try to create pointer resource */ + res = wl_resource_create(client, &wl_pointer_interface, + wl_resource_get_version(resource), id); + if (!res) + { + ERR("Could not create pointer on seat %s: %m", cdata->seat.name); + wl_client_post_no_memory(client); + return; + } + + cdata->ptr.resources = eina_list_append(cdata->ptr.resources, res); + wl_resource_set_implementation(res, &_e_pointer_interface, cdata, + _e_comp_wl_input_cb_pointer_unbind); +} + +static void +_e_comp_wl_input_cb_keyboard_unbind(struct wl_resource *resource) +{ + E_Comp_Data *cdata; + + /* get compositor data */ + if (!(cdata = wl_resource_get_user_data(resource))) return; + + cdata->kbd.resources = eina_list_remove(cdata->kbd.resources, resource); +} + +static void +_e_comp_wl_input_cb_keyboard_get(struct wl_client *client, struct wl_resource *resource, uint32_t id) +{ + E_Comp_Data *cdata; + struct wl_resource *res; + /* uint32_t serial; */ + + /* get compositor data */ + if (!(cdata = wl_resource_get_user_data(resource))) return; + + /* try to create keyboard resource */ + res = wl_resource_create(client, &wl_keyboard_interface, + wl_resource_get_version(resource), id); + if (!res) + { + ERR("Could not create keyboard on seat %s: %m", cdata->seat.name); + wl_client_post_no_memory(client); + return; + } + + cdata->kbd.resources = eina_list_append(cdata->kbd.resources, res); + wl_resource_set_implementation(res, &_e_keyboard_interface, cdata, + _e_comp_wl_input_cb_keyboard_unbind); + + /* send current keymap */ + wl_keyboard_send_keymap(res, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, + cdata->xkb.fd, cdata->xkb.size); + + /* FIXME: Should only need todo this if This client is focused */ + /* send modifiers */ + /* serial = wl_display_get_serial(cdata->wl.disp); */ + /* wl_keyboard_send_modifiers(res, serial, cdata->kbd.mods_depressed, */ + /* cdata->kbd.mods_latched, cdata->kbd.mods_locked, */ + /* cdata->kbd.mod_group); */ +} + +static void +_e_comp_wl_input_cb_touch_get(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t id EINA_UNUSED) +{ + E_Comp_Data *cdata; + + /* DBG("Input Touch Get"); */ + + /* NB: Needs new resource !! */ + + /* get compositor data */ + if (!(cdata = wl_resource_get_user_data(resource))) return; +} + +static const struct wl_seat_interface _e_seat_interface = +{ + _e_comp_wl_input_cb_pointer_get, + _e_comp_wl_input_cb_keyboard_get, + _e_comp_wl_input_cb_touch_get, +}; + +static void +_e_comp_wl_input_cb_unbind_seat(struct wl_resource *resource) +{ + E_Comp_Data *cdata; + + if (!(cdata = wl_resource_get_user_data(resource))) return; + + cdata->seat.resources = eina_list_remove(cdata->seat.resources, resource); +} + +static void +_e_comp_wl_input_cb_bind_seat(struct wl_client *client, void *data, uint32_t version, uint32_t id) +{ + E_Comp_Data *cdata; + struct wl_resource *res; + + if (!(cdata = data)) return; + + /* try to create the seat resource */ + res = wl_resource_create(client, &wl_seat_interface, MIN(version, 3), id); + if (!res) + { + ERR("Could not create seat resource: %m"); + return; + } + + /* store version of seat interface for reuse in updating capabilities */ + cdata->seat.version = version; + cdata->seat.resources = eina_list_append(cdata->seat.resources, res); + + wl_resource_set_implementation(res, &_e_seat_interface, cdata, + _e_comp_wl_input_cb_unbind_seat); + + _e_comp_wl_input_update_seat_caps(cdata); + if (cdata->seat.version >= 2) wl_seat_send_name(res, cdata->seat.name); +} + +static int +_e_comp_wl_input_keymap_fd_get(off_t size) +{ + int fd = 0, blen = 0, len = 0; + const char *path; + char tmp[PATH_MAX]; + long flags; + + blen = sizeof(tmp) - 1; + + if (!(path = getenv("XDG_RUNTIME_DIR"))) + return -1; + + len = strlen(path); + if (len < blen) + { + strcpy(tmp, path); + strcat(tmp, "/e-wl-keymap-XXXXXX"); + } + else + return -1; + + if ((fd = mkstemp(tmp)) < 0) return -1; + + flags = fcntl(fd, F_GETFD); + fcntl(fd, F_SETFD, (flags | FD_CLOEXEC)); + + if (ftruncate(fd, size) < 0) + { + close(fd); + return -1; + } + + unlink(tmp); + return fd; +} + +static void +_e_comp_wl_input_keymap_update(E_Comp_Data *cdata, struct xkb_keymap *keymap) +{ + char *tmp; + xkb_mod_mask_t latched, locked; + struct wl_resource *res; + Eina_List *l; + uint32_t serial; + + if (!cdata) return; + + /* unreference any existing keymap */ + if (cdata->xkb.keymap) xkb_map_unref(cdata->xkb.keymap); + + /* unmap any existing keyboard area */ + if (cdata->xkb.area) munmap(cdata->xkb.area, cdata->xkb.size); + if (cdata->xkb.fd >= 0) close(cdata->xkb.fd); + + /* unreference any existing keyboard state */ + if (cdata->xkb.state) xkb_state_unref(cdata->xkb.state); + + /* create a new xkb state */ + cdata->xkb.state = xkb_state_new(keymap); + + latched = + xkb_state_serialize_mods(cdata->xkb.state, XKB_STATE_MODS_LATCHED); + locked = + xkb_state_serialize_mods(cdata->xkb.state, XKB_STATE_MODS_LOCKED); + + xkb_state_update_mask(cdata->xkb.state, 0, latched, locked, 0, 0, 0); + + /* increment keymap reference */ + cdata->xkb.keymap = xkb_map_ref(keymap); + + /* fetch updated modifiers */ + cdata->kbd.mod_shift = xkb_map_mod_get_index(keymap, XKB_MOD_NAME_SHIFT); + cdata->kbd.mod_caps = xkb_map_mod_get_index(keymap, XKB_MOD_NAME_CAPS); + cdata->kbd.mod_ctrl = xkb_map_mod_get_index(keymap, XKB_MOD_NAME_CTRL); + cdata->kbd.mod_alt = xkb_map_mod_get_index(keymap, XKB_MOD_NAME_ALT); + cdata->kbd.mod_super = xkb_map_mod_get_index(keymap, XKB_MOD_NAME_LOGO); + + if (!(tmp = xkb_map_get_as_string(keymap))) + { + ERR("Could not get keymap string"); + return; + } + + cdata->xkb.size = strlen(tmp) + 1; + cdata->xkb.fd = _e_comp_wl_input_keymap_fd_get(cdata->xkb.size); + if (cdata->xkb.fd < 0) + { + ERR("Could not create keymap file"); + return; + } + + cdata->xkb.area = + mmap(NULL, cdata->xkb.size, (PROT_READ | PROT_WRITE), + MAP_SHARED, cdata->xkb.fd, 0); + if (cdata->xkb.area == MAP_FAILED) + { + ERR("Failed to mmap keymap area: %m"); + return; + } + + strcpy(cdata->xkb.area, tmp); + free(tmp); + + /* send updated keymap */ + EINA_LIST_FOREACH(cdata->kbd.resources, l, res) + wl_keyboard_send_keymap(res, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, + cdata->xkb.fd, cdata->xkb.size); + + /* update modifiers */ + e_comp_wl_input_keyboard_modifiers_update(cdata); + + if ((!latched) && (!locked)) return; + + /* send modifiers */ + serial = wl_display_get_serial(cdata->wl.disp); + EINA_LIST_FOREACH(cdata->kbd.resources, l, res) + wl_keyboard_send_modifiers(res, serial, cdata->kbd.mod_depressed, + cdata->kbd.mod_latched, cdata->kbd.mod_locked, + cdata->kbd.mod_group); +} + +EINTERN Eina_Bool +e_comp_wl_input_init(E_Comp_Data *cdata) +{ + /* check for valid compositor data */ + if (!cdata) return EINA_FALSE; + + /* set default seat name */ + if (!cdata->seat.name) cdata->seat.name = "default"; + + /* create the global resource for input seat */ + cdata->seat.global = + wl_global_create(cdata->wl.disp, &wl_seat_interface, 3, + cdata, _e_comp_wl_input_cb_bind_seat); + if (!cdata->seat.global) + { + ERR("Could not create global for seat: %m"); + return EINA_FALSE; + } + + wl_array_init(&cdata->kbd.keys); + + return EINA_TRUE; +} + +EINTERN void +e_comp_wl_input_shutdown(E_Comp_Data *cdata) +{ + Eina_List *l; + struct wl_resource *res; + + /* check for valid compositor data */ + if (!cdata) return; + + /* destroy pointer resources */ + EINA_LIST_FOREACH(cdata->ptr.resources, l, res) + wl_resource_destroy(res); + + /* destroy keyboard resources */ + EINA_LIST_FOREACH(cdata->kbd.resources, l, res) + wl_resource_destroy(res); + + /* TODO: destroy touch resources */ + + /* TODO: destroy cdata->kbd.keys array */ + + /* destroy the global seat resource */ + if (cdata->seat.global) wl_global_destroy(cdata->seat.global); + cdata->seat.global = NULL; +} + +EINTERN Eina_Bool +e_comp_wl_input_pointer_check(struct wl_resource *res) +{ + return wl_resource_instance_of(res, &wl_pointer_interface, + &_e_pointer_interface); +} + +EINTERN Eina_Bool +e_comp_wl_input_keyboard_check(struct wl_resource *res) +{ + return wl_resource_instance_of(res, &wl_keyboard_interface, + &_e_keyboard_interface); +} + +EINTERN void +e_comp_wl_input_keyboard_modifiers_update(E_Comp_Data *cdata) +{ + xkb_mod_mask_t depressed, latched, locked; + xkb_layout_index_t group; + + depressed = + xkb_state_serialize_mods(cdata->xkb.state, XKB_STATE_DEPRESSED); + latched = + xkb_state_serialize_mods(cdata->xkb.state, XKB_STATE_MODS_LATCHED); + locked = + xkb_state_serialize_mods(cdata->xkb.state, XKB_STATE_MODS_LOCKED); + group = + xkb_state_serialize_group(cdata->xkb.state, XKB_STATE_EFFECTIVE); + + if ((cdata->kbd.mod_depressed != depressed) || + (cdata->kbd.mod_latched != latched) || + (cdata->kbd.mod_locked != locked) || + (cdata->kbd.mod_group != group)) + { + uint32_t serial; + struct wl_resource *res; + Eina_List *l; + + cdata->kbd.mod_depressed = depressed; + cdata->kbd.mod_latched = latched; + cdata->kbd.mod_locked = locked; + cdata->kbd.mod_group = group; + + serial = wl_display_get_serial(cdata->wl.disp); + EINA_LIST_FOREACH(cdata->kbd.resources, l, res) + wl_keyboard_send_modifiers(res, serial, + depressed, latched, locked, group); + } +} + +EINTERN void +e_comp_wl_input_keyboard_state_update(E_Comp_Data *cdata, uint32_t keycode, Eina_Bool pressed) +{ + enum xkb_key_direction dir; + + if (!cdata->xkb.state) return; + + if (pressed) dir = XKB_KEY_DOWN; + else dir = XKB_KEY_UP; + + xkb_state_update_key(cdata->xkb.state, keycode + 8, dir); + + e_comp_wl_input_keyboard_modifiers_update(cdata); +} + +EAPI void +e_comp_wl_input_pointer_enabled_set(E_Comp_Data *cdata, Eina_Bool enabled) +{ + /* check for valid compositor data */ + if (!cdata) return; + + cdata->ptr.enabled = enabled; + _e_comp_wl_input_update_seat_caps(cdata); +} + +EAPI void +e_comp_wl_input_keyboard_enabled_set(E_Comp_Data *cdata, Eina_Bool enabled) +{ + /* check for valid compositor data */ + if (!cdata) return; + + cdata->kbd.enabled = enabled; + _e_comp_wl_input_update_seat_caps(cdata); +} + +EAPI void +e_comp_wl_input_keymap_set(E_Comp_Data *cdata, const char *rules, const char *model, const char *layout) +{ + struct xkb_keymap *keymap; + struct xkb_rule_names names; + + if (!cdata) return; + + /* DBG("COMP_WL: Keymap Set: %s %s %s", rules, model, layout); */ + + /* assemble xkb_rule_names so we can fetch keymap */ + memset(&names, 0, sizeof(names)); + if (rules) names.rules = strdup(rules); + if (model) names.model = strdup(model); + if (layout) names.layout = strdup(layout); + + /* unreference any existing context */ + if (cdata->xkb.context) xkb_context_unref(cdata->xkb.context); + + /* create a new xkb context */ + cdata->xkb.context = xkb_context_new(0); + + /* fetch new keymap based on names */ + keymap = xkb_map_new_from_names(cdata->xkb.context, &names, 0); + + /* update compositor keymap */ + _e_comp_wl_input_keymap_update(cdata, keymap); + + /* cleanup */ + free((char *)names.rules); + free((char *)names.model); + free((char *)names.layout); +} diff --git a/src/bin/e_comp_wl_input.h b/src/bin/e_comp_wl_input.h new file mode 100644 index 000000000..9c0000c9a --- /dev/null +++ b/src/bin/e_comp_wl_input.h @@ -0,0 +1,20 @@ +#ifdef E_TYPEDEFS +#else +# ifndef E_COMP_WL_INPUT_H +# define E_COMP_WL_INPUT_H + +EINTERN Eina_Bool e_comp_wl_input_init(E_Comp_Data *cdata); +EINTERN void e_comp_wl_input_shutdown(E_Comp_Data *cdata); +EINTERN Eina_Bool e_comp_wl_input_pointer_check(struct wl_resource *res); +EINTERN Eina_Bool e_comp_wl_input_keyboard_check(struct wl_resource *res); + +EINTERN void e_comp_wl_input_keyboard_modifiers_update(E_Comp_Data *cdata); +EINTERN void e_comp_wl_input_keyboard_state_update(E_Comp_Data *cdata, uint32_t keycode, Eina_Bool pressed); + +EAPI void e_comp_wl_input_pointer_enabled_set(E_Comp_Data *cdata, Eina_Bool enabled); +EAPI void e_comp_wl_input_keyboard_enabled_set(E_Comp_Data *cdata, Eina_Bool enabled); + +EAPI void e_comp_wl_input_keymap_set(E_Comp_Data *cdata, const char *rules, const char *model, const char *layout); + +# endif +#endif