diff dep/animia/src/win/x11.cc @ 158:80d6b28eb29f

dep/animia: fix most X11 stuff it looks like _NET_WM_PID isn't supported by MOST clients, or my code is wrong... core/filesystem: fix Linux config path handling on *nix
author Paper <mrpapersonic@gmail.com>
date Fri, 17 Nov 2023 02:07:33 -0500
parents 18c8eb5d1edc
children 54c5d80a737e
line wrap: on
line diff
--- a/dep/animia/src/win/x11.cc	Thu Nov 16 16:51:34 2023 -0500
+++ b/dep/animia/src/win/x11.cc	Fri Nov 17 02:07:33 2023 -0500
@@ -5,8 +5,11 @@
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
 #include <X11/Xatom.h> // XA_*
+
 #include <cstdint>
 #include <string>
+#include <memory>
+#include <set>
 
 /* The code for this is very fugly because X11 uses lots of generic type names
    (i.e., Window, Display), so I have to use :: when defining vars to distinguish
@@ -15,20 +18,17 @@
 namespace animia::internal::x11 {
 
 /* should return UTF8_STRING or STRING */
-static bool GetWindowPropertyAsString(::Display* display, ::Window window, const char* atom, std::string& result, ::Atom reqtype = AnyPropertyType) {
+static bool GetWindowPropertyAsString(::Display* display, ::Window window, ::Atom atom, std::string& result, ::Atom reqtype = AnyPropertyType) {
 	int format;
 	unsigned long leftover_bytes, num_of_items;
 	::Atom type;
 	unsigned char* data;
-
-	if (!::XGetWindowProperty(display, window, ::XInternAtom(display, atom, False), 0L, (~0L), False, reqtype,
-	                            &type, &format, &num_of_items, &leftover_bytes, &data))
+	if (!::XGetWindowProperty(display, window, atom, 0L, (~0L), False, reqtype,
+	                       &type, &format, &num_of_items, &leftover_bytes, &data))
 		return false;
 
 	result = std::string((char*)data, num_of_items);
 
-	::XFree(data);
-
 	return true;
 }
 
@@ -36,24 +36,22 @@
 static bool GetWindowPID(::Display* display, ::Window window, pid_t& result) {
 	int format;
 	unsigned long leftover_bytes, num_of_items;
-	::Atom reqtype = XA_CARDINAL, atom = ::XInternAtom(display, "_NET_WM_PID", False), type;
+	::Atom atom = ::XInternAtom(display, "_NET_WM_PID", False), type;
 	unsigned char* data;
 
-	/* TODO: check the type for this */
-	if (!::XGetWindowProperty(display, window, atom, 0L, (~0L), False, reqtype,
-	                          &type, &format, &num_of_items, &leftover_bytes, &data))
+	if (!::XGetWindowProperty(display, window, atom, 0L, (~0L), False, XA_CARDINAL,
+	                       &type, &format, &num_of_items, &leftover_bytes, &data))
 		return false;
 
 	result = static_cast<pid_t>(*(uint32_t*)data);
 
-	::XFree(data);
-
 	return true;
 }
 
 static bool FetchName(::Display* display, ::Window window, std::string& result) {
 	/* TODO: Check if XInternAtom created None or not... */
-	if (GetWindowPropertyAsString(display, window, "_NET_WM_NAME", result, ::XInternAtom(display, "UTF8_STRING", false)))
+	if (GetWindowPropertyAsString(display, window, ::XInternAtom(display, "_NET_WM_NAME", False),
+		                           result, ::XInternAtom(display, "UTF8_STRING", False)))
 		return true;
 
 	/* Fallback to XGetWMName() */
@@ -85,31 +83,29 @@
 }
 
 bool X11WinTools::EnumerateWindows(window_proc_t window_proc) {
-	auto get_window_property = [&](::Display* display, ::Window window, ::Atom atom, unsigned long& num_of_items, unsigned char** data) -> int {
-		int format;
-		unsigned long leftover_bytes;
-		::Atom realtype;
-
-		return ::XGetWindowProperty(display, window, atom, 0L, (~0L), false, AnyPropertyType,
-		                            &realtype, &format, &num_of_items, &leftover_bytes, data);
-	};
+	if (!window_proc)
+		return false;
 
 	::Display* display = ::XOpenDisplay(nullptr);
 	::Window root = DefaultRootWindow(display);
 
-	unsigned long num_windows;
+	unsigned int num_windows = 0;
 	::Window* windows = nullptr;
 
-	int status = get_window_property(display, root, ::XInternAtom(display, "_NET_CLIENT_LIST", true), num_windows, (unsigned char**)&windows);
+	{
+		::Window root_return;
+		::Window parent_return;
 
-	if (status < Success)
-		return false;
+		int status = ::XQueryTree(display, root, &root_return, &parent_return, &windows, &num_windows);
+		if (status < Success)
+			return false;
+	}
 
 	for (long k = 0; k < num_windows; k++) {
 		const ::Window window = windows[k];
 
 		Window win;
-		win.id = (long)windows[k];
+		win.id = window;
 		{
 			::XClassHint* hint = ::XAllocClassHint();
 			if (::XGetClassHint(display, window, hint)) {
@@ -126,6 +122,8 @@
 			return false;
 	}
 
+	::XFree(windows);
+
 	return true;
 }