comparison dep/animia/src/win/x11.cc @ 199:9f3534f6b8c4

dep/animia: initial Wayland support, drop non-working kvm fd plugin
author Paper <mrpapersonic@gmail.com>
date Tue, 02 Jan 2024 02:34:27 -0500
parents bc1ae1810855
children 58e81b42a0d6
comparison
equal deleted inserted replaced
198:bc1ae1810855 199:9f3534f6b8c4
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) {
96 /* This sucks. It takes waaaay too long to finish. 129 /* This can take a VERY long time if many windows are open. */
97 * TODO: Look at the code for xwininfo to see what they do.
98 */
99 if (windows.empty()) 130 if (windows.empty())
100 return false; 131 return false;
101 132
102 for (const ::Window& window : windows) { 133 for (const XWindow& window : windows) {
103 unsigned int num_children = 0; 134 unsigned int num_children = 0;
104 ::Window* children_arr = nullptr; 135 XWindow* children_arr = nullptr;
105 136
106 ::Window root_return; 137 XWindow root_return;
107 ::Window parent_return; 138 XWindow parent_return;
108 139
109 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);
110 if (!status || !children_arr) 141 if (!status || !children_arr)
111 continue; 142 continue;
112 143
119 if (!children.count(children_arr[i])) 150 if (!children.count(children_arr[i]))
120 children.insert(children_arr[i]); 151 children.insert(children_arr[i]);
121 152
122 ::XFree(children_arr); 153 ::XFree(children_arr);
123 154
124 std::set<::Window> children_children; 155 std::set<XWindow> children_children;
125 156
126 if (WalkWindows(display, children_children, children)) 157 if (WalkWindows(display, children_children, children))
127 children.insert(children_children.begin(), children_children.end()); 158 children.insert(children_children.begin(), children_children.end());
128 } 159 }
129 160
132 163
133 bool EnumerateWindows(window_proc_t window_proc) { 164 bool EnumerateWindows(window_proc_t window_proc) {
134 if (!window_proc) 165 if (!window_proc)
135 return false; 166 return false;
136 167
137 ::Display* display = ::XOpenDisplay(nullptr); 168 XDisplay* display = ::XOpenDisplay(nullptr);
138 if (!display) 169 if (!display)
139 return false; 170 return false;
140 171
141 ::Window root = DefaultRootWindow(display); 172 XWindow root = ::XDefaultRootWindow(display);
142 173
143 std::set<::Window> windows; 174 std::set<XWindow> windows;
144 WalkWindows(display, windows, {root}); 175 WalkWindows(display, windows, {root});
145 176
146 for (const auto& window : windows) { 177 for (const auto& window : windows) {
147 Window win; 178 Window win;
148 win.id = window; 179 win.id = window;