The initial Slint problem was larger than thought. Hopefully a more universal fix.

This commit is contained in:
Storm Dragon committed 2026-11-01 15:48:33 -05:00
1 parent d0fdce7285
commit 1c12bc6636
10 files changed
+294 -6

No files matched your search

+52
View File
@@ -175,6 +175,57 @@ PointerPosition cthulhu_read_pointer(Display *display) {
if (cthulhu_x11_end_read(display)) result = (PointerPosition){0};
return result;
}
// Resolve only the client's immediate enclosing frame. Some WMs omit or leave
// stale _NET_FRAME_EXTENTS, while GTK reports the real reparenting frame.
// A container with another managed client is not this client's decoration.
// The caller holds the Xlib error guard throughout these read-only queries.
static void cthulhu_read_frame_bounds(Display *display, Window window, Foreground *result) {
Window root, parent, *children = NULL;
unsigned int count = 0;
if (!XQueryTree(display, window, &root, &parent, &children, &count)) return;
if (children) XFree(children);
if (parent == None || parent == root) return;
XWindowAttributes attributes;
if (!XGetWindowAttributes(display, parent, &attributes) ||
attributes.class != InputOutput || attributes.override_redirect ||
attributes.map_state != IsViewable) return;
Atom stateAtom = XInternAtom(display, "WM_STATE", False);
Atom type = None; int format = 0; unsigned long items = 0;
unsigned char *data = cthulhu_window_property(display, parent, stateAtom, &type, &format, &items);
if (data) XFree(data);
if (type != None) return;
Window treeRoot, frameParent;
children = NULL;
if (!XQueryTree(display, parent, &treeRoot, &frameParent, &children, &count)) return;
int unambiguous = count <= 64, foundClient = 0;
for (unsigned int index = 0; unambiguous && index < count; index++) {
if (children[index] == window) { foundClient = 1; continue; }
data = cthulhu_window_property(display, children[index], stateAtom, &type, &format, &items);
if (data) XFree(data);
if (type != None) unambiguous = 0;
}
if (children) XFree(children);
if (!unambiguous || !foundClient) return;
int x, y;
Window child;
if (!XTranslateCoordinates(display, parent, root, 0, 0, &x, &y, &child)) return;
int border = attributes.border_width;
x -= border; y -= border;
int width = attributes.width + 2 * border, height = attributes.height + 2 * border;
// Decorations must enclose the client and remain bounded like the EWMH
// extents. Never turn an unrelated workspace into a frame match.
int left = result->x - x, top = result->y - y;
int right = x + width - result->x - result->width;
int bottom = y + height - result->y - result->height;
if (left < 0 || top < 0 || right < 0 || bottom < 0 ||
left >= 1024 || top >= 1024 || right >= 1024 || bottom >= 1024) return;
result->frameX = x; result->frameY = y;
result->frameWidth = width; result->frameHeight = height;
}
// Read-only metadata connection, owned by the caller's native event thread.
// All requests which can race window destruction share the Xlib error guard.
Foreground read_foreground(Display *display) {
@@ -227,6 +278,7 @@ Foreground read_foreground(Display *display) {
}
}
if (data) XFree(data);
cthulhu_read_frame_bounds(display, window, &result);
data=cthulhu_window_property(display,window,XInternAtom(display,"_NET_WM_PID",False),&type,&format,&items);
if (data && type==XA_CARDINAL && format==32 && items==1) result.pid=(int)((unsigned long *)data)[0];
if (data) XFree(data);