list windows: process (PID): as reported by the application itself in the _NET_WM_PID property v_0
authorFrantišek Kučera <franta-hg@frantovo.cz>
Sat, 10 Apr 2021 21:10:17 +0200
branchv_0
changeset 10 803beead60c4
parent 9 c8d681753bc2
child 11 3948229234cd
list windows: process (PID): as reported by the application itself in the _NET_WM_PID property Some applications do not report their PID.
src/X11Command.h
--- a/src/X11Command.h	Tue Apr 06 00:32:53 2021 +0200
+++ b/src/X11Command.h	Sat Apr 10 21:10:17 2021 +0200
@@ -24,6 +24,7 @@
 
 #include <X11/extensions/XInput.h>
 #include <X11/Xutil.h>
+#include <X11/Xatom.h>
 
 #include "Configuration.h"
 
@@ -280,6 +281,48 @@
 		return convertor.from_bytes(name);
 	}
 
+	void* findWindowProperty(const Display& display, Window window, Atom atom, long* length, Atom* type, int* size) {
+		// FIXME: review code
+		Atom actualType;
+		int actualFormat;
+		unsigned long itemCount;
+		unsigned long byteCount;
+		unsigned long bytesAfter;
+		unsigned char* result = nullptr;
+		int status;
+		unsigned long max_len = 500000;
+
+		status = XGetWindowProperty(display.display, window, atom, 0, (max_len + 3) / 4, False, AnyPropertyType, &actualType, &actualFormat, &itemCount, &bytesAfter, &result);
+		if (status == BadWindow) throw std::invalid_argument("Unable to get window property: BadWindow");
+		if (status != Success) throw std::invalid_argument("Unable to get window property: other error: " + std::to_string(status));
+
+		if (actualFormat == 32) byteCount = sizeof (long);
+		else if (actualFormat == 16) byteCount = sizeof (short);
+		else if (actualFormat == 8) byteCount = 1;
+		else if (actualFormat == 0) byteCount = 0;
+		else throw std::invalid_argument("Unable to get window property: unexpected format");
+		*length = min(itemCount * byteCount, max_len);
+		*type = actualType;
+		*size = actualFormat;
+		return (void*) result;
+	}
+
+	relpipe::common::type::Integer findWindowPropertyInteger(const Display& display, Window window, std::string propertyName) {
+		long length = -1;
+		Atom type = -1;
+		int size = -1;
+		void* rawResult = findWindowProperty(display, window, XInternAtom(display.display, propertyName.c_str(), False), &length, &type, &size);
+
+		relpipe::common::type::Integer result = -1; // TODO: null
+		if (size = 32 && type == XA_CARDINAL) result = *((uint32_t*) rawResult);
+		// TODO: review code
+		// TODO: support also other types (other integers, boolean, string etc.)
+
+		XFree(rawResult);
+
+		return result;
+	}
+
 	void listWindow(const Display& display, Window window, relpipe::common::type::Integer level, Configuration& configuration, std::shared_ptr<writer::RelationalWriter> writer, std::function<void() > relationalWriterFlush) {
 		Window rootWindow;
 		Window parentWindow;
@@ -302,10 +345,15 @@
 			XFree(classHint.res_name);
 		}
 
+		// The PID as reported by the application itself in the property. Some applications do not report their PID.
+		relpipe::common::type::Integer processId = findWindowPropertyInteger(display, window, "_NET_WM_PID");
+		// TODO: support also other properties: customizable through options or all in a nested structure/relation/xml
+
 		writer->writeAttribute(std::to_wstring(window));
 		writer->writeAttribute(std::to_wstring(windowAttributes.root));
 		writer->writeAttribute(std::to_wstring(parentWindow));
 		writer->writeAttribute(&level, typeid (level));
+		writer->writeAttribute(&processId, typeid (processId));
 		writer->writeAttribute(fetchWindowName(display, window));
 		writer->writeAttribute(resClass);
 		writer->writeAttribute(resName);
@@ -325,6 +373,7 @@
 			{L"root", relpipe::writer::TypeId::INTEGER},
 			{L"parent", relpipe::writer::TypeId::INTEGER},
 			{L"level", relpipe::writer::TypeId::INTEGER},
+			{L"process", relpipe::writer::TypeId::INTEGER},
 			{L"name", relpipe::writer::TypeId::STRING},
 			{L"res_class", relpipe::writer::TypeId::STRING},
 			{L"res_name", relpipe::writer::TypeId::STRING},