xwinwrap

Custom xwinwrap fork
git clone git://git.deurzen.net/xwinwrap
Log | Files | Refs

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 }