comparison dep/animia/src/win/x11.cc @ 158:80d6b28eb29f

dep/animia: fix most X11 stuff it looks like _NET_WM_PID isn't supported by MOST clients, or my code is wrong... core/filesystem: fix Linux config path handling on *nix
author Paper <mrpapersonic@gmail.com>
date Fri, 17 Nov 2023 02:07:33 -0500
parents 18c8eb5d1edc
children 54c5d80a737e
comparison
equal deleted inserted replaced
157:18c8eb5d1edc 158:80d6b28eb29f
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
8 #include <cstdint> 9 #include <cstdint>
9 #include <string> 10 #include <string>
11 #include <memory>
12 #include <set>
10 13
11 /* The code for this is very fugly because X11 uses lots of generic type names 14 /* The code for this is very fugly because X11 uses lots of generic type names
12 (i.e., Window, Display), so I have to use :: when defining vars to distinguish 15 (i.e., Window, Display), so I have to use :: when defining vars to distinguish
13 between Animia's types and X11's types */ 16 between Animia's types and X11's types */
14 17
15 namespace animia::internal::x11 { 18 namespace animia::internal::x11 {
16 19
17 /* should return UTF8_STRING or STRING */ 20 /* should return UTF8_STRING or STRING */
18 static bool GetWindowPropertyAsString(::Display* display, ::Window window, const char* atom, std::string& result, ::Atom reqtype = AnyPropertyType) { 21 static bool GetWindowPropertyAsString(::Display* display, ::Window window, ::Atom atom, std::string& result, ::Atom reqtype = AnyPropertyType) {
19 int format; 22 int format;
20 unsigned long leftover_bytes, num_of_items; 23 unsigned long leftover_bytes, num_of_items;
21 ::Atom type; 24 ::Atom type;
22 unsigned char* data; 25 unsigned char* data;
23 26 if (!::XGetWindowProperty(display, window, atom, 0L, (~0L), False, reqtype,
24 if (!::XGetWindowProperty(display, window, ::XInternAtom(display, atom, False), 0L, (~0L), False, reqtype, 27 &type, &format, &num_of_items, &leftover_bytes, &data))
25 &type, &format, &num_of_items, &leftover_bytes, &data))
26 return false; 28 return false;
27 29
28 result = std::string((char*)data, num_of_items); 30 result = std::string((char*)data, num_of_items);
29
30 ::XFree(data);
31 31
32 return true; 32 return true;
33 } 33 }
34 34
35 /* this should return CARDINAL, a 32-bit integer */ 35 /* this should return CARDINAL, a 32-bit integer */
36 static bool GetWindowPID(::Display* display, ::Window window, pid_t& result) { 36 static bool GetWindowPID(::Display* display, ::Window window, pid_t& result) {
37 int format; 37 int format;
38 unsigned long leftover_bytes, num_of_items; 38 unsigned long leftover_bytes, num_of_items;
39 ::Atom reqtype = XA_CARDINAL, atom = ::XInternAtom(display, "_NET_WM_PID", False), type; 39 ::Atom atom = ::XInternAtom(display, "_NET_WM_PID", False), type;
40 unsigned char* data; 40 unsigned char* data;
41 41
42 /* TODO: check the type for this */ 42 if (!::XGetWindowProperty(display, window, atom, 0L, (~0L), False, XA_CARDINAL,
43 if (!::XGetWindowProperty(display, window, atom, 0L, (~0L), False, reqtype, 43 &type, &format, &num_of_items, &leftover_bytes, &data))
44 &type, &format, &num_of_items, &leftover_bytes, &data))
45 return false; 44 return false;
46 45
47 result = static_cast<pid_t>(*(uint32_t*)data); 46 result = static_cast<pid_t>(*(uint32_t*)data);
48
49 ::XFree(data);
50 47
51 return true; 48 return true;
52 } 49 }
53 50
54 static bool FetchName(::Display* display, ::Window window, std::string& result) { 51 static bool FetchName(::Display* display, ::Window window, std::string& result) {
55 /* TODO: Check if XInternAtom created None or not... */ 52 /* TODO: Check if XInternAtom created None or not... */
56 if (GetWindowPropertyAsString(display, window, "_NET_WM_NAME", result, ::XInternAtom(display, "UTF8_STRING", false))) 53 if (GetWindowPropertyAsString(display, window, ::XInternAtom(display, "_NET_WM_NAME", False),
54 result, ::XInternAtom(display, "UTF8_STRING", False)))
57 return true; 55 return true;
58 56
59 /* Fallback to XGetWMName() */ 57 /* Fallback to XGetWMName() */
60 XTextProperty text; 58 XTextProperty text;
61 59
83 81
84 return true; 82 return true;
85 } 83 }
86 84
87 bool X11WinTools::EnumerateWindows(window_proc_t window_proc) { 85 bool X11WinTools::EnumerateWindows(window_proc_t window_proc) {
88 auto get_window_property = [&](::Display* display, ::Window window, ::Atom atom, unsigned long& num_of_items, unsigned char** data) -> int { 86 if (!window_proc)
89 int format; 87 return false;
90 unsigned long leftover_bytes;
91 ::Atom realtype;
92
93 return ::XGetWindowProperty(display, window, atom, 0L, (~0L), false, AnyPropertyType,
94 &realtype, &format, &num_of_items, &leftover_bytes, data);
95 };
96 88
97 ::Display* display = ::XOpenDisplay(nullptr); 89 ::Display* display = ::XOpenDisplay(nullptr);
98 ::Window root = DefaultRootWindow(display); 90 ::Window root = DefaultRootWindow(display);
99 91
100 unsigned long num_windows; 92 unsigned int num_windows = 0;
101 ::Window* windows = nullptr; 93 ::Window* windows = nullptr;
102 94
103 int status = get_window_property(display, root, ::XInternAtom(display, "_NET_CLIENT_LIST", true), num_windows, (unsigned char**)&windows); 95 {
96 ::Window root_return;
97 ::Window parent_return;
104 98
105 if (status < Success) 99 int status = ::XQueryTree(display, root, &root_return, &parent_return, &windows, &num_windows);
106 return false; 100 if (status < Success)
101 return false;
102 }
107 103
108 for (long k = 0; k < num_windows; k++) { 104 for (long k = 0; k < num_windows; k++) {
109 const ::Window window = windows[k]; 105 const ::Window window = windows[k];
110 106
111 Window win; 107 Window win;
112 win.id = (long)windows[k]; 108 win.id = window;
113 { 109 {
114 ::XClassHint* hint = ::XAllocClassHint(); 110 ::XClassHint* hint = ::XAllocClassHint();
115 if (::XGetClassHint(display, window, hint)) { 111 if (::XGetClassHint(display, window, hint)) {
116 win.class_name = hint->res_class; 112 win.class_name = hint->res_class;
117 ::XFree(hint); 113 ::XFree(hint);
124 120
125 if (!window_proc(proc, win)) 121 if (!window_proc(proc, win))
126 return false; 122 return false;
127 } 123 }
128 124
125 ::XFree(windows);
126
129 return true; 127 return true;
130 } 128 }
131 129
132 } 130 }