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