[mutter] wayland: save/restore numlock state



commit 4c106a9c9bc743fb83bfe3759fcbbea883a8a260
Author: Olivier Fourdan <ofourdan redhat com>
Date:   Thu Sep 8 09:55:44 2016 +0200

    wayland: save/restore numlock state
    
    Save the state on NumLock so that is can be (optionally) restored on
    next login.
    
    bugzilla: https://bugzilla.gnome.org/show_bug.cgi?id=757943

 .../clutter/evdev/clutter-device-manager-evdev.c   |   54 ++++++++
 clutter/clutter/evdev/clutter-evdev.h              |    4 +
 src/backends/meta-backend-private.h                |    3 +
 src/backends/meta-backend.c                        |    8 +
 src/backends/native/meta-backend-native.c          |    9 ++
 src/backends/x11/meta-backend-x11.c                |    9 ++
 src/meta/meta-backend.h                            |    3 +
 src/wayland/meta-wayland-keyboard.c                |  140 ++++++++++++++++++++
 src/wayland/meta-wayland-keyboard.h                |    1 +
 9 files changed, 231 insertions(+), 0 deletions(-)
---
diff --git a/clutter/clutter/evdev/clutter-device-manager-evdev.c 
b/clutter/clutter/evdev/clutter-device-manager-evdev.c
index b42b576..c03c68c 100644
--- a/clutter/clutter/evdev/clutter-device-manager-evdev.c
+++ b/clutter/clutter/evdev/clutter-device-manager-evdev.c
@@ -2531,6 +2531,60 @@ clutter_evdev_set_keyboard_layout_index (ClutterDeviceManager *evdev,
 }
 
 /**
+ * clutter_evdev_set_keyboard_numlock: (skip)
+ * @evdev: the #ClutterDeviceManager created by the evdev backend
+ * @numlock_set: TRUE to set NumLock ON, FALSE otherwise.
+ *
+ * Sets the NumLock state on the backend's #xkb_state .
+ *
+ * Stability: unstable
+ */
+void
+clutter_evdev_set_keyboard_numlock (ClutterDeviceManager *evdev,
+                                    gboolean              numlock_state)
+{
+  ClutterDeviceManagerEvdev *manager_evdev;
+  ClutterDeviceManagerEvdevPrivate *priv;
+  GSList *iter;
+  xkb_mod_mask_t numlock;
+
+  g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER_EVDEV (evdev));
+
+  manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (evdev);
+  priv = manager_evdev->priv;
+  numlock = (1 << xkb_keymap_mod_get_index(priv->keymap, "Mod2"));
+
+  for (iter = priv->seats; iter; iter = iter->next)
+    {
+      ClutterSeatEvdev *seat = iter->data;
+      xkb_mod_mask_t depressed_mods;
+      xkb_mod_mask_t latched_mods;
+      xkb_mod_mask_t locked_mods;
+      xkb_mod_mask_t group_mods;
+
+      depressed_mods = xkb_state_serialize_mods (seat->xkb, XKB_STATE_MODS_DEPRESSED);
+      latched_mods = xkb_state_serialize_mods (seat->xkb, XKB_STATE_MODS_LATCHED);
+      locked_mods = xkb_state_serialize_mods (seat->xkb, XKB_STATE_MODS_LOCKED);
+      group_mods = xkb_state_serialize_layout (seat->xkb, XKB_STATE_LAYOUT_EFFECTIVE);
+
+      if (numlock_state)
+        locked_mods |= numlock;
+      else
+        locked_mods &= ~numlock;
+
+      xkb_state_update_mask (seat->xkb,
+                             depressed_mods,
+                             latched_mods,
+                             locked_mods,
+                             0, 0,
+                             group_mods);
+
+      clutter_seat_evdev_sync_leds (seat);
+    }
+}
+
+
+/**
  * clutter_evdev_set_pointer_constrain_callback:
  * @evdev: the #ClutterDeviceManager created by the evdev backend
  * @callback: the callback
diff --git a/clutter/clutter/evdev/clutter-evdev.h b/clutter/clutter/evdev/clutter-evdev.h
index be8748f..1f5485c 100644
--- a/clutter/clutter/evdev/clutter-evdev.h
+++ b/clutter/clutter/evdev/clutter-evdev.h
@@ -105,6 +105,10 @@ CLUTTER_AVAILABLE_IN_1_20
 void clutter_evdev_set_keyboard_layout_index (ClutterDeviceManager *evdev,
                                               xkb_layout_index_t    idx);
 
+CLUTTER_AVAILABLE_IN_1_26
+void clutter_evdev_set_keyboard_numlock (ClutterDeviceManager *evdev,
+                                         gboolean              numlock_state);
+
 CLUTTER_AVAILABLE_IN_1_18
 void clutter_evdev_set_keyboard_repeat (ClutterDeviceManager *evdev,
                                         gboolean              repeat,
diff --git a/src/backends/meta-backend-private.h b/src/backends/meta-backend-private.h
index ee85e8a..b8abccf 100644
--- a/src/backends/meta-backend-private.h
+++ b/src/backends/meta-backend-private.h
@@ -103,6 +103,9 @@ struct _MetaBackendClass
                                            double       *dy,
                                            double       *dx_unaccel,
                                            double       *dy_unaccel);
+  void (* set_numlock) (MetaBackend *backend,
+                        gboolean     numlock_state);
+
 };
 
 void meta_init_backend (MetaBackendType backend_type);
diff --git a/src/backends/meta-backend.c b/src/backends/meta-backend.c
index 8c97765..872d0d3 100644
--- a/src/backends/meta-backend.c
+++ b/src/backends/meta-backend.c
@@ -542,6 +542,14 @@ meta_backend_lock_layout_group (MetaBackend *backend,
   META_BACKEND_GET_CLASS (backend)->lock_layout_group (backend, idx);
 }
 
+void
+meta_backend_set_numlock (MetaBackend *backend,
+                          gboolean     numlock_state)
+{
+  META_BACKEND_GET_CLASS (backend)->set_numlock (backend, numlock_state);
+}
+
+
 /**
  * meta_backend_get_stage:
  * @backend: A #MetaBackend
diff --git a/src/backends/native/meta-backend-native.c b/src/backends/native/meta-backend-native.c
index 385122c..09b235b 100644
--- a/src/backends/native/meta-backend-native.c
+++ b/src/backends/native/meta-backend-native.c
@@ -368,6 +368,14 @@ meta_backend_native_lock_layout_group (MetaBackend *backend,
   g_signal_emit_by_name (backend, "keymap-layout-group-changed", idx, 0);
 }
 
+static void
+meta_backend_native_set_numlock (MetaBackend *backend,
+                                 gboolean     numlock_state)
+{
+  ClutterDeviceManager *manager = clutter_device_manager_get_default ();
+  clutter_evdev_set_keyboard_numlock (manager, numlock_state);
+}
+
 static gboolean
 meta_backend_native_get_relative_motion_deltas (MetaBackend *backend,
                                                 const        ClutterEvent *event,
@@ -421,6 +429,7 @@ meta_backend_native_class_init (MetaBackendNativeClass *klass)
   backend_class->lock_layout_group = meta_backend_native_lock_layout_group;
   backend_class->get_relative_motion_deltas = meta_backend_native_get_relative_motion_deltas;
   backend_class->update_screen_size = meta_backend_native_update_screen_size;
+  backend_class->set_numlock = meta_backend_native_set_numlock;
 }
 
 static void
diff --git a/src/backends/x11/meta-backend-x11.c b/src/backends/x11/meta-backend-x11.c
index c9a6b9a..a0b196e 100644
--- a/src/backends/x11/meta-backend-x11.c
+++ b/src/backends/x11/meta-backend-x11.c
@@ -806,6 +806,14 @@ meta_backend_x11_lock_layout_group (MetaBackend *backend,
 }
 
 static void
+meta_backend_x11_set_numlock (MetaBackend *backend,
+                              gboolean     numlock_state)
+{
+  /* TODO: Currently handled by gnome-settings-deamon */
+}
+
+
+static void
 meta_backend_x11_update_screen_size (MetaBackend *backend,
                                      int width, int height)
 {
@@ -897,6 +905,7 @@ meta_backend_x11_class_init (MetaBackendX11Class *klass)
   backend_class->lock_layout_group = meta_backend_x11_lock_layout_group;
   backend_class->update_screen_size = meta_backend_x11_update_screen_size;
   backend_class->select_stage_events = meta_backend_x11_select_stage_events;
+  backend_class->set_numlock = meta_backend_x11_set_numlock;
 }
 
 static void
diff --git a/src/meta/meta-backend.h b/src/meta/meta-backend.h
index c50429a..fad8f55 100644
--- a/src/meta/meta-backend.h
+++ b/src/meta/meta-backend.h
@@ -44,6 +44,9 @@ void meta_backend_set_keymap (MetaBackend *backend,
 void meta_backend_lock_layout_group (MetaBackend *backend,
                                      guint        idx);
 
+void meta_backend_set_numlock (MetaBackend *backend,
+                               gboolean     numlock_state);
+
 ClutterActor *meta_backend_get_stage (MetaBackend *backend);
 
 void meta_clutter_init (void);
diff --git a/src/wayland/meta-wayland-keyboard.c b/src/wayland/meta-wayland-keyboard.c
index d505783..7f267b1 100644
--- a/src/wayland/meta-wayland-keyboard.c
+++ b/src/wayland/meta-wayland-keyboard.c
@@ -65,9 +65,19 @@
 #include "backends/native/meta-backend-native.h"
 #endif
 
+#define GSD_KEYBOARD_SCHEMA "org.gnome.settings-daemon.peripherals.keyboard"
+typedef enum
+{
+  GSD_KEYBOARD_NUM_LOCK_STATE_UNKNOWN,
+  GSD_KEYBOARD_NUM_LOCK_STATE_ON,
+  GSD_KEYBOARD_NUM_LOCK_STATE_OFF
+} GsdKeyboardNumLockState;
+
 G_DEFINE_TYPE (MetaWaylandKeyboard, meta_wayland_keyboard, G_TYPE_OBJECT);
 
 static void meta_wayland_keyboard_update_xkb_state (MetaWaylandKeyboard *keyboard);
+static void meta_wayland_keyboard_set_numlock (MetaWaylandKeyboard *keyboard,
+                                               gboolean             numlock_state);
 static void notify_modifiers (MetaWaylandKeyboard *keyboard);
 static guint evdev_code (const ClutterKeyEvent *event);
 
@@ -362,6 +372,107 @@ notify_modifiers (MetaWaylandKeyboard *keyboard)
 }
 
 static void
+numlock_set_xkb_state (MetaWaylandKeyboard    *keyboard,
+                       GsdKeyboardNumLockState state)
+{
+  MetaBackend *backend = meta_get_backend ();
+  gboolean numlock_state;
+
+  if (state != GSD_KEYBOARD_NUM_LOCK_STATE_ON &&
+      state != GSD_KEYBOARD_NUM_LOCK_STATE_OFF)
+    return;
+
+  numlock_state = (state == GSD_KEYBOARD_NUM_LOCK_STATE_ON);
+  meta_verbose ("set numlock state %s\n", (numlock_state ? "ON" : "OFF"));
+  meta_backend_set_numlock (backend, numlock_state);
+  meta_wayland_keyboard_set_numlock (keyboard, numlock_state);
+}
+
+static void
+maybe_restore_numlock_state (MetaWaylandKeyboard *keyboard)
+{
+  gboolean remember_numlock;
+
+  if (!keyboard->gsd_settings)
+    return;
+
+  /* We are cheating for now, we use g-s-d settings... */
+  remember_numlock = g_settings_get_boolean (keyboard->gsd_settings,
+                                             "remember-numlock-state");
+
+  if (remember_numlock)
+    {
+      GsdKeyboardNumLockState state;
+
+      state = g_settings_get_enum (keyboard->gsd_settings, "numlock-state");
+      numlock_set_xkb_state (keyboard, state);
+    }
+}
+
+static void
+maybe_save_numlock_state (MetaWaylandKeyboard *keyboard)
+{
+  MetaWaylandXkbInfo *xkb_info = &keyboard->xkb_info;
+  GDesktopKeyboardNumLockState numlock_state;
+  int numlock_active;
+
+  if (!META_IS_BACKEND_NATIVE (meta_get_backend ()))
+    return;
+
+  if (!xkb_info->state)
+    return;
+
+  if (!keyboard->gsd_settings)
+    return;
+
+  if (!g_settings_get_boolean (keyboard->gsd_settings, "remember-numlock-state"))
+    return;
+
+  numlock_active = xkb_state_mod_name_is_active(xkb_info->state,
+                                                "Mod2",
+                                                XKB_STATE_MODS_LOCKED);
+  switch (numlock_active)
+    {
+    case -1:
+      numlock_state = GSD_KEYBOARD_NUM_LOCK_STATE_UNKNOWN;
+      break;
+    case 0:
+      numlock_state = GSD_KEYBOARD_NUM_LOCK_STATE_OFF;
+      break;
+    default:
+      numlock_state = GSD_KEYBOARD_NUM_LOCK_STATE_ON;
+      break;
+    }
+  g_settings_set_enum (keyboard->gsd_settings, "numlock-state", numlock_state);
+}
+
+static void
+meta_wayland_keyboard_set_numlock (MetaWaylandKeyboard *keyboard,
+                                   gboolean     numlock_state)
+{
+  MetaWaylandXkbInfo *xkb_info = &keyboard->xkb_info;
+  xkb_mod_mask_t latched, locked, group, depressed;
+  xkb_mod_mask_t numlock;
+
+  meta_verbose ("backend numlock state %s\n", (numlock_state ? "ON" : "OFF"));
+
+  latched = xkb_state_serialize_mods (xkb_info->state, XKB_STATE_MODS_LATCHED);
+  locked = xkb_state_serialize_mods (xkb_info->state, XKB_STATE_MODS_LOCKED);
+  group = xkb_state_serialize_layout (xkb_info->state, XKB_STATE_LAYOUT_EFFECTIVE);
+  depressed = xkb_state_serialize_mods(xkb_info->state, XKB_STATE_DEPRESSED);
+  numlock = (1 <<  xkb_keymap_mod_get_index(xkb_info->keymap, "Mod2"));
+
+  if (numlock_state == TRUE)
+    locked |= numlock;
+  else
+    locked &= ~numlock;
+
+  xkb_state_update_mask (xkb_info->state, depressed, latched, locked, 0, 0, group);
+
+  notify_modifiers (keyboard);
+}
+
+static void
 meta_wayland_keyboard_update_xkb_state (MetaWaylandKeyboard *keyboard)
 {
   MetaWaylandXkbInfo *xkb_info = &keyboard->xkb_info;
@@ -431,6 +542,16 @@ notify_key_repeat (MetaWaylandKeyboard *keyboard)
 }
 
 static void
+remember_numlock_state_changed (GSettings  *settings,
+                                const char *key,
+                                gpointer    data)
+{
+  MetaWaylandKeyboard *keyboard = data;
+
+  maybe_save_numlock_state (keyboard);
+}
+
+static void
 settings_changed (GSettings           *settings,
                   const char          *key,
                   gpointer             data)
@@ -484,6 +605,7 @@ meta_wayland_keyboard_enable (MetaWaylandKeyboard *keyboard,
                               MetaWaylandSeat     *seat)
 {
   MetaBackend *backend = meta_get_backend ();
+  GSettingsSchema *schema;
 
   keyboard->seat = seat;
 
@@ -502,11 +624,25 @@ meta_wayland_keyboard_enable (MetaWaylandKeyboard *keyboard,
   g_signal_connect (keyboard->settings, "changed",
                     G_CALLBACK (settings_changed), keyboard);
 
+  /* We are cheating for now, we use g-s-d settings... Check if available */
+  schema = g_settings_schema_source_lookup (g_settings_schema_source_get_default (),
+                                            GSD_KEYBOARD_SCHEMA,
+                                            TRUE);
+  if (schema)
+    {
+      keyboard->gsd_settings = g_settings_new_full (schema, NULL, NULL);
+      g_settings_schema_unref (schema);
+      g_signal_connect (keyboard->gsd_settings, "changed::remember-numlock-state",
+                        G_CALLBACK (remember_numlock_state_changed), keyboard);
+    }
+
   g_signal_connect (backend, "keymap-changed",
                     G_CALLBACK (on_keymap_changed), keyboard);
   g_signal_connect (backend, "keymap-layout-group-changed",
                     G_CALLBACK (on_keymap_layout_group_changed), keyboard);
   meta_wayland_keyboard_take_keymap (keyboard, meta_backend_get_keymap (backend));
+
+  maybe_restore_numlock_state (keyboard);
 }
 
 static void
@@ -538,6 +674,8 @@ meta_wayland_keyboard_disable (MetaWaylandKeyboard *keyboard)
   /* XXX: What about keyboard->resource_list? */
 
   g_clear_object (&keyboard->settings);
+  if (keyboard->gsd_settings)
+    g_object_unref (keyboard->gsd_settings);
 
   keyboard->seat = NULL;
 }
@@ -593,6 +731,8 @@ meta_wayland_keyboard_handle_event (MetaWaylandKeyboard *keyboard,
 
   if (keyboard->mods_changed != 0)
     {
+      if (keyboard->mods_changed & XKB_STATE_MODS_LOCKED)
+        maybe_save_numlock_state (keyboard);
       notify_modifiers (keyboard);
       keyboard->mods_changed = 0;
     }
diff --git a/src/wayland/meta-wayland-keyboard.h b/src/wayland/meta-wayland-keyboard.h
index 5f7d15c..5e7d84b 100644
--- a/src/wayland/meta-wayland-keyboard.h
+++ b/src/wayland/meta-wayland-keyboard.h
@@ -100,6 +100,7 @@ struct _MetaWaylandKeyboard
   MetaWaylandKeyboardGrab default_grab;
 
   GSettings *settings;
+  GSettings *gsd_settings;
 };
 
 void meta_wayland_keyboard_enable (MetaWaylandKeyboard *keyboard,


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