Skip to content

Instantly share code, notes, and snippets.

@matyklug18
Created November 7, 2021 15:00
Show Gist options
  • Save matyklug18/1f589b5de426b1e207e06fa5a36aa45e to your computer and use it in GitHub Desktop.
Save matyklug18/1f589b5de426b1e207e06fa5a36aa45e to your computer and use it in GitHub Desktop.
+ main.c [No Name] X
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
#include <X11/extensions/Xcomposite.h>
#include <X11/extensions/Xrender.h>
#include <X11/extensions/Xdamage.h>
#include <X11/extensions/shape.h>
Window root;
int scr;
Display* dpy;
Picture frontbuffer;
Picture backbuffer;
#define WIDTH DisplayWidth(dpy, scr)
#define HEIGHT DisplayHeight(dpy, scr)
#define DEPTH DefaultDepth(dpy, scr)
// Register a CM
int reg_cm() {
Window w;
Atom a;
static char net_wm_cm[] = "_NET_WM_CM_Sxx";
snprintf(net_wm_cm, sizeof(net_wm_cm), "_NET_WM_CM_S%d", scr);
a = XInternAtom(dpy, net_wm_cm, False);
// Error Handling
w = XGetSelectionOwner(dpy, a);
if(w != None) {
XTextProperty tp;
char** strs;
int count;
Atom win_name_atom = XInternAtom(dpy, "_NET_WM_NAME", False);
if(!XGetTextProperty(dpy, w, &tp, win_name_atom) && !XGetTextProperty(dpy, w, &tp, XA_WM_NAME)) {
fprintf(stderr,"Another composite manager is already running (0x%lx)\n",(unsigned long) w);
return False;
}
if(XmbTextPropertyToTextList(dpy, &tp, &strs, &count) == Success) {
fprintf(stderr,"Another composite manager is already running (%s)\n",strs[0]);
XFreeStringList(strs);
}
XFree(tp.value);
return False;
}
// Actual Registering
w = XCreateSimpleWindow(dpy, root, 0, 0, 1, 1, 0, None, None);
Xutf8SetWMProperties(dpy, w, "jacc", "jacc", NULL, 0, NULL, NULL, NULL);
XSetSelectionOwner(dpy, a, w, 0);
return True;
}
void setup_events() {
XGrabServer(dpy);
XCompositeRedirectSubwindows(dpy, root, CompositeRedirectManual);
XSelectInput(dpy, root,
SubstructureNotifyMask|
ExposureMask|
StructureNotifyMask|
PropertyChangeMask);
XUngrabServer(dpy);
}
void setup_xrender() {
XRenderPictFormat* d_format = XRenderFindVisualFormat(dpy, DefaultVisual(dpy, scr));
XRenderPictureAttributes pa;
pa.subwindow_mode = IncludeInferiors;
frontbuffer = XRenderCreatePicture(dpy, root, d_format, CPSubwindowMode, &pa);
Pixmap root_pixmap = XCreatePixmap(dpy, root, WIDTH, HEIGHT, DEPTH);
backbuffer = XRenderCreatePicture(dpy, root_pixmap, d_format, 0, NULL);
XFreePixmap(dpy, root_pixmap);
XSync(dpy, False);
}
void damage_all() {
Window* children;
uint children_count;
Window root_o, parent;
XShapeSelectInput (dpy, root, ShapeNotifyMask);
XQueryTree(dpy, root, &root_o, &parent, &children, &children_count);
XSync(dpy, False);
for(uint i = 0; i < children_count; i++) {
//usleep(1000*10);
XWindowAttributes attrs;
XGetWindowAttributes(dpy, children[i], &attrs);
if(attrs.class != InputOnly) {
XDamageCreate(dpy, children[i], XDamageReportNonEmpty);
XSync(dpy, False);
}
}
}
void paint() {
Window* children;
uint children_count;
Window root_o, parent;
XQueryTree(dpy, root, &root_o, &parent, &children, &children_count);
XRenderColor color;
color.alpha = 50000;
color.red = 0;
color.green = 20000;
color.blue = 40000;
XRenderFillRectangle(dpy, PictOpSrc, backbuffer, &color,
0, 0, WIDTH, HEIGHT);
for(uint i = 0; i < children_count; i++) {
XSync(dpy, False);
XWindowAttributes attrs;
XGetWindowAttributes(dpy, children[i], &attrs);
XSync(dpy, False);
XRenderPictFormat* pict_format = XRenderFindVisualFormat(dpy, attrs.visual);
XSync(dpy, False);
if(!pict_format || (pict_format->type == picttypedirect || pict_format->direct.alphamask)) {
printf("discard:%ld(%d,%d)\n", children[i], pict_format->type, pict_format->direct.alphaMask);
continue;
}
printf("naming:%ld(%d,%d)\n", children[i], pict_format->type, pict_format->direct.alphaMask);
Pixmap pixmap = XCompositeNameWindowPixmap(dpy, children[i]);
XSync(dpy, False);
printf("pict:%ld\n", children[i]);
Picture picture = XRenderCreatePicture(dpy, pixmap, pict_format, 0, 0);
XSync(dpy, False);
XRenderComposite(dpy, PictOpOver,
picture, None, backbuffer,
0, 0, 0, 0,
attrs.x, attrs.y, attrs.width, attrs.height);
XSync(dpy, False);
}
XRenderComposite(dpy, PictOpSrc,
backbuffer, None, frontbuffer,
0, 0, 0, 0,
0, 0, WIDTH, HEIGHT);
XSync(dpy, False);
XFlush(dpy);
}
int main() {
dpy = XOpenDisplay(NULL);
scr = DefaultScreen(dpy);
root = DefaultRootWindow(dpy);
XGrabServer(dpy);
if(!reg_cm(dpy)) {
exit(1);
}
setup_events();
setup_xrender();
XUngrabServer(dpy);
int damage_event, damage_error;
if (!XDamageQueryExtension(dpy, &damage_event, &damage_error)) {
fprintf(stderr, "No damage extension\n");
exit(1);
}
damage_all();
usleep(100*1000);
paint();
while(1) {
XEvent e;
XNextEvent(dpy, &e);
if(e.type == MapNotify) {
XCreateWindowEvent ev = e.xcreatewindow;
XWindowAttributes attrs;
XGetWindowAttributes(dpy, ev.window, &attrs);
if(attrs.class != InputOnly) {
XDamageCreate(dpy, ev.window, XDamageReportNonEmpty);
}
} else if(e.type == damage_event + XDamageNotify) {
paint();
printf("paint\n");
XDamageNotifyEvent* ev = (XDamageNotifyEvent*)&e;
XDamageSubtract(dpy, ev->damage, None, None);
} else {
printf("uncaught event:%d\n", e.type);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment