sxhkd-rc

[fork] simple X hotkey daemon (but for the rc shell)
Log | Files | Refs | README | LICENSE

commit e2b5659eb4c42162b847d5a9f87c23b845e5849a
parent 07595089fee6aac5953af8acb2f2e98682fa03d5
Author: Bastien Dejean <nihilhill@gmail.com>
Date:   Mon,  6 Apr 2015 08:54:17 +0200

Provide a notation for synchronous execution

If a command starts with a semicolon it will be executed synchronously.

We need this for the *bspwm* pointer interactions: if we send the
grabbing message asynchronously, *bspwm* might not see the window below
the pointer because the pointer might have moved outside of the window
while the message was being transmitted.

Diffstat:
Mdoc/sxhkd.1 | 8+++++---
Mdoc/sxhkd.1.txt | 4+++-
Mhelpers.c | 33+++++++++++++++++++++------------
Mhelpers.h | 5+++--
Msxhkd.c | 2+-
Mtypes.c | 1+
Mtypes.h | 1+
7 files changed, 35 insertions(+), 19 deletions(-)

diff --git a/doc/sxhkd.1 b/doc/sxhkd.1 @@ -2,12 +2,12 @@ .\" Title: sxhkd .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/> -.\" Date: 04/05/2015 +.\" Date: 04/06/2015 .\" Manual: Sxhkd Manual .\" Source: Sxhkd 0.5.5 .\" Language: English .\" -.TH "SXHKD" "1" "04/05/2015" "Sxhkd 0\&.5\&.5" "Sxhkd Manual" +.TH "SXHKD" "1" "04/06/2015" "Sxhkd 0\&.5\&.5" "Sxhkd Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -168,6 +168,8 @@ When multiple chords are separated by semicolons, the hotkey is a chord chain: t .sp The colon character can be used instead of the semicolon to indicate that the chord chain shall not be aborted when the chain tail is reached\&. .sp +If a command starts with a semicolon, it will be executed synchronously, otherwise asynchronously\&. +.sp The \fIEscape\fR key can be used to abort a chord chain\&. .sp If \fB@\fR is added at the beginning of the keysym, the command will be run on key release events, otherwise on key press events\&. @@ -212,7 +214,7 @@ super + {alt,ctrl,alt + ctrl} + XF86Eject bspc pointer \-g focus super + button{1\-3} - bspc pointer \-g {move,resize_side,resize_corner} + ; bspc pointer \-g {move,resize_side,resize_corner} super + @button{1\-3} bspc pointer \-u diff --git a/doc/sxhkd.1.txt b/doc/sxhkd.1.txt @@ -102,6 +102,8 @@ When multiple chords are separated by semicolons, the hotkey is a chord chain: t The colon character can be used instead of the semicolon to indicate that the chord chain shall not be aborted when the chain tail is reached. +If a command starts with a semicolon, it will be executed synchronously, otherwise asynchronously. + The _Escape_ key can be used to abort a chord chain. If *@* is added at the beginning of the keysym, the command will be run on key release events, otherwise on key press events. @@ -146,7 +148,7 @@ super + {alt,ctrl,alt + ctrl} + XF86Eject bspc pointer -g focus super + button{1-3} - bspc pointer -g {move,resize_side,resize_corner} + ; bspc pointer -g {move,resize_side,resize_corner} super + @button{1-3} bspc pointer -u diff --git a/helpers.c b/helpers.c @@ -50,29 +50,38 @@ void err(char *fmt, ...) exit(EXIT_FAILURE); } -void spawn(char *cmd[]) +void run(char *command, bool sync) +{ + char *cmd[] = {shell, "-c", command, NULL}; + spawn(cmd, sync); +} + +void spawn(char *cmd[], bool sync) { if (fork() == 0) { if (dpy != NULL) close(xcb_get_file_descriptor(dpy)); - if (fork() == 0) { - setsid(); - if (redir_fd != -1) { - dup2(redir_fd, STDOUT_FILENO); - dup2(redir_fd, STDERR_FILENO); + if (sync) { + execute(cmd); + } else { + if (fork() == 0) { + execute(cmd); } - execvp(cmd[0], cmd); - err("Spawning failed.\n"); + exit(EXIT_SUCCESS); } - exit(EXIT_SUCCESS); } wait(NULL); } -void run(char *command) +void execute(char *cmd[]) { - char *cmd[] = {shell, "-c", command, NULL}; - spawn(cmd); + setsid(); + if (redir_fd != -1) { + dup2(redir_fd, STDOUT_FILENO); + dup2(redir_fd, STDERR_FILENO); + } + execvp(cmd[0], cmd); + err("Spawning failed.\n"); } char *lgraph(char *s) diff --git a/helpers.h b/helpers.h @@ -39,8 +39,9 @@ void warn(char *fmt, ...); __attribute__((noreturn)) void err(char *fmt, ...); -void spawn(char *cmd[]); -void run(char *command); +void execute(char *cmd[]); +void spawn(char *cmd[], bool sync); +void run(char *command, bool sync); char *lgraph(char *s); char *rgraph(char *s); diff --git a/sxhkd.c b/sxhkd.c @@ -233,7 +233,7 @@ void key_button_event(xcb_generic_event_t *evt, uint8_t event_type) if (keysym != XCB_NO_SYMBOL || button != XCB_NONE) { hotkey_t *hk = find_hotkey(keysym, button, modfield, event_type, &replay_event); if (hk != NULL) { - run(hk->command); + run(hk->command, hk->sync); if (status_fifo != NULL) put_status(COMMAND_PREFIX, hk->command); } diff --git a/types.c b/types.c @@ -194,6 +194,7 @@ hotkey_t *make_hotkey(chain_t *chain, char *command) hotkey_t *hk = malloc(sizeof(hotkey_t)); hk->chain = chain; snprintf(hk->command, sizeof(hk->command), "%s", command); + hk->sync = (command[0] == ';'); hk->cycle = NULL; hk->next = hk->prev = NULL; return hk; diff --git a/types.h b/types.h @@ -61,6 +61,7 @@ typedef struct hotkey_t hotkey_t; struct hotkey_t { chain_t *chain; char command[2 * MAXLEN]; + bool sync; cycle_t *cycle; hotkey_t *next; hotkey_t *prev;