Mercurial > minori
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; |