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