diff dep/animia/src/win/x11.cc @ 199:9f3534f6b8c4

dep/animia: initial Wayland support, drop non-working kvm fd plugin
author Paper <mrpapersonic@gmail.com>
date Tue, 02 Jan 2024 02:34:27 -0500
parents bc1ae1810855
children 58e81b42a0d6
line wrap: on
line diff
--- a/dep/animia/src/win/x11.cc	Sun Dec 24 02:59:42 2023 -0500
+++ b/dep/animia/src/win/x11.cc	Tue Jan 02 02:34:27 2024 -0500
@@ -5,6 +5,9 @@
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
 #include <X11/Xatom.h> // XA_*
+#ifdef HAVE_XRES
+#include <X11/extensions/XRes.h>
+#endif
 
 #include <cstdint>
 #include <string>
@@ -16,11 +19,16 @@
 
 namespace animia::internal::x11 {
 
+/* specify that these are X types. */
+typedef ::Window XWindow;
+typedef ::Display XDisplay;
+typedef ::Atom XAtom;
+
 /* should return UTF8_STRING or STRING */
-static bool GetWindowPropertyAsString(::Display* display, ::Window window, ::Atom atom, std::string& result, ::Atom reqtype = AnyPropertyType) {
+static bool GetWindowPropertyAsString(XDisplay* display, XWindow window, XAtom atom, std::string& result, XAtom reqtype = AnyPropertyType) {
 	int format;
 	unsigned long leftover_bytes, num_of_items;
-	::Atom type;
+	XAtom type;
 	unsigned char* data;
 
 	int status = ::XGetWindowProperty(display, window, atom, 0L, (~0L), False, reqtype,
@@ -36,10 +44,35 @@
 }
 
 /* this should return CARDINAL, a 32-bit integer */
-static bool GetWindowPID(::Display* display, ::Window window, pid_t& result) {
+static bool GetWindowPID(XDisplay* display, XWindow window, pid_t& result) {
+#ifdef HAVE_XRES
+	{
+		long num_ids;
+		XResClientIdValue *client_ids;
+		XResClientIdSpec spec = {
+			.client = window,
+			.mask = XRES_CLIENT_ID_PID_MASK
+		};
+
+		::XResQueryClientIds(display, 1, &spec, &num_ids, &client_ids);
+
+		for (long i = 0; i < num_ids; i++) {
+			if (client_ids[i].spec.mask == XRES_CLIENT_ID_PID_MASK) {
+				result = ::XResGetClientPid(&client_ids[i]);
+				::XResClientIdsDestroy(num_ids, client_ids);
+				return true;
+			}
+		}
+
+		::XResClientIdsDestroy(num_ids, client_ids);
+
+		return false;
+	}
+#endif
+
 	int format;
 	unsigned long leftover_bytes, num_of_items;
-	::Atom atom = ::XInternAtom(display, "_NET_WM_PID", False), type;
+	XAtom atom = ::XInternAtom(display, "_NET_WM_PID", False), type;
 	unsigned char* data;
 
 	int status = ::XGetWindowProperty(display, window, atom, 0L, (~0L), False, XA_CARDINAL,
@@ -47,14 +80,14 @@
 	if (status != Success || type != XA_CARDINAL || num_of_items < 1)
 		return false;
 
-	result = static_cast<pid_t>(*(uint32_t*)data);
+	result = static_cast<pid_t>(*reinterpret_cast<uint32_t*>(data));
 
 	::XFree(data);
 
 	return true;
 }
 
-static bool FetchName(::Display* display, ::Window window, std::string& result) {
+static bool FetchName(XDisplay* display, XWindow window, std::string& result) {
 	/* TODO: Check if XInternAtom created None or not... */
 	if (GetWindowPropertyAsString(display, window, ::XInternAtom(display, "_NET_WM_NAME", False),
 		                          result, ::XInternAtom(display, "UTF8_STRING", False)))
@@ -92,19 +125,17 @@
 	return true;
 }
 
-static bool WalkWindows(::Display* display, std::set<::Window>& children, const std::set<::Window>& windows) {
-	/* This sucks. It takes waaaay too long to finish.
-	 * TODO: Look at the code for xwininfo to see what they do.
-	*/
+static bool WalkWindows(XDisplay* display, std::set<XWindow>& children, const std::set<XWindow>& windows) {
+	/* This can take a VERY long time if many windows are open. */
 	if (windows.empty())
 		return false;
 
-	for (const ::Window& window : windows) {
+	for (const XWindow& window : windows) {
 		unsigned int num_children = 0;
-		::Window* children_arr = nullptr;
+		XWindow* children_arr = nullptr;
 
-		::Window root_return;
-		::Window parent_return;
+		XWindow root_return;
+		XWindow parent_return;
 
 		int status = ::XQueryTree(display, window, &root_return, &parent_return, &children_arr, &num_children);
 		if (!status || !children_arr)
@@ -121,7 +152,7 @@
 
 		::XFree(children_arr);
 
-		std::set<::Window> children_children;
+		std::set<XWindow> children_children;
 
 		if (WalkWindows(display, children_children, children))
 			children.insert(children_children.begin(), children_children.end());
@@ -134,13 +165,13 @@
 	if (!window_proc)
 		return false;
 
-	::Display* display = ::XOpenDisplay(nullptr);
+	XDisplay* display = ::XOpenDisplay(nullptr);
 	if (!display)
 		return false;
 
-	::Window root = DefaultRootWindow(display);
+	XWindow root = ::XDefaultRootWindow(display);
 
-	std::set<::Window> windows;
+	std::set<XWindow> windows;
 	WalkWindows(display, windows, {root});
 
 	for (const auto& window : windows) {