From dd7595a3475407a7fa96a97393bae8c5220e8762 Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Wed, 4 Jan 2012 18:41:13 +1000 Subject: Add the base Enlightenment Foundation Libraries - eina, eet, evas, ecore, embryo, and edje. Note that embryo wont be used, but I'm not sure yet if you can build edje without it. --- .../src/lib/ecore_x/xcb/ecore_xcb_window_shadow.c | 408 +++++++++++++++++++++ 1 file changed, 408 insertions(+) create mode 100644 libraries/ecore/src/lib/ecore_x/xcb/ecore_xcb_window_shadow.c (limited to 'libraries/ecore/src/lib/ecore_x/xcb/ecore_xcb_window_shadow.c') diff --git a/libraries/ecore/src/lib/ecore_x/xcb/ecore_xcb_window_shadow.c b/libraries/ecore/src/lib/ecore_x/xcb/ecore_xcb_window_shadow.c new file mode 100644 index 0000000..4f24d62 --- /dev/null +++ b/libraries/ecore/src/lib/ecore_x/xcb/ecore_xcb_window_shadow.c @@ -0,0 +1,408 @@ +#include "ecore_xcb_private.h" + +typedef struct _Shadow Shadow; +struct _Shadow +{ + Shadow *parent, **children; + Ecore_X_Window win; + int children_num; + short x, y; + unsigned short w, h; +}; + +static Eina_Bool _inside_rects(Shadow *s, + int x, + int y, + int bx, + int by, + Ecore_X_Rectangle *rects, + int num); + +//static int shadow_count = 0; +static Shadow **shadow_base = NULL; +static int shadow_num = 0; + +/* FIXME: round trips */ +static Shadow * +_ecore_x_window_tree_walk(Ecore_X_Window window) +{ + Shadow *s, **sl; + xcb_get_window_attributes_reply_t *reply_attr; + xcb_get_geometry_reply_t *reply_geom; + xcb_query_tree_reply_t *reply_tree; + xcb_get_window_attributes_cookie_t cookie_attr; + xcb_get_geometry_cookie_t cookie_geom; + xcb_query_tree_cookie_t cookie_tree; + int i, j; + + CHECK_XCB_CONN; + + cookie_attr = xcb_get_window_attributes_unchecked(_ecore_xcb_conn, window); + reply_attr = xcb_get_window_attributes_reply(_ecore_xcb_conn, cookie_attr, NULL); + if (!reply_attr) return NULL; + if (reply_attr->map_state != XCB_MAP_STATE_VIEWABLE) + { + free(reply_attr); + return NULL; + } + + free(reply_attr); + + cookie_geom = xcb_get_geometry_unchecked(_ecore_xcb_conn, window); + reply_geom = xcb_get_geometry_reply(_ecore_xcb_conn, cookie_geom, NULL); + if (!reply_geom) return NULL; + + if (!(s = calloc(1, sizeof(Shadow)))) + { + free(reply_geom); + return NULL; + } + + s->win = window; + s->x = reply_geom->x; + s->y = reply_geom->y; + s->w = reply_geom->width; + s->h = reply_geom->height; + + free(reply_geom); + + cookie_tree = xcb_query_tree_unchecked(_ecore_xcb_conn, window); + reply_tree = xcb_query_tree_reply(_ecore_xcb_conn, cookie_tree, NULL); + if (reply_tree) + { + xcb_window_t *list; + int num; + + num = xcb_query_tree_children_length(reply_tree); + list = xcb_query_tree_children(reply_tree); + + s->children = calloc(1, sizeof(Shadow *) * num); + if (s->children) + { + s->children_num = num; + for (i = 0; i < num; i++) + { + s->children[i] = _ecore_x_window_tree_walk(list[i]); + if (s->children[i]) + s->children[i]->parent = s; + } + /* compress list down */ + j = 0; + for (i = 0; i < num; i++) + { + if (s->children[i]) + { + s->children[j] = s->children[i]; + j++; + } + } + if (j == 0) + { + free(s->children); + s->children = NULL; + s->children_num = 0; + } + else + { + s->children_num = j; + sl = realloc(s->children, sizeof(Shadow *) * j); + if (sl) s->children = sl; + } + } + + free(reply_tree); + } + + return s; +} + +static void +_ecore_x_window_tree_shadow_free1(Shadow *s) +{ + int i = 0; + + if (!s) return; + if (s->children) + { + for (i = 0; i < s->children_num; i++) + { + if (s->children[i]) + _ecore_x_window_tree_shadow_free1(s->children[i]); + } + free(s->children); + } + + free(s); +} + +static void +_ecore_x_window_tree_shadow_free(void) +{ + int i = 0; + + if (!shadow_base) return; + + for (i = 0; i < shadow_num; i++) + { + if (!shadow_base[i]) continue; + _ecore_x_window_tree_shadow_free1(shadow_base[i]); + } + free(shadow_base); + shadow_base = NULL; + shadow_num = 0; +} + +static void +_ecore_x_window_tree_shadow_populate(void) +{ + Ecore_X_Window *roots = NULL; + int i = 0, num = 0; + + if ((roots = ecore_x_window_root_list(&num))) + { + shadow_base = calloc(1, sizeof(Shadow *) * num); + if (shadow_base) + { + shadow_num = num; + for (i = 0; i < num; i++) + shadow_base[i] = _ecore_x_window_tree_walk(roots[i]); + } + + free(roots); + } +} + +/* + static void + _ecore_x_window_tree_shadow_start(void) + { + shadow_count++; + if (shadow_count > 1) return; + _ecore_x_window_tree_shadow_populate(); + } + + static void + _ecore_x_window_tree_shadow_stop(void) + { + shadow_count--; + if (shadow_count != 0) return; + _ecore_x_window_tree_shadow_free(); + } + */ + +Shadow * +_ecore_x_window_shadow_tree_find_shadow(Shadow *s, + Ecore_X_Window win) +{ + Shadow *ss; + int i = 0; + + if (s->win == win) return s; + + if (s->children) + { + for (i = 0; i < s->children_num; i++) + { + if (!s->children[i]) continue; + + if ((ss = + _ecore_x_window_shadow_tree_find_shadow(s->children[i], win))) + return ss; + } + } + + return NULL; +} + +Shadow * +_ecore_x_window_shadow_tree_find(Ecore_X_Window base) +{ + Shadow *s; + int i = 0; + + for (i = 0; i < shadow_num; i++) + { + if (!shadow_base[i]) continue; + + if ((s = + _ecore_x_window_shadow_tree_find_shadow(shadow_base[i], base))) + return s; + } + return NULL; +} + +static Ecore_X_Window +_ecore_x_window_shadow_tree_at_xy_get_shadow(Shadow *s, + int bx, + int by, + int x, + int y, + Ecore_X_Window *skip, + int skip_num) +{ + Ecore_X_Window child; + Ecore_X_Rectangle *rects; + int i = 0, j = 0, wx = 0, wy = 0, num = 0; + + wx = s->x + bx; + wy = s->y + by; + if (!((x >= wx) && (y >= wy) && (x < (wx + s->w)) && (y < (wy + s->h)))) + return 0; + + rects = ecore_x_window_shape_rectangles_get(s->win, &num); + if (!_inside_rects(s, x, y, bx, by, rects, num)) return 0; + num = 0; + rects = ecore_x_window_shape_input_rectangles_get(s->win, &num); + if (!_inside_rects(s, x, y, bx, by, rects, num)) return 0; + + if (s->children) + { + int skipit = 0; + + for (i = s->children_num - 1; i >= 0; --i) + { + if (!s->children[i]) continue; + + skipit = 0; + if (skip) + { + for (j = 0; j < skip_num; j++) + { + if (s->children[i]->win == skip[j]) + { + skipit = 1; + goto onward; + } + } + } +onward: + if (!skipit) + { + if ((child = + _ecore_x_window_shadow_tree_at_xy_get_shadow(s->children[i], wx, wy, x, y, skip, skip_num))) + return child; + } + } + } + + return s->win; +} + +static Ecore_X_Window +_ecore_x_window_shadow_tree_at_xy_get(Ecore_X_Window base, + int bx, + int by, + int x, + int y, + Ecore_X_Window *skip, + int skip_num) +{ + Shadow *s; + + if (!shadow_base) + { + _ecore_x_window_tree_shadow_populate(); + if (!shadow_base) return 0; + } + + s = _ecore_x_window_shadow_tree_find(base); + if (!s) return 0; + + return _ecore_x_window_shadow_tree_at_xy_get_shadow(s, bx, by, x, y, skip, skip_num); +} + +static Eina_Bool +_inside_rects(Shadow *s, + int x, + int y, + int bx, + int by, + Ecore_X_Rectangle *rects, + int num) +{ + Eina_Bool inside = EINA_FALSE; + int i = 0; + + if (!rects) return EINA_FALSE; + for (i = 0; i < num; i++) + { + if ((x >= s->x + bx + rects[i].x) && + (y >= s->y + by + rects[i].y) && + (x < (int)(s->x + bx + rects[i].x + rects[i].width)) && + (y < (int)(s->y + by + rects[i].y + rects[i].height))) + { + inside = EINA_TRUE; + break; + } + } + free(rects); + return inside; +} + +/** + * Retrieves the top, visible window at the given location, + * but skips the windows in the list. This uses a shadow tree built from the + * window tree that is only updated the first time + * ecore_x_window_shadow_tree_at_xy_with_skip_get() is called, or the next time + * it is called after a ecore_x_window_shadow_tree_flush() + * @param base The base window to start searching from (normally root). + * @param x The given X position. + * @param y The given Y position. + * @return The window at that position. + * @ingroup Ecore_X_Window_Geometry_Group + */ +EAPI Ecore_X_Window +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) +{ + return _ecore_x_window_shadow_tree_at_xy_get(base, 0, 0, x, y, skip, skip_num); +} + +/** + * Retrieves the parent window a given window has. This uses the shadow window + * tree. + * @param root The root window of @p win - if 0, this will be automatically determined with extra processing overhead + * @param win The window to get the parent window of + * @return The parent window of @p win + * @ingroup Ecore_X_Window_Geometry_Group + */ +EAPI Ecore_X_Window +ecore_x_window_shadow_parent_get(Ecore_X_Window root __UNUSED__, + Ecore_X_Window win) +{ + Shadow *s; + int i = 0; + + if (!shadow_base) + { + _ecore_x_window_tree_shadow_populate(); + if (!shadow_base) return 0; + } + + for (i = 0; i < shadow_num; i++) + { + if (!shadow_base[i]) continue; + + s = _ecore_x_window_shadow_tree_find_shadow(shadow_base[i], win); + if (s) + { + if (!s->parent) return 0; + return s->parent->win; + } + } + return 0; +} + +/** + * Flushes the window shadow tree so nothing is stored. + * @ingroup Ecore_X_Window_Geometry_Group + */ +EAPI void +ecore_x_window_shadow_tree_flush(void) +{ + _ecore_x_window_tree_shadow_free(); +} + -- cgit v1.1