mirror of
https://github.com/alols/xcape.git
synced 2026-09-10 11:16:14 -04:00
Compare commits
17 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a34d6bae27 | ||
|
|
3cc6e1eb8c | ||
|
|
5f9ea17074 | ||
|
|
791057b8af | ||
|
|
97f79a3ec8 | ||
|
|
6ded5b453b | ||
|
|
99dda44922 | ||
|
|
d2a9bcb1cc | ||
|
|
d8dbbf8a25 | ||
|
|
6901647283 | ||
|
|
48171b2443 | ||
|
|
ac6e3723f5 | ||
|
|
6331193ef0 | ||
|
|
853ca153fe | ||
|
|
ccf79e6118 | ||
|
|
5481a17e6b | ||
|
|
958e3c7c8e |
26
README.md
26
README.md
|
|
@ -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
10
xcape.1
|
|
@ -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
97
xcape.c
|
|
@ -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");
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue