1 /***************************************************************************
2 xbindkeys : a program to bind keys to commands under X11.
3 -------------------
4 begin : Sat Oct 13 14:11:34 CEST 2001
5 copyright : (C) 2001 by Philippe Brochard
6 email : hocwp@free.fr
7 ***************************************************************************/
8
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <X11/Xlib.h>
22 #include <X11/Xutil.h>
23 #include <unistd.h>
24 #include "keys.h"
25 #include "options.h"
26
27
28
29 #define STOP_KEY "q"
30
31
32 #define INNER_WINDOW_WIDTH 50
33 #define INNER_WINDOW_HEIGHT 50
34 #define INNER_WINDOW_BORDER 4
35 #define INNER_WINDOW_X 10
36 #define INNER_WINDOW_Y 10
37 #define OUTER_WINDOW_MIN_WIDTH (INNER_WINDOW_WIDTH + \
38 2 * (INNER_WINDOW_BORDER + INNER_WINDOW_X))
39 #define OUTER_WINDOW_MIN_HEIGHT (INNER_WINDOW_HEIGHT + \
40 2 * (INNER_WINDOW_BORDER + INNER_WINDOW_Y))
41 #define OUTER_WINDOW_DEF_WIDTH (OUTER_WINDOW_MIN_WIDTH + 200)
42 #define OUTER_WINDOW_DEF_HEIGHT (OUTER_WINDOW_MIN_HEIGHT + 4)
43 #define OUTER_WINDOW_DEF_X 200
44 #define OUTER_WINDOW_DEF_Y 4
45
46
47
48 void
set_sizehints(Display * dpy,XSizeHints * hintp,int min_width,int min_height,int defwidth,int defheight,int defx,int defy)49 set_sizehints (Display * dpy, XSizeHints * hintp, int min_width,
50 int min_height, int defwidth, int defheight, int defx,
51 int defy)
52 {
53 int geom_result;
54
55 /* set the size hints, algorithm from xlib xbiff */
56
57 hintp->width = hintp->min_width = min_width;
58 hintp->height = hintp->min_height = min_height;
59 hintp->flags = PMinSize;
60 hintp->x = hintp->y = 0;
61 geom_result = NoValue;
62 if (geom != NULL)
63 {
64 geom_result = XParseGeometry (geom, &hintp->x, &hintp->y,
65 (unsigned int *) &hintp->width,
66 (unsigned int *) &hintp->height);
67 if ((geom_result & WidthValue) && (geom_result & HeightValue))
68 {
69 #define max(a,b) ((a) > (b) ? (a) : (b))
70 hintp->width = max (hintp->width, hintp->min_width);
71 hintp->height = max (hintp->height, hintp->min_height);
72 hintp->flags |= USSize;
73 }
74 if ((geom_result & XValue) && (geom_result & YValue))
75 {
76 hintp->flags += USPosition;
77 }
78 }
79 if (!(hintp->flags & USSize))
80 {
81 hintp->width = defwidth;
82 hintp->height = defheight;
83 hintp->flags |= PSize;
84 }
85
86 if (geom_result & XNegative)
87 {
88 hintp->x = DisplayWidth (dpy, DefaultScreen (dpy)) + hintp->x -
89 hintp->width;
90 }
91 if (geom_result & YNegative)
92 {
93 hintp->y = DisplayHeight (dpy, DefaultScreen (dpy)) + hintp->y -
94 hintp->height;
95 }
96 }
97
98
99
100 void
get_key_binding(Display * dpy,char ** argv,int argc)101 get_key_binding (Display * dpy, char **argv, int argc)
102 {
103 XSizeHints hints;
104 int borderwidth = 2;
105 Window w;
106 XSetWindowAttributes attr;
107 unsigned long mask = 0L;
108 int done;
109 char *name = "XBindKey: Hit a key";
110 int screen;
111 Keys_t key;
112 int min_keycode, max_keycode;
113
114 printf ("Press combination of keys or/and click under the window.\n");
115 printf ("You can use one of the two lines after \"NoCommand\"\n");
116 printf ("in $HOME/.xbindkeysrc to bind a key.\n");
117 if (have_to_get_binding == 2)
118 printf ("\n--- Press \"%s\" to stop. ---\n", STOP_KEY);
119
120 screen = DefaultScreen (dpy);
121
122 attr.event_mask = KeyReleaseMask | ButtonReleaseMask;
123
124 set_sizehints (dpy, &hints, OUTER_WINDOW_MIN_WIDTH, OUTER_WINDOW_MIN_HEIGHT,
125 OUTER_WINDOW_DEF_WIDTH, OUTER_WINDOW_DEF_HEIGHT,
126 OUTER_WINDOW_DEF_X, OUTER_WINDOW_DEF_Y);
127
128 attr.background_pixel = WhitePixel (dpy, screen);;
129 attr.border_pixel = BlackPixel (dpy, screen);;
130 mask |= (CWBackPixel | CWBorderPixel | CWEventMask);
131
132 w = XCreateWindow (dpy, RootWindow (dpy, screen), hints.x, hints.y,
133 hints.width, hints.height, borderwidth, 0,
134 InputOutput, (Visual *) CopyFromParent, mask, &attr);
135
136 XSetStandardProperties (dpy, w, name, NULL, (Pixmap) 0, argv, argc, &hints);
137
138 XMapWindow (dpy, w);
139
140 XDisplayKeycodes (dpy, &min_keycode, &max_keycode);
141
142 sleep (1);
143
144 verbose = 1;
145
146 for (done = 0; !done;)
147 {
148 XEvent event;
149
150 XNextEvent (dpy, &event);
151
152 switch (event.type)
153 {
154 case KeyRelease:
155 key.type = CODE;
156 key.event_type = PRESS;
157 key.key.code = event.xkey.keycode;
158 key.modifier = event.xkey.state;
159 key.command = NULL;
160
161 if (have_to_get_binding == 2)
162 {
163 print_key (dpy, &key);
164
165 if (event.xkey.keycode ==
166 XKeysymToKeycode (dpy, XStringToKeysym (STOP_KEY)))
167 {
168 done = 1;
169 }
170 }
171 else
172 {
173 print_key (dpy, &key);
174
175 done = 1;
176 }
177
178 if (event.xkey.keycode < min_keycode
179 || event.xkey.keycode > max_keycode)
180 {
181 fprintf (stderr,
182 "Note:\n"
183 " The keycode %d cannot be used, as it's not between the\n"
184 " min(%d) and max(%d) keycode of your keyboard.\n"
185 " Please increase the 'maximum' value in\n"
186 " /usr/X11R6/lib/X11/xkb/keycodes/xfree86,\n"
187 " then restart X.\n",
188 event.xkey.keycode, min_keycode, max_keycode);
189 }
190
191 break;
192
193 case ButtonRelease :
194 key.type = BUTTON;
195 key.event_type = PRESS;
196 key.key.button = event.xbutton.button;
197 key.modifier = event.xbutton.state;
198 key.command = NULL;
199
200 print_key (dpy, &key);
201
202 if (have_to_get_binding == 1)
203 done = 1;
204 break;
205
206
207 default:
208 break;
209 }
210 }
211 }
212