annotate dep/animia/src/win/x11.cc @ 157:18c8eb5d1edc

x11: make it work
author Paper <mrpapersonic@gmail.com>
date Thu, 16 Nov 2023 16:51:34 -0500
parents cdf79282d647
children 80d6b28eb29f
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
157
18c8eb5d1edc x11: make it work
Paper <mrpapersonic@gmail.com>
parents: 156
diff changeset
1 #include "animia/win/x11.h"
18c8eb5d1edc x11: make it work
Paper <mrpapersonic@gmail.com>
parents: 156
diff changeset
2 #include "animia/win.h"
18c8eb5d1edc x11: make it work
Paper <mrpapersonic@gmail.com>
parents: 156
diff changeset
3 #include "animia.h"
18c8eb5d1edc x11: make it work
Paper <mrpapersonic@gmail.com>
parents: 156
diff changeset
4
156
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
5 #include <X11/Xlib.h>
157
18c8eb5d1edc x11: make it work
Paper <mrpapersonic@gmail.com>
parents: 156
diff changeset
6 #include <X11/Xutil.h>
18c8eb5d1edc x11: make it work
Paper <mrpapersonic@gmail.com>
parents: 156
diff changeset
7 #include <X11/Xatom.h> // XA_*
18c8eb5d1edc x11: make it work
Paper <mrpapersonic@gmail.com>
parents: 156
diff changeset
8 #include <cstdint>
18c8eb5d1edc x11: make it work
Paper <mrpapersonic@gmail.com>
parents: 156
diff changeset
9 #include <string>
156
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
10
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
11 /* 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
12 (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
13 between Animia's types and X11's types */
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
14
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
15 namespace animia::internal::x11 {
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
16
157
18c8eb5d1edc x11: make it work
Paper <mrpapersonic@gmail.com>
parents: 156
diff changeset
17 /* should return UTF8_STRING or STRING */
156
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
18 static bool GetWindowPropertyAsString(::Display* display, ::Window window, const char* atom, std::string& result, ::Atom reqtype = AnyPropertyType) {
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
19 int format;
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
20 unsigned long leftover_bytes, num_of_items;
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
21 ::Atom type;
157
18c8eb5d1edc x11: make it work
Paper <mrpapersonic@gmail.com>
parents: 156
diff changeset
22 unsigned char* data;
156
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
23
157
18c8eb5d1edc x11: make it work
Paper <mrpapersonic@gmail.com>
parents: 156
diff changeset
24 if (!::XGetWindowProperty(display, window, ::XInternAtom(display, atom, False), 0L, (~0L), False, reqtype,
156
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
25 &type, &format, &num_of_items, &leftover_bytes, &data))
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
26 return false;
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
27
157
18c8eb5d1edc x11: make it work
Paper <mrpapersonic@gmail.com>
parents: 156
diff changeset
28 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
29
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
30 ::XFree(data);
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
31
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
32 return true;
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
33 }
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
34
157
18c8eb5d1edc x11: make it work
Paper <mrpapersonic@gmail.com>
parents: 156
diff changeset
35 /* 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
36 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
37 int format;
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
38 unsigned long leftover_bytes, num_of_items;
157
18c8eb5d1edc x11: make it work
Paper <mrpapersonic@gmail.com>
parents: 156
diff changeset
39 ::Atom reqtype = XA_CARDINAL, atom = ::XInternAtom(display, "_NET_WM_PID", False), type;
18c8eb5d1edc x11: make it work
Paper <mrpapersonic@gmail.com>
parents: 156
diff changeset
40 unsigned char* data;
156
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
41
157
18c8eb5d1edc x11: make it work
Paper <mrpapersonic@gmail.com>
parents: 156
diff changeset
42 /* TODO: check the type for this */
18c8eb5d1edc x11: make it work
Paper <mrpapersonic@gmail.com>
parents: 156
diff changeset
43 if (!::XGetWindowProperty(display, window, atom, 0L, (~0L), False, reqtype,
18c8eb5d1edc x11: make it work
Paper <mrpapersonic@gmail.com>
parents: 156
diff changeset
44 &type, &format, &num_of_items, &leftover_bytes, &data))
156
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
45 return false;
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
46
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
47 result = static_cast<pid_t>(*(uint32_t*)data);
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
48
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
49 ::XFree(data);
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
50
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
51 return true;
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
52 }
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
53
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
54 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
55 /* TODO: Check if XInternAtom created None or not... */
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
56 if (GetWindowPropertyAsString(display, window, "_NET_WM_NAME", result, ::XInternAtom(display, "UTF8_STRING", false)))
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
57 return true;
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
58
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
59 /* Fallback to XGetWMName() */
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
60 XTextProperty text;
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
61
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
62 {
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
63 int status = ::XGetWMName(display, window, &text);
157
18c8eb5d1edc x11: make it work
Paper <mrpapersonic@gmail.com>
parents: 156
diff changeset
64 if (!status || !text.value || !text.nitems)
156
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
65 return false;
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
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
68 char** list;
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 {
157
18c8eb5d1edc x11: make it work
Paper <mrpapersonic@gmail.com>
parents: 156
diff changeset
71 int count;
156
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
72
157
18c8eb5d1edc x11: make it work
Paper <mrpapersonic@gmail.com>
parents: 156
diff changeset
73 int status = ::XmbTextPropertyToTextList(display, &text, &list, &count);
18c8eb5d1edc x11: make it work
Paper <mrpapersonic@gmail.com>
parents: 156
diff changeset
74 if (status < Success || !count || !*list)
156
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
75 return false;
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
76 }
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 ::XFree(text.value);
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
79
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
80 result = *list;
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
81
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
82 ::XFreeStringList(list);
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
83
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
84 return true;
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
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
87 bool X11WinTools::EnumerateWindows(window_proc_t window_proc) {
157
18c8eb5d1edc x11: make it work
Paper <mrpapersonic@gmail.com>
parents: 156
diff changeset
88 auto get_window_property = [&](::Display* display, ::Window window, ::Atom atom, unsigned long& num_of_items, unsigned char** data) -> int {
156
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
89 int format;
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
90 unsigned long leftover_bytes;
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
91 ::Atom realtype;
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
92
157
18c8eb5d1edc x11: make it work
Paper <mrpapersonic@gmail.com>
parents: 156
diff changeset
93 return ::XGetWindowProperty(display, window, atom, 0L, (~0L), false, AnyPropertyType,
18c8eb5d1edc x11: make it work
Paper <mrpapersonic@gmail.com>
parents: 156
diff changeset
94 &realtype, &format, &num_of_items, &leftover_bytes, data);
18c8eb5d1edc x11: make it work
Paper <mrpapersonic@gmail.com>
parents: 156
diff changeset
95 };
156
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
96
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
97 ::Display* display = ::XOpenDisplay(nullptr);
157
18c8eb5d1edc x11: make it work
Paper <mrpapersonic@gmail.com>
parents: 156
diff changeset
98 ::Window root = DefaultRootWindow(display);
156
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
99
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
100 unsigned long num_windows;
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
101 ::Window* windows = nullptr;
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
102
157
18c8eb5d1edc x11: make it work
Paper <mrpapersonic@gmail.com>
parents: 156
diff changeset
103 int status = get_window_property(display, root, ::XInternAtom(display, "_NET_CLIENT_LIST", true), num_windows, (unsigned char**)&windows);
156
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
104
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
105 if (status < Success)
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
106 return false;
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
107
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
108 for (long k = 0; k < num_windows; k++) {
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
109 const ::Window window = windows[k];
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
110
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
111 Window win;
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
112 win.id = (long)windows[k];
157
18c8eb5d1edc x11: make it work
Paper <mrpapersonic@gmail.com>
parents: 156
diff changeset
113 {
18c8eb5d1edc x11: make it work
Paper <mrpapersonic@gmail.com>
parents: 156
diff changeset
114 ::XClassHint* hint = ::XAllocClassHint();
18c8eb5d1edc x11: make it work
Paper <mrpapersonic@gmail.com>
parents: 156
diff changeset
115 if (::XGetClassHint(display, window, hint)) {
18c8eb5d1edc x11: make it work
Paper <mrpapersonic@gmail.com>
parents: 156
diff changeset
116 win.class_name = hint->res_class;
18c8eb5d1edc x11: make it work
Paper <mrpapersonic@gmail.com>
parents: 156
diff changeset
117 ::XFree(hint);
18c8eb5d1edc x11: make it work
Paper <mrpapersonic@gmail.com>
parents: 156
diff changeset
118 }
18c8eb5d1edc x11: make it work
Paper <mrpapersonic@gmail.com>
parents: 156
diff changeset
119 }
18c8eb5d1edc x11: make it work
Paper <mrpapersonic@gmail.com>
parents: 156
diff changeset
120 FetchName(display, windows[k], win.text);
156
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
121
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
122 Process proc;
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
123 GetWindowPID(display, window, proc.pid);
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
124
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
125 if (!window_proc(proc, win))
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
126 return false;
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
127 }
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
128
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
129 return true;
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
130 }
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
131
cdf79282d647 dep/animia: add VERY early x11 window stuff
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
132 }