Mercurial > minori
comparison dep/animia/src/win/x11.cc @ 156:cdf79282d647
dep/animia: add VERY early x11 window stuff
author | Paper <mrpapersonic@gmail.com> |
---|---|
date | Wed, 15 Nov 2023 18:04:04 -0500 |
parents | |
children | 18c8eb5d1edc |
comparison
equal
deleted
inserted
replaced
155:d2bbb5773616 | 156:cdf79282d647 |
---|---|
1 #include <X11/Xlib.h> | |
2 | |
3 /* The code for this is very fugly because X11 uses lots of generic type names | |
4 (i.e., Window, Display), so I have to use :: when defining vars to distinguish | |
5 between Animia's types and X11's types */ | |
6 | |
7 namespace animia::internal::x11 { | |
8 | |
9 static bool GetWindowPropertyAsString(::Display* display, ::Window window, const char* atom, std::string& result, ::Atom reqtype = AnyPropertyType) { | |
10 int format; | |
11 unsigned long leftover_bytes, num_of_items; | |
12 ::Atom type; | |
13 void* data; | |
14 | |
15 if (!::XGetWindowProperty(display, root, ::XInternAtom(display, atom, true), 0L, (~0L), false, reqtype, | |
16 &type, &format, &num_of_items, &leftover_bytes, &data)) | |
17 return false; | |
18 | |
19 result = std::string(data, num_of_items); | |
20 | |
21 ::XFree(data); | |
22 | |
23 return true; | |
24 } | |
25 | |
26 static bool GetWindowPID(::Display* display, ::Window window, pid_t& result) { | |
27 int format; | |
28 unsigned long leftover_bytes, num_of_items; | |
29 ::Atom type; | |
30 void* data; | |
31 | |
32 if (!::XGetWindowProperty(display, root, ::XInternAtom(display, atom, true), 0L, (~0L), false, reqtype, | |
33 &type, &format, &num_of_items, &leftover_bytes, &data)) | |
34 return false; | |
35 | |
36 result = static_cast<pid_t>(*(uint32_t*)data); | |
37 | |
38 ::XFree(data); | |
39 | |
40 return true; | |
41 } | |
42 | |
43 static bool FetchName(::Display* display, ::Window window, std::string& result) { | |
44 /* TODO: Check if XInternAtom created None or not... */ | |
45 if (GetWindowPropertyAsString(display, window, "_NET_WM_NAME", result, ::XInternAtom(display, "UTF8_STRING", false))) | |
46 return true; | |
47 | |
48 /* Fallback to XGetWMName() */ | |
49 XTextProperty text; | |
50 | |
51 { | |
52 int status = ::XGetWMName(display, window, &text); | |
53 if (!status || !text_prop.value || !text_prop.nitems) | |
54 return false; | |
55 } | |
56 | |
57 char** list; | |
58 | |
59 { | |
60 int num; | |
61 | |
62 int status = ::XmbTextPropertyToTextList(display, &text, &list, &num); | |
63 if (status < Success || !num || !*list) | |
64 return false; | |
65 } | |
66 | |
67 ::XFree(text.value); | |
68 | |
69 result = *list; | |
70 | |
71 ::XFreeStringList(list); | |
72 | |
73 return true; | |
74 } | |
75 | |
76 bool X11WinTools::EnumerateWindows(window_proc_t window_proc) { | |
77 auto get_window_property = [&](Display* display, Window window, Atom atom, unsigned long& num_of_items, void*& data) -> int { | |
78 int format; | |
79 unsigned long leftover_bytes; | |
80 ::Atom realtype; | |
81 | |
82 return ::XGetWindowProperty(display, root, atom, 0L, (~0L), false, AnyPropertyType, | |
83 &realtype, &format, &num_of_items, &leftover_bytes, &data); | |
84 } | |
85 | |
86 ::Display* display = ::XOpenDisplay(nullptr); | |
87 ::Window root = ::DefaultRootWindow(display); | |
88 | |
89 unsigned long num_windows; | |
90 ::Window* windows = nullptr; | |
91 | |
92 int status = get_window_property(display, root, ::XInternAtom(display, "_NET_CLIENT_LIST", true), num_windows, (void*)windows); | |
93 | |
94 if (status < Success) | |
95 return false; | |
96 | |
97 for (long k = 0; k < num_windows; k++) { | |
98 const ::Window window = windows[k]; | |
99 | |
100 Window win; | |
101 win.id = (long)windows[k]; | |
102 GetWindowPropertyAsString(display, window, "_NET_ACTIVE_WINDOW", win.class_name, ::XInternAtom(display, "STRING", false)); | |
103 win.title = FetchName(display, windows[k]); | |
104 | |
105 Process proc; | |
106 GetWindowPID(display, window, proc.pid); | |
107 | |
108 if (!window_proc(proc, win)) | |
109 return false; | |
110 } | |
111 | |
112 return true; | |
113 } | |
114 | |
115 } |