Skip to content

Commit

Permalink
Implement modifiers in the from side.
Browse files Browse the repository at this point in the history
This commit makes two modifiers as a key possible (#69). The expression
grammar becomes 'ModKeyA:ModKeyB=Key[|OtherKey][;NextExpression]'.
ModKeyB being pressed along will only be remapped if ModKeyA is being
pressed. Leaving out ModKeyA behaves like the old xcape.

Examples,
'Alt_L:Control_L=equal;Control_L:Alt_L=grave;Control_L=Escape'

*Be aware the output `equal` and `grave` will become `Alt_L + equal` and
 `Control_L + grave`.*
  • Loading branch information
amosbird committed Jun 22, 2016
1 parent 7fca364 commit 7644b29
Showing 1 changed file with 44 additions and 2 deletions.
46 changes: 44 additions & 2 deletions xcape.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <X11/extensions/XTest.h>
#include <X11/XKBlib.h>

#define BIT(c, x) ( c[x/8]&(1<<(x%8)) )

/************************************************************************
* Internal data types
Expand All @@ -47,6 +48,8 @@ typedef struct _KeyMap_t
Bool UseKeyCode; /* (for from) instead of KeySym; ignore latter */
KeySym from_ks;
KeyCode from_kc;
Bool UseModifier;
KeySym modifier;
Key_t *to_keys;
Bool used;
Bool pressed;
Expand Down Expand Up @@ -325,6 +328,16 @@ void handle_key (XCape_t *self, KeyMap_t *key,

if (!self->timeout_valid || timercmp (&timev, &self->timeout, <))
{
char buf[32], *keys = buf;
XQueryKeymap(self->ctrl_conn, keys);
if (key->UseModifier) {
if (!BIT(keys, XKeysymToKeycode (self->ctrl_conn, key->modifier))) {
goto skip;
}
} else {
for (int i = 0; i < 32; i++)
if (keys[i]) goto skip;
}
for (k = key->to_keys; k != NULL; k = k->next)
{
if (self->debug) fprintf (stdout, "Generating %s!\n",
Expand All @@ -344,6 +357,7 @@ void handle_key (XCape_t *self, KeyMap_t *key,
XFlush (self->ctrl_conn);
}
}
skip:
key->used = False;
key->pressed = False;
}
Expand Down Expand Up @@ -414,19 +428,25 @@ void intercept (XPointer user_data, XRecordInterceptData *data)
}

exit:
XUnlockDisplay (self->ctrl_conn);
XUnlockDisplay (self->ctrl_conn);
XRecordFreeData (data);
}

KeyMap_t *parse_token (Display *dpy, char *token, Bool debug)
{
KeyMap_t *km = NULL;
KeySym ks;
char *from, *to, *key;
char *modifier, *from, *to, *key;
KeyCode code; /* keycode (to) */
long fromcode; /* keycode (from) */

to = token;
modifier = strsep (&to, ":");
if (to == NULL) {
to = token;
modifier = NULL;
}

from = strsep (&to, "=");
if (to != NULL)
{
Expand Down Expand Up @@ -481,6 +501,28 @@ KeyMap_t *parse_token (Display *dpy, char *token, Bool debug)
}
}

if (modifier != NULL) {
if ((ks = XStringToKeysym (modifier)) == NoSymbol)
{
fprintf (stderr, "Invalid key: %s\n", token);
return NULL;
}

km->UseModifier = True;
km->modifier = ks;

if (debug)
{
fprintf(stderr, "Assigned mapping with modifier \"%s\" ( keysym 0x%x, "
"key code %d)\n",
XKeysymToString (km->modifier),
(unsigned) km->modifier,
(unsigned) XKeysymToKeycode (dpy, km->modifier));
}
} else {
km->UseModifier = False;
}

for(;;)
{
key = strsep (&to, "|");
Expand Down

0 comments on commit 7644b29

Please sign in to comment.