1 #include "ecore_xcb_private.h"
3 typedef struct _Shadow Shadow;
6 Shadow *parent, **children;
13 static Eina_Bool _inside_rects(Shadow *s,
18 Ecore_X_Rectangle *rects,
21 //static int shadow_count = 0;
22 static Shadow **shadow_base = NULL;
23 static int shadow_num = 0;
25 /* FIXME: round trips */
27 _ecore_x_window_tree_walk(Ecore_X_Window window)
30 xcb_get_window_attributes_reply_t *reply_attr;
31 xcb_get_geometry_reply_t *reply_geom;
32 xcb_query_tree_reply_t *reply_tree;
33 xcb_get_window_attributes_cookie_t cookie_attr;
34 xcb_get_geometry_cookie_t cookie_geom;
35 xcb_query_tree_cookie_t cookie_tree;
40 cookie_attr = xcb_get_window_attributes_unchecked(_ecore_xcb_conn, window);
41 reply_attr = xcb_get_window_attributes_reply(_ecore_xcb_conn, cookie_attr, NULL);
42 if (!reply_attr) return NULL;
43 if (reply_attr->map_state != XCB_MAP_STATE_VIEWABLE)
51 cookie_geom = xcb_get_geometry_unchecked(_ecore_xcb_conn, window);
52 reply_geom = xcb_get_geometry_reply(_ecore_xcb_conn, cookie_geom, NULL);
53 if (!reply_geom) return NULL;
55 if (!(s = calloc(1, sizeof(Shadow))))
64 s->w = reply_geom->width;
65 s->h = reply_geom->height;
69 cookie_tree = xcb_query_tree_unchecked(_ecore_xcb_conn, window);
70 reply_tree = xcb_query_tree_reply(_ecore_xcb_conn, cookie_tree, NULL);
76 num = xcb_query_tree_children_length(reply_tree);
77 list = xcb_query_tree_children(reply_tree);
79 s->children = calloc(1, sizeof(Shadow *) * num);
82 s->children_num = num;
83 for (i = 0; i < num; i++)
85 s->children[i] = _ecore_x_window_tree_walk(list[i]);
87 s->children[i]->parent = s;
89 /* compress list down */
91 for (i = 0; i < num; i++)
95 s->children[j] = s->children[i];
108 sl = realloc(s->children, sizeof(Shadow *) * j);
109 if (sl) s->children = sl;
120 _ecore_x_window_tree_shadow_free1(Shadow *s)
127 for (i = 0; i < s->children_num; i++)
130 _ecore_x_window_tree_shadow_free1(s->children[i]);
139 _ecore_x_window_tree_shadow_free(void)
143 if (!shadow_base) return;
145 for (i = 0; i < shadow_num; i++)
147 if (!shadow_base[i]) continue;
148 _ecore_x_window_tree_shadow_free1(shadow_base[i]);
156 _ecore_x_window_tree_shadow_populate(void)
158 Ecore_X_Window *roots = NULL;
161 if ((roots = ecore_x_window_root_list(&num)))
163 shadow_base = calloc(1, sizeof(Shadow *) * num);
167 for (i = 0; i < num; i++)
168 shadow_base[i] = _ecore_x_window_tree_walk(roots[i]);
177 _ecore_x_window_tree_shadow_start(void)
180 if (shadow_count > 1) return;
181 _ecore_x_window_tree_shadow_populate();
185 _ecore_x_window_tree_shadow_stop(void)
188 if (shadow_count != 0) return;
189 _ecore_x_window_tree_shadow_free();
194 _ecore_x_window_shadow_tree_find_shadow(Shadow *s,
200 if (s->win == win) return s;
204 for (i = 0; i < s->children_num; i++)
206 if (!s->children[i]) continue;
209 _ecore_x_window_shadow_tree_find_shadow(s->children[i], win)))
218 _ecore_x_window_shadow_tree_find(Ecore_X_Window base)
223 for (i = 0; i < shadow_num; i++)
225 if (!shadow_base[i]) continue;
228 _ecore_x_window_shadow_tree_find_shadow(shadow_base[i], base)))
234 static Ecore_X_Window
235 _ecore_x_window_shadow_tree_at_xy_get_shadow(Shadow *s,
240 Ecore_X_Window *skip,
243 Ecore_X_Window child;
244 Ecore_X_Rectangle *rects;
245 int i = 0, j = 0, wx = 0, wy = 0, num = 0;
249 if (!((x >= wx) && (y >= wy) && (x < (wx + s->w)) && (y < (wy + s->h))))
252 rects = ecore_x_window_shape_rectangles_get(s->win, &num);
253 if (!_inside_rects(s, x, y, bx, by, rects, num)) return 0;
255 rects = ecore_x_window_shape_input_rectangles_get(s->win, &num);
256 if (!_inside_rects(s, x, y, bx, by, rects, num)) return 0;
262 for (i = s->children_num - 1; i >= 0; --i)
264 if (!s->children[i]) continue;
269 for (j = 0; j < skip_num; j++)
271 if (s->children[i]->win == skip[j])
282 _ecore_x_window_shadow_tree_at_xy_get_shadow(s->children[i], wx, wy, x, y, skip, skip_num)))
291 static Ecore_X_Window
292 _ecore_x_window_shadow_tree_at_xy_get(Ecore_X_Window base,
297 Ecore_X_Window *skip,
304 _ecore_x_window_tree_shadow_populate();
305 if (!shadow_base) return 0;
308 s = _ecore_x_window_shadow_tree_find(base);
311 return _ecore_x_window_shadow_tree_at_xy_get_shadow(s, bx, by, x, y, skip, skip_num);
315 _inside_rects(Shadow *s,
320 Ecore_X_Rectangle *rects,
323 Eina_Bool inside = EINA_FALSE;
326 if (!rects) return EINA_FALSE;
327 for (i = 0; i < num; i++)
329 if ((x >= s->x + bx + rects[i].x) &&
330 (y >= s->y + by + rects[i].y) &&
331 (x < (int)(s->x + bx + rects[i].x + rects[i].width)) &&
332 (y < (int)(s->y + by + rects[i].y + rects[i].height)))
343 * Retrieves the top, visible window at the given location,
344 * but skips the windows in the list. This uses a shadow tree built from the
345 * window tree that is only updated the first time
346 * ecore_x_window_shadow_tree_at_xy_with_skip_get() is called, or the next time
347 * it is called after a ecore_x_window_shadow_tree_flush()
348 * @param base The base window to start searching from (normally root).
349 * @param x The given X position.
350 * @param y The given Y position.
351 * @param skip The list of windows to be skipped.
352 * @param skip_num The number of windows to be skipped.
353 * @return The window at the desired position.
354 * @ingroup Ecore_X_Window_Geometry_Group
357 ecore_x_window_shadow_tree_at_xy_with_skip_get(Ecore_X_Window base,
360 Ecore_X_Window *skip,
363 return _ecore_x_window_shadow_tree_at_xy_get(base, 0, 0, x, y, skip, skip_num);
367 * Retrieves the parent window a given window has. This uses the shadow window
369 * @param root The root window of @p win - if 0, this will be automatically determined with extra processing overhead
370 * @param win The window to get the parent window of
371 * @return The parent window of @p win
372 * @ingroup Ecore_X_Window_Geometry_Group
375 ecore_x_window_shadow_parent_get(Ecore_X_Window root __UNUSED__,
383 _ecore_x_window_tree_shadow_populate();
384 if (!shadow_base) return 0;
387 for (i = 0; i < shadow_num; i++)
389 if (!shadow_base[i]) continue;
391 s = _ecore_x_window_shadow_tree_find_shadow(shadow_base[i], win);
394 if (!s->parent) return 0;
395 return s->parent->win;
402 * Flushes the window shadow tree so nothing is stored.
403 * @ingroup Ecore_X_Window_Geometry_Group
406 ecore_x_window_shadow_tree_flush(void)
408 _ecore_x_window_tree_shadow_free();