Mercurial > minori
view dep/animia/src/win/x11.cc @ 162:61b76c7b656a
dep/animia: add os x launchservices method
author | Paper <mrpapersonic@gmail.com> |
---|---|
date | Fri, 17 Nov 2023 16:49:57 -0500 |
parents | 80d6b28eb29f |
children | 54c5d80a737e |
line wrap: on
line source
#include "animia/win/x11.h" #include "animia/win.h" #include "animia.h" #include <X11/Xlib.h> #include <X11/Xutil.h> #include <X11/Xatom.h> // XA_* #include <cstdint> #include <string> #include <memory> #include <set> /* The code for this is very fugly because X11 uses lots of generic type names (i.e., Window, Display), so I have to use :: when defining vars to distinguish between Animia's types and X11's types */ namespace animia::internal::x11 { /* should return UTF8_STRING or STRING */ static bool GetWindowPropertyAsString(::Display* display, ::Window window, ::Atom atom, std::string& result, ::Atom reqtype = AnyPropertyType) { int format; unsigned long leftover_bytes, num_of_items; ::Atom type; unsigned char* data; if (!::XGetWindowProperty(display, window, atom, 0L, (~0L), False, reqtype, &type, &format, &num_of_items, &leftover_bytes, &data)) return false; result = std::string((char*)data, num_of_items); return true; } /* this should return CARDINAL, a 32-bit integer */ static bool GetWindowPID(::Display* display, ::Window window, pid_t& result) { int format; unsigned long leftover_bytes, num_of_items; ::Atom atom = ::XInternAtom(display, "_NET_WM_PID", False), type; unsigned char* data; if (!::XGetWindowProperty(display, window, atom, 0L, (~0L), False, XA_CARDINAL, &type, &format, &num_of_items, &leftover_bytes, &data)) return false; result = static_cast<pid_t>(*(uint32_t*)data); return true; } static bool FetchName(::Display* display, ::Window window, std::string& result) { /* TODO: Check if XInternAtom created None or not... */ if (GetWindowPropertyAsString(display, window, ::XInternAtom(display, "_NET_WM_NAME", False), result, ::XInternAtom(display, "UTF8_STRING", False))) return true; /* Fallback to XGetWMName() */ XTextProperty text; { int status = ::XGetWMName(display, window, &text); if (!status || !text.value || !text.nitems) return false; } char** list; { int count; int status = ::XmbTextPropertyToTextList(display, &text, &list, &count); if (status < Success || !count || !*list) return false; } ::XFree(text.value); result = *list; ::XFreeStringList(list); return true; } bool X11WinTools::EnumerateWindows(window_proc_t window_proc) { if (!window_proc) return false; ::Display* display = ::XOpenDisplay(nullptr); ::Window root = DefaultRootWindow(display); unsigned int num_windows = 0; ::Window* windows = nullptr; { ::Window root_return; ::Window parent_return; int status = ::XQueryTree(display, root, &root_return, &parent_return, &windows, &num_windows); if (status < Success) return false; } for (long k = 0; k < num_windows; k++) { const ::Window window = windows[k]; Window win; win.id = window; { ::XClassHint* hint = ::XAllocClassHint(); if (::XGetClassHint(display, window, hint)) { win.class_name = hint->res_class; ::XFree(hint); } } FetchName(display, windows[k], win.text); Process proc; GetWindowPID(display, window, proc.pid); if (!window_proc(proc, win)) return false; } ::XFree(windows); return true; } }