Compare commits

..

17 commits
v1.2 ... master

Author SHA1 Message Date
Albin Olsson a34d6bae27
Merge pull request #78 from PaulPorfiroff/allow-mapping-to-keycodes
Allow mapping to keycodes
2018-03-01 08:56:23 +01:00
Albin Olsson 3cc6e1eb8c
Merge pull request #98 from thebillywayne/master
Update README.md
2018-02-19 08:44:34 +01:00
Albin Olsson 5f9ea17074
Merge pull request #93 from thebinarypenguin/patch-1
change "conjugation" to "conjunction" in README.md
2018-02-19 08:43:58 +01:00
Billy Wayne McCann 791057b8af
Update README.md
Fixed a small spelling error ("relased" -> "released") in the README.
2018-02-17 00:32:25 -05:00
Ethan Zimmerman 97f79a3ec8 change "conjugation" to "conjunction" in README.md 2017-08-19 14:13:57 -04:00
Albin Olsson 6ded5b453b Merge pull request #89 from qu1x/add-foreground-flag
Add '-f' flag (implied by '-d' flag).
2017-08-07 13:19:39 +02:00
Albin Olsson 99dda44922 Merge pull request #91 from jbernard/master
Remove trailing whitespace from manpage
2017-08-07 13:10:19 +02:00
Jon Bernard d2a9bcb1cc Remove trailing whitespace from manpage 2017-07-07 07:20:52 -04:00
Rouven Spreckels d8dbbf8a25 Add '-f' flag (implied by '-d' flag). 2017-07-03 20:58:26 +02:00
Paul Porfiroff 6901647283 "Describe" changes in README. 2016-12-11 15:59:09 +03:00
Paul Porfiroff 48171b2443 Allow specifying keys to map to with keycodes. 2016-12-11 15:58:05 +03:00
Paul Porfiroff ac6e3723f5 Fix typo. 2016-12-11 14:59:31 +03:00
Albin Olsson 6331193ef0 Merge pull request #76 from orestisf1993/fix-50
Fix #50. Invalid '-t' argument
2016-11-19 12:17:36 +01:00
orestisf 853ca153fe Remove useless timeout_valid flag
It's always true.
2016-11-17 04:48:29 +02:00
orestisf ccf79e6118 Fix #50. Exit on invalid '-t' argument
Since the program has a default timeout anyway the '-t' flag is not needed.
2016-11-17 04:48:29 +02:00
Albin Olsson 5481a17e6b Merge pull request #68 from gunnihinn/master
Add installation instructions for Fedora systems
2016-11-15 18:42:45 +01:00
Gunnar Þór Magnússon 958e3c7c8e Add installation instructions for Fedora systems
The original instructions were for derivatives of Debian. Adding
instructions for Fedora-based systems is just a matter of finding what
the corresponding devel packages are called there.
2016-05-25 16:38:07 -05:00
3 changed files with 85 additions and 48 deletions

View file

@ -12,7 +12,17 @@ editor ;)
Minimal building instructions
-----------------------------
First install the development dependencies. On Debian-based systems
(including Ubuntu and Linux Mint), run:
$ sudo apt-get install git gcc make pkg-config libx11-dev libxtst-dev libxi-dev
On Fedora-based systems, run:
$ sudo dnf install git gcc make pkgconfig libX11-devel libXtst-devel libXi-devel
Then run:
$ git clone https://github.com/alols/xcape.git
$ cd xcape
$ make
@ -20,11 +30,15 @@ Minimal building instructions
Usage
-----
$ xcape [-d] [-t <timeout ms>] [-e <map-expression>]
$ xcape [-d] [-f] [-t <timeout ms>] [-e <map-expression>]
### `-d`
Debug mode. Does not fork into the background.
Debug mode. Does not fork into the background. Prints debug information.
### `-f`
Foreground mode. Does not fork into the background.
### `-t <timeout ms>`
@ -42,8 +56,8 @@ the actual name of the character. For example to generate "{" the
expression `'ModKey=Shift_L|bracketleft'` could be used (assuming that you
have a key with "{" above "[").
You can also specify ModKey in decimal (prefix `#`), octal (`#0`), or
hexadecimal (`#0x`). It will be interpreted as a keycode unless no corresponding
You can also specify keys in decimal (prefix `#`), octal (`#0`), or
hexadecimal (`#0x`). They will be interpreted as keycodes unless no corresponding
key name is found.
#### Examples
@ -54,11 +68,11 @@ key name is found.
xcape -e 'Shift_L=Escape;Control_L=Control_L|O'
+ In conjugation with xmodmap it is possible to make an ordinary key act
+ In conjunction with xmodmap it is possible to make an ordinary key act
as an extra modifier. First map the key to the modifier with xmodmap
and then the modifier back to the key with xcape. However, this has
several limitations: the key will not work as ordinary until it is
relased, and in particular, *it may act as a modifier unintentionally if
released, and in particular, *it may act as a modifier unintentionally if
you type too fast.* This is not a bug in xcape, but an unavoidable
consequence of using these two tools together in this way.
As an example, we can make the space bar work as an additional ctrl

10
xcape.1
View file

@ -1,4 +1,4 @@
.TH XCAPE 1 2014-02-13 "John Hill" "xcape Manual"
.TH XCAPE 1 2017-07-03 "John Hill" "xcape Manual"
.SH NAME
xcape \- use a modifier key as another key
@ -6,6 +6,7 @@ xcape \- use a modifier key as another key
.SH SYNOPSIS
.B xcape
[\fB-d\fR]
[\fB-f\fR]
[\fB-t\fR \fItimeout\fR]
[\fB-e\fR \fImap-expression\fR]
@ -17,7 +18,10 @@ key in place of \fIControl_L\fR (Left Control).
.SH OPTIONS
.TP
.BR \-d
Debug mode. Will run as a foreground process.
Debug mode. Will run as a foreground process and print debug information.
.TP
.BR \-f
Foreground mode. Will run as a foreground process.
.TP
.BR \-t " " \fItimeout\fR
Give a \fItimeout\fR in milliseconds. If you hold a key longer than
@ -28,7 +32,7 @@ Use \fImap-expression\fR as the expression(s).
.SH EXPRESSION SYNTAX
Expression syntax is \'\fBModKey\fR=\fBKey\fR[|\fBOtherKey\fR]\'. Multiple
expressions can be passed, delimited by semi-colons (;).
expressions can be passed, delimited by semi-colons (;).
.PP
A list of keysyms can be found in the header file <\fIX11/keysymdef.h\fR>
(without the \fIXK_\fR prefix).

97
xcape.c
View file

@ -62,11 +62,11 @@ typedef struct _XCape_t
XRecordContext record_ctx;
pthread_t sigwait_thread;
sigset_t sigset;
Bool foreground;
Bool debug;
KeyMap_t *map;
Key_t *generated;
struct timeval timeout;
Bool timeout_valid;
} XCape_t;
/************************************************************************
@ -101,21 +101,24 @@ int main (int argc, char **argv)
XRecordRange *rec_range = XRecordAllocRange();
XRecordClientSpec client_spec = XRecordAllClients;
self->foreground = False;
self->debug = False;
self->timeout.tv_sec = 0;
self->timeout.tv_usec = 500000;
self->timeout_valid = True;
self->generated = NULL;
rec_range->device_events.first = KeyPress;
rec_range->device_events.last = ButtonRelease;
while ((ch = getopt (argc, argv, "de:t:")) != -1)
while ((ch = getopt (argc, argv, "dfe:t:")) != -1)
{
switch (ch)
{
case 'd':
self->debug = True;
/* imply -f (no break) */
case 'f':
self->foreground = True;
break;
case 'e':
mapping = optarg;
@ -125,13 +128,14 @@ int main (int argc, char **argv)
int ms = atoi (optarg);
if (ms > 0)
{
self->timeout_valid = True;
self->timeout.tv_sec = ms / 1000;
self->timeout.tv_usec = (ms % 1000) * 1000;
}
else
{
self->timeout_valid = False;
fprintf (stderr, "Invalid argument for '-t': %s.\n", optarg);
print_usage (argv[0]);
return EXIT_FAILURE;
}
}
break;
@ -188,7 +192,7 @@ int main (int argc, char **argv)
exit (EXIT_FAILURE);
}
if (self->debug != True)
if (self->foreground != True)
daemon (0, 0);
sigemptyset (&self->sigset);
@ -303,8 +307,7 @@ void handle_key (XCape_t *self, KeyMap_t *key,
key->pressed = True;
if (self->timeout_valid)
gettimeofday (&key->down_at, NULL);
gettimeofday (&key->down_at, NULL);
if (mouse_pressed)
{
@ -317,13 +320,10 @@ void handle_key (XCape_t *self, KeyMap_t *key,
if (key->used == False)
{
struct timeval timev = self->timeout;
if (self->timeout_valid)
{
gettimeofday (&timev, NULL);
timersub (&timev, &key->down_at, &timev);
}
gettimeofday (&timev, NULL);
timersub (&timev, &key->down_at, &timev);
if (!self->timeout_valid || timercmp (&timev, &self->timeout, <))
if (timercmp (&timev, &self->timeout, <))
{
for (k = key->to_keys; k != NULL; k = k->next)
{
@ -423,8 +423,8 @@ KeyMap_t *parse_token (Display *dpy, char *token, Bool debug)
KeyMap_t *km = NULL;
KeySym ks;
char *from, *to, *key;
KeyCode code; /* keycode (to) */
long fromcode; /* keycode (from) */
KeyCode code; /* keycode */
long parsed_code; /* parsed keycode value */
to = token;
from = strsep (&to, "=");
@ -436,17 +436,17 @@ KeyMap_t *parse_token (Display *dpy, char *token, Bool debug)
&& strsep (&from, "#") != NULL)
{
errno = 0;
fromcode = strtoul (from, NULL, 0); /* dec, oct, hex automatically */
parsed_code = strtoul (from, NULL, 0); /* dec, oct, hex automatically */
if (errno == 0
&& fromcode <=255
&& XkbKeycodeToKeysym (dpy, (KeyCode) fromcode, 0, 0) != NoSymbol)
&& parsed_code <=255
&& XkbKeycodeToKeysym (dpy, (KeyCode) parsed_code, 0, 0) != NoSymbol)
{
km->UseKeyCode = True;
km->from_kc = (KeyCode) fromcode;
km->from_kc = (KeyCode) parsed_code;
if (debug)
{
KeySym ks_temp = XkbKeycodeToKeysym (dpy, (KeyCode) fromcode, 0, 0);
fprintf(stderr, "Assigned mapping from from \"%s\" ( keysym 0x%x, "
KeySym ks_temp = XkbKeycodeToKeysym (dpy, (KeyCode) parsed_code, 0, 0);
fprintf(stderr, "Assigned mapping from \"%s\" ( keysym 0x%x, "
"key code %d)\n",
XKeysymToString(ks_temp),
(unsigned) ks_temp,
@ -487,28 +487,47 @@ KeyMap_t *parse_token (Display *dpy, char *token, Bool debug)
if (key == NULL)
break;
if ((ks = XStringToKeysym (key)) == NoSymbol)
if (!strncmp (key, "#", 1)
&& strsep (&key, "#") != NULL)
{
fprintf (stderr, "Invalid key: %s\n", key);
return NULL;
errno = 0;
parsed_code = strtoul (key, NULL, 0); /* dec, oct, hex automatically */
if (!(errno == 0
&& parsed_code <=255
&& XkbKeycodeToKeysym (dpy, (KeyCode) parsed_code, 0, 0) != NoSymbol))
{
fprintf (stderr, "Invalid keycode: %s\n", key);
return NULL;
}
code = (KeyCode) parsed_code;
}
else
{
if ((ks = XStringToKeysym (key)) == NoSymbol)
{
fprintf (stderr, "Invalid key: %s\n", key);
return NULL;
}
code = XKeysymToKeycode (dpy, ks);
if (code == 0)
{
fprintf (stderr, "WARNING: No keycode found for keysym "
"%s (0x%x) in mapping %s. Ignoring this "
"mapping.\n", key, (unsigned int)ks, token);
return NULL;
}
}
code = XKeysymToKeycode (dpy, ks);
if (code == 0)
{
fprintf (stderr, "WARNING: No keycode found for keysym "
"%s (0x%x) in mapping %s. Ignoring this "
"mapping.\n", key, (unsigned int)ks, token);
return NULL;
}
km->to_keys = key_add_key (km->to_keys, code);
if (debug)
{
KeySym ks_temp = XkbKeycodeToKeysym (dpy, code, 0, 0);
fprintf(stderr, "to \"%s\" (keysym 0x%x, key code %d)\n",
key,
(unsigned) XStringToKeysym (key),
(unsigned) code);
XKeysymToString(ks_temp),
(unsigned) ks_temp,
(unsigned) code);
}
}
}
@ -570,6 +589,6 @@ void delete_keys (Key_t *keys)
void print_usage (const char *program_name)
{
fprintf (stdout, "Usage: %s [-d] [-t timeout_ms] [-e <mapping>]\n", program_name);
fprintf (stdout, "Runs as a daemon unless -d flag is set\n");
fprintf (stdout, "Usage: %s [-d] [-f] [-t timeout_ms] [-e <mapping>]\n", program_name);
fprintf (stdout, "Runs as a daemon unless -d or -f flag is set\n");
}