[mutter/wip/wayland-work: 11/21] MetaWaylandKeyboard: use the new clutter-evdev support for xkbcommon



commit 861b340433b0588cfdaadacc4b7bc729723bd848
Author: Giovanni Campagna <gcampagn redhat com>
Date:   Fri Aug 9 17:28:41 2013 +0200

    MetaWaylandKeyboard: use the new clutter-evdev support for xkbcommon
    
    We need to track the full xkb_state to have the necessary information
    to send to the clients, otherwise they may get confused and lock
    or invert the modifiers. In the evdev backend, we just retrieve the
    same state object that clutter is using, while in the other backends
    we fake the state using what clutter is providing (which is a subset
    of what X11 provides, which would be necessary to have full state)
    
    https://bugzilla.gnome.org/show_bug.cgi?id=705862

 src/wayland/meta-wayland-keyboard.c |  105 ++++++++++++++++++++++++++--------
 src/wayland/meta-wayland-keyboard.h |    3 +-
 src/wayland/meta-wayland-pointer.c  |    8 +-
 src/wayland/meta-wayland-private.h  |   20 ++++---
 src/wayland/meta-wayland-seat.c     |    5 +-
 src/wayland/meta-wayland-seat.h     |    3 +-
 src/wayland/meta-wayland.c          |    3 +-
 7 files changed, 104 insertions(+), 43 deletions(-)
---
diff --git a/src/wayland/meta-wayland-keyboard.c b/src/wayland/meta-wayland-keyboard.c
index c43de91..70d29b2 100644
--- a/src/wayland/meta-wayland-keyboard.c
+++ b/src/wayland/meta-wayland-keyboard.c
@@ -56,6 +56,7 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include <sys/mman.h>
+#include <clutter/evdev/clutter-evdev.h>
 
 #include "meta-wayland-keyboard.h"
 
@@ -258,12 +259,11 @@ default_grab_modifiers (MetaWaylandKeyboardGrab *grab, uint32_t serial,
                                       pointer->focus);
       if (pr)
         {
-          wl_keyboard_send_modifiers (pr,
-                                      serial,
-                                      keyboard->modifiers.mods_depressed,
-                                      keyboard->modifiers.mods_latched,
-                                      keyboard->modifiers.mods_locked,
-                                      keyboard->modifiers.group);
+          wl_keyboard_send_modifiers (pr, serial,
+                                     mods_depressed,
+                                      mods_latched,
+                                      mods_locked,
+                                      group);
         }
     }
 }
@@ -276,8 +276,11 @@ static const MetaWaylandKeyboardGrabInterface
 
 gboolean
 meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
-                            struct wl_display *display)
+                            struct wl_display   *display,
+                           gboolean             is_evdev)
 {
+  ClutterDeviceManager *manager;
+
   memset (keyboard, 0, sizeof *keyboard);
 
   wl_list_init (&keyboard->resource_list);
@@ -293,8 +296,22 @@ meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
   keyboard->xkb_context = xkb_context_new (0 /* flags */);
 
   meta_wayland_keyboard_build_global_keymap (keyboard->xkb_context,
-                                         &keyboard->xkb_names,
-                                         &keyboard->xkb_info);
+                                            &keyboard->xkb_names,
+                                            &keyboard->xkb_info);
+
+  keyboard->is_evdev = is_evdev;
+  if (is_evdev)
+    {
+      manager = clutter_device_manager_get_default ();
+
+      clutter_evdev_set_keyboard_map (manager, keyboard->xkb_info.keymap);
+      keyboard->xkb_state = clutter_evdev_get_keyboard_state (manager);
+      xkb_state_ref (keyboard->xkb_state);
+    }
+  else
+    {
+      keyboard->xkb_state = xkb_state_new (keyboard->xkb_info.keymap);
+    }
 
   return TRUE;
 }
@@ -312,17 +329,12 @@ meta_wayland_xkb_info_destroy (MetaWaylandXkbInfo *xkb_info)
 }
 
 static void
-set_modifiers (MetaWaylandKeyboard *keyboard,
-               guint32 serial,
-               ClutterModifierType modifier_state)
+update_state_from_clutter (MetaWaylandKeyboard *keyboard,
+                          ClutterModifierType  modifier_state)
 {
-  MetaWaylandKeyboardGrab *grab = keyboard->grab;
   uint32_t depressed_mods = 0;
   uint32_t locked_mods = 0;
 
-  if (keyboard->last_modifier_state == modifier_state)
-    return;
-
   if ((modifier_state & CLUTTER_SHIFT_MASK) &&
       keyboard->xkb_info.shift_mod != XKB_MOD_INVALID)
     depressed_mods |= (1 << keyboard->xkb_info.shift_mod);
@@ -355,14 +367,56 @@ set_modifiers (MetaWaylandKeyboard *keyboard,
       keyboard->xkb_info.mod5_mod != XKB_MOD_INVALID)
     depressed_mods |= (1 << keyboard->xkb_info.mod5_mod);
 
-  keyboard->last_modifier_state = modifier_state;
+  xkb_state_update_mask (keyboard->xkb_state,
+                        depressed_mods,
+                        0,
+                        locked_mods,
+                        0, 0, 0);
+}
+
+static gboolean
+state_equal (MetaWaylandXkbState *one,
+            MetaWaylandXkbState *two)
+{
+  return one->mods_depressed == two->mods_depressed &&
+    one->mods_latched == two->mods_latched &&
+    one->mods_locked == two->mods_locked &&
+    one->group == two->group;
+}
+
+static void
+set_modifiers (MetaWaylandKeyboard *keyboard,
+               guint32 serial,
+               ClutterModifierType modifier_state)
+{
+  MetaWaylandKeyboardGrab *grab = keyboard->grab;
+  MetaWaylandXkbState new_state;
+
+  /* In the evdev case, the state is shared with the clutter backend, so
+     we don't need to update it */
+  if (!keyboard->is_evdev)
+    update_state_from_clutter (keyboard, modifier_state);
+
+  new_state.mods_depressed = xkb_state_serialize_mods (keyboard->xkb_state,
+                                                      XKB_STATE_MODS_DEPRESSED);
+  new_state.mods_latched = xkb_state_serialize_mods (keyboard->xkb_state,
+                                                    XKB_STATE_MODS_LATCHED);
+  new_state.mods_locked = xkb_state_serialize_mods (keyboard->xkb_state,
+                                                   XKB_STATE_MODS_LOCKED);
+  new_state.group = xkb_state_serialize_layout (keyboard->xkb_state,
+                                               XKB_STATE_LAYOUT_EFFECTIVE);
+
+  if (state_equal (&keyboard->modifier_state, &new_state))
+    return;
+
+  keyboard->modifier_state = new_state;
 
   grab->interface->modifiers (grab,
                               serial,
-                              depressed_mods,
-                              0, /* latched_modes */
-                              locked_mods,
-                              0 /* group */);
+                              new_state.mods_depressed,
+                             new_state.mods_latched,
+                             new_state.mods_locked,
+                              new_state.group);
 }
 
 void
@@ -462,10 +516,10 @@ meta_wayland_keyboard_set_focus (MetaWaylandKeyboard *keyboard,
       display = wl_client_get_display (client);
       serial = wl_display_next_serial (display);
       wl_keyboard_send_modifiers (resource, serial,
-                                  keyboard->modifiers.mods_depressed,
-                                  keyboard->modifiers.mods_latched,
-                                  keyboard->modifiers.mods_locked,
-                                  keyboard->modifiers.group);
+                                  keyboard->modifier_state.mods_depressed,
+                                  keyboard->modifier_state.mods_latched,
+                                  keyboard->modifier_state.mods_locked,
+                                  keyboard->modifier_state.group);
       wl_keyboard_send_enter (resource, serial, surface->resource,
                               &keyboard->keys);
       wl_resource_add_destroy_listener (resource, &keyboard->focus_listener);
@@ -504,6 +558,7 @@ meta_wayland_keyboard_release (MetaWaylandKeyboard *keyboard)
 
   meta_wayland_xkb_info_destroy (&keyboard->xkb_info);
   xkb_context_unref (keyboard->xkb_context);
+  xkb_state_unref (keyboard->xkb_state);
 
   /* XXX: What about keyboard->resource_list? */
   if (keyboard->focus_resource)
diff --git a/src/wayland/meta-wayland-keyboard.h b/src/wayland/meta-wayland-keyboard.h
index fd0d0b3..e092366 100644
--- a/src/wayland/meta-wayland-keyboard.h
+++ b/src/wayland/meta-wayland-keyboard.h
@@ -52,7 +52,8 @@
 
 gboolean
 meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
-                            struct wl_display *display);
+                            struct wl_display   *display,
+                           gboolean             is_evdev);
 
 void
 meta_wayland_keyboard_handle_event (MetaWaylandKeyboard *keyboard,
diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c
index 7564a5c..49ac2ec 100644
--- a/src/wayland/meta-wayland-pointer.c
+++ b/src/wayland/meta-wayland-pointer.c
@@ -194,10 +194,10 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
             {
               wl_keyboard_send_modifiers (kr,
                                           serial,
-                                          kbd->modifiers.mods_depressed,
-                                          kbd->modifiers.mods_latched,
-                                          kbd->modifiers.mods_locked,
-                                          kbd->modifiers.group);
+                                          kbd->modifier_state.mods_depressed,
+                                          kbd->modifier_state.mods_latched,
+                                          kbd->modifier_state.mods_locked,
+                                          kbd->modifier_state.group);
             }
         }
       wl_pointer_send_enter (resource, serial, surface->resource, sx, sy);
diff --git a/src/wayland/meta-wayland-private.h b/src/wayland/meta-wayland-private.h
index 8857891..38c3d49 100644
--- a/src/wayland/meta-wayland-private.h
+++ b/src/wayland/meta-wayland-private.h
@@ -238,6 +238,14 @@ typedef struct
   xkb_mod_index_t mod5_mod;
 } MetaWaylandXkbInfo;
 
+typedef struct
+{
+  uint32_t mods_depressed;
+  uint32_t mods_latched;
+  uint32_t mods_locked;
+  uint32_t group;
+} MetaWaylandXkbState;
+
 struct _MetaWaylandKeyboard
 {
   struct wl_list resource_list;
@@ -255,25 +263,19 @@ struct _MetaWaylandKeyboard
 
   struct wl_array keys;
 
-  struct
-  {
-    uint32_t mods_depressed;
-    uint32_t mods_latched;
-    uint32_t mods_locked;
-    uint32_t group;
-  } modifiers;
+  MetaWaylandXkbState modifier_state;
 
   struct wl_display *display;
 
   struct xkb_context *xkb_context;
+  struct xkb_state *xkb_state;
+  gboolean is_evdev;
 
   MetaWaylandXkbInfo xkb_info;
   struct xkb_rule_names xkb_names;
 
   MetaWaylandKeyboardGrab input_method_grab;
   struct wl_resource *input_method_resource;
-
-  ClutterModifierType last_modifier_state;
 };
 
 struct _MetaWaylandDataOffer
diff --git a/src/wayland/meta-wayland-seat.c b/src/wayland/meta-wayland-seat.c
index 82dcb20..3720919 100644
--- a/src/wayland/meta-wayland-seat.c
+++ b/src/wayland/meta-wayland-seat.c
@@ -271,7 +271,8 @@ pointer_handle_sprite_destroy (struct wl_listener *listener, void *data)
 }
 
 MetaWaylandSeat *
-meta_wayland_seat_new (struct wl_display *display)
+meta_wayland_seat_new (struct wl_display *display,
+                      gboolean           is_native)
 {
   MetaWaylandSeat *seat = g_new0 (MetaWaylandSeat, 1);
 
@@ -285,7 +286,7 @@ meta_wayland_seat_new (struct wl_display *display)
 
   meta_wayland_pointer_init (&seat->pointer);
 
-  meta_wayland_keyboard_init (&seat->keyboard, display);
+  meta_wayland_keyboard_init (&seat->keyboard, display, is_native);
 
   seat->display = display;
 
diff --git a/src/wayland/meta-wayland-seat.h b/src/wayland/meta-wayland-seat.h
index 89bcd76..d5a0597 100644
--- a/src/wayland/meta-wayland-seat.h
+++ b/src/wayland/meta-wayland-seat.h
@@ -30,7 +30,8 @@
 #include "meta-wayland-private.h"
 
 MetaWaylandSeat *
-meta_wayland_seat_new (struct wl_display *display);
+meta_wayland_seat_new (struct wl_display *display,
+                      gboolean           is_native);
 
 void
 meta_wayland_seat_handle_event (MetaWaylandSeat *seat,
diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c
index 6ecbdfb..e50a245 100644
--- a/src/wayland/meta-wayland.c
+++ b/src/wayland/meta-wayland.c
@@ -1614,7 +1614,8 @@ meta_wayland_init (void)
 
   meta_wayland_data_device_manager_init (compositor->wayland_display);
 
-  compositor->seat = meta_wayland_seat_new (compositor->wayland_display);
+  compositor->seat = meta_wayland_seat_new (compositor->wayland_display,
+                                           compositor->drm_fd >= 0);
 
   g_signal_connect (compositor->stage,
                     "captured-event",


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]