2 * Copyright (C) 2002,2013 Ian Jackson <ian@chiark.greenend.org.uk>
4 * This is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 3,
7 * or (at your option) any later version.
9 * This is distributed in the hope that it will be useful, but
10 * 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, see <http://www.gnu.org/licenses/>.
19 #include <X11/keysym.h>
20 #include <X11/cursorfont.h>
21 #include <X11/cursorfont.h>
22 #include <X11/Xmu/WinUtil.h>
23 #include <X11/XKBlib.h>
31 static Display *display;
32 static int selecting, l1_x, l1_y;
33 static char stringbuf[20];
34 static unsigned long c_black, c_white, c_red, c_yellow;
35 static Window w, root;
45 static unsigned long getcolour(const char *name, int def) {
47 XColor screen_def, exact_def;
48 st= XAllocNamedColor(display,cmap,name,&screen_def,&exact_def);
49 fprintf(stdout,"name %s pixel %lu\n",name,screen_def.pixel);
50 return st ? screen_def.pixel : def;
53 static void beep(void) { XBell(display,100); }
58 * application select deselect
59 * root start typing deselect all
60 * xduplic start typing quit
64 * xduplic start selecting quit
68 * While typing: yellow on black
69 * While selecting: white on black
70 * Idle (typing into nowhere): red on black
73 static void redisplay(void) {
74 XClearWindow(display,w);
75 XDrawString(display,w,gc, l1_x,l1_y, stringbuf,strlen(stringbuf));
78 static void restatus(void) {
83 v.foreground= (selecting ? c_white :
90 XClearWindow(display,w);
92 for (count=0, own=headwn; own; own=own->next) count++;
93 snprintf(stringbuf,sizeof(stringbuf),
101 static void stopselecting(void) {
102 XUngrabPointer(display,CurrentTime);
107 static void startselecting(void) {
109 st= XGrabPointer(display,root,True,
110 ButtonPressMask,GrabModeAsync,
111 GrabModeAsync,None,cursor,CurrentTime);
112 if (st != Success) beep();
117 static void buttonpress(XButtonEvent *e) {
118 struct wnode *own, **ownp, *ownn;
123 case Button1: rightbutton=0; break;
124 case Button3: rightbutton=1; break;
128 fprintf(stdout,"button right=%d in=%lx sub=%lx (w=%lx root=%lx)\n",
129 rightbutton, (unsigned long)e->window, (unsigned long)e->subwindow,
130 (unsigned long)w, (unsigned long)e->root);
132 if (e->window == w) {
133 if (rightbutton) _exit(0);
136 /* move pointer to where it already is, just in case wm is confused */
137 XWarpPointer(display,None,root, 0,0,0,0, e->x_root,e->y_root);
144 if (!selecting) return;
146 if (e->window != e->root) return;
152 if (!headwn) { beep(); return; }
153 for (own=headwn; own; own=ownn) {
163 sw= XmuClientWindow(display, e->subwindow);
165 if (sw == w) { beep(); return; }
168 (own=(*ownp)) && own->w != sw;
169 ownp= &(*ownp)->next);
173 if (own) { beep(); return; }
174 own= malloc(sizeof(*own)); if (!own) { perror("malloc"); exit(-1); }
181 if (!own) { beep(); return; }
190 static void keypress(XKeyEvent *e) {
196 fprintf(stdout,"key type %d serial %lu (send %d) "
197 "window %lx root %lx sub %lx time %lx @%dx%d (%dx%dabs) "
198 "state %x keycode %u same %d\n",
199 e->type, e->serial, (int)e->send_event,
200 (unsigned long)e->window,
201 (unsigned long)e->root,
202 (unsigned long)e->subwindow,
203 (unsigned long)e->time,
204 e->x,e->y, e->x_root,e->y_root,
205 e->state, e->keycode, (int)e->same_screen);
206 if (XkbKeycodeToKeysym(display, e->keycode, 0, 0) == XK_q) _exit(1);
209 for (own=headwn; own; own=own->next) {
210 mask= (e->type == KeyPress ? KeyPressMask :
211 e->type == KeyRelease ? KeyReleaseMask :
212 KeyPressMask|KeyReleaseMask);
216 st= XSendEvent(display,own->w,True,mask,(XEvent*)e);
218 fprintf(stdout,"sendevent to %lx %d mask %lx\n",
219 (unsigned long)own->w, st, mask);
224 static void expose(XExposeEvent *e) {
225 if (e->count) return;
229 int main(int argc, const char **argv) {
232 XSetWindowAttributes wv;
233 int screen, direction, ascent, descent, l1_width, l1_height;
237 display= XOpenDisplay(0);
238 if (!display) { fputs("XOpenDisplay failed\n",stderr); exit(-1); }
239 screen= DefaultScreen(display);
240 cmap= DefaultColormap(display,screen);
241 root= DefaultRootWindow(display);
243 c_black= getcolour("black", 0);
244 c_white= getcolour("white", 1);
245 c_yellow= getcolour("yellow", c_white);
246 c_red= getcolour("red", c_white);
248 cursor= XCreateFontCursor(display,XC_crosshair);
250 wv.event_mask= KeyPressMask|KeyReleaseMask|ButtonPressMask|ExposureMask;
251 w= XCreateWindow(display, root,
252 0,0, 50,21, 0,DefaultDepth(display,screen),
253 InputOutput, DefaultVisual(display,screen),
256 font= XLoadFont(display,"fixed");
258 gcv.background= c_black;
260 gc= XCreateGC(display,w,GCBackground|GCFont,&gcv);
262 XQueryTextExtents(display,font, "SIT 0689", 8,
263 &direction,&ascent,&descent,&overall);
264 l1_width= overall.lbearing + overall.rbearing;
265 l1_x= overall.lbearing;
267 l1_height= descent+ascent;
269 XResizeWindow(display,w, l1_width,l1_height);
270 XSetWindowBackground(display,w,c_black);
272 XMapWindow(display,w);
276 XNextEvent(display,&e);
277 fprintf(stdout,"selecting = %d; event type = %lu\n",
278 selecting, (unsigned long)e.type);
280 case Expose: expose(&e.xexpose); break;
281 case ButtonPress: buttonpress(&e.xbutton); break;
282 case KeyPress: case KeyRelease: keypress(&e.xkey); break;