Mercurial > minori
annotate dep/animia/src/win/x11.cc @ 167:31735c8592bc
dep/animia: make x11 window walking actually work
this is HORRIBLY slow, and I'm not *entirely* sure why...
author | paper@DavesDouble.local |
---|---|
date | Sun, 19 Nov 2023 05:32:06 -0500 |
parents | 54c5d80a737e |
children | 0fc126d52de4 |
rev | line source |
---|---|
157 | 1 #include "animia/win/x11.h" |
2 #include "animia/win.h" | |
3 #include "animia.h" | |
4 | |
156
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
5 #include <X11/Xlib.h> |
157 | 6 #include <X11/Xutil.h> |
7 #include <X11/Xatom.h> // XA_* | |
158
80d6b28eb29f
dep/animia: fix most X11 stuff
Paper <mrpapersonic@gmail.com>
parents:
157
diff
changeset
|
8 |
157 | 9 #include <cstdint> |
10 #include <string> | |
158
80d6b28eb29f
dep/animia: fix most X11 stuff
Paper <mrpapersonic@gmail.com>
parents:
157
diff
changeset
|
11 #include <set> |
156
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
12 |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
13 /* The code for this is very fugly because X11 uses lots of generic type names |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
14 (i.e., Window, Display), so I have to use :: when defining vars to distinguish |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
15 between Animia's types and X11's types */ |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
16 |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
17 namespace animia::internal::x11 { |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
18 |
157 | 19 /* should return UTF8_STRING or STRING */ |
158
80d6b28eb29f
dep/animia: fix most X11 stuff
Paper <mrpapersonic@gmail.com>
parents:
157
diff
changeset
|
20 static bool GetWindowPropertyAsString(::Display* display, ::Window window, ::Atom atom, std::string& result, ::Atom reqtype = AnyPropertyType) { |
156
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
21 int format; |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
22 unsigned long leftover_bytes, num_of_items; |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
23 ::Atom type; |
157 | 24 unsigned char* data; |
166 | 25 |
26 int status = ::XGetWindowProperty(display, window, atom, 0L, (~0L), False, reqtype, | |
27 &type, &format, &num_of_items, &leftover_bytes, &data); | |
28 if (status != Success || !(reqtype == AnyPropertyType || type == reqtype) || !num_of_items) | |
156
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
29 return false; |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
30 |
157 | 31 result = std::string((char*)data, num_of_items); |
156
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
32 |
166 | 33 ::XFree(data); |
34 | |
156
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
35 return true; |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
36 } |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
37 |
157 | 38 /* this should return CARDINAL, a 32-bit integer */ |
156
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
39 static bool GetWindowPID(::Display* display, ::Window window, pid_t& result) { |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
40 int format; |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
41 unsigned long leftover_bytes, num_of_items; |
158
80d6b28eb29f
dep/animia: fix most X11 stuff
Paper <mrpapersonic@gmail.com>
parents:
157
diff
changeset
|
42 ::Atom atom = ::XInternAtom(display, "_NET_WM_PID", False), type; |
157 | 43 unsigned char* data; |
156
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
44 |
166 | 45 int status = ::XGetWindowProperty(display, window, atom, 0L, (~0L), False, XA_CARDINAL, |
46 &type, &format, &num_of_items, &leftover_bytes, &data); | |
47 if (status != Success || type != XA_CARDINAL || num_of_items < 1) | |
156
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
48 return false; |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
49 |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
50 result = static_cast<pid_t>(*(uint32_t*)data); |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
51 |
166 | 52 ::XFree(data); |
53 | |
156
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
54 return true; |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
55 } |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
56 |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
57 static bool FetchName(::Display* display, ::Window window, std::string& result) { |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
58 /* TODO: Check if XInternAtom created None or not... */ |
158
80d6b28eb29f
dep/animia: fix most X11 stuff
Paper <mrpapersonic@gmail.com>
parents:
157
diff
changeset
|
59 if (GetWindowPropertyAsString(display, window, ::XInternAtom(display, "_NET_WM_NAME", False), |
166 | 60 result, ::XInternAtom(display, "UTF8_STRING", False))) |
61 return true; | |
62 | |
63 if (GetWindowPropertyAsString(display, window, ::XInternAtom(display, "WM_NAME", False), | |
64 result, XA_STRING)) | |
156
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
65 return true; |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
66 |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
67 /* Fallback to XGetWMName() */ |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
68 XTextProperty text; |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
69 |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
70 { |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
71 int status = ::XGetWMName(display, window, &text); |
157 | 72 if (!status || !text.value || !text.nitems) |
156
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
73 return false; |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
74 } |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
75 |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
76 char** list; |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
77 |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
78 { |
157 | 79 int count; |
156
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
80 |
157 | 81 int status = ::XmbTextPropertyToTextList(display, &text, &list, &count); |
166 | 82 if (status != Success || !count || !*list) |
156
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
83 return false; |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
84 } |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
85 |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
86 ::XFree(text.value); |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
87 |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
88 result = *list; |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
89 |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
90 ::XFreeStringList(list); |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
91 |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
92 return true; |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
93 } |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
94 |
166 | 95 static bool WalkWindows(::Display* display, std::set<::Window>& children, const std::set<::Window>& windows) { |
96 if (windows.empty()) | |
97 return false; | |
98 | |
99 for (const ::Window& window : windows) { | |
100 unsigned int num_children = 0; | |
101 ::Window* children_arr = nullptr; | |
102 | |
103 ::Window root_return; | |
104 ::Window parent_return; | |
105 | |
106 int status = ::XQueryTree(display, window, &root_return, &parent_return, &children_arr, &num_children); | |
167
31735c8592bc
dep/animia: make x11 window walking actually work
paper@DavesDouble.local
parents:
166
diff
changeset
|
107 if (!status || !children_arr) |
166 | 108 continue; |
109 | |
110 if (num_children < 1) { | |
111 ::XFree(children_arr); | |
112 continue; | |
113 } | |
114 | |
115 for (int i = 0; i < num_children; i++) | |
116 if (!children.count(children_arr[i])) | |
117 children.insert(children_arr[i]); | |
118 | |
119 ::XFree(children_arr); | |
120 | |
121 std::set<::Window> children_children; | |
122 | |
167
31735c8592bc
dep/animia: make x11 window walking actually work
paper@DavesDouble.local
parents:
166
diff
changeset
|
123 if (WalkWindows(display, children_children, children)) |
166 | 124 children.insert(children_children.begin(), children_children.end()); |
125 } | |
126 | |
127 return true; | |
128 } | |
129 | |
156
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
130 bool X11WinTools::EnumerateWindows(window_proc_t window_proc) { |
158
80d6b28eb29f
dep/animia: fix most X11 stuff
Paper <mrpapersonic@gmail.com>
parents:
157
diff
changeset
|
131 if (!window_proc) |
80d6b28eb29f
dep/animia: fix most X11 stuff
Paper <mrpapersonic@gmail.com>
parents:
157
diff
changeset
|
132 return false; |
156
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
133 |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
134 ::Display* display = ::XOpenDisplay(nullptr); |
166 | 135 if (!display) |
136 return false; | |
137 | |
157 | 138 ::Window root = DefaultRootWindow(display); |
156
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
139 |
166 | 140 std::set<::Window> windows; |
141 WalkWindows(display, windows, {root}); | |
156
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
142 |
166 | 143 for (const auto& window : windows) { |
156
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
144 Window win; |
158
80d6b28eb29f
dep/animia: fix most X11 stuff
Paper <mrpapersonic@gmail.com>
parents:
157
diff
changeset
|
145 win.id = window; |
157 | 146 { |
147 ::XClassHint* hint = ::XAllocClassHint(); | |
148 if (::XGetClassHint(display, window, hint)) { | |
149 win.class_name = hint->res_class; | |
150 ::XFree(hint); | |
151 } | |
152 } | |
166 | 153 FetchName(display, window, win.text); |
156
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
154 |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
155 Process proc; |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
156 GetWindowPID(display, window, proc.pid); |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
157 |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
158 if (!window_proc(proc, win)) |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
159 return false; |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
160 } |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
161 |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
162 return true; |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
163 } |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
164 |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
165 } |