2 * Copyright (c) 2007 Daniel Borca All rights reserved.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
32 #define LOG(x) printf x
36 grab_key (Display
*dpy
, KeyCode keycode
, unsigned int modifier
, Window win
)
38 XGrabKey(dpy
, keycode
, modifier
, (win
? win
: DefaultRootWindow(dpy
)),
39 False
, GrabModeAsync
, GrabModeAsync
);
44 xhk_grab (Display
*dpy
, int num
, KTUPLE keys
[])
46 int screen
= DefaultScreen(dpy
);
47 for (screen
= 0; screen
< ScreenCount(dpy
); screen
++) {
49 for (i
= 0; i
< num
; i
++) {
50 grab_key(dpy
, keys
[i
].key
, keys
[i
].mod
, RootWindow(dpy
, screen
));
58 xhk_ungrab (Display
*dpy
)
60 int screen
= DefaultScreen(dpy
);
61 for (screen
= 0; screen
< ScreenCount(dpy
); screen
++) {
62 XUngrabKey(dpy
, AnyKey
, AnyModifier
, RootWindow(dpy
, screen
));
68 xhk_parse (int argc
, char **argv
, KTUPLE
**out_keys
)
73 keys
= malloc((argc
- 1) * sizeof(KTUPLE
));
79 const char *p
= *++argv
;
80 if (!strncmp(p
, "-key=", 5)) {
86 if (!strncmp(p
, "Shift+", 6)) {
88 keys
[i
].mod
|= ShiftMask
;
91 if (!strncmp(p
, "Control+", 8)) {
93 keys
[i
].mod
|= ControlMask
;
96 if (!strncmp(p
, "Alt+", 4)) {
98 keys
[i
].mod
|= Mod1Mask
;
103 keys
[i
].key
= strtol(p
, &q
, 0);
104 if (errno
|| q
== p
|| !isspace(*q
)) {
105 LOG(("ignoring `%s'\n", p
));
108 while (isspace(*++q
)) {
111 LOG(("key%d: 0x%X+%d -> \"%s\"\n", i
, keys
[i
].mod
, keys
[i
].key
, keys
[i
].command
));
127 xhk_sig_handler (int sig
)
129 if (sig
== SIGCHLD
) {
132 /* if more than one child exits at approximately the same time, the signals may get merged. */
133 while ((child
= waitpid(-1, &status
, WNOHANG
)) > 0) {
134 LOG(("pid %d exited\n", child
));
143 xhk_eks_handler (Display
*dpy
, XErrorEvent
*evt
)
145 static int been_there_done_that
= 0;
146 if (!been_there_done_that
) {
147 been_there_done_that
++;
148 fprintf(stderr
, "*** X ERROR %d\n", evt
->error_code
);
157 display_env (Display
*dpy
)
159 const char *display_name
= DisplayString(dpy
);
160 char *envstr
= malloc(strlen(display_name
) + 8 + 1);
161 if (envstr
!= NULL
) {
162 strcat(strcpy(envstr
, "DISPLAY="), display_name
);
169 run_command (Display
*dpy
, KTUPLE
*key
)
184 exit(execlp("sh", "sh", "-c", key
->command
, (char *)0));
189 #else /* !XHK_SIGFORK */
201 /* fork again and exit, so that init(1) reaps the grandchildren */
210 exit(execlp("sh", "sh", "-c", key
->command
, (char *)0));
212 waitpid(pid
, &status
, 0);
214 return WEXITSTATUS(status
);
216 #endif /* !XHK_SIGFORK */
221 xhk_run (Display
*dpy
, XEvent
*evt
, int num
, KTUPLE keys
[])
223 if (evt
->type
== KeyPress
) {
225 unsigned int mod
= evt
->xkey
.state
& (ShiftMask
| ControlMask
| Mod1Mask
);
226 for (i
= 0; i
< num
; i
++) {
227 if (evt
->xkey
.keycode
== keys
[i
].key
&& mod
== keys
[i
].mod
) {
228 LOG(("key: 0x%X+%d, cmd: %s\n", keys
[i
].mod
, keys
[i
].key
, keys
[i
].command
));
229 return run_command(dpy
, &keys
[i
]);