diff --git a/src/linux/window_manager.cc b/src/linux/window_manager.cc index eebaf9c..6380238 100644 --- a/src/linux/window_manager.cc +++ b/src/linux/window_manager.cc @@ -2,69 +2,124 @@ #include #include "../window_manager.h" extern "C" { - #include "../xdisplay.h" + #include "../xdisplay.h" } WindowHandle getActiveWindow() { - Display* xServer = XGetMainDisplay(); - Window window; - if (xServer != NULL) { - int32_t revertToWindow; - XGetInputFocus(xServer, &window, &revertToWindow); - return window; - } - return -1; + Display* display; + Window focus; + int32_t revert_to; + + display = XGetMainDisplay(); + if (display == NULL) { + return -1; + } + + XGetInputFocus(display, &focus, &revert_to); + return focus; +} + +std::vector getWindowsRecursive(Display* display, Window w) { + std::vector windowHandles; + std::vector childrenWindowHandles; + Window root, parent; + Window* children; + uint32_t nchildren; + + if (!XQueryTree(display, w, &root, &parent, &children, &nchildren)) { + return windowHandles; + } + + if (children != NULL) { + for (uint32_t i = 0; i < nchildren; i++) { + windowHandles.push_back(children[i]); + childrenWindowHandles = getWindowsRecursive(display, children[i]); + windowHandles.insert(windowHandles.end(), childrenWindowHandles.begin(), childrenWindowHandles.end()); + } + XFree(children); + } + + return windowHandles; } std::vector getWindows() { - Display* xServer = XGetMainDisplay(); - std::vector windowHandles; - if (xServer != NULL) { - Window defaultRootWindow = DefaultRootWindow(xServer); - Window rootWindow; - Window parentWindow; - Window* windowList; - uint32_t windowCount; - - Status queryTreeResult = XQueryTree(xServer, defaultRootWindow, &rootWindow, &parentWindow, &windowList, &windowCount); - if (queryTreeResult > 0) { - for (size_t idx = 0; idx < windowCount; ++idx) { - windowHandles.push_back(windowList[idx]); - } - } - } - return windowHandles; + Display* display; + Window root; + std::vector windowHandles; + + display = XGetMainDisplay(); + if (display == NULL) { + return windowHandles; + } + + root = DefaultRootWindow(display); + windowHandles = getWindowsRecursive(display, root); + + return windowHandles; } std::string getWindowTitle(const WindowHandle windowHandle) { - Display* xServer = XGetMainDisplay(); - std::string windowName = ""; - if (xServer != NULL && windowHandle >= 0) { - /* - * While there's also `XFetchName` to retrieve a window's `WM_NAME` property, in my tests `XFetchName` always failed and return 0 - * `XGetWMName` on the other hand just worked as expected. - * Keep that in mind in case you're considering changing this implementation - */ - XTextProperty windowTextProperty; - Status getWMNameResult = XGetWMName(xServer, windowHandle, &windowTextProperty); - if (getWMNameResult > 0) { - windowName = std::string(reinterpret_cast(windowTextProperty.value)); - } - } - return windowName; + Display* display; + XTextProperty text_prop; + + display = XGetMainDisplay(); + if (display == NULL || windowHandle < 0) { + return ""; + } + + /* + * While there's also `XFetchName` to retrieve a window's `WM_NAME` property, in my tests `XFetchName` always failed and return 0 + * `XGetWMName` on the other hand just worked as expected. + * Keep that in mind in case you're considering changing this implementation + */ + if (!XGetWMName(display, windowHandle, &text_prop)) { + return ""; + } + + return std::string(reinterpret_cast(text_prop.value)); +} + +MMPoint getAbsoluteOriginRecursive(Display* display, const WindowHandle w, MMPoint origin) { + Window root, parent; + Window* children; + int32_t x, y; + uint32_t width, height, border_width, border_height, nchildren; + + if (!XQueryTree(display, w, &root, &parent, &children, &nchildren)) { + return MMPointMake(0,0); + } + if (children != NULL) { + XFree(children); + } + if (parent == root) { + return origin; + } + + if (!XGetGeometry(display, parent, &root, &x, &y, &width, &height, &border_width, &border_height)) { + return MMPointMake(0,0); + } + origin.x += x; + origin.y += y; + + return getAbsoluteOriginRecursive(display, parent, origin); } -MMRect getWindowRect(const WindowHandle windowHandle) { - Display* xServer = XGetMainDisplay(); - MMRect windowRect = MMRectMake(0, 0, 0, 0); - if (xServer != NULL && windowHandle >= 0) { - Window rootWindow; - int32_t x, y; - uint32_t width, height, border_width, border_height; - Status getXGeometryResult = XGetGeometry(xServer, windowHandle, &rootWindow, &x, &y, &width, &height, &border_width, &border_height); - if (getXGeometryResult > 0) { - windowRect = MMRectMake(x, y, width, height); - } - } - return windowRect; +MMRect getWindowRect(const WindowHandle w) { + Display* display; + Window root; + int32_t x, y; + uint32_t width, height, border_width, border_height; + MMPoint absoluteOrigin; + + display = XGetMainDisplay(); + if (display == NULL || w < 0) { + return MMRectMake(0, 0, 0, 0); + } + + if (!XGetGeometry(display, w, &root, &x, &y, &width, &height, &border_width, &border_height)) { + return MMRectMake(0, 0, 0, 0); + } + absoluteOrigin = getAbsoluteOriginRecursive(display, w, MMPointMake(x, y)); + + return MMRectMake(absoluteOrigin.x, absoluteOrigin.y, width, height); }