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