Mercurial > minori
comparison dep/animia/src/win/x11.cc @ 156:cdf79282d647
dep/animia: add VERY early x11 window stuff
| author | Paper <mrpapersonic@gmail.com> |
|---|---|
| date | Wed, 15 Nov 2023 18:04:04 -0500 (24 months ago) |
| parents | |
| children | 18c8eb5d1edc |
comparison
equal
deleted
inserted
replaced
| 155:d2bbb5773616 | 156:cdf79282d647 |
|---|---|
| 1 #include <X11/Xlib.h> | |
| 2 | |
| 3 /* 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 | |
| 5 between Animia's types and X11's types */ | |
| 6 | |
| 7 namespace animia::internal::x11 { | |
| 8 | |
| 9 static bool GetWindowPropertyAsString(::Display* display, ::Window window, const char* atom, std::string& result, ::Atom reqtype = AnyPropertyType) { | |
| 10 int format; | |
| 11 unsigned long leftover_bytes, num_of_items; | |
| 12 ::Atom type; | |
| 13 void* data; | |
| 14 | |
| 15 if (!::XGetWindowProperty(display, root, ::XInternAtom(display, atom, true), 0L, (~0L), false, reqtype, | |
| 16 &type, &format, &num_of_items, &leftover_bytes, &data)) | |
| 17 return false; | |
| 18 | |
| 19 result = std::string(data, num_of_items); | |
| 20 | |
| 21 ::XFree(data); | |
| 22 | |
| 23 return true; | |
| 24 } | |
| 25 | |
| 26 static bool GetWindowPID(::Display* display, ::Window window, pid_t& result) { | |
| 27 int format; | |
| 28 unsigned long leftover_bytes, num_of_items; | |
| 29 ::Atom type; | |
| 30 void* data; | |
| 31 | |
| 32 if (!::XGetWindowProperty(display, root, ::XInternAtom(display, atom, true), 0L, (~0L), false, reqtype, | |
| 33 &type, &format, &num_of_items, &leftover_bytes, &data)) | |
| 34 return false; | |
| 35 | |
| 36 result = static_cast<pid_t>(*(uint32_t*)data); | |
| 37 | |
| 38 ::XFree(data); | |
| 39 | |
| 40 return true; | |
| 41 } | |
| 42 | |
| 43 static bool FetchName(::Display* display, ::Window window, std::string& result) { | |
| 44 /* TODO: Check if XInternAtom created None or not... */ | |
| 45 if (GetWindowPropertyAsString(display, window, "_NET_WM_NAME", result, ::XInternAtom(display, "UTF8_STRING", false))) | |
| 46 return true; | |
| 47 | |
| 48 /* Fallback to XGetWMName() */ | |
| 49 XTextProperty text; | |
| 50 | |
| 51 { | |
| 52 int status = ::XGetWMName(display, window, &text); | |
| 53 if (!status || !text_prop.value || !text_prop.nitems) | |
| 54 return false; | |
| 55 } | |
| 56 | |
| 57 char** list; | |
| 58 | |
| 59 { | |
| 60 int num; | |
| 61 | |
| 62 int status = ::XmbTextPropertyToTextList(display, &text, &list, &num); | |
| 63 if (status < Success || !num || !*list) | |
| 64 return false; | |
| 65 } | |
| 66 | |
| 67 ::XFree(text.value); | |
| 68 | |
| 69 result = *list; | |
| 70 | |
| 71 ::XFreeStringList(list); | |
| 72 | |
| 73 return true; | |
| 74 } | |
| 75 | |
| 76 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 { | |
| 78 int format; | |
| 79 unsigned long leftover_bytes; | |
| 80 ::Atom realtype; | |
| 81 | |
| 82 return ::XGetWindowProperty(display, root, atom, 0L, (~0L), false, AnyPropertyType, | |
| 83 &realtype, &format, &num_of_items, &leftover_bytes, &data); | |
| 84 } | |
| 85 | |
| 86 ::Display* display = ::XOpenDisplay(nullptr); | |
| 87 ::Window root = ::DefaultRootWindow(display); | |
| 88 | |
| 89 unsigned long num_windows; | |
| 90 ::Window* windows = nullptr; | |
| 91 | |
| 92 int status = get_window_property(display, root, ::XInternAtom(display, "_NET_CLIENT_LIST", true), num_windows, (void*)windows); | |
| 93 | |
| 94 if (status < Success) | |
| 95 return false; | |
| 96 | |
| 97 for (long k = 0; k < num_windows; k++) { | |
| 98 const ::Window window = windows[k]; | |
| 99 | |
| 100 Window win; | |
| 101 win.id = (long)windows[k]; | |
| 102 GetWindowPropertyAsString(display, window, "_NET_ACTIVE_WINDOW", win.class_name, ::XInternAtom(display, "STRING", false)); | |
| 103 win.title = FetchName(display, windows[k]); | |
| 104 | |
| 105 Process proc; | |
| 106 GetWindowPID(display, window, proc.pid); | |
| 107 | |
| 108 if (!window_proc(proc, win)) | |
| 109 return false; | |
| 110 } | |
| 111 | |
| 112 return true; | |
| 113 } | |
| 114 | |
| 115 } |
