dsimple.c revision 9f1d9476
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 "dsimple.h"
44
45/*
46 * Just_display: A group of routines designed to make the writing of simple
47 *               X11 applications which open a display but do not open
48 *               any windows much faster and easier.  Unless a routine says
49 *               otherwise, it may be assumed to require program_name, dpy,
50 *               and screen already defined on entry.
51 *
52 * Written by Mark Lillibridge.   Last updated 7/1/87
53 */
54
55
56/* This stuff is defined in the calling program by dsimple.h */
57const char *program_name = "unknown_program";
58Display *dpy;
59int screen;
60
61/*
62 * Get_Display_Name (argc, argv) Look for -display, -d, or host:dpy (obsolete)
63 * If found, remove it from command line.  Don't go past a lone -.
64 */
65static char *
66Get_Display_Name (int *pargc, char **argv)
67{
68    int argc = *pargc;
69    char **pargv = argv + 1;
70    char *displayname = NULL;
71    int i;
72
73    for (i = 1; i < argc; i++) {
74        char *arg = argv[i];
75
76        if (!strcmp (arg, "-display") || !strcmp (arg, "-d")) {
77            if (++i >= argc)
78                Usage ();
79
80            displayname = argv[i];
81            *pargc -= 2;
82            continue;
83        }
84        if (!strcmp (arg, "-")) {
85            while (i <argc)
86                *pargv++ = argv[i++];
87            break;
88        }
89        *pargv++ = arg;
90    }
91
92    *pargv = NULL;
93    return (displayname);
94}
95
96
97/*
98 * Open_Display: Routine to open a display with correct error handling.
99 *               Does not require dpy or screen defined on entry.
100 */
101static Display *
102Open_Display (char *display_name)
103{
104    Display *d;
105
106    d = XOpenDisplay (display_name);
107    if (d == NULL) {
108        fprintf (stderr, "%s:  unable to open display '%s'\n",
109                 program_name, XDisplayName (display_name));
110        Usage ();
111    }
112
113    return (d);
114}
115
116
117/*
118 * Setup_Display_And_Screen: This routine opens up the correct display (i.e.,
119 *                           it calls Get_Display_Name) and then stores a
120 *                           pointer to it in dpy.  The default screen
121 *                           for this display is then stored in screen.
122 *                           Does not require dpy or screen defined.
123 */
124void
125Setup_Display_And_Screen (int *argc, char **argv)
126{
127    dpy = Open_Display (Get_Display_Name (argc, argv));
128    screen = DefaultScreen (dpy);
129}
130
131/*
132 * Other_stuff: A group of routines which do common X11 tasks.
133 *
134 * Written by Mark Lillibridge.   Last updated 7/1/87
135 */
136
137/*
138 * Standard fatal error routine - call like printf but maximum of 7 arguments.
139 * Does not require dpy or screen defined.
140 */
141void
142Fatal_Error (const char *msg, ...)
143{
144    va_list args;
145    fflush (stdout);
146    fflush (stderr);
147    fprintf (stderr, "%s: error: ", program_name);
148    va_start (args, msg);
149    vfprintf (stderr, msg, args);
150    va_end (args);
151    fprintf (stderr, "\n");
152    exit (1);
153}
154
155/*
156 * Routine to let user select a window using the mouse
157 */
158
159Window
160Select_Window (Display *disp)
161{
162    int status;
163    Cursor cursor;
164    XEvent event;
165    Window target_win = None, root = RootWindow (disp, screen);
166    int buttons = 0;
167
168    /* Make the target cursor */
169    cursor = XCreateFontCursor (disp, XC_crosshair);
170
171    /* Grab the pointer using target cursor, letting it room all over */
172    status = XGrabPointer (disp, root, False,
173                           ButtonPressMask|ButtonReleaseMask, GrabModeSync,
174                           GrabModeAsync, root, cursor, CurrentTime);
175    if (status != GrabSuccess)
176        Fatal_Error ("Can't grab the mouse.");
177
178    /* Let the user select a window... */
179    while ((target_win == None) || (buttons != 0)) {
180        /* allow one more event */
181        XAllowEvents (disp, SyncPointer, CurrentTime);
182        XWindowEvent (disp, root, ButtonPressMask | ButtonReleaseMask, &event);
183        switch (event.type) {
184        case ButtonPress:
185            if (target_win == None) {
186                target_win = event.xbutton.subwindow; /* window selected */
187                if (target_win == None)
188                    target_win = root;
189            }
190            buttons++;
191            break;
192        case ButtonRelease:
193            if (buttons > 0) /* there may have been some down before we started */
194                buttons--;
195            break;
196        }
197    }
198
199    XUngrabPointer (disp, CurrentTime); /* Done with pointer */
200
201    return (target_win);
202}
203
204/*
205 * Routine that returns the window currently under the cursor
206 * Added by Daniel Forchheimer.   Last updated 19/12/04
207 */
208
209Window
210Get_Window_Under_Cursor (Display *disp)
211{
212    int status;
213    Cursor cursor;
214    //XEvent event;
215    Window target_win = None, root = RootWindow (disp, screen);
216    //int buttons = 0;
217    Window tmp;
218    int rx, ry, cx, cy;
219    unsigned int mask;
220
221    /* Make the target cursor */
222    cursor = XCreateFontCursor (disp, XC_crosshair);
223
224    /* Grab the pointer using target cursor, letting it roam all over */
225    status = XGrabPointer (disp, root, False,
226                           ButtonPressMask|ButtonReleaseMask, GrabModeSync,
227                           GrabModeAsync, root, cursor, CurrentTime);
228    if (status != GrabSuccess)
229        Fatal_Error ("Can't grab the mouse.");
230
231    /* get the window under the cursor */
232    XQueryPointer (disp, root, &tmp, &target_win, &rx, &ry,
233                   &cx, &cy, &mask);
234
235    XUngrabPointer (disp, CurrentTime);      /* Done with pointer */
236
237    return (target_win);
238}
239
240/*
241 * Window_With_Name: routine to locate a window with a given name on a display.
242 *                   If no window with the given name is found, 0 is returned.
243 *                   If more than one window has the given name, the first
244 *                   one found will be returned.  Only top and its subwindows
245 *                   are looked at.  Normally, top should be the RootWindow.
246 */
247Window
248Window_With_Name (Display *disp, Window top, char *name)
249{
250    Window *children, dummy;
251    unsigned int nchildren, i;
252    Window w = 0;
253    char *window_name;
254
255    if (XFetchName (disp, top, &window_name) && !strcmp (window_name, name))
256        return (top);
257
258    if (!XQueryTree (disp, top, &dummy, &dummy, &children, &nchildren))
259        return (0);
260
261    for (i = 0; i < nchildren; i++) {
262        w = Window_With_Name (disp, children[i], name);
263        if (w)
264            break;
265    }
266    if (children)
267        XFree (children);
268    return (w);
269}
270
271/*
272 * Window_With_Name_Regex: Same as above but use regular expressions
273 *                         to match a window name. Only returns the first
274 *                         result.
275 * Window_With_Name_Regex_Recurse: Takes regex_t struct as argument instead of char*
276 * Written by Daniel Forchheimer 2005
277 * */
278static Window
279Window_With_Name_Regex_Recurse (Display *disp, Window top,
280                                regex_t *reg_name)
281{
282    Window *children, dummy;
283    unsigned int nchildren, i;
284    Window w = 0;
285    char *window_name;
286
287    if (XFetchName (disp, top, &window_name) &&
288        !regexec (reg_name, window_name, 0, NULL, 0))
289        return (top);
290
291    if (!XQueryTree (disp, top, &dummy, &dummy, &children, &nchildren))
292        return (0);
293
294    for (i = 0; i < nchildren; i++) {
295        w = Window_With_Name_Regex_Recurse (disp, children[i], reg_name);
296        if (w)
297            break;
298    }
299    if (children)
300        XFree (children);
301    return (w);
302}
303
304/* prepare the reg-exp for use with above function */
305Window
306Window_With_Name_Regex (Display *disp, Window top, char *name)
307{
308    int err_no = 0;
309    regex_t *regexp_name;
310    Window target_win;
311    regexp_name = malloc (sizeof (regex_t));
312    if ((err_no = regcomp (regexp_name, name, 0)) != 0) {
313        size_t length;
314        char *buffer;
315        length = regerror (err_no, regexp_name, NULL, 0);
316        buffer = malloc (length);
317        regerror (err_no, regexp_name, buffer, length);
318        fprintf (stderr, "%s\n", buffer);
319        free (buffer);
320        regfree (regexp_name);
321        exit (1);
322    }
323    target_win = Window_With_Name_Regex_Recurse (disp,
324                                                 RootWindow (disp, screen),
325                                                 regexp_name);
326
327    regfree (regexp_name);
328    free (regexp_name);
329    return target_win;
330}
331