├── Makefile ├── README.md └── xwinwrap.c /Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS= -g -Wall 3 | INCLUDE = -L /usr/lib/x86_64-linux-gnu 4 | LIBS = -lX11 -lXext -lXrender 5 | 6 | all: 7 | ${CC} xwinwrap.c ${CFLAGS} ${INCLUDE} ${LIBS} -o xwinwrap 8 | 9 | install: 10 | install xwinwrap '/usr/local/bin' 11 | 12 | uninstall: 13 | rm -f '/usr/local/bin/xwinwrap' 14 | 15 | clean: 16 | rm -f xwinwrap 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Xwinwrap 2 | 3 | My fork of xwinwrap. 4 | Xwinwrap allows you to stick most of the apps to your desktop background. 5 | My use case - can use gif as a background 6 | 7 | ![demo gif](https://github.com/ujjwal96/xwinwrap/blob/demo/demo.gif) 8 | 9 | ### Installing 10 | 11 | ``` 12 | sudo apt-get install xorg-dev build-essential libx11-dev x11proto-xext-dev libxrender-dev libxext-dev 13 | git clone https://github.com/ujjwal96/xwinwrap.git 14 | cd xwinwrap 15 | make 16 | sudo make install 17 | make clean 18 | ``` 19 | 20 | ### Usage 21 | 22 | ``` 23 | Usage: xwinwrap [-g {w}x{h}+{x}+{y}] [-ni] [-argb] [-fdt] [-fs] [-s] [-st] [-sp] [-a] [-d] [-b] [-nf] [-o OPACITY] [-sh SHAPE] [-ov]-- COMMAND ARG1... 24 | Options: 25 | -g - Specify Geometry (w=width, h=height, x=x-coord, y=y-coord. ex: -g 640x480+100+100) 26 | -ni - Ignore Input 27 | -argb - RGB 28 | -fdt - force WID window a desktop type window 29 | -fs - Full Screen 30 | -un - Undecorated 31 | -s - Sticky 32 | -st - Skip Taskbar 33 | -sp - Skip Pager 34 | -a - Above 35 | -b - Below 36 | -nf - No Focus 37 | -o - Opacity value between 0 to 1 (ex: -o 0.20) 38 | -sh - Shape of window (choose between rectangle, circle or triangle. Default is rectangle) 39 | -ov - Set override_redirect flag (For seamless desktop background integration in non-fullscreenmode) 40 | -d - Daemonize 41 | -debug - Enable debug messages 42 | ``` 43 | Example 44 | `xwinwrap -g 400x400 -ni -s -nf -b -un -argb -sh circle -- gifview -w WID mygif.gif -a` 45 | 46 | ### Changes 47 | 48 | * Added ability to make undecorated window 49 | * Changed how desktop window is found 50 | * Refactored window hints 51 | 52 | ---- 53 | Original source - https://launchpad.net/xwinwrap 54 | -------------------------------------------------------------------------------- /xwinwrap.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define WIDTH 512 20 | #define HEIGHT 384 21 | 22 | #define OPAQUE 0xffffffff 23 | 24 | #define NAME "xwinwrap" 25 | 26 | #define ATOM(a) XInternAtom(display, #a, False) 27 | 28 | Display *display = NULL; 29 | int display_width; 30 | int display_height; 31 | int screen; 32 | 33 | typedef enum 34 | { 35 | SHAPE_RECT = 0, 36 | SHAPE_CIRCLE, 37 | SHAPE_TRIG, 38 | } win_shape; 39 | 40 | struct window { 41 | Window root, window, desktop; 42 | Drawable drawable; 43 | Visual *visual; 44 | Colormap colourmap; 45 | 46 | unsigned int width; 47 | unsigned int height; 48 | int x; 49 | int y; 50 | } window; 51 | 52 | bool debug = false; 53 | 54 | static pid_t pid = 0; 55 | 56 | static char **childArgv = 0; 57 | static int nChildArgv = 0; 58 | 59 | static int addArguments (char **argv, int n) 60 | { 61 | char **newArgv; 62 | int i; 63 | 64 | newArgv = realloc (childArgv, sizeof (char *) * (nChildArgv + n)); 65 | if (!newArgv) 66 | return 0; 67 | 68 | for (i = 0; i < n; i++) 69 | newArgv[nChildArgv + i] = argv[i]; 70 | 71 | childArgv = newArgv; 72 | nChildArgv += n; 73 | 74 | return n; 75 | } 76 | 77 | static void setWindowOpacity (unsigned int opacity) 78 | { 79 | CARD32 o; 80 | 81 | o = opacity; 82 | 83 | XChangeProperty (display, window.window, ATOM(_NET_WM_WINDOW_OPACITY), 84 | XA_CARDINAL, 32, PropModeReplace, 85 | (unsigned char *) &o, 1); 86 | } 87 | 88 | static void init_x11() 89 | { 90 | display = XOpenDisplay (NULL); 91 | if (!display) 92 | { 93 | fprintf (stderr, NAME": Error: couldn't open display\n"); 94 | return; 95 | } 96 | screen = DefaultScreen(display); 97 | display_width = DisplayWidth(display, screen); 98 | display_height = DisplayHeight(display, screen); 99 | } 100 | 101 | static int get_argb_visual(Visual** visual, int *depth) { 102 | XVisualInfo visual_template; 103 | XVisualInfo *visual_list; 104 | int nxvisuals = 0, i; 105 | 106 | visual_template.screen = screen; 107 | visual_list = XGetVisualInfo (display, VisualScreenMask, 108 | &visual_template, &nxvisuals); 109 | for (i = 0; i < nxvisuals; i++) { 110 | if (visual_list[i].depth == 32 && 111 | (visual_list[i].red_mask == 0xff0000 && 112 | visual_list[i].green_mask == 0x00ff00 && 113 | visual_list[i].blue_mask == 0x0000ff)) { 114 | *visual = visual_list[i].visual; 115 | *depth = visual_list[i].depth; 116 | if (debug) 117 | fprintf(stderr, "Found ARGB Visual\n"); 118 | XFree(visual_list); 119 | return 1; 120 | } 121 | } 122 | if (debug) 123 | fprintf(stderr, "No ARGB Visual found"); 124 | XFree(visual_list); 125 | return 0; 126 | } 127 | 128 | static void sigHandler (int sig) 129 | { 130 | kill (pid, sig); 131 | } 132 | 133 | static void usage (void) 134 | { 135 | fprintf(stderr, "%s \n", NAME); 136 | fprintf (stderr, "\nUsage: %s [-g {w}x{h}+{x}+{y}] [-ni] [-argb] [-fdt] [-fs] [-s] [-st] [-sp] [-a] [-d] " 137 | "[-b] [-nf] [-o OPACITY] [-sh SHAPE] [-ov]-- COMMAND ARG1...\n", NAME); 138 | fprintf (stderr, "Options:\n \ 139 | -g - Specify Geometry (w=width, h=height, x=x-coord, y=y-coord. ex: -g 640x480+100+100)\n \ 140 | -ni - Ignore Input\n \ 141 | -argb - RGB\n \ 142 | -fdt - force WID window a desktop type window\n \ 143 | -fs - Full Screen\n \ 144 | -un - Undecorated\n \ 145 | -s - Sticky\n \ 146 | -st - Skip Taskbar\n \ 147 | -sp - Skip Pager\n \ 148 | -a - Above\n \ 149 | -b - Below\n \ 150 | -nf - No Focus\n \ 151 | -o - Opacity value between 0 to 1 (ex: -o 0.20)\n \ 152 | -sh - Shape of window (choose between rectangle, circle or triangle. Default is rectangle)\n \ 153 | -ov - Set override_redirect flag (For seamless desktop background integration in non-fullscreenmode)\n \ 154 | -d - Daemonize\n \ 155 | -debug - Enable debug messages\n"); 156 | } 157 | 158 | 159 | static Window find_subwindow(Window win, int w, int h) 160 | { 161 | unsigned int i, j; 162 | Window troot, parent, *children; 163 | unsigned int n; 164 | 165 | /* search subwindows with same size as display or work area */ 166 | 167 | for (i = 0; i < 10; i++) { 168 | XQueryTree(display, win, &troot, &parent, &children, &n); 169 | 170 | for (j = 0; j < n; j++) { 171 | XWindowAttributes attrs; 172 | 173 | if (XGetWindowAttributes(display, children[j], &attrs)) { 174 | /* Window must be mapped and same size as display or 175 | * work space */ 176 | if (attrs.map_state != 0 && ((attrs.width == display_width 177 | && attrs.height == display_height) 178 | || (attrs.width == w && attrs.height == h))) { 179 | win = children[j]; 180 | break; 181 | } 182 | } 183 | } 184 | 185 | XFree(children); 186 | if (j == n) { 187 | break; 188 | } 189 | } 190 | 191 | return win; 192 | } 193 | 194 | static Window find_desktop_window(Window *p_root, Window *p_desktop) 195 | { 196 | Atom type; 197 | int format, i; 198 | unsigned long nitems, bytes; 199 | unsigned int n; 200 | Window root = RootWindow(display, screen); 201 | Window win = root; 202 | Window troot, parent, *children; 203 | unsigned char *buf = NULL; 204 | 205 | if (!p_root || !p_desktop) { 206 | return 0; 207 | } 208 | 209 | /* some window managers set __SWM_VROOT to some child of root window */ 210 | 211 | XQueryTree(display, root, &troot, &parent, &children, &n); 212 | for (i = 0; i < (int) n; i++) { 213 | if (XGetWindowProperty(display, children[i], ATOM(__SWM_VROOT), 0, 1, 214 | False, XA_WINDOW, &type, &format, &nitems, &bytes, &buf) 215 | == Success && type == XA_WINDOW) { 216 | win = *(Window *) buf; 217 | XFree(buf); 218 | XFree(children); 219 | if (debug) 220 | { 221 | fprintf(stderr, 222 | NAME": desktop window (%lx) found from __SWM_VROOT property\n", 223 | win); 224 | } 225 | fflush(stderr); 226 | *p_root = win; 227 | *p_desktop = win; 228 | return win; 229 | } 230 | 231 | if (buf) { 232 | XFree(buf); 233 | buf = 0; 234 | } 235 | } 236 | XFree(children); 237 | 238 | /* get subwindows from root */ 239 | win = find_subwindow(root, -1, -1); 240 | 241 | display_width = DisplayWidth(display, screen); 242 | display_height = DisplayHeight(display, screen); 243 | 244 | win = find_subwindow(win, display_width, display_height); 245 | 246 | if (buf) { 247 | XFree(buf); 248 | buf = 0; 249 | } 250 | 251 | if (win != root && debug) { 252 | fprintf(stderr, 253 | NAME": desktop window (%lx) is subwindow of root window (%lx)\n", 254 | win, root); 255 | } else if (debug) { 256 | fprintf(stderr, NAME": desktop window (%lx) is root window\n", win); 257 | } 258 | 259 | fflush(stderr); 260 | 261 | *p_root = root; 262 | *p_desktop = win; 263 | 264 | return win; 265 | } 266 | 267 | int main(int argc, char **argv) 268 | { 269 | char widArg[256]; 270 | char *widArgv[] = { widArg }; 271 | char *endArg = NULL; 272 | int status = 0; 273 | unsigned int opacity = OPAQUE; 274 | 275 | int i; 276 | bool have_argb_visual = false; 277 | bool noInput = false; 278 | bool argb = false; 279 | bool set_desktop_type = false; 280 | bool fullscreen = false; 281 | bool noFocus = false; 282 | bool override = false; 283 | bool undecorated = false; 284 | bool sticky = false; 285 | bool below = false; 286 | bool above = false; 287 | bool skip_taskbar = false; 288 | bool skip_pager = false; 289 | bool daemonize = false; 290 | 291 | win_shape shape = SHAPE_RECT; 292 | Pixmap mask; 293 | GC mask_gc; 294 | XGCValues xgcv; 295 | 296 | window.width = WIDTH; 297 | window.height = HEIGHT; 298 | 299 | for (i = 1; i < argc; i++) 300 | { 301 | if (strcmp (argv[i], "-g") == 0) 302 | { 303 | if (++i < argc) 304 | XParseGeometry (argv[i], &window.x, &window.y, &window.width, &window.height); 305 | } 306 | else if (strcmp (argv[i], "-ni") == 0) 307 | { 308 | noInput = 1; 309 | } 310 | else if (strcmp (argv[i], "-argb") == 0) 311 | { 312 | argb = true; 313 | } 314 | else if (strcmp (argv[i], "-fdt") == 0) 315 | { 316 | set_desktop_type = true; 317 | } 318 | else if (strcmp (argv[i], "-fs") == 0) 319 | { 320 | fullscreen = 1; 321 | } 322 | else if (strcmp (argv[i], "-un") == 0) 323 | { 324 | undecorated = true; 325 | } 326 | else if (strcmp (argv[i], "-s") == 0) 327 | { 328 | sticky = true; 329 | } 330 | else if (strcmp (argv[i], "-st") == 0) 331 | { 332 | skip_taskbar = true; 333 | } 334 | else if (strcmp (argv[i], "-sp") == 0) 335 | { 336 | skip_pager = true; 337 | } 338 | else if (strcmp (argv[i], "-a") == 0) 339 | { 340 | above = true; 341 | } 342 | else if (strcmp (argv[i], "-b") == 0) 343 | { 344 | below = true; 345 | } 346 | else if (strcmp (argv[i], "-nf") == 0) 347 | { 348 | noFocus = 1; 349 | } 350 | else if (strcmp (argv[i], "-o") == 0) 351 | { 352 | if (++i < argc) 353 | opacity = (unsigned int) (atof (argv[i]) * OPAQUE); 354 | } 355 | else if (strcmp (argv[i], "-sh") == 0) 356 | { 357 | if (++i < argc) 358 | { 359 | if (strcasecmp(argv[i], "circle") == 0) 360 | { 361 | shape = SHAPE_CIRCLE; 362 | } 363 | else if (strcasecmp(argv[i], "triangle") == 0) 364 | { 365 | shape = SHAPE_TRIG; 366 | } 367 | } 368 | } 369 | else if (strcmp (argv[i], "-ov") == 0) 370 | { 371 | override = true; 372 | } 373 | else if (strcmp (argv[i], "-debug") == 0) 374 | { 375 | debug = true; 376 | } 377 | else if (strcmp (argv[i], "-d") == 0) 378 | { 379 | daemonize = true; 380 | } 381 | else if (strcmp (argv[i], "--") == 0) 382 | { 383 | break; 384 | } 385 | else 386 | { 387 | usage (); 388 | return 1; 389 | } 390 | } 391 | 392 | if (daemonize) 393 | { 394 | pid_t process_id = 0; 395 | pid_t sid = 0; 396 | process_id = fork(); 397 | if (process_id < 0) 398 | { 399 | fprintf(stderr, "fork failed!\n"); 400 | exit(1); 401 | } 402 | 403 | if (process_id > 0) 404 | { 405 | fprintf(stderr, "pid of child process %d \n", process_id); 406 | exit(0); 407 | } 408 | umask(0); 409 | sid = setsid(); 410 | if (sid < 0) 411 | { 412 | exit(1); 413 | } 414 | 415 | chdir("/"); 416 | close(STDIN_FILENO); 417 | close(STDOUT_FILENO); 418 | close(STDERR_FILENO); 419 | } 420 | 421 | for (i = i + 1; i < argc; i++) 422 | { 423 | if (strcmp (argv[i], "WID") == 0) 424 | addArguments (widArgv, 1); 425 | else 426 | addArguments (&argv[i], 1); 427 | } 428 | 429 | if (!nChildArgv) 430 | { 431 | fprintf (stderr, "%s: Error: couldn't create command line\n", argv[0]); 432 | usage (); 433 | 434 | return 1; 435 | } 436 | 437 | addArguments (&endArg, 1); 438 | 439 | init_x11(); 440 | if (!display) 441 | return 1; 442 | 443 | if (fullscreen) 444 | { 445 | window.x = 0; 446 | window.y = 0; 447 | window.width = DisplayWidth (display, screen); 448 | window.height = DisplayHeight (display, screen); 449 | } 450 | int depth = 0, flags = CWOverrideRedirect | CWBackingStore; 451 | Visual *visual = NULL; 452 | 453 | if (!find_desktop_window(&window.root, &window.desktop)) { 454 | fprintf (stderr, NAME": Error: couldn't find desktop window\n"); 455 | return 1; 456 | } 457 | 458 | if (argb && get_argb_visual(&visual, &depth)) 459 | { 460 | have_argb_visual = true; 461 | window.visual = visual; 462 | window.colourmap = XCreateColormap(display, 463 | DefaultRootWindow(display), window.visual, AllocNone); 464 | } 465 | else 466 | { 467 | window.visual = DefaultVisual(display, screen); 468 | window.colourmap = DefaultColormap(display, screen); 469 | depth = CopyFromParent; 470 | visual = CopyFromParent; 471 | 472 | } 473 | 474 | if (override) { 475 | /* An override_redirect True window. 476 | * No WM hints or button processing needed. */ 477 | XSetWindowAttributes attrs = { ParentRelative, 0L, 0, 0L, 0, 0, 478 | Always, 0L, 0L, False, StructureNotifyMask | ExposureMask, 0L, 479 | True, 0, 0 480 | }; 481 | 482 | if (have_argb_visual) 483 | { 484 | attrs.colormap = window.colourmap; 485 | flags |= CWBorderPixel | CWColormap; 486 | } 487 | else 488 | { 489 | flags |= CWBackPixel; 490 | } 491 | 492 | window.window = XCreateWindow(display, window.desktop, window.x, 493 | window.y, window.width, window.height, 0, depth, InputOutput, visual, 494 | flags, &attrs); 495 | XLowerWindow(display, window.window); 496 | 497 | fprintf(stderr, NAME": window type - override\n"); 498 | fflush(stderr); 499 | } 500 | else 501 | { 502 | XSetWindowAttributes attrs = { ParentRelative, 0L, 0, 0L, 0, 0, 503 | Always, 0L, 0L, False, StructureNotifyMask | ExposureMask | 504 | ButtonPressMask | ButtonReleaseMask, 0L, False, 0, 0 505 | }; 506 | 507 | XWMHints wmHint; 508 | Atom xa; 509 | 510 | if (have_argb_visual) 511 | { 512 | attrs.colormap = window.colourmap; 513 | flags |= CWBorderPixel | CWColormap; 514 | } 515 | else 516 | { 517 | flags |= CWBackPixel; 518 | } 519 | 520 | window.window = XCreateWindow(display, window.root, window.x, 521 | window.y, window.width, window.height, 0, depth, InputOutput, visual, 522 | flags, &attrs); 523 | 524 | wmHint.flags = InputHint | StateHint; 525 | // wmHint.input = undecorated ? False : True; 526 | wmHint.input = !noFocus; 527 | wmHint.initial_state = NormalState; 528 | 529 | XSetWMProperties(display, window.window, NULL, NULL, argv, 530 | argc, NULL, &wmHint, NULL); 531 | 532 | xa = ATOM(_NET_WM_WINDOW_TYPE); 533 | 534 | Atom prop; 535 | if (set_desktop_type) 536 | { 537 | prop = ATOM(_NET_WM_WINDOW_TYPE_DESKTOP); 538 | } else { 539 | prop = ATOM(_NET_WM_WINDOW_TYPE_NORMAL); 540 | } 541 | 542 | XChangeProperty(display, window.window, xa, XA_ATOM, 32, 543 | PropModeReplace, (unsigned char *) &prop, 1); 544 | 545 | if (undecorated) { 546 | xa = ATOM(_MOTIF_WM_HINTS); 547 | if (xa != None) { 548 | long prop[5] = { 2, 0, 0, 0, 0 }; 549 | XChangeProperty(display, window.window, xa, xa, 32, 550 | PropModeReplace, (unsigned char *) prop, 5); 551 | } 552 | } 553 | 554 | /* Below other windows */ 555 | if (below) { 556 | 557 | xa = ATOM(_WIN_LAYER); 558 | if (xa != None) { 559 | long prop = 0; 560 | 561 | XChangeProperty(display, window.window, xa, XA_CARDINAL, 32, 562 | PropModeAppend, (unsigned char *) &prop, 1); 563 | } 564 | 565 | xa = ATOM(_NET_WM_STATE); 566 | if (xa != None) { 567 | Atom xa_prop = ATOM(_NET_WM_STATE_BELOW); 568 | 569 | XChangeProperty(display, window.window, xa, XA_ATOM, 32, 570 | PropModeAppend, (unsigned char *) &xa_prop, 1); 571 | } 572 | } 573 | 574 | /* Above other windows */ 575 | if (above) { 576 | 577 | xa = ATOM(_WIN_LAYER); 578 | if (xa != None) { 579 | long prop = 6; 580 | 581 | XChangeProperty(display, window.window, xa, XA_CARDINAL, 32, 582 | PropModeAppend, (unsigned char *) &prop, 1); 583 | } 584 | 585 | xa = ATOM(_NET_WM_STATE); 586 | if (xa != None) { 587 | Atom xa_prop = ATOM(_NET_WM_STATE_ABOVE); 588 | 589 | XChangeProperty(display, window.window, xa, XA_ATOM, 32, 590 | PropModeAppend, (unsigned char *) &xa_prop, 1); 591 | } 592 | } 593 | 594 | /* Sticky */ 595 | if (sticky) { 596 | 597 | xa = ATOM(_NET_WM_DESKTOP); 598 | if (xa != None) { 599 | CARD32 xa_prop = 0xFFFFFFFF; 600 | 601 | XChangeProperty(display, window.window, xa, XA_CARDINAL, 32, 602 | PropModeAppend, (unsigned char *) &xa_prop, 1); 603 | } 604 | 605 | xa = ATOM(_NET_WM_STATE); 606 | if (xa != None) { 607 | Atom xa_prop = ATOM(_NET_WM_STATE_STICKY); 608 | 609 | XChangeProperty(display, window.window, xa, XA_ATOM, 32, 610 | PropModeAppend, (unsigned char *) &xa_prop, 1); 611 | } 612 | } 613 | 614 | /* Skip taskbar */ 615 | if (skip_taskbar) { 616 | 617 | xa = ATOM(_NET_WM_STATE); 618 | if (xa != None) { 619 | Atom xa_prop = ATOM(_NET_WM_STATE_SKIP_TASKBAR); 620 | 621 | XChangeProperty(display, window.window, xa, XA_ATOM, 32, 622 | PropModeAppend, (unsigned char *) &xa_prop, 1); 623 | } 624 | } 625 | 626 | /* Skip pager */ 627 | if (skip_pager) { 628 | 629 | xa = ATOM(_NET_WM_STATE); 630 | if (xa != None) { 631 | Atom xa_prop = ATOM(_NET_WM_STATE_SKIP_PAGER); 632 | 633 | XChangeProperty(display, window.window, xa, XA_ATOM, 32, 634 | PropModeAppend, (unsigned char *) &xa_prop, 1); 635 | } 636 | } 637 | } 638 | 639 | if (opacity != OPAQUE) 640 | setWindowOpacity (opacity); 641 | 642 | if (noInput) 643 | { 644 | Region region; 645 | 646 | region = XCreateRegion (); 647 | if (region) 648 | { 649 | XShapeCombineRegion (display, window.window, ShapeInput, 0, 0, region, ShapeSet); 650 | XDestroyRegion (region); 651 | } 652 | } 653 | 654 | if (shape) 655 | { 656 | mask = XCreatePixmap(display, window.window, window.width, window.height, 1); 657 | mask_gc = XCreateGC(display, mask, 0, &xgcv); 658 | 659 | switch (shape) 660 | { 661 | //Nothing special to be done if it's a rectangle 662 | case SHAPE_CIRCLE: 663 | /* fill mask */ 664 | XSetForeground(display, mask_gc, 0); 665 | XFillRectangle(display, mask, mask_gc, 0, 0, window.width, window.height); 666 | 667 | XSetForeground(display, mask_gc, 1); 668 | XFillArc(display, mask, mask_gc, 0, 0, window.width, window.height, 0, 23040); 669 | break; 670 | 671 | case SHAPE_TRIG: 672 | { 673 | XPoint points[3] = { {0, window.height}, 674 | {window.width / 2, 0}, 675 | {window.width, window.height} 676 | }; 677 | 678 | XSetForeground(display, mask_gc, 0); 679 | XFillRectangle(display, mask, mask_gc, 0, 0, window.width, window.height); 680 | 681 | XSetForeground(display, mask_gc, 1); 682 | XFillPolygon(display, mask, mask_gc, points, 3, Complex, CoordModeOrigin); 683 | } 684 | 685 | break; 686 | 687 | default: 688 | break; 689 | 690 | } 691 | /* combine */ 692 | XShapeCombineMask(display, window.window, ShapeBounding, 0, 0, mask, ShapeSet); 693 | } 694 | 695 | 696 | 697 | XMapWindow(display, window.window); 698 | 699 | XSync (display, window.window); 700 | 701 | sprintf (widArg, "0x%x", (int) window.window); 702 | 703 | pid = fork (); 704 | 705 | switch (pid) { 706 | case -1: 707 | perror ("fork"); 708 | return 1; 709 | case 0: 710 | execvp (childArgv[0], childArgv); 711 | perror (childArgv[0]); 712 | exit (2); 713 | break; 714 | default: 715 | break; 716 | } 717 | 718 | signal (SIGTERM, sigHandler); 719 | signal (SIGINT, sigHandler); 720 | 721 | for (;;) 722 | { 723 | if (waitpid (pid, &status, 0) != -1) 724 | { 725 | if (WIFEXITED (status)) 726 | fprintf (stderr, "%s died, exit status %d\n", childArgv[0], 727 | WEXITSTATUS (status)); 728 | 729 | break; 730 | } 731 | } 732 | 733 | XDestroyWindow (display, window.window); 734 | XCloseDisplay (display); 735 | 736 | 737 | return 0; 738 | } 739 | --------------------------------------------------------------------------------