discomfitor pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=a32735e9a7bc537430d155a4af853d498dda2009

commit a32735e9a7bc537430d155a4af853d498dda2009
Author: Mike Blumenkrantz <[email protected]>
Date:   Wed Jan 24 16:16:17 2018 -0500

    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 T6631
---
 configure.ac                      |   1 +
 src/lib/efl_wl/copiedfromweston.x |  50 ++++++++++++++++
 src/lib/efl_wl/efl_wl.c           |  57 ++++++++++++------
 src/lib/efl_wl/x11.x              | 118 ++++++++++++++++++++++++++++++++++++--
 4 files changed, 201 insertions(+), 25 deletions(-)

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)
-     {
-        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;
 }

-- 


Reply via email to