diff options
author | Daiki Ueno <ueno@unixuser.org> | 2012-10-28 10:45:31 +0900 |
---|---|---|
committer | Daiki Ueno <ueno@unixuser.org> | 2012-10-30 14:34:26 +0900 |
commit | 0e34f29f73c80034882db6547f99313f6a29ad65 (patch) | |
tree | a0c2818d96dadf6b4c4f4df79b6558d549d5707f /libcaribou | |
parent | e39364ba5a8930ade20af80ad30aba69ea9398cd (diff) | |
download | caribou-0e34f29f73c80034882db6547f99313f6a29ad65.tar.gz |
xadapter: use level3 shift if possible
Some international keyboards (such as Czech) assign more than two
keysyms to each key. Use level 3 shift modifier (so called AltGr) to
designate those keysyms and avoid needless keysym remapping.
https://bugzilla.gnome.org/show_bug.cgi?id=687018
Diffstat (limited to 'libcaribou')
-rw-r--r-- | libcaribou/external-libs.vapi | 5 | ||||
-rw-r--r-- | libcaribou/xadapter.vala | 32 |
2 files changed, 31 insertions, 6 deletions
diff --git a/libcaribou/external-libs.vapi b/libcaribou/external-libs.vapi index 930e582..1489216 100644 --- a/libcaribou/external-libs.vapi +++ b/libcaribou/external-libs.vapi @@ -78,8 +78,8 @@ namespace Xkb { public X.Display dpy; public ushort flags; public ushort device_spec; - public char min_key_code; - public char max_key_code; + public uchar min_key_code; + public uchar max_key_code; public Controls ctrls; public ServerMap server; public ClientMap map; @@ -149,6 +149,7 @@ namespace Xkb { [CCode (array_length = false, array_null_terminated = true)] public SymMap[] key_sym_map; + [CCode (array_length = false, array_null_terminated = true)] public uchar[] modmap; } diff --git a/libcaribou/xadapter.vala b/libcaribou/xadapter.vala index 8319313..38e9c8e 100644 --- a/libcaribou/xadapter.vala +++ b/libcaribou/xadapter.vala @@ -21,6 +21,7 @@ namespace Caribou { uchar reserved_keycode; uchar modifiers; uchar group; + uint[] level_switch_modifiers; public delegate void KeyButtonCallback (uint keybuttoncode, bool pressed); @@ -57,6 +58,16 @@ namespace Caribou { this.reserved_keycode = 0; + this.level_switch_modifiers = { + 0, + Gdk.ModifierType.SHIFT_MASK + }; + var lv3_mod = keysym_to_modifier (Gdk.Key.ISO_Level3_Shift); + if (lv3_mod != 0) { + level_switch_modifiers += lv3_mod; + level_switch_modifiers += Gdk.ModifierType.SHIFT_MASK | lv3_mod; + } + button_funcs = new HashTable<uint, KeyButtonHandler> (direct_hash, direct_equal); @@ -122,6 +133,18 @@ namespace Caribou { self.group_changed (self.group, group_name, variant_name); } + private uchar keysym_to_modifier (uint keyval) { + for (var i = xkbdesc.min_key_code; i <= xkbdesc.max_key_code; i++) { + unowned Xkb.SymMap symmap = xkbdesc.map.key_sym_map[i]; + for (var j = 0; + j < symmap.width * (symmap.group_info & 0x0f); + j++) + if (xkbdesc.map.syms[symmap.offset + j] == keyval) + return xkbdesc.map.modmap[i]; + } + return 0; + } + private uchar get_reserved_keycode () { uchar i; unowned Xkb.Desc xkbdesc = this.xkbdesc; @@ -196,16 +219,17 @@ namespace Caribou { Gdk.KeymapKey? best_match = null; foreach (KeymapKey km in kmk) - if (km.group == this.group && km.level <= 1) + if (km.group == this.group && + km.level < this.level_switch_modifiers.length) best_match = km; if (best_match == null) return false; - keycode = (uchar) best_match.keycode; - modmask = (best_match.level == 1) ? Gdk.ModifierType.SHIFT_MASK : 0; + keycode = (uchar) best_match.keycode; + modmask = this.level_switch_modifiers[best_match.level]; - return true; + return true; } private uchar keycode_for_keyval (uint keyval, out uint modmask) { |