# HG changeset patch # User František Kučera # Date 1618081817 -7200 # Node ID 803beead60c4b1be40f34cb87b84cd38287515a7 # Parent c8d681753bc2f57da1c49824cb4c576c3df510ed list windows: process (PID): as reported by the application itself in the _NET_WM_PID property Some applications do not report their PID. diff -r c8d681753bc2 -r 803beead60c4 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 #include +#include #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, std::function 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},