Skip to content

Commit 0a902f5

Browse files
Implement finding grandchildren windows on X11
Fixes #33, improves code structure and uses variable names in accordance with X11 manual
1 parent 45529ed commit 0a902f5

File tree

1 file changed

+109
-54
lines changed

1 file changed

+109
-54
lines changed

src/linux/window_manager.cc

+109-54
Original file line numberDiff line numberDiff line change
@@ -2,69 +2,124 @@
22
#include <X11/Xutil.h>
33
#include "../window_manager.h"
44
extern "C" {
5-
#include "../xdisplay.h"
5+
#include "../xdisplay.h"
66
}
77

88
WindowHandle getActiveWindow() {
9-
Display* xServer = XGetMainDisplay();
10-
Window window;
11-
if (xServer != NULL) {
12-
int32_t revertToWindow;
13-
XGetInputFocus(xServer, &window, &revertToWindow);
14-
return window;
15-
}
16-
return -1;
9+
Display* display;
10+
Window focus;
11+
int32_t revert_to;
12+
13+
display = XGetMainDisplay();
14+
if (display == NULL) {
15+
return -1;
16+
}
17+
18+
XGetInputFocus(display, &focus, &revert_to);
19+
return focus;
20+
}
21+
22+
std::vector<WindowHandle> getWindowsRecursive(Display* display, Window w) {
23+
std::vector<WindowHandle> windowHandles;
24+
std::vector<WindowHandle> childrenWindowHandles;
25+
Window root, parent;
26+
Window* children;
27+
uint32_t nchildren;
28+
29+
if (!XQueryTree(display, w, &root, &parent, &children, &nchildren)) {
30+
return windowHandles;
31+
}
32+
33+
if (children != NULL) {
34+
for (uint32_t i = 0; i < nchildren; i++) {
35+
windowHandles.push_back(children[i]);
36+
childrenWindowHandles = getWindowsRecursive(display, children[i]);
37+
windowHandles.insert(windowHandles.end(), childrenWindowHandles.begin(), childrenWindowHandles.end());
38+
}
39+
XFree(children);
40+
}
41+
42+
return windowHandles;
1743
}
1844

1945
std::vector<WindowHandle> getWindows() {
20-
Display* xServer = XGetMainDisplay();
21-
std::vector<WindowHandle> windowHandles;
22-
if (xServer != NULL) {
23-
Window defaultRootWindow = DefaultRootWindow(xServer);
24-
Window rootWindow;
25-
Window parentWindow;
26-
Window* windowList;
27-
uint32_t windowCount;
28-
29-
Status queryTreeResult = XQueryTree(xServer, defaultRootWindow, &rootWindow, &parentWindow, &windowList, &windowCount);
30-
if (queryTreeResult > 0) {
31-
for (size_t idx = 0; idx < windowCount; ++idx) {
32-
windowHandles.push_back(windowList[idx]);
33-
}
34-
}
35-
}
36-
return windowHandles;
46+
Display* display;
47+
Window root;
48+
std::vector<WindowHandle> windowHandles;
49+
50+
display = XGetMainDisplay();
51+
if (display == NULL) {
52+
return windowHandles;
53+
}
54+
55+
root = DefaultRootWindow(display);
56+
windowHandles = getWindowsRecursive(display, root);
57+
58+
return windowHandles;
3759
}
3860

3961
std::string getWindowTitle(const WindowHandle windowHandle) {
40-
Display* xServer = XGetMainDisplay();
41-
std::string windowName = "";
42-
if (xServer != NULL && windowHandle >= 0) {
43-
/*
44-
* While there's also `XFetchName` to retrieve a window's `WM_NAME` property, in my tests `XFetchName` always failed and return 0
45-
* `XGetWMName` on the other hand just worked as expected.
46-
* Keep that in mind in case you're considering changing this implementation
47-
*/
48-
XTextProperty windowTextProperty;
49-
Status getWMNameResult = XGetWMName(xServer, windowHandle, &windowTextProperty);
50-
if (getWMNameResult > 0) {
51-
windowName = std::string(reinterpret_cast<const char*>(windowTextProperty.value));
52-
}
53-
}
54-
return windowName;
62+
Display* display;
63+
XTextProperty text_prop;
64+
65+
display = XGetMainDisplay();
66+
if (display == NULL || windowHandle < 0) {
67+
return "";
68+
}
69+
70+
/*
71+
* While there's also `XFetchName` to retrieve a window's `WM_NAME` property, in my tests `XFetchName` always failed and return 0
72+
* `XGetWMName` on the other hand just worked as expected.
73+
* Keep that in mind in case you're considering changing this implementation
74+
*/
75+
if (!XGetWMName(display, windowHandle, &text_prop)) {
76+
return "";
77+
}
78+
79+
return std::string(reinterpret_cast<const char*>(text_prop.value));
80+
}
81+
82+
MMPoint getAbsoluteOriginRecursive(Display* display, const WindowHandle w, MMPoint origin) {
83+
Window root, parent;
84+
Window* children;
85+
int32_t x, y;
86+
uint32_t width, height, border_width, border_height, nchildren;
87+
88+
if (!XQueryTree(display, w, &root, &parent, &children, &nchildren)) {
89+
return MMPointMake(0,0);
90+
}
91+
if (children != NULL) {
92+
XFree(children);
93+
}
94+
if (parent == root) {
95+
return origin;
96+
}
97+
98+
if (!XGetGeometry(display, parent, &root, &x, &y, &width, &height, &border_width, &border_height)) {
99+
return MMPointMake(0,0);
100+
}
101+
origin.x += x;
102+
origin.y += y;
103+
104+
return getAbsoluteOriginRecursive(display, parent, origin);
55105
}
56106

57-
MMRect getWindowRect(const WindowHandle windowHandle) {
58-
Display* xServer = XGetMainDisplay();
59-
MMRect windowRect = MMRectMake(0, 0, 0, 0);
60-
if (xServer != NULL && windowHandle >= 0) {
61-
Window rootWindow;
62-
int32_t x, y;
63-
uint32_t width, height, border_width, border_height;
64-
Status getXGeometryResult = XGetGeometry(xServer, windowHandle, &rootWindow, &x, &y, &width, &height, &border_width, &border_height);
65-
if (getXGeometryResult > 0) {
66-
windowRect = MMRectMake(x, y, width, height);
67-
}
68-
}
69-
return windowRect;
107+
MMRect getWindowRect(const WindowHandle w) {
108+
Display* display;
109+
Window root;
110+
int32_t x, y;
111+
uint32_t width, height, border_width, border_height;
112+
MMPoint absoluteOrigin;
113+
114+
display = XGetMainDisplay();
115+
if (display == NULL || w < 0) {
116+
return MMRectMake(0, 0, 0, 0);
117+
}
118+
119+
if (!XGetGeometry(display, w, &root, &x, &y, &width, &height, &border_width, &border_height)) {
120+
return MMRectMake(0, 0, 0, 0);
121+
}
122+
absoluteOrigin = getAbsoluteOriginRecursive(display, w, MMPointMake(x, y));
123+
124+
return MMRectMake(absoluteOrigin.x, absoluteOrigin.y, width, height);
70125
}

0 commit comments

Comments
 (0)