2 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
5 /* #include "Ecore.h" */
6 #include "ecore_xcb_private.h"
10 typedef struct _Shadow Shadow;
21 static int shadow_count = 0;
22 static Shadow **shadow_base = NULL;
23 static int shadow_num = 0;
26 /* FIXME: round trips */
28 _ecore_x_window_tree_walk(Ecore_X_Window window)
32 xcb_get_window_attributes_reply_t *reply_attr;
33 xcb_get_geometry_reply_t *reply_geom;
34 xcb_query_tree_reply_t *reply_tree;
35 xcb_get_window_attributes_cookie_t cookie_attr;
36 xcb_get_geometry_cookie_t cookie_geom;
37 xcb_query_tree_cookie_t cookie_tree;
41 cookie_attr = xcb_get_window_attributes_unchecked(_ecore_xcb_conn, window);
42 cookie_geom = xcb_get_geometry_unchecked(_ecore_xcb_conn, window);
43 cookie_tree = xcb_query_tree_unchecked(_ecore_xcb_conn, window);
45 reply_attr = xcb_get_window_attributes_reply(_ecore_xcb_conn, cookie_attr, NULL);
48 reply_geom = xcb_get_geometry_reply(_ecore_xcb_conn, cookie_geom, NULL);
49 if (reply_geom) free(reply_geom);
50 reply_tree = xcb_query_tree_reply(_ecore_xcb_conn, cookie_tree, NULL);
51 if (reply_tree) free(reply_tree);
55 if (reply_attr->map_state != XCB_MAP_STATE_VIEWABLE)
57 reply_geom = xcb_get_geometry_reply(_ecore_xcb_conn, cookie_geom, NULL);
58 if (reply_geom) free(reply_geom);
59 reply_tree = xcb_query_tree_reply(_ecore_xcb_conn, cookie_tree, NULL);
60 if (reply_tree) free(reply_tree);
66 s = calloc(1, sizeof(Shadow));
69 reply_geom = xcb_get_geometry_reply(_ecore_xcb_conn, cookie_geom, NULL);
72 reply_tree = xcb_query_tree_reply(_ecore_xcb_conn, cookie_tree, NULL);
73 if (reply_tree) free(reply_tree);
80 s->w = reply_geom->width;
81 s->h = reply_geom->height;
85 reply_tree = xcb_query_tree_reply(_ecore_xcb_conn, cookie_tree, NULL);
87 /* if (XQueryTree(_ecore_xcb_conn, s->win, &root_win, &parent_win, */
93 num = xcb_query_tree_children_length(reply_tree);
94 list = xcb_query_tree_children(reply_tree);
96 s->children = calloc(1, sizeof(Shadow *) * num);
99 s->children_num = num;
100 for (i = 0; i < num; i++)
102 s->children[i] = _ecore_x_window_tree_walk(list[i]);
103 if (s->children[i]) s->children[i]->parent = s;
105 /* compress list down */
107 for (i = 0; i < num; i++)
111 s->children[j] = s->children[i];
124 sl = realloc(s->children, sizeof(Shadow *) * j);
125 if (sl) s->children = sl;
134 _ecore_x_window_tree_shadow_free1(Shadow *s)
141 for (i = 0; i < s->children_num; i++)
144 _ecore_x_window_tree_shadow_free1(s->children[i]);
152 _ecore_x_window_tree_shadow_free(void)
156 if (!shadow_base) return;
157 for (i = 0; i < shadow_num; i++)
159 if (!shadow_base[i]) continue;
160 _ecore_x_window_tree_shadow_free1(shadow_base[i]);
168 _ecore_x_window_tree_shadow_populate(void)
170 Ecore_X_Window *roots;
173 roots = ecore_x_window_root_list(&num);
176 shadow_base = calloc(1, sizeof(Shadow *) * num);
180 for (i = 0; i < num; i++)
181 shadow_base[i] = _ecore_x_window_tree_walk(roots[i]);
188 _ecore_x_window_tree_shadow_start(void)
191 if (shadow_count > 1) return;
192 _ecore_x_window_tree_shadow_populate();
196 _ecore_x_window_tree_shadow_stop(void)
199 if (shadow_count != 0) return;
200 _ecore_x_window_tree_shadow_free();
204 _ecore_x_window_shadow_tree_find_shadow(Shadow *s, Ecore_X_Window win)
209 if (s->win == win) return s;
212 for (i = 0; i < s->children_num; i++)
214 if (!s->children[i]) continue;
215 if ((ss = _ecore_x_window_shadow_tree_find_shadow(s->children[i], win)))
223 _ecore_x_window_shadow_tree_find(Ecore_X_Window base)
228 for (i = 0; i < shadow_num; i++)
230 if (!shadow_base[i]) continue;
231 if ((s = _ecore_x_window_shadow_tree_find_shadow(shadow_base[i], base)))
237 static Ecore_X_Window
238 _ecore_x_window_shadow_tree_at_xy_get_shadow(Shadow *s, int bx, int by, int x, int y,
239 Ecore_X_Window *skip, int skip_num)
241 Ecore_X_Window child;
247 if (!((x >= wx) && (y >= wy) && (x < (wx + s->w)) && (y < (wy + s->h))))
253 for (i = s->children_num - 1; i >= 0; --i)
255 if (!s->children[i]) continue;
259 for (j = 0; j < skip_num; j++)
261 if (s->children[i]->win == skip[j])
271 if ((child = _ecore_x_window_shadow_tree_at_xy_get_shadow(s->children[i], wx, wy, x, y, skip, skip_num)))
281 static Ecore_X_Window
282 _ecore_x_window_shadow_tree_at_xy_get(Ecore_X_Window base, int bx, int by, int x, int y,
283 Ecore_X_Window *skip, int skip_num)
289 _ecore_x_window_tree_shadow_populate();
290 if (!shadow_base) return 0;
292 s = _ecore_x_window_shadow_tree_find(base);
294 return _ecore_x_window_shadow_tree_at_xy_get_shadow(s, bx, by, x, y, skip, skip_num);
298 * Retrieves the top, visible window at the given location,
299 * but skips the windows in the list. This uses a shadow tree built from the
300 * window tree that is only updated the first time
301 * ecore_x_window_shadow_tree_at_xy_with_skip_get() is called, or the next time
302 * it is called after a ecore_x_window_shadow_tree_flush()
303 * @param base The base window to start searching from (normally root).
304 * @param x The given X position.
305 * @param y The given Y position.
306 * @return The window at that position.
307 * @ingroup Ecore_X_Window_Geometry_Group
310 ecore_x_window_shadow_tree_at_xy_with_skip_get(Ecore_X_Window base, int x, int y, Ecore_X_Window *skip, int skip_num)
312 return _ecore_x_window_shadow_tree_at_xy_get(base, 0, 0, x, y, skip, skip_num);
316 * Retrieves the parent window a given window has. This uses the shadow window
318 * @param root The root window of @p win - if 0, this will be automatically determined with extra processing overhead
319 * @param win The window to get the parent window of
320 * @return The parent window of @p win
321 * @ingroup Ecore_X_Window_Geometry_Group
324 ecore_x_window_shadow_parent_get(Ecore_X_Window root, Ecore_X_Window win)
331 _ecore_x_window_tree_shadow_populate();
332 if (!shadow_base) return 0;
334 for (i = 0; i < shadow_num; i++)
336 if (!shadow_base[i]) continue;
337 s = _ecore_x_window_shadow_tree_find_shadow(shadow_base[i], win);
340 if (!s->parent) return 0;
341 return s->parent->win;
348 * Flushes the window shadow tree so nothing is stored.
349 * @ingroup Ecore_X_Window_Geometry_Group
352 ecore_x_window_shadow_tree_flush(void)
354 _ecore_x_window_tree_shadow_free();