Neale Pickett
·
2012-03-01
xkeygrab.c
1/*
2 * xkeygrab -- grab keyboard and mouse, writing typed lines to stdout
3 * Copyright (C) 2008 Neale Pickett <neale@woozle.org>
4 *
5 * This program is free software: you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation, either version 3 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <stdio.h>
20#include <unistd.h>
21#include <ctype.h>
22#include <poll.h>
23#include <X11/Xlib.h>
24#include <X11/Xutil.h>
25#include <X11/keysym.h>
26
27#include "obj.h"
28
29int
30main(int argc, char *argv[])
31{
32 Display *display = NULL;
33
34 if (argc != 1) {
35 (void) fprintf(stderr, "Usage: %s\n", argv[0]);
36 return 64; /* EX_USAGE */
37 }
38
39 try {
40 Window root;
41 char obuf[4096];
42 int obuflen = 0;
43 struct pollfd fds[2];
44
45 if (!(display = XOpenDisplay(NULL)))
46 raise("cannot open display");
47 root = DefaultRootWindow(display);
48
49 if (getenv("NOROOT")) {
50 int screen = DefaultScreen(display);
51
52 XSetWindowAttributes wa;
53
54 zero(wa);
55
56 wa.override_redirect = 1;
57 wa.background_pixel = BlackPixel(display, screen);
58 root = XCreateWindow(display, root,
59 0, 0,
60 50, 50, 0,
61 CopyFromParent, CopyFromParent,
62 CopyFromParent, CWBackPixel, &wa);
63 XMapWindow(display, root);
64 }
65
66
67 fds[0].fd = STDOUT_FILENO;
68 fds[0].events = 0;
69 fds[1].fd = ConnectionNumber(display);
70 fds[1].events = POLLIN;
71 while (1) {
72 int tograb = 3;
73 int ret;
74
75 if (tograb) {
76 if ((tograb & 1)
77 && (GrabSuccess ==
78 XGrabKeyboard(display, root, True, GrabModeAsync,
79 GrabModeAsync, CurrentTime))) {
80 tograb |= 1;
81 }
82 if ((tograb & 2)
83 && (GrabSuccess ==
84 XGrabPointer(display, root, False,
85 ButtonPressMask | ButtonReleaseMask |
86 PointerMotionMask, GrabModeAsync,
87 GrabModeAsync, None, None,
88 CurrentTime))) {
89 tograb |= 2;
90 }
91 }
92
93 ret = poll(fds, 2, (tograb ? 100 : -1));
94 if (-1 == ret)
95 break;
96
97 if (fds[0].revents & POLLERR) {
98 break;
99 }
100 if (fds[1].revents & POLLIN) {
101 XEvent event;
102
103 do {
104 (void) XNextEvent(display, &event);
105 if (KeyPress == event.type) {
106 char buf[32];
107 KeySym ksym;
108 int i;
109
110 if (obuflen == sizeof(obuf))
111 continue;
112 i = XLookupString(&event.xkey, buf, sizeof(buf),
113 &ksym, NULL);
114 switch (ksym) {
115 case XK_Return:
116 if (obuflen) {
117 (void) write(STDOUT_FILENO, obuf,
118 obuflen);
119 (void) write(STDOUT_FILENO, "\n", 1);
120 obuflen = 0;
121 }
122 break;
123 case XK_BackSpace:
124 if (obuflen)
125 obuflen -= 1;
126 break;
127 default:
128 if (1 == i) {
129 switch (buf[0]) {
130 case '\025':
131 obuflen = 0;
132 break;
133 case ' ' ... '~':
134 obuf[obuflen++] = buf[0];
135 break;
136 }
137 }
138 break;
139 }
140 if (obuflen == sizeof(obuf)) {
141 (void) write(STDOUT_FILENO, obuf, obuflen);
142 obuflen = 0;
143 }
144 }
145 } while (XPending(display));
146 }
147 }
148 }
149 while (0);
150
151 if (display) {
152 (void) XUngrabKeyboard(display, CurrentTime);
153 (void) XUngrabPointer(display, CurrentTime);
154 (void) XCloseDisplay(display);
155 }
156
157 except {
158 (void) fprintf(stderr, "Error: %s\n", exception);
159 return 69; /* EX_UNAVAILABLE */
160 }
161
162 return 0;
163}