static MappedKeys MapKeys(Gdk.EventKey evt) { MappedKeys mapped; ushort keycode = evt.HardwareKeycode; Gdk.ModifierType modifier = evt.State; byte grp = evt.Group; if (GtkMinorVersion >= 20) { gdk_keymap_add_virtual_modifiers(keymap.Handle, ref modifier); } //full key mapping uint keyval; int effectiveGroup, level; Gdk.ModifierType consumedModifiers; TranslateKeyboardState(keycode, modifier, grp, out keyval, out effectiveGroup, out level, out consumedModifiers); mapped.Key = (Gdk.Key)keyval; mapped.State = FixMacModifiers(evt.State & ~consumedModifiers, grp); //decompose the key into accel combinations var accelList = new List <KeyboardShortcut> (); const Gdk.ModifierType accelMods = Gdk.ModifierType.ShiftMask | Gdk.ModifierType.Mod1Mask | Gdk.ModifierType.ControlMask | Gdk.ModifierType.SuperMask | Gdk.ModifierType.MetaMask; //all accels ignore the lock key modifier &= ~Gdk.ModifierType.LockMask; //fully decomposed TranslateKeyboardState(evt.HardwareKeycode, Gdk.ModifierType.None, 0, out keyval, out effectiveGroup, out level, out consumedModifiers); accelList.Add(new KeyboardShortcut((Gdk.Key)keyval, FixMacModifiers(modifier, grp) & accelMods)); //with shift composed if ((modifier & Gdk.ModifierType.ShiftMask) != 0) { keymap.TranslateKeyboardState(evt.HardwareKeycode, Gdk.ModifierType.ShiftMask, 0, out keyval, out effectiveGroup, out level, out consumedModifiers); var m = FixMacModifiers((modifier & ~consumedModifiers), grp) & accelMods; AddIfNotDuplicate(accelList, new KeyboardShortcut((Gdk.Key)keyval, m)); } //with group 1 composed if (grp == 1) { TranslateKeyboardState(evt.HardwareKeycode, modifier & ~Gdk.ModifierType.ShiftMask, 1, out keyval, out effectiveGroup, out level, out consumedModifiers); //somehow GTK on mac manages to consume a shift that we don't even pass to it if (oldMacKeyHacks) { consumedModifiers &= ~Gdk.ModifierType.ShiftMask; } var m = FixMacModifiers((modifier & ~consumedModifiers), 0) & accelMods; AddIfNotDuplicate(accelList, new KeyboardShortcut((Gdk.Key)keyval, m)); } //with group 1 and shift composed if (grp == 1 && (modifier & Gdk.ModifierType.ShiftMask) != 0) { TranslateKeyboardState(evt.HardwareKeycode, modifier, 1, out keyval, out effectiveGroup, out level, out consumedModifiers); var m = FixMacModifiers((modifier & ~consumedModifiers), 0) & accelMods; AddIfNotDuplicate(accelList, new KeyboardShortcut((Gdk.Key)keyval, m)); } //and also allow the fully mapped key as an accel AddIfNotDuplicate(accelList, new KeyboardShortcut(mapped.Key, mapped.State & accelMods)); mapped.Accels = accelList.ToArray(); return(mapped); }
public static void MapRawKeys(Gdk.EventKey evt, out Gdk.Key key, out Gdk.ModifierType mod) { mod = evt.State; key = evt.Key; uint keyval; int effectiveGroup, level; Gdk.ModifierType consumedModifiers; keymap.TranslateKeyboardState(evt.HardwareKeycode, evt.State, evt.Group, out keyval, out effectiveGroup, out level, out consumedModifiers); key = (Gdk.Key)keyval; mod = evt.State & ~consumedModifiers; if (MainClass.Platform.IsX11) { //this is a workaround for a common X mapping issue //where the alt key is mapped to the meta key when the shift modifier is active if (key.Equals(Gdk.Key.Meta_L) || key.Equals(Gdk.Key.Meta_R)) { key = Gdk.Key.Alt_L; } } //HACK: the MAC GTK+ port currently does some horrible, un-GTK-ish key mappings // so we work around them by playing some tricks to remap and decompose modifiers. // We also decompose keys to the root physical key so that the Mac command // combinations appear as expected, e.g. shift-{ is treated as shift-[. if (MainClass.Platform.IsMac && !MainClass.Platform.IsX11) { // Mac GTK+ maps the command key to the Mod1 modifier, which usually means alt/ // We map this instead to meta, because the Mac GTK+ has mapped the cmd key // to the meta key (yay inconsistency!). IMO super would have been saner. if ((mod & Gdk.ModifierType.Mod1Mask) != 0) { mod ^= Gdk.ModifierType.Mod1Mask; mod |= Gdk.ModifierType.MetaMask; } // If Mod5 is active it *might* mean that opt/alt is active, // so we can unset this and map it back to the normal modifier. if ((mod & Gdk.ModifierType.Mod5Mask) != 0) { mod ^= Gdk.ModifierType.Mod5Mask; mod |= Gdk.ModifierType.Mod1Mask; } // When opt modifier is active, we need to decompose this to make the command appear correct for Mac. // In addition, we can only inspect whether the opt/alt key is pressed by examining // the key's "group", because the Mac GTK+ treats opt as a group modifier and does // not expose it as an actual GDK modifier. if (evt.Group == (byte)1) { mod |= Gdk.ModifierType.Mod1Mask; key = GetGroupZeroKey(key, evt); } } //fix shift-tab weirdness. There isn't a nice name for untab, so make it shift-tab if (key == Gdk.Key.ISO_Left_Tab) { key = Gdk.Key.Tab; mod |= Gdk.ModifierType.ShiftMask; } }
static MappedKeys MapKeys(Gdk.EventKey evt) { MappedKeys mapped; ushort keycode = evt.HardwareKeycode; Gdk.ModifierType modifier = evt.State; byte grp = evt.Group; if (GtkMinorVersion >= 20) { gdk_keymap_add_virtual_modifiers(keymap.Handle, ref modifier); } // Workaround for bug "Bug 688247 - Ctrl+Alt key not work on windows7 with bootcamp on a Mac Book Pro" // Ctrl+Alt should behave like right alt key - unfortunately TranslateKeyboardState doesn't handle it. if (Platform.IsWindows) { const Gdk.ModifierType ctrlAlt = Gdk.ModifierType.ControlMask | Gdk.ModifierType.Mod1Mask; if ((modifier & ctrlAlt) == ctrlAlt) { modifier = (modifier & ~ctrlAlt) | Gdk.ModifierType.Mod2Mask; grp = 1; } } //full key mapping uint keyval; int effectiveGroup, level; Gdk.ModifierType consumedModifiers; keymap.TranslateKeyboardState(keycode, modifier, grp, out keyval, out effectiveGroup, out level, out consumedModifiers); mapped.Key = (Gdk.Key)keyval; mapped.State = FixMacModifiers(evt.State & ~consumedModifiers, grp); //decompose the key into accel combinations var accelList = new List <KeyboardShortcut> (); const Gdk.ModifierType accelMods = Gdk.ModifierType.ShiftMask | Gdk.ModifierType.Mod1Mask | Gdk.ModifierType.ControlMask | Gdk.ModifierType.SuperMask | Gdk.ModifierType.MetaMask; //all accels ignore the lock key modifier &= ~Gdk.ModifierType.LockMask; //fully decomposed keymap.TranslateKeyboardState(evt.HardwareKeycode, Gdk.ModifierType.None, 0, out keyval, out effectiveGroup, out level, out consumedModifiers); accelList.Add(new KeyboardShortcut((Gdk.Key)keyval, FixMacModifiers(modifier, grp) & accelMods)); //with shift composed if ((modifier & Gdk.ModifierType.ShiftMask) != 0) { keymap.TranslateKeyboardState(evt.HardwareKeycode, Gdk.ModifierType.ShiftMask, 0, out keyval, out effectiveGroup, out level, out consumedModifiers); var m = FixMacModifiers((modifier & ~consumedModifiers), grp) & accelMods; AddIfNotDuplicate(accelList, new KeyboardShortcut((Gdk.Key)keyval, m)); } //with group 1 composed if (grp == 1) { keymap.TranslateKeyboardState(evt.HardwareKeycode, modifier & ~Gdk.ModifierType.ShiftMask, 1, out keyval, out effectiveGroup, out level, out consumedModifiers); //somehow GTK on mac manages to consume a shift that we don't even pass to it if (oldMacKeyHacks) { consumedModifiers &= ~Gdk.ModifierType.ShiftMask; } var m = FixMacModifiers((modifier & ~consumedModifiers), 0) & accelMods; AddIfNotDuplicate(accelList, new KeyboardShortcut((Gdk.Key)keyval, m)); } //with group 1 and shift composed if (grp == 1 && (modifier & Gdk.ModifierType.ShiftMask) != 0) { keymap.TranslateKeyboardState(evt.HardwareKeycode, modifier, 1, out keyval, out effectiveGroup, out level, out consumedModifiers); var m = FixMacModifiers((modifier & ~consumedModifiers), 0) & accelMods; AddIfNotDuplicate(accelList, new KeyboardShortcut((Gdk.Key)keyval, m)); } //and also allow the fully mapped key as an accel AddIfNotDuplicate(accelList, new KeyboardShortcut(mapped.Key, mapped.State & accelMods)); mapped.Accels = accelList.ToArray(); return(mapped); }