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