diff options
author | Mike Blumenkrantz <zmike@osg.samsung.com> | 2018-01-25 14:00:50 -0500 |
---|---|---|
committer | Mike Blumenkrantz <zmike@osg.samsung.com> | 2018-01-25 14:00:50 -0500 |
commit | 564e693c032afcfa9a5f7c624dc97d9fec24bb43 (patch) | |
tree | 1366314c7c89022a1f6144554c779b61583c0bab | |
parent | bd41e4626fdcab15e5f0bb9ecd13b9249537fa67 (diff) | |
download | efl-devs/discomfitor/6640.tar.gz |
-rw-r--r-- | src/lib/efl_wl/efl_wl.c | 170 | ||||
-rw-r--r-- | src/lib/efl_wl/x11.x | 28 |
2 files changed, 114 insertions, 84 deletions
diff --git a/src/lib/efl_wl/efl_wl.c b/src/lib/efl_wl/efl_wl.c index 4c16eb6c33..6513ba7304 100644 --- a/src/lib/efl_wl/efl_wl.c +++ b/src/lib/efl_wl/efl_wl.c @@ -95,6 +95,18 @@ typedef struct Input_Sequence Eina_Bool pass : 1; } Input_Sequence; +typedef struct Keyboard_Info +{ + unsigned int refs; + struct xkb_context *context; + struct xkb_keymap *keymap; + char *keymap_mem; + int keymap_mem_size; + int keymap_fd; + int repeat_rate; + int repeat_delay; +} Keyboard_Info; + typedef struct Comp_Subsurface Comp_Subsurface; typedef struct Comp_Surface Comp_Surface; @@ -202,14 +214,8 @@ typedef struct Comp_Seat xkb_layout_index_t group; Eina_Bool changed : 1; } mods; - struct xkb_context *context; - struct xkb_keymap *keymap; + Keyboard_Info *info; struct xkb_state *state; - char *keymap_mem; - int keymap_mem_size; - int keymap_fd; - int repeat_rate; - int repeat_delay; Eina_Hash *resources; Comp_Surface *enter; Eina_Bool external : 1; @@ -400,6 +406,7 @@ typedef struct Comp_Data_Device_Transfer static Eina_List *comps; static Eina_List *handlers; +static Eina_Hash *kbd_infos; static inline Eina_Tiler * tiler_new(void) @@ -446,6 +453,61 @@ array_clear(Eina_Array **arr) *arr = NULL; } +static void +keyboard_info_free(Keyboard_Info *info) +{ + if (info->refs) return; + if (info->state) xkb_state_unref(info->state); + if (info->keymap) xkb_keymap_unref(info->keymap); + if (info->context) xkb_context_unref(info->context); + if (info->keymap_mem) munmap(info->keymap_mem, info->keymap_mem_size); + if (info->keymap_fd > -1) close(info->keymap_fd); + free(info); +} + +static Keyboard_Info * +keyboard_info_create(struct xkb_keymap *keymap) +{ + Eina_Tmpstr *file; + char *str; + Keyboard_Info *info; + + info = eina_hash_find(kbd_infos, &keymap); + if (info) + { + info->refs++; + return info; + } + info = calloc(1, sizeof(Keyboard_Info)); + info->refs = 1; + str = xkb_map_get_as_string(keymap); + info->keymap_mem_size = strlen(str) + 1; + info->keymap_fd = eina_file_mkstemp("comp-keymapXXXXXX", &file); + if (info->keymap_fd < 0) + { + EINA_LOG_ERR("mkstemp failed!\n"); + free(info); + return NULL; + } + if (!eina_file_close_on_exec(info->keymap_fd, 1)) + { + EINA_LOG_ERR("Failed to set CLOEXEC on fd %d\n", info->keymap_fd); + close(info->keymap_fd); + free(info); + return NULL; + } + ftruncate(info->keymap_fd, info->keymap_mem_size); + eina_file_unlink(file); + eina_tmpstr_del(file); + info->keymap_mem = mmap(NULL, info->keymap_mem_size + 1, + PROT_READ | PROT_WRITE, MAP_SHARED, info->keymap_fd, 0); + + memcpy(info->keymap_mem, str, info->keymap_mem_size); + info->keymap_mem[info->keymap_mem_size] = 0; + free(str); + return info; +} + static inline Eina_Bool client_allowed_check(Comp *c, struct wl_client *client) { @@ -3704,68 +3766,44 @@ seat_kbd_external_init(Comp_Seat *s) } static void -seat_keymap_update(Comp_Seat *s) +seat_keymap_update(Comp_Seat *s, struct xkb_keymap *keymap) { - char *str; - Eina_Tmpstr *file; - xkb_mod_mask_t latched = 0, locked = 0; - - if (s->kbd.keymap_mem) munmap(s->kbd.keymap_mem, s->kbd.keymap_mem_size); - if (s->kbd.keymap_fd > -1) close(s->kbd.keymap_fd); - #ifdef HAVE_ECORE_X - if (!x11_kbd_keymap) + if (!x11_kbd_state) { #endif + xkb_mod_mask_t latched = 0, locked = 0; + if (s->kbd.info) + { + s->kbd.info->refs--; + if (!s->kbd.info->refs) + eina_hash_del_by_key(kbd_infos, &s->kbd.info->keymap); + s->kbd.info = NULL; + } if (s->kbd.state) { latched = xkb_state_serialize_mods(s->kbd.state, XKB_STATE_MODS_LATCHED); locked = xkb_state_serialize_mods(s->kbd.state, XKB_STATE_MODS_LOCKED); xkb_state_unref(s->kbd.state); } - if (!s->kbd.keymap) - { - s->kbd.state = NULL; - s->kbd.keymap_fd = -1; - s->kbd.keymap_mem = NULL; - return; - } - - s->kbd.state = xkb_state_new(s->kbd.keymap); + if (!s->kbd.info) return; + s->kbd.state = xkb_state_new(keymap); xkb_state_update_mask(s->kbd.state, 0, latched, locked, 0, 0, 0); #ifdef HAVE_ECORE_X } #endif - str = xkb_map_get_as_string(s->kbd.keymap); - s->kbd.keymap_mem_size = strlen(str) + 1; - s->kbd.keymap_fd = eina_file_mkstemp("comp-keymapXXXXXX", &file); - if (s->kbd.keymap_fd < 0) - { - EINA_LOG_ERR("mkstemp failed!\n"); - s->kbd.keymap_fd = -1; - xkb_state_unref(s->kbd.state); - s->kbd.state = NULL; - return; - } - if (!eina_file_close_on_exec(s->kbd.keymap_fd, 1)) + s->kbd.info = keyboard_info_create(keymap); + if (!s->kbd.info) { - EINA_LOG_ERR("Failed to set CLOEXEC on fd %d\n", s->kbd.keymap_fd); - close(s->kbd.keymap_fd); - s->kbd.keymap_fd = -1; - xkb_state_unref(s->kbd.state); - s->kbd.state = NULL; - return; +#ifdef HAVE_ECORE_X + if (!x11_kbd_state) + { + xkb_state_unref(s->kbd.state); + s->kbd.state = NULL; + return; + } +#endif } - ftruncate(s->kbd.keymap_fd, s->kbd.keymap_mem_size); - eina_file_unlink(file); - eina_tmpstr_del(file); - s->kbd.keymap_mem = - mmap(NULL, s->kbd.keymap_mem_size + 1, - PROT_READ | PROT_WRITE, MAP_SHARED, s->kbd.keymap_fd, 0); - - memcpy(s->kbd.keymap_mem, str, s->kbd.keymap_mem_size); - s->kbd.keymap_mem[s->kbd.keymap_mem_size] = 0; - free(str); seat_keymap_send(s); } @@ -4048,20 +4086,12 @@ seat_resource_hash_free(Eina_Hash *h) static void seat_kbd_destroy(Comp_Seat *s) { - if (s->kbd.external) return; -#ifdef HAVE_ECORE_X - if (!x11_kbd_keymap) - { -#endif - if (s->kbd.state) xkb_state_unref(s->kbd.state); - if (s->kbd.keymap) xkb_keymap_unref(s->kbd.keymap); - if (s->kbd.context) xkb_context_unref(s->kbd.context); -#ifdef HAVE_ECORE_X - } -#endif - if (s->kbd.keymap_mem) munmap(s->kbd.keymap_mem, s->kbd.keymap_mem_size); - if (s->kbd.keymap_fd > -1) close(s->kbd.keymap_fd); - wl_array_release(&s->kbd.keys); + s->kbd.info->refs--; + if (!s->kbd.info->refs) + eina_hash_del_by_key(kbd_infos, &s->kbd.info->keymap); + s->kbd.info = NULL; + if (!s->kbd.external) + wl_array_release(&s->kbd.keys); } static void @@ -5381,7 +5411,11 @@ comp_smart_add(Evas_Object *obj) evas_object_event_callback_add(c->obj, EVAS_CALLBACK_FOCUS_IN, comp_focus_in, c); evas_object_event_callback_add(c->obj, EVAS_CALLBACK_FOCUS_OUT, comp_focus_out, c); - if (!comps) comp_handlers_init(); + if (!comps) + { + comp_handlers_init(); + kbd_infos = eina_hash_pointer_new((Eina_Free_Cb)keyboard_info_free); + } comps = eina_list_append(comps, c); free(env); } diff --git a/src/lib/efl_wl/x11.x b/src/lib/efl_wl/x11.x index 2d7a88352f..f558d1a0fe 100644 --- a/src/lib/efl_wl/x11.x +++ b/src/lib/efl_wl/x11.x @@ -565,8 +565,7 @@ x11_dnd_move(void *data, Ecore_X_Xdnd_Position *pos) } static int32_t x11_core_device = -1; -static struct xkb_context *x11_kbd_context; -static struct xkb_keymap *x11_kbd_keymap; +static Keyboard_Info *x11_kbd_info; static struct xkb_state *x11_kbd_state; static Eina_Bool seat_kbd_mods_update(Comp_Seat *s); @@ -606,12 +605,8 @@ x11_xkb_state(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_X_Event_Xkb *ev) static void x11_kbd_destroy(void) { - if (x11_kbd_state) xkb_state_unref(x11_kbd_state); - x11_kbd_state = NULL; - if (x11_kbd_keymap) xkb_keymap_unref(x11_kbd_keymap); - x11_kbd_keymap = NULL; - if (x11_kbd_context) xkb_context_unref(x11_kbd_context); - x11_kbd_context = NULL; + x11_kbd_info->refs = 0; + eina_hash_del_by_key(kbd_infos, &x11_kbd_info->keymap); } static void @@ -621,23 +616,24 @@ x11_kbd_create(void) x11_kbd_destroy(); - x11_kbd_context = xkb_context_new(0); x11_core_device = xkb_x11_get_core_keyboard_device_id(conn); - x11_kbd_keymap = xkb_x11_keymap_new_from_device(x11_kbd_context, conn, x11_core_device, 0); - x11_kbd_state = xkb_x11_state_new_from_device(x11_kbd_keymap, conn, x11_core_device); - keymap_mods_init(x11_kbd_keymap); + x11_kbd_info.context = xkb_context_new(0); + x11_kbd_info.keymap = xkb_x11_keymap_new_from_device(x11_kbd_info.context, conn, x11_core_device, 0); + x11_kbd_state = xkb_x11_state_new_from_device(x11_kbd_info.keymap, conn, x11_core_device); + keymap_mods_init(x11_kbd_info.keymap); + eina_hash_add(kbd_infos, &x11_kbd_info.keymap, &x11_kbd_info); } static void x11_kbd_apply(Comp_Seat *s) { if (!x11_kbd_state) x11_kbd_create(); - s->kbd.context = x11_kbd_context; - s->kbd.keymap = x11_kbd_keymap; - s->kbd.state = x11_kbd_state; + x11_kbd_info.refs++; + s->kbd.info = &x11_kbd_info; + s->kbd.state = x11_kbd_state); } -static void seat_keymap_update(Comp_Seat *s); +static void seat_keymap_update(Comp_Seat *s, struct xkb_keymap *keymap); static Eina_Bool x11_xkb_refresh() |