1 /* Grok X modifier mappings for shortcuts.
3 Most of this code was taken from src/event-Xt.c in XEmacs 20.3-b17.
4 The copyright(s) from the original XEmacs code are included below.
6 Perpetrator: Sudish Joseph <sj@eng.mindspring.net>, Sept. 1997. */
8 /* The event_stream interface for X11 with Xt, and/or tty frames.
9 Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
10 Copyright (C) 1995 Sun Microsystems, Inc.
11 Copyright (C) 1996 Ben Wing.
13 This file is part of XEmacs.
15 XEmacs is free software; you can redistribute it and/or modify it
16 under the terms of the GNU General Public License as published by the
17 Free Software Foundation; either version 2, or (at your option) any
20 XEmacs is distributed in the hope that it will be useful, but WITHOUT
21 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
22 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25 You should have received a copy of the GNU General Public License along
26 with XEmacs; see the file COPYING. if not, write to the
27 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
28 Boston, MA 02110-1301 USA. */
35 #include <X11/keysym.h>
36 #include <X11/XKBlib.h>
38 #include <WINGs/WUtil.h>
39 #include "WindowMaker.h"
40 #include "xmodifier.h"
43 /************************************************************************/
45 /************************************************************************/
47 /* X bogusly doesn't define the interpretations of any bits besides
48 ModControl, ModShift, and ModLock; so the Interclient Communication
49 Conventions Manual says that we have to bend over backwards to figure
50 out what the other modifier bits mean. According to ICCCM:
52 - Any keycode which is assigned ModControl is a "control" key.
54 - Any modifier bit which is assigned to a keycode which generates Meta_L
55 or Meta_R is the modifier bit meaning "meta". Likewise for Super, Hyper,
58 - Any keypress event which contains ModControl in its state should be
59 interpreted as a "control" character.
61 - Any keypress event which contains a modifier bit in its state which is
62 generated by a keycode whose corresponding keysym is Meta_L or Meta_R
63 should be interpreted as a "meta" character. Likewise for Super, Hyper,
66 - It is illegal for a keysym to be associated with more than one modifier
69 This means that the only thing that emacs can reasonably interpret as a
70 "meta" key is a key whose keysym is Meta_L or Meta_R, and which generates
71 one of the modifier bits Mod1-Mod5.
73 Unfortunately, many keyboards don't have Meta keys in their default
74 configuration. So, if there are no Meta keys, but there are "Alt" keys,
75 emacs will interpret Alt as Meta. If there are both Meta and Alt keys,
76 then the Meta keys mean "Meta", and the Alt keys mean "Alt" (it used to
77 mean "Symbol," but that just confused the hell out of way too many people).
79 This works with the default configurations of the 19 keyboard-types I've
82 Emacs detects keyboard configurations which violate the above rules, and
83 prints an error message on the standard-error-output. (Perhaps it should
84 use a pop-up-window instead.)
87 static int MetaMask
, HyperMask
, SuperMask
, AltMask
, ModeMask
;
89 static const char *index_to_name(int indice
)
113 static void x_reset_modifier_mapping(Display
* display
)
115 int modifier_index
, modifier_key
, column
, mkpm
;
121 XModifierKeymap
*x_modifier_keymap
= XGetModifierMapping(display
);
123 mkpm
= x_modifier_keymap
->max_keypermod
;
124 for (modifier_index
= 0; modifier_index
< 8; modifier_index
++)
125 for (modifier_key
= 0; modifier_key
< mkpm
; modifier_key
++) {
128 for (column
= 0; column
< 4; column
+= 2) {
132 inline void modwarn(const char *key_name
, int old_mod
, const char *other_key
)
134 wwarning(_("key %s (0x%x) generates %s, which is generated by %s"),
135 key_name
, code
, index_to_name(old_mod
), other_key
);
138 inline void modbarf(const char *key_name
, const char *other_mod
)
140 wwarning(_("key %s (0x%x) generates %s, which is nonsensical"),
141 key_name
, code
, other_mod
);
144 inline void check_modifier(const char *key_name
, int mask
)
146 if ((1 << modifier_index
) != mask
)
147 modbarf(key_name
, index_to_name(modifier_index
));
150 inline void store_modifier(const char *key_name
, int *old_mod
)
152 if (*old_mod
&& *old_mod
!= modifier_index
)
153 wwarning(_("key %s (0x%x) generates both %s and %s, which is nonsensical"),
154 key_name
, code
, index_to_name(*old_mod
), index_to_name(modifier_index
));
155 if (modifier_index
== ShiftMapIndex
) {
156 modbarf(key_name
, "ModShift");
157 } else if (modifier_index
== LockMapIndex
) {
158 modbarf(key_name
, "ModLock");
159 } else if (modifier_index
== ControlMapIndex
) {
160 modbarf(key_name
, "ModControl");
161 } else if (sym
== XK_Mode_switch
) {
162 mode_bit
= modifier_index
; /* Mode_switch is special, see below... */
163 } else if (modifier_index
== meta_bit
&& *old_mod
!= meta_bit
) {
164 modwarn(key_name
, meta_bit
, "Meta");
165 } else if (modifier_index
== super_bit
&& *old_mod
!= super_bit
) {
166 modwarn(key_name
, super_bit
, "Super");
167 } else if (modifier_index
== hyper_bit
&& *old_mod
!= hyper_bit
) {
168 modwarn(key_name
, hyper_bit
, "Hyper");
169 } else if (modifier_index
== alt_bit
&& *old_mod
!= alt_bit
) {
170 modwarn(key_name
, alt_bit
, "Alt");
172 *(old_mod
) = modifier_index
;
176 code
= x_modifier_keymap
->modifiermap
[modifier_index
* mkpm
+ modifier_key
];
177 sym
= (code
? XkbKeycodeToKeysym(display
, code
, 0, column
) : NoSymbol
);
185 store_modifier("Mode_switch", &mode_bit
);
188 store_modifier("Meta_L", &meta_bit
);
191 store_modifier("Meta_R", &meta_bit
);
194 store_modifier("Super_L", &super_bit
);
197 store_modifier("Super_R", &super_bit
);
200 store_modifier("Hyper_L", &hyper_bit
);
203 store_modifier("Hyper_R", &hyper_bit
);
206 store_modifier("Alt_L", &alt_bit
);
209 store_modifier("Alt_R", &alt_bit
);
212 check_modifier("Control_L", ControlMask
);
215 check_modifier("Control_R", ControlMask
);
218 check_modifier("Shift_L", ShiftMask
);
221 check_modifier("Shift_R", ShiftMask
);
224 check_modifier("Shift_Lock", LockMask
);
227 check_modifier("Caps_Lock", LockMask
);
230 /* It probably doesn't make any sense for a modifier bit to be
231 assigned to a key that is not one of the above, but OpenWindows
232 assigns modifier bits to a couple of random function keys for
233 no reason that I can discern, so printing a warning here would
239 /* If there was no Meta key, then try using the Alt key instead.
240 If there is both a Meta key and an Alt key, then the Alt key
241 is not disturbed and remains an Alt key. */
242 if (!meta_bit
&& alt_bit
)
243 meta_bit
= alt_bit
, alt_bit
= 0;
245 /* mode_bit overrides everything, since it's processed down inside of
246 XLookupString() instead of by us. If Meta and Mode_switch both
247 generate the same modifier bit (which is an error), then we don't
248 interpret that bit as Meta, because we can't make XLookupString()
249 not interpret it as Mode_switch; and interpreting it as both would
252 const char *warn
= NULL
;
254 if (mode_bit
== meta_bit
)
255 warn
= "Meta", meta_bit
= 0;
256 else if (mode_bit
== hyper_bit
)
257 warn
= "Hyper", hyper_bit
= 0;
258 else if (mode_bit
== super_bit
)
259 warn
= "Super", super_bit
= 0;
260 else if (mode_bit
== alt_bit
)
261 warn
= "Alt", alt_bit
= 0;
263 wwarning("%s is being used for both Mode_switch and %s.",
264 index_to_name(mode_bit
), warn
);
268 MetaMask
= (meta_bit
? (1 << meta_bit
) : 0);
269 HyperMask
= (hyper_bit
? (1 << hyper_bit
) : 0);
270 SuperMask
= (super_bit
? (1 << super_bit
) : 0);
271 AltMask
= (alt_bit
? (1 << alt_bit
) : 0);
272 ModeMask
= (mode_bit
? (1 << mode_bit
) : 0); /* unused */
274 XFreeModifiermap(x_modifier_keymap
);
277 const char *wXModifierToShortcutLabel(int mask
)
282 if (mask
== ShiftMask
)
284 if (mask
== ControlMask
)
288 if (mask
== Mod1Mask
)
290 if (mask
== Mod2Mask
)
292 if (mask
== Mod3Mask
)
294 if (mask
== Mod4Mask
)
296 if (mask
== Mod5Mask
)
298 if (mask
== MetaMask
)
301 wwarning(_("Can't convert keymask 0x%04X to a shortcut label"), mask
);
305 int wXModifierFromKey(const char *key
)
307 if (strcasecmp(key
, "SHIFT") == 0 && ShiftMask
!= 0)
309 else if (strcasecmp(key
, "CONTROL") == 0 && ControlMask
!= 0)
311 else if (strcasecmp(key
, "ALT") == 0 && AltMask
!= 0)
313 else if (strcasecmp(key
, "META") == 0 && MetaMask
!= 0)
315 else if (strcasecmp(key
, "SUPER") == 0 && SuperMask
!= 0)
317 else if (strcasecmp(key
, "HYPER") == 0 && HyperMask
!= 0)
319 else if (strcasecmp(key
, "MOD1") == 0 && Mod1Mask
!= 0)
321 else if (strcasecmp(key
, "MOD2") == 0 && Mod2Mask
!= 0)
323 else if (strcasecmp(key
, "MOD3") == 0 && Mod3Mask
!= 0)
325 else if (strcasecmp(key
, "MOD4") == 0 && Mod4Mask
!= 0)
327 else if (strcasecmp(key
, "MOD5") == 0 && Mod5Mask
!= 0)
333 /* Wrapper so that we may fit the WM naming conventions, yet leave the
334 original XEmacs function name in place. */
335 void wXModifierInitialize(void)
337 x_reset_modifier_mapping(dpy
);