diff --git a/configure.ac b/configure.ac index 8043adfecf..196ca21334 100644 --- a/configure.ac +++ b/configure.ac @@ -3807,6 +3807,7 @@ EFL_OPTIONAL_INTERNAL_DEPEND_PKG([EFL_WL], [${want_x11_any}], [ecore_x]) EFL_DEPEND_PKG([EFL_WL], [WAYLAND], [wayland-server >= 1.11.0 xkbcommon >= 0.6.0]) +EFL_OPTIONAL_DEPEND_PKG([EFL_WL], [${want_x11_any}], [XKBCOMMONX11], [xkbcommon-x11]) EFL_EVAL_PKGS([EFL_WL]) diff --git a/src/lib/efl_wl/copiedfromweston.x b/src/lib/efl_wl/copiedfromweston.x index 0b1388b064..17a31cbe55 100644 --- a/src/lib/efl_wl/copiedfromweston.x +++ b/src/lib/efl_wl/copiedfromweston.x @@ -356,3 +356,53 @@ drag_grab_button(Comp_Seat *s, #endif } } + +#ifdef HAVE_ECORE_X +static xkb_mod_index_t x11_kbd_shift_mod; +static xkb_mod_index_t x11_kbd_caps_mod; +static xkb_mod_index_t x11_kbd_ctrl_mod; +static xkb_mod_index_t x11_kbd_alt_mod; +static xkb_mod_index_t x11_kbd_mod2_mod; +static xkb_mod_index_t x11_kbd_mod3_mod; +static xkb_mod_index_t x11_kbd_super_mod; +static xkb_mod_index_t x11_kbd_mod5_mod; + +static void +keymap_mods_init(struct xkb_keymap *keymap) +{ + x11_kbd_shift_mod = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_SHIFT); + x11_kbd_caps_mod = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CAPS); + x11_kbd_ctrl_mod = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CTRL); + x11_kbd_alt_mod = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_ALT); + x11_kbd_mod2_mod = xkb_keymap_mod_get_index(keymap, "Mod2"); + x11_kbd_mod3_mod = xkb_keymap_mod_get_index(keymap, "Mod3"); + x11_kbd_super_mod = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_LOGO); + x11_kbd_mod5_mod = xkb_keymap_mod_get_index(keymap, "Mod5"); +} + +static uint32_t +get_xkb_mod_mask(uint32_t in) +{ + uint32_t ret = 0; + + if ((in & ECORE_X_MODIFIER_SHIFT) && x11_kbd_shift_mod != XKB_MOD_INVALID) + ret |= (1 << x11_kbd_shift_mod); + if ((in & ECORE_X_LOCK_CAPS) && x11_kbd_caps_mod != XKB_MOD_INVALID) + ret |= (1 << x11_kbd_caps_mod); + if ((in & ECORE_X_MODIFIER_CTRL) && x11_kbd_ctrl_mod != XKB_MOD_INVALID) + ret |= (1 << x11_kbd_ctrl_mod); + if ((in & ECORE_X_MODIFIER_ALT) && x11_kbd_alt_mod != XKB_MOD_INVALID) + ret |= (1 << x11_kbd_alt_mod); + if ((in & ECORE_X_LOCK_NUM) && x11_kbd_mod2_mod != XKB_MOD_INVALID) + ret |= (1 << x11_kbd_mod2_mod); + if ((in & ECORE_X_LOCK_SCROLL) && x11_kbd_mod3_mod != XKB_MOD_INVALID) + ret |= (1 << x11_kbd_mod3_mod); + if ((in & ECORE_X_MODIFIER_WIN) && x11_kbd_super_mod != XKB_MOD_INVALID) + ret |= (1 << x11_kbd_super_mod); + if ((in & ECORE_X_MODIFIER_ALTGR) && x11_kbd_mod5_mod != XKB_MOD_INVALID) + ret |= (1 << x11_kbd_mod5_mod); + + return ret; +} + +#endif diff --git a/src/lib/efl_wl/efl_wl.c b/src/lib/efl_wl/efl_wl.c index d6622ef8dd..fd02aed44a 100644 --- a/src/lib/efl_wl/efl_wl.c +++ b/src/lib/efl_wl/efl_wl.c @@ -3710,26 +3710,32 @@ seat_keymap_update(Comp_Seat *s) 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); - - if (s->kbd.state) +#ifdef HAVE_ECORE_X + if (!x11_kbd_keymap) { - 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; - } +#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); - s->kbd.state = xkb_state_new(s->kbd.keymap); - xkb_state_update_mask(s->kbd.state, 0, latched, locked, 0, 0, 0); + 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); + 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); @@ -4395,6 +4401,11 @@ comp_device_caps_update(Comp_Seat *s) { if (s->keyboard) { +#ifdef HAVE_ECORE_X + if ((!s->c->parent_disp) && ecore_x_display_get()) + x11_kbd_apply(s); + else +#endif seat_keymap_create(s); seat_kbd_repeat_rate_update(s); } @@ -4462,9 +4473,16 @@ comp_seats_proxy(Comp *c) if (s->kbd.keymap) xkb_keymap_ref(s->kbd.keymap); } else - seat_keymap_create(s); - seat_kbd_repeat_rate_update(s); + { +#ifdef HAVE_ECORE_X + if ((!s->c->parent_disp) && ecore_x_display_get()) + x11_kbd_apply(s); + else +#endif + seat_keymap_create(s); + } seat_keymap_update(s); + seat_kbd_repeat_rate_update(s); s->keyboard = !!s->kbd.state; } } @@ -5339,6 +5357,7 @@ comp_smart_add(Evas_Object *obj) #ifdef HAVE_ECORE_X if (ecore_x_display_get()) { + ecore_x_xkb_track_state(); // if proxiedallowed ecore_x_dnd_aware_set(ecore_evas_window_get(ecore_evas_ecore_evas_get(c->evas)), EINA_TRUE); if (!comps) x11_init(); diff --git a/src/lib/efl_wl/x11.x b/src/lib/efl_wl/x11.x index bebd017519..2d7a88352f 100644 --- a/src/lib/efl_wl/x11.x +++ b/src/lib/efl_wl/x11.x @@ -1,3 +1,5 @@ +#include "xkbcommon/xkbcommon-x11.h" + #define WL_TEXT_STR "text/plain;charset=utf-8" #define INCR_CHUNK_SIZE 1 << 17 @@ -562,6 +564,99 @@ x11_dnd_move(void *data, Ecore_X_Xdnd_Position *pos) evas_object_move(data, pos->position.x, pos->position.y); } +static int32_t x11_core_device = -1; +static struct xkb_context *x11_kbd_context; +static struct xkb_keymap *x11_kbd_keymap; +static struct xkb_state *x11_kbd_state; + +static Eina_Bool seat_kbd_mods_update(Comp_Seat *s); +static void comp_seat_send_modifiers(Comp_Seat *s, struct wl_resource *res, uint32_t serial); + +static Eina_Bool +x11_xkb_state(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_X_Event_Xkb *ev) +{ + Comp *c; + Eina_List *l; + Comp_Seat *s; + + if (!xkb_state_update_mask(x11_kbd_state, + get_xkb_mod_mask(ev->base_mods), + get_xkb_mod_mask(ev->latched_mods), + get_xkb_mod_mask(ev->locked_mods), + 0, + 0, + ev->group)) return ECORE_CALLBACK_RENEW; + EINA_LIST_FOREACH(comps, l, c) + EINA_INLIST_FOREACH(c->seats, s) + { + Eina_List *ll, *lll; + uint32_t serial; + struct wl_resource *res; + + seat_kbd_mods_update(s); + ll = seat_kbd_active_resources_get(s); + if (!ll) continue; + serial = wl_display_next_serial(s->c->display); + EINA_LIST_FOREACH(ll, lll, res) + comp_seat_send_modifiers(s, res, serial); + } + return ECORE_CALLBACK_RENEW; +} + +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; +} + +static void +x11_kbd_create(void) +{ + Ecore_X_Connection *conn = ecore_x_connection_get(); + + 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); +} + +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; +} + +static void seat_keymap_update(Comp_Seat *s); + +static Eina_Bool +x11_xkb_refresh() +{ + Eina_List *l; + Comp *c; + Comp_Seat *s; + + x11_kbd_create(); + EINA_LIST_FOREACH(comps, l, c) + EINA_INLIST_FOREACH(c->seats, s) + { + if (!s->keyboard) continue; + x11_kbd_apply(s); + seat_keymap_update(s); + } + return ECORE_CALLBACK_RENEW; +} + static void x11_init(void) { @@ -589,18 +684,29 @@ x11_init(void) handlers = eina_list_append(handlers, h); h = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP, (Ecore_Event_Handler_Cb)x11_dnd_mouse_up, NULL); handlers = eina_list_append(handlers, h); - xconvertselection = dlsym(NULL, "XConvertSelection"); - string_atom = ecore_x_atom_get("UTF8_STRING"); - timestamp_atom = ecore_x_atom_get("TIMESTAMP"); - int_atom = ecore_x_atom_get("INTEGER"); - incr_atom = ecore_x_atom_get("TIMESTAMP"); - comp_dnd_atom = ecore_x_atom_get("SIRCMPWIDG_ATOM"); + h = ecore_event_handler_add(ECORE_X_EVENT_XKB_STATE_NOTIFY, (Ecore_Event_Handler_Cb)x11_xkb_state, NULL); + handlers = eina_list_append(handlers, h); + h = ecore_event_handler_add(ECORE_X_EVENT_XKB_NEWKBD_NOTIFY, (Ecore_Event_Handler_Cb)x11_xkb_refresh, NULL); + handlers = eina_list_append(handlers, h); + if (!xconvertselection) + { + xconvertselection = dlsym(NULL, "XConvertSelection"); + string_atom = ecore_x_atom_get("UTF8_STRING"); + timestamp_atom = ecore_x_atom_get("TIMESTAMP"); + int_atom = ecore_x_atom_get("INTEGER"); + incr_atom = ecore_x_atom_get("TIMESTAMP"); + comp_dnd_atom = ecore_x_atom_get("SIRCMPWIDG_ATOM"); + ecore_x_xkb_track_state(); + } + pipes = eina_hash_int32_new((Eina_Free_Cb)_pipe_free); } static void x11_shutdown(void) { + x11_core_device = -1; + x11_kbd_destroy(); eina_hash_free(pipes); pipes = NULL; }