Mercurial > minori
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)) |