/* SPDX-License-Identifier: GPL-2.0-or-later */ #include #include #include #include #include #include #include #include #define VERSION "0.1" void set_motif_no_title_decoration_hint(Display *dpy, Window win, Bool border_only) { #define PROP_MOTIF_WM_HINTS_ELEMENTS 5 #define MWM_HINTS_DECORATIONS (1L << 1) #define MWM_DECOR_BORDER (1L << 1) typedef struct { unsigned long flags; unsigned long functions; unsigned long decorations; long inputMode; unsigned long status; } PropMotifWmHints; PropMotifWmHints *hints; Atom atom_MOTIF_WM_HINTS = XInternAtom(dpy, "_MOTIF_WM_HINTS", False); hints = malloc(sizeof(PropMotifWmHints)); memset(hints, 0, sizeof(PropMotifWmHints)); hints->flags = MWM_HINTS_DECORATIONS; if (border_only) hints->decorations = MWM_DECOR_BORDER; else hints->decorations = 0; XChangeProperty(dpy, win, atom_MOTIF_WM_HINTS, XA_ATOM, 32, PropModeReplace, (unsigned char *)hints, PROP_MOTIF_WM_HINTS_ELEMENTS); free(hints); return; } static Visual * find_argb_visual (Display *dpy, int scr) { XVisualInfo *xvi; XVisualInfo template; int nvi; int i; XRenderPictFormat *format; Visual *visual; template.screen = scr; template.depth = 32; template.class = TrueColor; xvi = XGetVisualInfo (dpy, VisualScreenMask | VisualDepthMask | VisualClassMask, &template, &nvi); if (!xvi) return 0; visual = 0; for (i = 0; i < nvi; i++) { format = XRenderFindVisualFormat (dpy, xvi[i].visual); if (format->type == PictTypeDirect && format->direct.alphaMask) { visual = xvi[i].visual; break; } } XFree (xvi); return visual; } void usage(char *progname) { fprintf(stderr, "%s " VERSION " usage:\n" "--image, -i . ( default 'test.png')\n" "--no-title, -nt Window has borders only\n" "--no-border, -nb Window has no decorations\n" "--override-redirect, -or Window is overide redirect\n" "--pos, -p Window position\n" "--move, -m Move window by x,y in z steps\n" "--help, -h Show this help\n", progname); exit(1); } int main(int argc, char **argv) { Display *dpy; Window winroot, win; int screen; GC gc; MBPixbuf *pb; MBPixbufImage *img; int depth = 32; Visual *vis; XEvent xev; Pixmap pxm; XSetWindowAttributes attributes; unsigned long attributemask = 0; Bool is_no_title = False; Bool is_no_border = False; Bool is_override = False; int i, x1 = 0, y1 = 0, x2 = -1 , y2 = -1, n_steps = 0; char *imgpath = "test.png"; for (i = 1; i < argc; i++) { if (!strcmp ("--image", argv[i]) || !strcmp ("-i", argv[i])) { if (++i>=argc) usage (argv[0]); imgpath = argv[i]; continue; } if (!strcmp ("--pos", argv[i]) || !strcmp ("-p", argv[i])) { char *p = NULL; if (++i>=argc) usage (argv[0]); if ((p = strchr(argv[i], ',')) == NULL) usage (argv[0]); *p='\0'; p++; x1 = atoi(argv[i]); y1 = atoi(p); continue; } if (!strcmp ("--move", argv[i]) || !strcmp ("-m", argv[i])) { if (++i>=argc) usage (argv[0]); if (sscanf(argv[i], "%d,%d,%d", &x2, &y2, &n_steps) != 3) usage (argv[0]); continue; } if (!strcmp ("--no-title", argv[i]) || !strcmp ("-nt", argv[i])) { is_no_title = True; continue; } if (!strcmp ("--no-border", argv[i]) || !strcmp ("-nb", argv[i])) { is_no_border = True; continue; } if (!strcmp ("--override-redirect", argv[i]) || !strcmp ("-or", argv[i])) { is_override = True; continue; } if (!strcmp("--help", argv[i]) || !strcmp("-h", argv[i])) { usage(argv[0]); } usage(argv[0]); } if ((dpy = XOpenDisplay(getenv("DISPLAY"))) == NULL) { fprintf(stderr, "Unable to open DISPLAY. Giving up.\n"); return 1; } screen = DefaultScreen(dpy); winroot = RootWindow(dpy, screen); vis = find_argb_visual (dpy, screen); if (!vis) { fprintf(stderr, "failed to find argb32 visual\n"); return 1; } pb = mb_pixbuf_new_extended(dpy, screen, vis, 32); img = mb_pixbuf_img_new_from_file(pb, imgpath); if (!img) { fprintf(stderr, "failed to load image '%s'\n", imgpath); return 1; } if (is_override) attributes.override_redirect = True; else attributes.override_redirect = False; attributes.background_pixel = 1; attributes.border_pixel = 1; attributes.colormap = XCreateColormap (dpy, winroot, vis, AllocNone); attributemask = (CWBackPixel| CWBorderPixel| CWColormap| CWOverrideRedirect); win = XCreateWindow (dpy, winroot, x1, y1, mb_pixbuf_img_get_width(img), mb_pixbuf_img_get_height(img), 0, depth, InputOutput, vis, attributemask, &attributes); if ( is_no_title || is_no_border ) set_motif_no_title_decoration_hint(dpy, win, is_no_title); XStoreName(dpy, win, imgpath); pxm = XCreatePixmap(dpy, winroot, mb_pixbuf_img_get_width(img), mb_pixbuf_img_get_height(img), depth); pb->gc = XCreateGC(dpy, pxm, 0, 0); XFlush(dpy); /* Needed ? */ mb_pixbuf_img_render_to_drawable(pb, img, pxm, 0, 0); XSetWindowBackgroundPixmap(dpy, win, pxm); XClearWindow(dpy, win); XSetTransientForHint(dpy, win, winroot); XMapWindow(dpy, win); XFlush(dpy); /* Move the window */ if (x2 != -1 && y2 != -1) { int i; XSync(dpy, True); for (i=0; i < n_steps; i++) { XMoveWindow(dpy, win, x1 + (( x2 / n_steps) * i ), y1 + (( y2 / n_steps) * i )); // XSync(dpy, True); } } for (;;) XNextEvent(dpy, &xev); }