aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/efl_wl
diff options
context:
space:
mode:
authorMike Blumenkrantz <zmike@osg.samsung.com>2018-01-24 16:16:17 -0500
committerMike Blumenkrantz <zmike@osg.samsung.com>2018-01-24 16:18:51 -0500
commita32735e9a7bc537430d155a4af853d498dda2009 (patch)
treea3076403e7c261d3e229e51991005f6d3bc3fcbf /src/lib/efl_wl
parentefl-wl: use image border to optimize surface rendering with 1 opaque rect (diff)
downloadefl-a32735e9a7bc537430d155a4af853d498dda2009.tar.gz
efl-wl: create and maintain xserver-based keymap and keyboard states under x11
when run in a non-wayland environment, it's necessary to do some extra work in order to guarantee that the keymap remains the same in the compositor as in the xserver and to also guarantee that modifier states are accurately applied even when the compositor is not actively focused fix https://phab.enlightenment.org/T6631
Diffstat (limited to 'src/lib/efl_wl')
-rw-r--r--src/lib/efl_wl/copiedfromweston.x50
-rw-r--r--src/lib/efl_wl/efl_wl.c57
-rw-r--r--src/lib/efl_wl/x11.x118
3 files changed, 200 insertions, 25 deletions
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)
- {
- 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)
+#ifdef HAVE_ECORE_X
+ if (!x11_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;
}