summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaiki Ueno <ueno@unixuser.org>2012-10-28 10:45:31 +0900
committerDaiki Ueno <ueno@unixuser.org>2012-10-30 14:34:26 +0900
commit0e34f29f73c80034882db6547f99313f6a29ad65 (patch)
treea0c2818d96dadf6b4c4f4df79b6558d549d5707f
parente39364ba5a8930ade20af80ad30aba69ea9398cd (diff)
downloadcaribou-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
-rw-r--r--libcaribou/external-libs.vapi5
-rw-r--r--libcaribou/xadapter.vala32
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) {