|
3 | 3 | #include <X11/Xlib.h>
|
4 | 4 | #include <X11/extensions/XRes.h>
|
5 | 5 | #include <X11/extensions/XShm.h>
|
| 6 | +#include <stdio.h> |
| 7 | +#include <stdlib.h> |
6 | 8 |
|
7 | 9 | #include "util.h"
|
8 | 10 | #include "display.h"
|
@@ -92,25 +94,50 @@ has_property(DisplayObject *self, Window window, Atom property) {
|
92 | 94 | return status == Success && !(actual_type_return == None && actual_format_return == 0);
|
93 | 95 | }
|
94 | 96 |
|
| 97 | +static void |
| 98 | +get_child_window_ids_helper(Display *display, Window window, |
| 99 | + Window **total_children, unsigned int *total_num_children) { |
| 100 | + Window _, *children; |
| 101 | + unsigned int num_children; |
| 102 | + |
| 103 | + XQueryTree(display, window, &_, &_, &children, &num_children); |
| 104 | + if (!children) return; |
| 105 | + |
| 106 | + if (!*total_children) { |
| 107 | + *total_children = calloc(num_children, sizeof(Window)); |
| 108 | + } else { |
| 109 | + Window *tmp = reallocarray(*total_children, num_children + *total_num_children, sizeof(Window)); |
| 110 | + if (tmp) { |
| 111 | + *total_children = tmp; |
| 112 | + } |
| 113 | + } |
| 114 | + |
| 115 | + for (int i = 0; i < num_children; ++i) { |
| 116 | + (*total_children)[i + *total_num_children] = children[i]; |
| 117 | + } |
| 118 | + *total_num_children += num_children; |
| 119 | + |
| 120 | + for (int i = 0; i < num_children; ++i) { |
| 121 | + get_child_window_ids_helper(display, children[i], total_children, total_num_children); |
| 122 | + } |
| 123 | + |
| 124 | + XFree(children); |
| 125 | +} |
95 | 126 |
|
96 | 127 | static PyObject *
|
97 | 128 | Display_get_child_window_ids(DisplayObject *self, PyObject *args, PyObject *kwds) {
|
98 | 129 | static char *kwlist[] = {"parent_id", NULL};
|
99 | 130 | Window parent = XDefaultRootWindow(self->info_display);
|
100 |
| - Window _, *children; |
101 |
| - unsigned int children_count; |
| 131 | + Window *children = NULL; |
| 132 | + unsigned int children_count = 0; |
102 | 133 |
|
103 | 134 | if (!PyArg_ParseTupleAndKeywords(
|
104 | 135 | args, kwds, "|k", kwlist,
|
105 | 136 | &parent)) {
|
106 | 137 | Py_RETURN_ERROR;
|
107 | 138 | }
|
108 | 139 |
|
109 |
| - if (!XQueryTree( |
110 |
| - self->info_display, parent, |
111 |
| - &_, &_, &children, &children_count)) { |
112 |
| - raise(OSError, "failed to query child windows of %lu", parent); |
113 |
| - } |
| 140 | + get_child_window_ids_helper(self->info_display, parent, &children, &children_count); |
114 | 141 |
|
115 | 142 | PyObject *child_ids = PyList_New(0);
|
116 | 143 | if (children) {
|
|
0 commit comments