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;