xwinwrap.c (6663B)
1 /* 2 * Copyright © 2005 Novell, Inc. 3 * 4 * Permission to use, copy, modify, distribute, and sell this software 5 * and its documentation for any purpose is hereby granted without 6 * fee, provided that the above copyright notice appear in all copies 7 * and that both that copyright notice and this permission notice 8 * appear in supporting documentation, and that the name of 9 * Novell, Inc. not be used in advertising or publicity pertaining to 10 * distribution of the software without specific, written prior permission. 11 * Novell, Inc. makes no representations about the suitability of this 12 * software for any purpose. It is provided "as is" without express or 13 * implied warranty. 14 * 15 * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN 17 * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR 18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 19 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 20 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 21 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22 * 23 * Author: David Reveman <davidr@novell.com> 24 */ 25 26 /* 27 * Modified by: Max van Deurzen 28 * Homepage: https://git.deurzen.net/ 29 */ 30 31 #include <X11/Xlib.h> 32 #include <X11/Xutil.h> 33 #include <X11/Xatom.h> 34 #include <X11/Xproto.h> 35 36 #include <X11/extensions/shape.h> 37 #include <X11/extensions/Xrender.h> 38 39 #include <stdlib.h> 40 #include <string.h> 41 #include <signal.h> 42 #include <stdio.h> 43 #include <unistd.h> 44 #include <sys/wait.h> 45 #include <sys/stat.h> 46 #include <sys/types.h> 47 48 typedef enum { 49 SHAPE_RECT = 0, 50 SHAPE_CIRCLE, 51 SHAPE_TRIG, 52 } win_shape; 53 54 static pid_t pid = 0; 55 56 static char** childArgv = 0; 57 static int nChildArgv = 0; 58 int debug = 0; 59 60 static int 61 addArguments(char** argv, int n) 62 { 63 char** newArgv; 64 int i; 65 66 newArgv = realloc(childArgv, sizeof(char*) * (nChildArgv + n)); 67 if (!newArgv) 68 return 0; 69 70 for (i = 0; i < n; i++) 71 newArgv[nChildArgv + i] = argv[i]; 72 73 childArgv = newArgv; 74 nChildArgv += n; 75 76 return n; 77 } 78 79 static void 80 sigHandler(int sig) 81 { 82 kill(pid, sig); 83 } 84 85 static Window 86 find_desktop_window(Display* display, int screen, Window* root, Window* p_desktop) 87 { 88 int i; 89 unsigned int n; 90 Window win = *root; 91 Window troot, parent, *children; 92 char* name; 93 int status; 94 int width = DisplayWidth(display, screen); 95 int height = DisplayHeight(display, screen); 96 XWindowAttributes attrs; 97 98 XQueryTree(display, *root, &troot, &parent, &children, &n); 99 for (i = 0; i < (int)n; i++) { 100 status = XFetchName(display, children[i], &name); 101 status |= XGetWindowAttributes(display, children[i], &attrs); 102 if ((status != 0) && (NULL != name)) { 103 if ((attrs.map_state != 0) && (attrs.width == width) && (attrs.height == height)) 104 { 105 win = children[i]; 106 XFree(children); 107 XFree(name); 108 *p_desktop = win; 109 return win; 110 } 111 if (name) { 112 XFree(name); 113 } 114 } 115 } 116 return 0; 117 } 118 119 int 120 main(int argc, char** argv) 121 { 122 Display* dpy; 123 Window win; 124 Window root; 125 Window p_desktop = 0; 126 int screen; 127 XSizeHints xsh; 128 XWMHints xwmh; 129 char widArg[256]; 130 char* widArgv[] = { widArg }; 131 char* endArg = NULL; 132 int i; 133 int status = 0; 134 int x; 135 int y; 136 unsigned int width; 137 unsigned int height; 138 139 dpy = XOpenDisplay(NULL); 140 if (!dpy) { 141 fprintf(stderr, "%s: could not open display\n", argv[0]); 142 return 1; 143 } 144 145 screen = DefaultScreen(dpy); 146 root = RootWindow(dpy, screen); 147 148 XWindowAttributes root_attrs; 149 XGetWindowAttributes(dpy, root, &root_attrs); 150 x = root_attrs.x; 151 y = root_attrs.y; 152 width = root_attrs.width; 153 height = root_attrs.height; 154 155 for (i = 1; i < argc; i++) { 156 if (strcmp(argv[i], "-g") == 0) { 157 if (++i < argc) 158 XParseGeometry(argv[i], &x, &y, &width, &height); 159 } else if (strcmp(argv[i], "--") == 0) { 160 break; 161 } else { 162 return 1; 163 } 164 } 165 166 for (i = i + 1; i < argc; i++) { 167 if (strcmp(argv[i], "WID") == 0) 168 addArguments(widArgv, 1); 169 else 170 addArguments(&argv[i], 1); 171 } 172 173 if (!nChildArgv) { 174 fprintf(stderr, "%s: could not create command line\n", argv[0]); 175 return 1; 176 } 177 178 addArguments(&endArg, 1); 179 180 xsh.flags = PSize; 181 xsh.width = width; 182 xsh.height = height; 183 184 xwmh.flags = InputHint; 185 xwmh.input = 0; 186 187 XSetWindowAttributes attr; 188 attr.override_redirect = 1; 189 190 if (win == root) { 191 { // override-redirect 192 if (find_desktop_window(dpy, screen, &root, &p_desktop)) { 193 win = XCreateWindow(dpy, p_desktop, x, y, xsh.width, xsh.height, 0, 194 CopyFromParent, InputOutput, CopyFromParent, CWOverrideRedirect, &attr); 195 } else { 196 win = XCreateWindow(dpy, root, x, y, xsh.width, xsh.height, 0, CopyFromParent, 197 InputOutput, CopyFromParent, CWOverrideRedirect, &attr); 198 } 199 } 200 201 XSetWMProperties(dpy, win, NULL, NULL, argv, argc, &xsh, &xwmh, NULL); 202 203 { // noinput 204 Region region; 205 region = XCreateRegion(); 206 if (region) { 207 XShapeCombineRegion(dpy, win, ShapeInput, 0, 0, region, ShapeSet); 208 XDestroyRegion(region); 209 } 210 } 211 212 { // below state 213 Atom window_type = XInternAtom(dpy, "_NET_WM_STATE", False); 214 Atom desktop = XInternAtom(dpy, "_NET_WM_STATE_BELOW", False); 215 XChangeProperty(dpy, win, window_type, XA_ATOM, 32, PropModeReplace, 216 (unsigned char*)&desktop, 1); 217 } 218 219 XMapWindow(dpy, win); 220 } 221 222 XSync(dpy, win); 223 sprintf(widArg, "0x%x", (int)win); 224 225 pid = fork(); 226 switch (pid) { 227 case -1: 228 perror("fork"); 229 return 1; 230 case 0: 231 execvp(childArgv[0], childArgv); 232 perror(childArgv[0]); 233 exit(2); 234 break; 235 default: 236 break; 237 } 238 239 signal(SIGTERM, sigHandler); 240 signal(SIGINT, sigHandler); 241 242 for (;;) { 243 if (waitpid(pid, &status, 0) != -1) { 244 if (WIFEXITED(status)) 245 fprintf(stderr, "%s died, exit status %d\n", childArgv[0], 246 WEXITSTATUS(status)); 247 248 break; 249 } 250 } 251 252 XDestroyWindow(dpy, win); 253 XCloseDisplay(dpy); 254 255 return 0; 256 }