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