Mercurial > minori
annotate dep/animia/src/win/x11.cc @ 198:bc1ae1810855
dep/animia: switch from using classes to global functions
the old idea was ok, but sort of hackish; this method doesn't use classes
at all, and this way (especially important!) we can do wayland stuff AND x11
at the same time, which wasn't really possible without stupid workarounds in
the other method
author | Paper <mrpapersonic@gmail.com> |
---|---|
date | Sun, 24 Dec 2023 02:59:42 -0500 |
parents | 0fc126d52de4 |
children | 9f3534f6b8c4 |
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) { |
191
0fc126d52de4
animia: multiple stylistic choices
Paper <mrpapersonic@gmail.com>
parents:
167
diff
changeset
|
96 /* This sucks. It takes waaaay too long to finish. |
0fc126d52de4
animia: multiple stylistic choices
Paper <mrpapersonic@gmail.com>
parents:
167
diff
changeset
|
97 * TODO: Look at the code for xwininfo to see what they do. |
0fc126d52de4
animia: multiple stylistic choices
Paper <mrpapersonic@gmail.com>
parents:
167
diff
changeset
|
98 */ |
166 | 99 if (windows.empty()) |
100 return false; | |
101 | |
102 for (const ::Window& window : windows) { | |
103 unsigned int num_children = 0; | |
104 ::Window* children_arr = nullptr; | |
105 | |
106 ::Window root_return; | |
107 ::Window parent_return; | |
108 | |
109 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
|
110 if (!status || !children_arr) |
166 | 111 continue; |
112 | |
113 if (num_children < 1) { | |
114 ::XFree(children_arr); | |
115 continue; | |
116 } | |
117 | |
118 for (int i = 0; i < num_children; i++) | |
119 if (!children.count(children_arr[i])) | |
120 children.insert(children_arr[i]); | |
121 | |
122 ::XFree(children_arr); | |
123 | |
124 std::set<::Window> children_children; | |
125 | |
167
31735c8592bc
dep/animia: make x11 window walking actually work
paper@DavesDouble.local
parents:
166
diff
changeset
|
126 if (WalkWindows(display, children_children, children)) |
166 | 127 children.insert(children_children.begin(), children_children.end()); |
128 } | |
129 | |
130 return true; | |
131 } | |
132 | |
198
bc1ae1810855
dep/animia: switch from using classes to global functions
Paper <mrpapersonic@gmail.com>
parents:
191
diff
changeset
|
133 bool EnumerateWindows(window_proc_t window_proc) { |
158
80d6b28eb29f
dep/animia: fix most X11 stuff
Paper <mrpapersonic@gmail.com>
parents:
157
diff
changeset
|
134 if (!window_proc) |
80d6b28eb29f
dep/animia: fix most X11 stuff
Paper <mrpapersonic@gmail.com>
parents:
157
diff
changeset
|
135 return false; |
156
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
136 |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
137 ::Display* display = ::XOpenDisplay(nullptr); |
166 | 138 if (!display) |
139 return false; | |
140 | |
157 | 141 ::Window root = DefaultRootWindow(display); |
156
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
142 |
166 | 143 std::set<::Window> windows; |
144 WalkWindows(display, windows, {root}); | |
156
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
145 |
166 | 146 for (const auto& window : windows) { |
156
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
147 Window win; |
158
80d6b28eb29f
dep/animia: fix most X11 stuff
Paper <mrpapersonic@gmail.com>
parents:
157
diff
changeset
|
148 win.id = window; |
157 | 149 { |
150 ::XClassHint* hint = ::XAllocClassHint(); | |
151 if (::XGetClassHint(display, window, hint)) { | |
152 win.class_name = hint->res_class; | |
153 ::XFree(hint); | |
154 } | |
155 } | |
166 | 156 FetchName(display, window, win.text); |
156
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 Process proc; |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
159 GetWindowPID(display, window, proc.pid); |
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 if (!window_proc(proc, win)) |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
162 return false; |
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 return true; |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
166 } |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
167 |
cdf79282d647
dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
168 } |