--- 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},