[caribou] Track XKB group configuration change



commit f037563b9e99cc831b16d8f4821743dcdcafc2bd
Author: Daiki Ueno <ueno unixuser org>
Date:   Sun Feb 17 17:22:22 2013 +0900

    Track XKB group configuration change
    
    Since GNOME 3.6, switching XKB layouts changes the group
    configuration, while libcaribou assumes that the configuration is
    fixed during the session.
    
    This patch tries to track group configuration changes and allow
    clients to reconstruct keyboard UI through two new signals:
    KeyboardModel::group-added and KeyboardModel::group-removed.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=694011

 libcaribou/keyboard-model.vala |   52 +++++++++++++++++++++++++++++----------
 libcaribou/xadapter.vala       |    6 ++++
 2 files changed, 44 insertions(+), 14 deletions(-)
---
diff --git a/libcaribou/keyboard-model.vala b/libcaribou/keyboard-model.vala
index 785a668..be00b5c 100644
--- a/libcaribou/keyboard-model.vala
+++ b/libcaribou/keyboard-model.vala
@@ -15,39 +15,63 @@ namespace Caribou {
         private KeyModel last_activated_key;
         private Gee.HashSet<KeyModel> active_mod_keys;
 
-        construct {
-            uint grpid;
-            string group, variant;
-            string[] grps, variants;
-            int i;
+        public signal void group_added (string name);
+        public signal void group_removed (string name);
 
+        construct {
             assert (keyboard_type != null);
 
             xadapter = XAdapter.get_default ();
             xadapter.group_changed.connect (on_group_changed);
+            xadapter.config_changed.connect (on_config_changed);
+
+            groups = new Gee.HashMap<string, GroupModel> ();
+            on_config_changed ();
 
+            active_mod_keys = new Gee.HashSet<KeyModel> ();
+        }
+
+        private void on_config_changed () {
+            string[] grps, variants;
             xadapter.get_groups (out grps, out variants);
 
-            groups = new Gee.HashMap<string, GroupModel> ();
+            var group_names = new Gee.HashSet<string> ();
+            for (var i = 0; i < grps.length; i++) {
+                var group_name = GroupModel.create_group_name (grps[i],
+                                                               variants[i]);
+                group_names.add (group_name);
+                if (!groups.has_key (group_name)) {
+                    var grp = populate_group (grps[i], variants[i]);
+                    if (grp != null) {
+                        groups.set (group_name, grp);
+                        group_added (group_name);
+                    }
+                }
+            }
 
-            for (i=0;i<grps.length;i++)
-                populate_group (grps[i], variants[i]);
+            var iter = groups.map_iterator ();
+            while (iter.next ()) {
+                var group_name = iter.get_key ();
+                if (!group_names.contains (group_name)) {
+                    iter.unset ();
+                    group_removed (group_name);
+                }
+            }
 
-            grpid = xadapter.get_current_group (out group, out variant);
+            string group, variant;
+            var grpid = xadapter.get_current_group (out group, out variant);
             on_group_changed (grpid, group, variant);
-
-            active_mod_keys = new Gee.HashSet<KeyModel> ();
         }
 
-        private void populate_group (string group, string variant) {
+        private GroupModel? populate_group (string group, string variant) {
             GroupModel grp = XmlDeserializer.load_group (keyboard_type,
-                                                          group, variant);
+                                                         group, variant);
             if (grp != null) {
-                groups.set (GroupModel.create_group_name (group, variant), grp);
                 grp.key_clicked.connect (on_key_clicked);
                 grp.key_pressed.connect (on_key_pressed);
                 grp.key_released.connect (on_key_released);
             }
+            return grp;
         }
 
         private void on_key_clicked (KeyModel key) {
diff --git a/libcaribou/xadapter.vala b/libcaribou/xadapter.vala
index 49aeb68..dbc34f9 100644
--- a/libcaribou/xadapter.vala
+++ b/libcaribou/xadapter.vala
@@ -7,6 +7,7 @@ namespace Caribou {
         /* Signals */
         public signal void modifiers_changed (uint modifiers);
         public signal void group_changed (uint gid, string group, string variant);
+        public signal void config_changed ();
 
         /* Private properties */
         static XAdapter instance;
@@ -47,6 +48,7 @@ namespace Caribou {
             xkl_state = this.xkl_engine.get_current_state ();
             this.group = (uchar) xkl_state.group;
             xkl_engine.X_state_changed.connect_after (xkl_state_changed);
+            xkl_engine.X_config_changed.connect_after (xkl_config_changed);
 
             Xkb.get_state (this.xdisplay, Xkb.UseCoreKbd, out xkb_state);
             this.modifiers = xkb_state.mods;
@@ -137,6 +139,10 @@ namespace Caribou {
             group_changed (this.group, group_name, variant_name);
         }
 
+        private void xkl_config_changed () {
+            config_changed ();
+        }
+
         private uchar keysym_to_modifier (uint keyval) {
             for (int i = xkbdesc.min_key_code; i <= xkbdesc.max_key_code; i++) {
                 unowned Xkb.SymMap symmap = xkbdesc.map.key_sym_map[i];


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