Convert over to use GetOpt::Long and introduce -f and -h.
[fvwm.git] / libs / Target.c
blobae732a8c1ba97e735593aff21d9d186101307005
1 /* -*-c-*- */
2 /* This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 ** fvwmlib_get_target_window and fvwmlib_keyboard_shortcuts - handle window
19 ** selection from modules and fvwm.
22 #include "config.h"
24 #include <stdio.h>
25 #include <signal.h>
26 #include <ctype.h>
27 #include <unistd.h>
29 #include <X11/keysym.h>
30 #include <X11/X.h>
31 #include <X11/Xlib.h>
32 #include <X11/cursorfont.h>
34 #include "fvwmlib.h"
35 #include "Grab.h"
36 #include "Target.h"
38 void fvwmlib_keyboard_shortcuts(
39 Display *dpy, int screen, XEvent *Event, int x_move_size,
40 int y_move_size, int *x_defect, int *y_defect, int ReturnEvent)
42 int x;
43 int y;
44 int x_root;
45 int y_root;
46 int x_move;
47 int y_move;
48 KeySym keysym;
49 Window JunkRoot;
50 unsigned int JunkMask;
52 if (y_move_size < DEFAULT_KDB_SHORTCUT_MOVE_DISTANCE)
54 y_move_size = DEFAULT_KDB_SHORTCUT_MOVE_DISTANCE;
56 if (x_move_size < DEFAULT_KDB_SHORTCUT_MOVE_DISTANCE)
58 x_move_size = DEFAULT_KDB_SHORTCUT_MOVE_DISTANCE;
60 if (Event->xkey.state & ControlMask)
62 x_move_size = y_move_size = KDB_SHORTCUT_MOVE_DISTANCE_SMALL;
64 if (Event->xkey.state & ShiftMask)
66 x_move_size = y_move_size = KDB_SHORTCUT_MOVE_DISTANCE_BIG;
69 keysym = XLookupKeysym(&Event->xkey,0);
71 x_move = 0;
72 y_move = 0;
73 switch(keysym)
75 case XK_Up:
76 case XK_KP_8:
77 case XK_k:
78 case XK_p:
79 y_move = -y_move_size;
80 break;
81 case XK_Down:
82 case XK_KP_2:
83 case XK_n:
84 case XK_j:
85 y_move = y_move_size;
86 break;
87 case XK_Left:
88 case XK_KP_4:
89 case XK_b:
90 case XK_h:
91 x_move = -x_move_size;
92 break;
93 case XK_Right:
94 case XK_KP_6:
95 case XK_f:
96 case XK_l:
97 x_move = x_move_size;
98 break;
99 case XK_KP_1:
100 x_move = -x_move_size;
101 y_move = y_move_size;
102 break;
103 case XK_KP_3:
104 x_move = x_move_size;
105 y_move = y_move_size;
106 break;
107 case XK_KP_7:
108 x_move = -x_move_size;
109 y_move = -y_move_size;
110 break;
111 case XK_KP_9:
112 x_move = x_move_size;
113 y_move = -y_move_size;
114 break;
115 case XK_Return:
116 case XK_KP_Enter:
117 case XK_space:
118 /* beat up the event */
119 Event->type = ReturnEvent;
120 break;
121 case XK_Escape:
122 /* simple code to bag out of move - CKH */
123 /* return keypress event instead */
124 Event->type = KeyPress;
125 Event->xkey.keycode = XKeysymToKeycode(
126 Event->xkey.display,keysym);
127 break;
128 default:
129 break;
131 if (x_move || y_move)
133 int x_def_new = 0;
134 int y_def_new = 0;
136 if (FQueryPointer(
137 dpy, RootWindow(dpy, screen), &JunkRoot,
138 &Event->xany.window, &x_root, &y_root, &x, &y,
139 &JunkMask) == False)
141 /* pointer is on a different screen - do nothing */
142 return;
144 if (x + x_move < 0)
146 x_def_new = x + x_move;
147 x_move = -x;
149 else if (x + x_move >= DisplayWidth(dpy, DefaultScreen(dpy)))
151 x_def_new = x + x_move - DisplayWidth(
152 dpy, DefaultScreen(dpy));
153 x_move = DisplayWidth(dpy, DefaultScreen(dpy)) - x - 1;
155 if (y + y_move < 0)
157 y_def_new = y + y_move;
158 y_move = -y;
160 else if (y + y_move >= DisplayHeight(dpy, DefaultScreen(dpy)))
162 y_def_new = y + y_move - DisplayHeight(
163 dpy, DefaultScreen(dpy));
164 y_move = DisplayHeight(
165 dpy, DefaultScreen(dpy)) - y - 1;
167 if (x_defect)
169 int diff = 0;
171 *x_defect += x_def_new;
172 if (*x_defect > 0 && x_move < 0)
174 diff = min(*x_defect, -x_move);
176 else if (*x_defect < 0 && x_move > 0)
178 diff = max(*x_defect, -x_move);
180 *x_defect -= diff;
181 x_move += diff;
183 if (y_defect)
185 int diff = 0;
187 *y_defect += y_def_new;
188 if (*y_defect > 0 && y_move < 0)
190 diff = min(*y_defect, -y_move);
192 else if (*y_defect < 0 && y_move > 0)
194 diff = max(*y_defect, -y_move);
196 *y_defect -= diff;
197 y_move += diff;
199 if (x_move || y_move)
201 FWarpPointer(
202 dpy, None, RootWindow(dpy, screen), 0, 0, 0, 0,
203 x_root + x_move, y_root + y_move);
205 /* beat up the event */
206 Event->type = MotionNotify;
207 Event->xkey.x += x_move;
208 Event->xkey.y += y_move;
209 Event->xkey.x_root += x_move;
210 Event->xkey.y_root += y_move;
214 void fvwmlib_get_target_window(
215 Display *dpy, int screen, char *MyName, Window *app_win,
216 Bool return_subwindow)
218 XEvent eventp;
219 int val = -10,trials;
220 Bool finished = False;
221 Bool canceled = False;
222 Window Root = RootWindow(dpy, screen);
223 int is_key_pressed = 0;
224 int is_button_pressed = 0;
225 KeySym keysym;
227 trials = 0;
228 while((trials <10)&&(val != GrabSuccess))
230 val=XGrabPointer(dpy, Root, True,
231 ButtonPressMask | ButtonReleaseMask,
232 GrabModeAsync, GrabModeAsync, Root,
233 XCreateFontCursor(dpy,XC_crosshair),
234 CurrentTime);
235 switch (val)
237 case GrabInvalidTime:
238 case GrabNotViewable:
239 /* give up */
240 trials += 100000;
241 break;
242 case GrabSuccess:
243 break;
244 case AlreadyGrabbed:
245 case GrabFrozen:
246 default:
247 usleep(10000);
248 trials++;
249 break;
252 if(val != GrabSuccess)
254 fprintf(stderr,"%s: Couldn't grab the cursor!\n",MyName);
255 exit(1);
257 MyXGrabKeyboard(dpy);
259 while (!finished && !canceled)
261 FMaskEvent(dpy, ButtonPressMask | ButtonReleaseMask |
262 KeyPressMask | KeyReleaseMask, &eventp);
263 switch (eventp.type)
265 case KeyPress:
266 is_key_pressed++;
267 break;
268 case KeyRelease:
269 keysym = XLookupKeysym(&eventp.xkey,0);
270 if( !is_key_pressed ) break;
271 switch (keysym)
273 case XK_Escape:
274 canceled = True;
275 break;
276 case XK_space:
277 case XK_Return:
278 case XK_KP_Enter:
279 finished = True;
280 break;
281 default:
282 fvwmlib_keyboard_shortcuts(
283 dpy, screen, &eventp, 0, 0, NULL,
284 NULL, 0);
285 break;
287 break;
288 case ButtonPress:
289 is_button_pressed++;
290 break;
291 case ButtonRelease:
292 if( is_button_pressed ) finished = True;
293 break;
297 MyXUngrabKeyboard(dpy);
298 XUngrabPointer(dpy, CurrentTime);
299 XSync(dpy,0);
300 if (canceled)
302 *app_win = None;
303 return;
305 *app_win = eventp.xany.window;
306 if(return_subwindow && eventp.xbutton.subwindow != None)
307 *app_win = eventp.xbutton.subwindow;
309 return;
312 Window fvwmlib_client_window(Display *dpy, Window input)
314 Atom _XA_WM_STATE;
315 unsigned int nchildren;
316 Window root, parent, *children,target;
317 unsigned long nitems, bytesafter;
318 unsigned char *prop;
319 Atom atype;
320 int aformat;
321 int i;
323 _XA_WM_STATE = XInternAtom (dpy, "WM_STATE", False);
325 if (
326 XGetWindowProperty(
327 dpy, input, _XA_WM_STATE , 0L, 3L , False,
328 _XA_WM_STATE, &atype, &aformat, &nitems, &bytesafter,
329 &prop) == Success)
331 if(prop != NULL)
333 XFree(prop);
334 return input;
338 if (!XQueryTree(dpy, input, &root, &parent, &children, &nchildren))
339 return None;
341 for (i = 0; i < nchildren; i++)
343 target = fvwmlib_client_window(dpy, children[i]);
344 if(target != None)
346 XFree((char *)children);
347 return target;
350 XFree((char *)children);
352 return None;