xwinwrap

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

commit 0fd31504b960f3d9a62a4a24acb2685e3405ba76
Author: deurzen <max@deurzen.net>
Date:   Wed, 25 May 2022 05:32:52 +0200

initial commit

Diffstat:
AMakefile | 8++++++++
Axwinwrap | 0
Axwinwrap.c | 256+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 264 insertions(+), 0 deletions(-)

diff --git a/Makefile b/Makefile @@ -0,0 +1,8 @@ +all: + gcc xwinwrap.c -o xwinwrap `pkg-config --libs x11 xext xrender` + +install: + install xwinwrap /usr/bin/ + +clean: + -rm -f xwinwrap diff --git a/xwinwrap b/xwinwrap Binary files differ. diff --git a/xwinwrap.c b/xwinwrap.c @@ -0,0 +1,256 @@ +/* + * Copyright © 2005 Novell, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of + * Novell, Inc. not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior permission. + * Novell, Inc. makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: David Reveman <davidr@novell.com> + */ + +/* + * Modified by: Max van Deurzen + * Homepage: https://git.deurzen.net/ + */ + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Xatom.h> +#include <X11/Xproto.h> + +#include <X11/extensions/shape.h> +#include <X11/extensions/Xrender.h> + +#include <stdlib.h> +#include <string.h> +#include <signal.h> +#include <stdio.h> +#include <unistd.h> +#include <sys/wait.h> +#include <sys/stat.h> +#include <sys/types.h> + +typedef enum { + SHAPE_RECT = 0, + SHAPE_CIRCLE, + SHAPE_TRIG, +} win_shape; + +static pid_t pid = 0; + +static char** childArgv = 0; +static int nChildArgv = 0; +int debug = 0; + +static int +addArguments(char** argv, int n) +{ + char** newArgv; + int i; + + newArgv = realloc(childArgv, sizeof(char*) * (nChildArgv + n)); + if (!newArgv) + return 0; + + for (i = 0; i < n; i++) + newArgv[nChildArgv + i] = argv[i]; + + childArgv = newArgv; + nChildArgv += n; + + return n; +} + +static void +sigHandler(int sig) +{ + kill(pid, sig); +} + +static Window +find_desktop_window(Display* display, int screen, Window* root, Window* p_desktop) +{ + int i; + unsigned int n; + Window win = *root; + Window troot, parent, *children; + char* name; + int status; + int width = DisplayWidth(display, screen); + int height = DisplayHeight(display, screen); + XWindowAttributes attrs; + + XQueryTree(display, *root, &troot, &parent, &children, &n); + for (i = 0; i < (int)n; i++) { + status = XFetchName(display, children[i], &name); + status |= XGetWindowAttributes(display, children[i], &attrs); + if ((status != 0) && (NULL != name)) { + if ((attrs.map_state != 0) && (attrs.width == width) && (attrs.height == height)) + { + win = children[i]; + XFree(children); + XFree(name); + *p_desktop = win; + return win; + } + if (name) { + XFree(name); + } + } + } + return 0; +} + +int +main(int argc, char** argv) +{ + Display* dpy; + Window win; + Window root; + Window p_desktop = 0; + int screen; + XSizeHints xsh; + XWMHints xwmh; + char widArg[256]; + char* widArgv[] = { widArg }; + char* endArg = NULL; + int i; + int status = 0; + int x; + int y; + unsigned int width; + unsigned int height; + + dpy = XOpenDisplay(NULL); + if (!dpy) { + fprintf(stderr, "%s: could not open display\n", argv[0]); + return 1; + } + + screen = DefaultScreen(dpy); + root = RootWindow(dpy, screen); + + XWindowAttributes root_attrs; + XGetWindowAttributes(dpy, root, &root_attrs); + x = root_attrs.x; + y = root_attrs.y; + width = root_attrs.width; + height = root_attrs.height; + + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-g") == 0) { + if (++i < argc) + XParseGeometry(argv[i], &x, &y, &width, &height); + } else if (strcmp(argv[i], "--") == 0) { + break; + } else { + return 1; + } + } + + for (i = i + 1; i < argc; i++) { + if (strcmp(argv[i], "WID") == 0) + addArguments(widArgv, 1); + else + addArguments(&argv[i], 1); + } + + if (!nChildArgv) { + fprintf(stderr, "%s: could not create command line\n", argv[0]); + return 1; + } + + addArguments(&endArg, 1); + + xsh.flags = PSize; + xsh.width = width; + xsh.height = height; + + xwmh.flags = InputHint; + xwmh.input = 0; + + XSetWindowAttributes attr; + attr.override_redirect = 1; + + if (win == root) { + { // override-redirect + if (find_desktop_window(dpy, screen, &root, &p_desktop)) { + win = XCreateWindow(dpy, p_desktop, x, y, xsh.width, xsh.height, 0, + CopyFromParent, InputOutput, CopyFromParent, CWOverrideRedirect, &attr); + } else { + win = XCreateWindow(dpy, root, x, y, xsh.width, xsh.height, 0, CopyFromParent, + InputOutput, CopyFromParent, CWOverrideRedirect, &attr); + } + } + + XSetWMProperties(dpy, win, NULL, NULL, argv, argc, &xsh, &xwmh, NULL); + + { // noinput + Region region; + region = XCreateRegion(); + if (region) { + XShapeCombineRegion(dpy, win, ShapeInput, 0, 0, region, ShapeSet); + XDestroyRegion(region); + } + } + + { // below state + Atom window_type = XInternAtom(dpy, "_NET_WM_STATE", False); + Atom desktop = XInternAtom(dpy, "_NET_WM_STATE_BELOW", False); + XChangeProperty(dpy, win, window_type, XA_ATOM, 32, PropModeReplace, + (unsigned char*)&desktop, 1); + } + + XMapWindow(dpy, win); + } + + XSync(dpy, win); + sprintf(widArg, "0x%x", (int)win); + + pid = fork(); + switch (pid) { + case -1: + perror("fork"); + return 1; + case 0: + execvp(childArgv[0], childArgv); + perror(childArgv[0]); + exit(2); + break; + default: + break; + } + + signal(SIGTERM, sigHandler); + signal(SIGINT, sigHandler); + + for (;;) { + if (waitpid(pid, &status, 0) != -1) { + if (WIFEXITED(status)) + fprintf(stderr, "%s died, exit status %d\n", childArgv[0], + WEXITSTATUS(status)); + + break; + } + } + + XDestroyWindow(dpy, win); + XCloseDisplay(dpy); + + return 0; +}