Mercurial > minori
comparison dep/animia/src/win/x11.cc @ 202:71832ffe425a
animia: re-add kvm fd source
this is all being merged from my wildly out-of-date laptop. SORRY!
in other news, I edited the CI file to install the wayland client
as well, so the linux CI build might finally get wayland stuff.
| author | Paper <paper@paper.us.eu.org> |
|---|---|
| date | Tue, 02 Jan 2024 06:05:06 -0500 |
| parents | 9f3534f6b8c4 |
| children | 58e81b42a0d6 |
comparison
equal
deleted
inserted
replaced
| 201:8f6f8dd2eb23 | 202:71832ffe425a |
|---|---|
| 3 #include "animia.h" | 3 #include "animia.h" |
| 4 | 4 |
| 5 #include <X11/Xlib.h> | 5 #include <X11/Xlib.h> |
| 6 #include <X11/Xutil.h> | 6 #include <X11/Xutil.h> |
| 7 #include <X11/Xatom.h> // XA_* | 7 #include <X11/Xatom.h> // XA_* |
| 8 #ifdef HAVE_XRES | |
| 9 #include <X11/extensions/XRes.h> | |
| 10 #endif | |
| 8 | 11 |
| 9 #include <cstdint> | 12 #include <cstdint> |
| 10 #include <string> | 13 #include <string> |
| 11 #include <set> | 14 #include <set> |
| 12 | 15 |
| 14 (i.e., Window, Display), so I have to use :: when defining vars to distinguish | 17 (i.e., Window, Display), so I have to use :: when defining vars to distinguish |
| 15 between Animia's types and X11's types */ | 18 between Animia's types and X11's types */ |
| 16 | 19 |
| 17 namespace animia::internal::x11 { | 20 namespace animia::internal::x11 { |
| 18 | 21 |
| 22 /* specify that these are X types. */ | |
| 23 typedef ::Window XWindow; | |
| 24 typedef ::Display XDisplay; | |
| 25 typedef ::Atom XAtom; | |
| 26 | |
| 19 /* should return UTF8_STRING or STRING */ | 27 /* should return UTF8_STRING or STRING */ |
| 20 static bool GetWindowPropertyAsString(::Display* display, ::Window window, ::Atom atom, std::string& result, ::Atom reqtype = AnyPropertyType) { | 28 static bool GetWindowPropertyAsString(XDisplay* display, XWindow window, XAtom atom, std::string& result, XAtom reqtype = AnyPropertyType) { |
| 21 int format; | 29 int format; |
| 22 unsigned long leftover_bytes, num_of_items; | 30 unsigned long leftover_bytes, num_of_items; |
| 23 ::Atom type; | 31 XAtom type; |
| 24 unsigned char* data; | 32 unsigned char* data; |
| 25 | 33 |
| 26 int status = ::XGetWindowProperty(display, window, atom, 0L, (~0L), False, reqtype, | 34 int status = ::XGetWindowProperty(display, window, atom, 0L, (~0L), False, reqtype, |
| 27 &type, &format, &num_of_items, &leftover_bytes, &data); | 35 &type, &format, &num_of_items, &leftover_bytes, &data); |
| 28 if (status != Success || !(reqtype == AnyPropertyType || type == reqtype) || !num_of_items) | 36 if (status != Success || !(reqtype == AnyPropertyType || type == reqtype) || !num_of_items) |
| 34 | 42 |
| 35 return true; | 43 return true; |
| 36 } | 44 } |
| 37 | 45 |
| 38 /* this should return CARDINAL, a 32-bit integer */ | 46 /* this should return CARDINAL, a 32-bit integer */ |
| 39 static bool GetWindowPID(::Display* display, ::Window window, pid_t& result) { | 47 static bool GetWindowPID(XDisplay* display, XWindow window, pid_t& result) { |
| 48 #ifdef HAVE_XRES | |
| 49 { | |
| 50 long num_ids; | |
| 51 XResClientIdValue *client_ids; | |
| 52 XResClientIdSpec spec = { | |
| 53 .client = window, | |
| 54 .mask = XRES_CLIENT_ID_PID_MASK | |
| 55 }; | |
| 56 | |
| 57 ::XResQueryClientIds(display, 1, &spec, &num_ids, &client_ids); | |
| 58 | |
| 59 for (long i = 0; i < num_ids; i++) { | |
| 60 if (client_ids[i].spec.mask == XRES_CLIENT_ID_PID_MASK) { | |
| 61 result = ::XResGetClientPid(&client_ids[i]); | |
| 62 ::XResClientIdsDestroy(num_ids, client_ids); | |
| 63 return true; | |
| 64 } | |
| 65 } | |
| 66 | |
| 67 ::XResClientIdsDestroy(num_ids, client_ids); | |
| 68 | |
| 69 return false; | |
| 70 } | |
| 71 #endif | |
| 72 | |
| 40 int format; | 73 int format; |
| 41 unsigned long leftover_bytes, num_of_items; | 74 unsigned long leftover_bytes, num_of_items; |
| 42 ::Atom atom = ::XInternAtom(display, "_NET_WM_PID", False), type; | 75 XAtom atom = ::XInternAtom(display, "_NET_WM_PID", False), type; |
| 43 unsigned char* data; | 76 unsigned char* data; |
| 44 | 77 |
| 45 int status = ::XGetWindowProperty(display, window, atom, 0L, (~0L), False, XA_CARDINAL, | 78 int status = ::XGetWindowProperty(display, window, atom, 0L, (~0L), False, XA_CARDINAL, |
| 46 &type, &format, &num_of_items, &leftover_bytes, &data); | 79 &type, &format, &num_of_items, &leftover_bytes, &data); |
| 47 if (status != Success || type != XA_CARDINAL || num_of_items < 1) | 80 if (status != Success || type != XA_CARDINAL || num_of_items < 1) |
| 48 return false; | 81 return false; |
| 49 | 82 |
| 50 result = static_cast<pid_t>(*(uint32_t*)data); | 83 result = static_cast<pid_t>(*reinterpret_cast<uint32_t*>(data)); |
| 51 | 84 |
| 52 ::XFree(data); | 85 ::XFree(data); |
| 53 | 86 |
| 54 return true; | 87 return true; |
| 55 } | 88 } |
| 56 | 89 |
| 57 static bool FetchName(::Display* display, ::Window window, std::string& result) { | 90 static bool FetchName(XDisplay* display, XWindow window, std::string& result) { |
| 58 /* TODO: Check if XInternAtom created None or not... */ | 91 /* TODO: Check if XInternAtom created None or not... */ |
| 59 if (GetWindowPropertyAsString(display, window, ::XInternAtom(display, "_NET_WM_NAME", False), | 92 if (GetWindowPropertyAsString(display, window, ::XInternAtom(display, "_NET_WM_NAME", False), |
| 60 result, ::XInternAtom(display, "UTF8_STRING", False))) | 93 result, ::XInternAtom(display, "UTF8_STRING", False))) |
| 61 return true; | 94 return true; |
| 62 | 95 |
| 90 ::XFreeStringList(list); | 123 ::XFreeStringList(list); |
| 91 | 124 |
| 92 return true; | 125 return true; |
| 93 } | 126 } |
| 94 | 127 |
| 95 static bool WalkWindows(::Display* display, std::set<::Window>& children, const std::set<::Window>& windows) { | 128 static bool WalkWindows(XDisplay* display, std::set<XWindow>& children, const std::set<XWindow>& windows) { |
| 129 /* This can take a VERY long time if many windows are open. */ | |
| 96 if (windows.empty()) | 130 if (windows.empty()) |
| 97 return false; | 131 return false; |
| 98 | 132 |
| 99 for (const ::Window& window : windows) { | 133 for (const XWindow& window : windows) { |
| 100 unsigned int num_children = 0; | 134 unsigned int num_children = 0; |
| 101 ::Window* children_arr = nullptr; | 135 XWindow* children_arr = nullptr; |
| 102 | 136 |
| 103 ::Window root_return; | 137 XWindow root_return; |
| 104 ::Window parent_return; | 138 XWindow parent_return; |
| 105 | 139 |
| 106 int status = ::XQueryTree(display, window, &root_return, &parent_return, &children_arr, &num_children); | 140 int status = ::XQueryTree(display, window, &root_return, &parent_return, &children_arr, &num_children); |
| 107 if (!status || !children_arr) | 141 if (!status || !children_arr) |
| 108 continue; | 142 continue; |
| 109 | 143 |
| 116 if (!children.count(children_arr[i])) | 150 if (!children.count(children_arr[i])) |
| 117 children.insert(children_arr[i]); | 151 children.insert(children_arr[i]); |
| 118 | 152 |
| 119 ::XFree(children_arr); | 153 ::XFree(children_arr); |
| 120 | 154 |
| 121 std::set<::Window> children_children; | 155 std::set<XWindow> children_children; |
| 122 | 156 |
| 123 if (WalkWindows(display, children_children, children)) | 157 if (WalkWindows(display, children_children, children)) |
| 124 children.insert(children_children.begin(), children_children.end()); | 158 children.insert(children_children.begin(), children_children.end()); |
| 125 } | 159 } |
| 126 | 160 |
| 127 return true; | 161 return true; |
| 128 } | 162 } |
| 129 | 163 |
| 130 bool X11WinTools::EnumerateWindows(window_proc_t window_proc) { | 164 bool EnumerateWindows(window_proc_t window_proc) { |
| 131 if (!window_proc) | 165 if (!window_proc) |
| 132 return false; | 166 return false; |
| 133 | 167 |
| 134 ::Display* display = ::XOpenDisplay(nullptr); | 168 XDisplay* display = ::XOpenDisplay(nullptr); |
| 135 if (!display) | 169 if (!display) |
| 136 return false; | 170 return false; |
| 137 | 171 |
| 138 ::Window root = DefaultRootWindow(display); | 172 XWindow root = ::XDefaultRootWindow(display); |
| 139 | 173 |
| 140 std::set<::Window> windows; | 174 std::set<XWindow> windows; |
| 141 WalkWindows(display, windows, {root}); | 175 WalkWindows(display, windows, {root}); |
| 142 | 176 |
| 143 for (const auto& window : windows) { | 177 for (const auto& window : windows) { |
| 144 Window win; | 178 Window win; |
| 145 win.id = window; | 179 win.id = window; |
