summaryrefslogtreecommitdiff
path: root/src/lib/efl_wl/x11.x
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/efl_wl/x11.x')
-rw-r--r--src/lib/efl_wl/x11.x118
1 files changed, 112 insertions, 6 deletions
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;
}