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 <WINGs/WINGsP.h>
40 #include "WindowMaker.h"
41 #include "xmodifier.h"
44 /************************************************************************/
46 /************************************************************************/
48 /* X bogusly doesn't define the interpretations of any bits besides
49 ModControl, ModShift, and ModLock; so the Interclient Communication
50 Conventions Manual says that we have to bend over backwards to figure
51 out what the other modifier bits mean. According to ICCCM:
53 - Any keycode which is assigned ModControl is a "control" key.
55 - Any modifier bit which is assigned to a keycode which generates Meta_L
56 or Meta_R is the modifier bit meaning "meta". Likewise for Super, Hyper,
59 - Any keypress event which contains ModControl in its state should be
60 interpreted as a "control" character.
62 - Any keypress event which contains a modifier bit in its state which is
63 generated by a keycode whose corresponding keysym is Meta_L or Meta_R
64 should be interpreted as a "meta" character. Likewise for Super, Hyper,
67 - It is illegal for a keysym to be associated with more than one modifier
70 This means that the only thing that emacs can reasonably interpret as a
71 "meta" key is a key whose keysym is Meta_L or Meta_R, and which generates
72 one of the modifier bits Mod1-Mod5.
74 Unfortunately, many keyboards don't have Meta keys in their default
75 configuration. So, if there are no Meta keys, but there are "Alt" keys,
76 emacs will interpret Alt as Meta. If there are both Meta and Alt keys,
77 then the Meta keys mean "Meta", and the Alt keys mean "Alt" (it used to
78 mean "Symbol," but that just confused the hell out of way too many people).
80 This works with the default configurations of the 19 keyboard-types I've
83 Emacs detects keyboard configurations which violate the above rules, and
84 prints an error message on the standard-error-output. (Perhaps it should
85 use a pop-up-window instead.)
88 static int MetaMask
, HyperMask
, SuperMask
, AltMask
, ModeMask
;
90 static const char *index_to_name(int indice
)
114 static void x_reset_modifier_mapping(Display
* display
)
116 int modifier_index
, modifier_key
, column
, mkpm
;
122 XModifierKeymap
*x_modifier_keymap
= XGetModifierMapping(display
);
124 mkpm
= x_modifier_keymap
->max_keypermod
;
125 for (modifier_index
= 0; modifier_index
< 8; modifier_index
++)
126 for (modifier_key
= 0; modifier_key
< mkpm
; modifier_key
++) {
129 for (column
= 0; column
< 4; column
+= 2) {
133 inline void modwarn(const char *key_name
, int old_mod
, const char *other_key
)
135 wwarning(_("key %s (0x%x) generates %s, which is generated by %s"),
136 key_name
, code
, index_to_name(old_mod
), other_key
);
139 inline void modbarf(const char *key_name
, const char *other_mod
)
141 wwarning(_("key %s (0x%x) generates %s, which is nonsensical"),
142 key_name
, code
, other_mod
);
145 inline void check_modifier(const char *key_name
, int mask
)
147 if ((1 << modifier_index
) != mask
)
148 modbarf(key_name
, index_to_name(modifier_index
));
151 inline void store_modifier(const char *key_name
, int *old_mod
)
153 if (*old_mod
&& *old_mod
!= modifier_index
)
154 wwarning(_("key %s (0x%x) generates both %s and %s, which is nonsensical"),
155 key_name
, code
, index_to_name(*old_mod
), index_to_name(modifier_index
));
156 if (modifier_index
== ShiftMapIndex
) {
157 modbarf(key_name
, "ModShift");
158 } else if (modifier_index
== LockMapIndex
) {
159 modbarf(key_name
, "ModLock");
160 } else if (modifier_index
== ControlMapIndex
) {
161 modbarf(key_name
, "ModControl");
162 } else if (sym
== XK_Mode_switch
) {
163 mode_bit
= modifier_index
; /* Mode_switch is special, see below... */
164 } else if (modifier_index
== meta_bit
&& *old_mod
!= meta_bit
) {
165 modwarn(key_name
, meta_bit
, "Meta");
166 } else if (modifier_index
== super_bit
&& *old_mod
!= super_bit
) {
167 modwarn(key_name
, super_bit
, "Super");
168 } else if (modifier_index
== hyper_bit
&& *old_mod
!= hyper_bit
) {
169 modwarn(key_name
, hyper_bit
, "Hyper");
170 } else if (modifier_index
== alt_bit
&& *old_mod
!= alt_bit
) {
171 modwarn(key_name
, alt_bit
, "Alt");
173 *(old_mod
) = modifier_index
;
177 code
= x_modifier_keymap
->modifiermap
[modifier_index
* mkpm
+ modifier_key
];
178 sym
= W_KeycodeToKeysym(display
, code
, column
);
186 store_modifier("Mode_switch", &mode_bit
);
189 store_modifier("Meta_L", &meta_bit
);
192 store_modifier("Meta_R", &meta_bit
);
195 store_modifier("Super_L", &super_bit
);
198 store_modifier("Super_R", &super_bit
);
201 store_modifier("Hyper_L", &hyper_bit
);
204 store_modifier("Hyper_R", &hyper_bit
);
207 store_modifier("Alt_L", &alt_bit
);
210 store_modifier("Alt_R", &alt_bit
);
213 check_modifier("Control_L", ControlMask
);
216 check_modifier("Control_R", ControlMask
);
219 check_modifier("Shift_L", ShiftMask
);
222 check_modifier("Shift_R", ShiftMask
);
225 check_modifier("Shift_Lock", LockMask
);
228 check_modifier("Caps_Lock", LockMask
);
231 /* It probably doesn't make any sense for a modifier bit to be
232 assigned to a key that is not one of the above, but OpenWindows
233 assigns modifier bits to a couple of random function keys for
234 no reason that I can discern, so printing a warning here would
240 /* If there was no Meta key, then try using the Alt key instead.
241 If there is both a Meta key and an Alt key, then the Alt key
242 is not disturbed and remains an Alt key. */
243 if (!meta_bit
&& alt_bit
)
244 meta_bit
= alt_bit
, alt_bit
= 0;
246 /* mode_bit overrides everything, since it's processed down inside of
247 XLookupString() instead of by us. If Meta and Mode_switch both
248 generate the same modifier bit (which is an error), then we don't
249 interpret that bit as Meta, because we can't make XLookupString()
250 not interpret it as Mode_switch; and interpreting it as both would
253 const char *warn
= NULL
;
255 if (mode_bit
== meta_bit
)
256 warn
= "Meta", meta_bit
= 0;
257 else if (mode_bit
== hyper_bit
)
258 warn
= "Hyper", hyper_bit
= 0;
259 else if (mode_bit
== super_bit
)
260 warn
= "Super", super_bit
= 0;
261 else if (mode_bit
== alt_bit
)
262 warn
= "Alt", alt_bit
= 0;
264 wwarning("%s is being used for both Mode_switch and %s.",
265 index_to_name(mode_bit
), warn
);
269 MetaMask
= (meta_bit
? (1 << meta_bit
) : 0);
270 HyperMask
= (hyper_bit
? (1 << hyper_bit
) : 0);
271 SuperMask
= (super_bit
? (1 << super_bit
) : 0);
272 AltMask
= (alt_bit
? (1 << alt_bit
) : 0);
273 ModeMask
= (mode_bit
? (1 << mode_bit
) : 0); /* unused */
275 XFreeModifiermap(x_modifier_keymap
);
278 const char *wXModifierToShortcutLabel(int mask
)
283 if (mask
== ShiftMask
)
285 if (mask
== ControlMask
)
289 if (mask
== Mod1Mask
)
291 if (mask
== Mod2Mask
)
293 if (mask
== Mod3Mask
)
295 if (mask
== Mod4Mask
)
297 if (mask
== Mod5Mask
)
299 if (mask
== MetaMask
)
302 wwarning(_("Can't convert keymask 0x%04X to a shortcut label"), mask
);
306 int wXModifierFromKey(const char *key
)
308 if (strcasecmp(key
, "SHIFT") == 0 && ShiftMask
!= 0)
310 else if (strcasecmp(key
, "CONTROL") == 0 && ControlMask
!= 0)
312 else if (strcasecmp(key
, "ALT") == 0 && AltMask
!= 0)
314 else if (strcasecmp(key
, "META") == 0 && MetaMask
!= 0)
316 else if (strcasecmp(key
, "SUPER") == 0 && SuperMask
!= 0)
318 else if (strcasecmp(key
, "HYPER") == 0 && HyperMask
!= 0)
320 else if (strcasecmp(key
, "MOD1") == 0 && Mod1Mask
!= 0)
322 else if (strcasecmp(key
, "MOD2") == 0 && Mod2Mask
!= 0)
324 else if (strcasecmp(key
, "MOD3") == 0 && Mod3Mask
!= 0)
326 else if (strcasecmp(key
, "MOD4") == 0 && Mod4Mask
!= 0)
328 else if (strcasecmp(key
, "MOD5") == 0 && Mod5Mask
!= 0)
334 /* Wrapper so that we may fit the WM naming conventions, yet leave the
335 original XEmacs function name in place. */
336 void wXModifierInitialize(void)
338 x_reset_modifier_mapping(dpy
);