dsimple.c revision 8b5ec993
1/* $Xorg: dsimple.c,v 1.4 2001/02/09 02:05:54 xorgcvs Exp $ */
2/*
3
4  Copyright 1993, 1998  The Open Group
5
6  Permission to use, copy, modify, distribute, and sell this software and its
7  documentation for any purpose is hereby granted without fee, provided that
8  the above copyright notice appear in all copies and that both that
9  copyright notice and this permission notice appear in supporting
10  documentation.
11
12  The above copyright notice and this permission notice shall be included
13  in all copies or substantial portions of the Software.
14
15  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
19  OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20  ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21  OTHER DEALINGS IN THE SOFTWARE.
22
23  Except as contained in this notice, the name of The Open Group shall
24  not be used in advertising or otherwise to promote the sale, use or
25  other dealings in this Software without prior written authorization
26  from The Open Group.
27
28*/
29
30#include <X11/Xlib.h>
31#include <X11/cursorfont.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include <stdarg.h>
35#include <string.h>
36#include <regex.h>
37/*
38 * Other_stuff.h: Definitions of routines in other_stuff.
39 *
40 * Written by Mark Lillibridge.   Last updated 7/1/87
41 */
42
43#include "clientwin.h"
44#include "dsimple.h"
45
46/*
47 * Just_display: A group of routines designed to make the writing of simple
48 *               X11 applications which open a display but do not open
49 *               any windows much faster and easier.  Unless a routine says
50 *               otherwise, it may be assumed to require program_name, dpy,
51 *               and screen already defined on entry.
52 *
53 * Written by Mark Lillibridge.   Last updated 7/1/87
54 */
55
56
57/* This stuff is defined in the calling program by dsimple.h */
58const char *program_name = "unknown_program";
59Display *dpy;
60int screen;
61
62/*
63 * Get_Display_Name (argc, argv) Look for -display, -d, or host:dpy (obsolete)
64 * If found, remove it from command line.  Don't go past a lone -.
65 */
66static char *
67Get_Display_Name (int *pargc, char **argv)
68{
69    int argc = *pargc;
70    char **pargv = argv + 1;
71    char *displayname = NULL;
72    int i;
73
74    for (i = 1; i < argc; i++) {
75        char *arg = argv[i];
76
77        if (!strcmp (arg, "-display") || !strcmp (arg, "-d")) {
78            if (++i >= argc)
79                Usage ();
80
81            displayname = argv[i];
82            *pargc -= 2;
83            continue;
84        }
85        if (!strcmp (arg, "-")) {
86            while (i <argc)
87                *pargv++ = argv[i++];
88            break;
89        }
90        *pargv++ = arg;
91    }
92
93    *pargv = NULL;
94    return (displayname);
95}
96
97
98/*
99 * Open_Display: Routine to open a display with correct error handling.
100 *               Does not require dpy or screen defined on entry.
101 */
102static Display *
103Open_Display (const char *display_name)
104{
105    Display *d;
106
107    d = XOpenDisplay (display_name);
108    if (d == NULL) {
109        fprintf (stderr, "%s:  unable to open display '%s'\n",
110                 program_name, XDisplayName (display_name));
111        Usage ();
112    }
113
114    return (d);
115}
116
117
118/*
119 * Setup_Display_And_Screen: This routine opens up the correct display (i.e.,
120 *                           it calls Get_Display_Name) and then stores a
121 *                           pointer to it in dpy.  The default screen
122 *                           for this display is then stored in screen.
123 *                           Does not require dpy or screen defined.
124 */
125void
126Setup_Display_And_Screen (int *argc, char **argv)
127{
128    dpy = Open_Display (Get_Display_Name (argc, argv));
129    screen = DefaultScreen (dpy);
130}
131
132/*
133 * Other_stuff: A group of routines which do common X11 tasks.
134 *
135 * Written by Mark Lillibridge.   Last updated 7/1/87
136 */
137
138/*
139 * Standard fatal error routine - call like printf but maximum of 7 arguments.
140 * Does not require dpy or screen defined.
141 */
142void
143Fatal_Error (const char *msg, ...)
144{
145    va_list args;
146    fflush (stdout);
147    fflush (stderr);
148    fprintf (stderr, "%s: error: ", program_name);
149    va_start (args, msg);
150    vfprintf (stderr, msg, args);
151    va_end (args);
152    fprintf (stderr, "\n");
153    exit (1);
154}
155
156/*
157 * Routine to let user select a window using the mouse
158 */
159
160Window
161Select_Window (Display *disp, int descend)
162{
163    int status;
164    Cursor cursor;
165    XEvent event;
166    Window target_win = None, root = RootWindow (disp, screen);
167    int buttons = 0;
168
169    /* Make the target cursor */
170    cursor = XCreateFontCursor (disp, XC_crosshair);
171
172    /* Grab the pointer using target cursor, letting it room all over */
173    status = XGrabPointer (disp, root, False,
174                           ButtonPressMask|ButtonReleaseMask, GrabModeSync,
175                           GrabModeAsync, root, cursor, CurrentTime);
176    if (status != GrabSuccess)
177        Fatal_Error ("Can't grab the mouse.");
178
179    /* Let the user select a window... */
180    while ((target_win == None) || (buttons != 0)) {
181        /* allow one more event */
182        XAllowEvents (disp, SyncPointer, CurrentTime);
183        XWindowEvent (disp, root, ButtonPressMask | ButtonReleaseMask, &event);
184        switch (event.type) {
185        case ButtonPress:
186            if (target_win == None) {
187                target_win = event.xbutton.subwindow; /* window selected */
188                if (target_win == None)
189                    target_win = root;
190            }
191            buttons++;
192            break;
193        case ButtonRelease:
194            if (buttons > 0) /* there may have been some down before we started */
195                buttons--;
196            break;
197        }
198    }
199
200    XUngrabPointer (disp, CurrentTime); /* Done with pointer */
201
202    if (!descend || (target_win == root))
203        return(target_win);
204
205    target_win = Find_Client(dpy, root, target_win);
206
207    return (target_win);
208}
209
210/*
211 * Routine that returns the window currently under the cursor
212 * Added by Daniel Forchheimer.   Last updated 19/12/04
213 */
214
215Window
216Get_Window_Under_Cursor (Display *disp, int descend)
217{
218    int status;
219    Cursor cursor;
220    //XEvent event;
221    Window target_win = None, root = RootWindow (disp, screen);
222    //int buttons = 0;
223    Window tmp;
224    int rx, ry, cx, cy;
225    unsigned int mask;
226
227    /* Make the target cursor */
228    cursor = XCreateFontCursor (disp, XC_crosshair);
229
230    /* Grab the pointer using target cursor, letting it roam all over */
231    status = XGrabPointer (disp, root, False,
232                           ButtonPressMask|ButtonReleaseMask, GrabModeSync,
233                           GrabModeAsync, root, cursor, CurrentTime);
234    if (status != GrabSuccess)
235        Fatal_Error ("Can't grab the mouse.");
236
237    /* get the window under the cursor */
238    XQueryPointer (disp, root, &tmp, &target_win, &rx, &ry,
239                   &cx, &cy, &mask);
240
241    XUngrabPointer (disp, CurrentTime);      /* Done with pointer */
242
243    if (!descend || (target_win == root))
244        return(target_win);
245
246    target_win = Find_Client(dpy, root, target_win);
247
248    return (target_win);
249}
250
251/*
252 * Window_With_Name: routine to locate a window with a given name on a display.
253 *                   If no window with the given name is found, 0 is returned.
254 *                   If more than one window has the given name, the first
255 *                   one found will be returned.  Only top and its subwindows
256 *                   are looked at.  Normally, top should be the RootWindow.
257 */
258Window
259Window_With_Name (Display *disp, Window top, char *name)
260{
261    Window *children, dummy;
262    unsigned int nchildren, i;
263    Window w = 0;
264    char *window_name;
265
266    if (XFetchName (disp, top, &window_name) && !strcmp (window_name, name))
267        return (top);
268
269    if (!XQueryTree (disp, top, &dummy, &dummy, &children, &nchildren))
270        return (0);
271
272    for (i = 0; i < nchildren; i++) {
273        w = Window_With_Name (disp, children[i], name);
274        if (w)
275            break;
276    }
277    if (children)
278        XFree (children);
279    return (w);
280}
281
282/*
283 * Window_With_Name_Regex: Same as above but use regular expressions
284 *                         to match a window name. Only returns the first
285 *                         result.
286 * Window_With_Name_Regex_Recurse: Takes regex_t struct as argument instead of char*
287 * Written by Daniel Forchheimer 2005
288 * */
289static Window
290Window_With_Name_Regex_Recurse (Display *disp, Window top,
291                                regex_t *reg_name)
292{
293    Window *children, dummy;
294    unsigned int nchildren, i;
295    Window w = 0;
296    char *window_name;
297
298    if (XFetchName (disp, top, &window_name) &&
299        !regexec (reg_name, window_name, 0, NULL, 0))
300        return (top);
301
302    if (!XQueryTree (disp, top, &dummy, &dummy, &children, &nchildren))
303        return (0);
304
305    for (i = 0; i < nchildren; i++) {
306        w = Window_With_Name_Regex_Recurse (disp, children[i], reg_name);
307        if (w)
308            break;
309    }
310    if (children)
311        XFree (children);
312    return (w);
313}
314
315/* prepare the reg-exp for use with above function */
316Window
317Window_With_Name_Regex (Display *disp, Window top, const char *name)
318{
319    int err_no = 0;
320    regex_t *regexp_name;
321    Window target_win;
322    regexp_name = malloc (sizeof (regex_t));
323    if ((err_no = regcomp (regexp_name, name, 0)) != 0) {
324        size_t length;
325        char *buffer;
326        length = regerror (err_no, regexp_name, NULL, 0);
327        buffer = malloc (length);
328        regerror (err_no, regexp_name, buffer, length);
329        fprintf (stderr, "%s\n", buffer);
330        free (buffer);
331        regfree (regexp_name);
332        exit (1);
333    }
334    target_win = Window_With_Name_Regex_Recurse (disp,
335                                                 RootWindow (disp, screen),
336                                                 regexp_name);
337
338    regfree (regexp_name);
339    free (regexp_name);
340    return target_win;
341}
342