[PATCH xmodmap] Add support for hyphen as placeholder for preserving a current keysym
Markus Kuhn
Markus.Kuhn at cl.cam.ac.uk
Thu Mar 6 07:11:19 PST 2014
So far, a keycode or keysym command always overwrote the entire list
of keysyms associated with a keycode. However, users often want to
modify only some of the keysyms in the list, e.g. only the keysyms
assigned when the Mode_switch key is pressed. With this patch, it is
now possible to reassign some symkeys without affecting others on the
same key, by listing a "-" where no change is requested.
Example:
Previously, if I wanted to have "twosuperior" (²) assigned to the key
"2" when Mode_shift is pressed, I had to write
xmodmap -e "keysym 2 = 2 quotedbl twosuperior NoSymbol"
on a UK keyboard, but
xmodmap -e "keysym 2 = 2 at twosuperior NoSymbol"
on a US keyboard, which is tedious where multiple layouts are used.
After this patch, the simpler command
xmodmap -e "keysym 2 = - - twosuperior NoSymbol"
will work on both UK and US keyboards alike.
---
handle.c | 43 ++++++++++++++++++++++++++++++++-----------
man/xmodmap.man | 2 ++
2 files changed, 34 insertions(+), 11 deletions(-)
diff --git a/handle.c b/handle.c
index 3f05a46..cc18c33 100644
--- a/handle.c
+++ b/handle.c
@@ -51,6 +51,8 @@ static XModifierKeymap *map = NULL;
struct wq work_queue = {NULL, NULL};
+/* placeholder for a KeySym that should not be changed */
+#define KeepSymbol ((KeySym) -1)
/*
* common utility routines
@@ -304,6 +306,10 @@ parse_keysym(const char *line, int n, char **name, KeySym *keysym)
*keysym = NoSymbol;
return (True);
}
+ if (!strcmp(*name, "-")) {
+ *keysym = KeepSymbol;
+ return (True);
+ }
*keysym = XStringToKeysym (*name);
if (*keysym == NoSymbol && '0' <= **name && **name <= '9')
return parse_number(*name, keysym);
@@ -1213,12 +1219,14 @@ execute_work_queue (void)
static int
exec_keycode(struct op_keycode *opk)
{
- if (!opk->target_keycode) {
- int i, j;
- KeyCode free;
+ KeyCode keycode = opk->target_keycode;
+ int i, old_count = 0;
+ KeySym *old_keysyms = NULL;
+
+ if (!keycode) {
+ int j;
if (!opk->count)
return (0);
- free = 0;
for (i = min_keycode; i <= max_keycode; i++) {
for (j = 0; j < opk->count; j++) {
if (XKeycodeToKeysym(dpy, (KeyCode) i, j) != opk->keysyms[j])
@@ -1226,29 +1234,42 @@ exec_keycode(struct op_keycode *opk)
}
if (j >= opk->count)
return (0);
- if (free)
+ if (keycode)
continue;
for (j = 0; j < 8; j++) {
if (XKeycodeToKeysym(dpy, (KeyCode) i, j) != None)
break;
}
if (j >= 8)
- free = i;
+ keycode = i;
}
- if (!free) {
+ if (!keycode) {
fprintf(stderr, "%s: no available keycode for assignment\n",
ProgramName);
return (-1);
}
- XChangeKeyboardMapping (dpy, free, opk->count, opk->keysyms, 1);
} else if (opk->count == 0) {
KeySym dummy = NoSymbol;
XChangeKeyboardMapping (dpy, opk->target_keycode, 1,
&dummy, 1);
- } else {
- XChangeKeyboardMapping (dpy, opk->target_keycode, opk->count,
- opk->keysyms, 1);
+ return (0);
}
+
+ /* replace any KeepSymbol keysyms with fetched previous value */
+ for (i = 0; i < opk->count; i++) {
+ if (opk->keysyms[i] == KeepSymbol) {
+ if (!old_keysyms)
+ old_keysyms = XGetKeyboardMapping (dpy, keycode, 1, &old_count);
+ if (old_keysyms && i < old_count)
+ opk->keysyms[i] = old_keysyms[i];
+ else
+ opk->keysyms[i] = NoSymbol;
+ }
+ }
+ if (old_keysyms) XFree(old_keysyms);
+
+ XChangeKeyboardMapping (dpy, keycode, opk->count, opk->keysyms, 1);
+
return (0);
}
diff --git a/man/xmodmap.man b/man/xmodmap.man
index 1ed1ca1..fcb7773 100644
--- a/man/xmodmap.man
+++ b/man/xmodmap.man
@@ -153,6 +153,8 @@ are not used in any major X server implementation. The first keysym is used
when no modifier key is pressed in conjunction with this key, the second with
Shift, the third when the Mode_switch key is used with this key and the fourth
when both the Mode_switch and Shift keys are used.
+A hyphen instead of a keysym name keeps the keysym currently assigned
+at that position.
.TP 8
.B keycode any = \fIKEYSYMNAME ...\fP
If no existing key has the specified list of keysyms assigned to it,
--
1.7.9.5
More information about the xorg-devel
mailing list