Skip to content

Implement finding grandchildren windows on X11 #34

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
163 changes: 109 additions & 54 deletions src/linux/window_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,69 +2,124 @@
#include <X11/Xutil.h>
#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<WindowHandle> getWindowsRecursive(Display* display, Window w) {
std::vector<WindowHandle> windowHandles;
std::vector<WindowHandle> 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<WindowHandle> getWindows() {
Display* xServer = XGetMainDisplay();
std::vector<WindowHandle> 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<WindowHandle> 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<const char*>(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<const char*>(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);
}