From 3f80f51a24fe5090433805ab734dece0f2aeaffb Mon Sep 17 00:00:00 2001 From: doursse Date: Tue, 29 Jul 2008 09:00:17 +0000 Subject: [PATCH] add ecore_x_window_shadow* api, use latest xcb_icccm api, remove trailing spaces, formatting SVN revision: 35243 --- legacy/ecore/src/lib/ecore_x/xcb/Makefile.am | 1 + legacy/ecore/src/lib/ecore_x/xcb/ecore_xcb.c | 12 +- .../src/lib/ecore_x/xcb/ecore_xcb_icccm.c | 68 ++-- .../src/lib/ecore_x/xcb/ecore_xcb_window.c | 2 +- .../lib/ecore_x/xcb/ecore_xcb_window_shadow.c | 355 ++++++++++++++++++ 5 files changed, 392 insertions(+), 46 deletions(-) create mode 100644 legacy/ecore/src/lib/ecore_x/xcb/ecore_xcb_window_shadow.c diff --git a/legacy/ecore/src/lib/ecore_x/xcb/Makefile.am b/legacy/ecore/src/lib/ecore_x/xcb/Makefile.am index f77a80b7ef..39dde65a82 100644 --- a/legacy/ecore/src/lib/ecore_x/xcb/Makefile.am +++ b/legacy/ecore/src/lib/ecore_x/xcb/Makefile.am @@ -50,6 +50,7 @@ ecore_xcb_shape.c \ ecore_xcb_sync.c \ ecore_xcb_window.c \ ecore_xcb_window_prop.c \ +ecore_xcb_window_shadow.c \ ecore_xcb_xinerama.c \ ecore_xcb.c diff --git a/legacy/ecore/src/lib/ecore_x/xcb/ecore_xcb.c b/legacy/ecore/src/lib/ecore_x/xcb/ecore_xcb.c index 3bfcd05498..9ccf5f79b2 100644 --- a/legacy/ecore/src/lib/ecore_x/xcb/ecore_xcb.c +++ b/legacy/ecore/src/lib/ecore_x/xcb/ecore_xcb.c @@ -148,9 +148,9 @@ EAPI int ECORE_X_LOCK_CAPS = 0; EAPI int ecore_x_init(const char *name) { - xcb_screen_iterator_t iter; - int screen; - uint32_t max_request_length; + xcb_screen_iterator_t iter; + int screen; + uint32_t max_request_length; const xcb_query_extension_reply_t *reply_big_requests; #ifdef ECORE_XCB_DAMAGE const xcb_query_extension_reply_t *reply_damage; @@ -171,8 +171,8 @@ ecore_x_init(const char *name) const xcb_query_extension_reply_t *reply_shape; #endif /* ECORE_XCB_SHAPE */ #ifdef ECORE_XCB_SYNC - xcb_sync_initialize_cookie_t cookie_sync_init; - xcb_sync_initialize_reply_t *reply_sync_init; + xcb_sync_initialize_cookie_t cookie_sync_init; + xcb_sync_initialize_reply_t *reply_sync_init; const xcb_query_extension_reply_t *reply_sync; #endif /* ECORE_XCB_SYNC */ #ifdef ECORE_XCB_FIXES @@ -185,7 +185,7 @@ ecore_x_init(const char *name) const xcb_query_extension_reply_t *reply_xprint; #endif /* ECORE_XCB_XPRINT */ - xcb_intern_atom_cookie_t atom_cookies[ECORE_X_ATOMS_COUNT]; + xcb_intern_atom_cookie_t atom_cookies[ECORE_X_ATOMS_COUNT]; if (_ecore_xcb_init_count > 0) { diff --git a/legacy/ecore/src/lib/ecore_x/xcb/ecore_xcb_icccm.c b/legacy/ecore/src/lib/ecore_x/xcb/ecore_xcb_icccm.c index 1d4c6ecec4..c5b011365a 100644 --- a/legacy/ecore/src/lib/ecore_x/xcb/ecore_xcb_icccm.c +++ b/legacy/ecore/src/lib/ecore_x/xcb/ecore_xcb_icccm.c @@ -22,20 +22,6 @@ */ -typedef enum { - USPosition = 1 << 0, - USSize = 1 << 1, - PPosition = 1 << 2, - PSize = 1 << 3, - PMinSize = 1 << 4, - PMaxSize = 1 << 5, - PResizeInc = 1 << 6, - PAspect = 1 << 7, - PBaseSize = 1 << 8, - PWinGravity = 1 << 9 -} SizeHintsFlags; - - static int _ecore_x_icccm_size_hints_get (const void *reply, Ecore_X_Atom property, xcb_size_hints_t *hints) @@ -56,13 +42,13 @@ static int _ecore_x_icccm_size_hints_get (const void *reply, xcb_get_property_value((xcb_get_property_reply_t *)reply), ((xcb_get_property_reply_t *)reply)->value_len); - s = (USPosition | USSize | - PPosition | PSize | - PMinSize | PMaxSize | - PResizeInc | PAspect); + s = (XCB_SIZE_US_POSITION_HINT | XCB_SIZE_US_SIZE_HINT | + XCB_SIZE_P_POSITION_HINT | XCB_SIZE_P_SIZE_HINT | + XCB_SIZE_P_MIN_SIZE_HINT | XCB_SIZE_P_MAX_SIZE_HINT | + XCB_SIZE_P_RESIZE_INC_HINT | XCB_SIZE_P_ASPECT_HINT); if (((xcb_get_property_reply_t *)reply)->value_len >= 18) /* NumPropSizeElements = 18 (ICCCM version 1) */ - s |= (PBaseSize | PWinGravity); + s |= (XCB_SIZE_BASE_SIZE_HINT | XCB_SIZE_P_WIN_GRAVITY_HINT); else { xcb_size_hints_set_base_size(hints, 0, 0); @@ -301,7 +287,7 @@ ecore_x_icccm_hints_set(Ecore_X_Window window, if (window_group != 0) xcb_wm_hints_set_window_group(hints, window_group); if (is_urgent) - xcb_wm_hints_set_urgent(hints); + xcb_wm_hints_set_urgency(hints); xcb_set_wm_hints(_ecore_xcb_conn, window, hints); free(hints); } @@ -366,6 +352,7 @@ ecore_x_icccm_hints_get(Ecore_X_Window window __UNUSED__, { xcb_wm_hints_t *hints; xcb_get_property_reply_t *reply; + uint32_t flags; if (accepts_focus) *accepts_focus = 1; @@ -397,42 +384,43 @@ ecore_x_icccm_hints_get(Ecore_X_Window window __UNUSED__, memcpy(hints, xcb_get_property_value(reply), reply->value_len); - if ((xcb_wm_hints_is_input_hint(hints)) && (accepts_focus)) + flags = xcb_wm_hints_get_flags(hints); + if ((flags & XCB_WM_INPUT_HINT) && (accepts_focus)) { if (xcb_wm_hints_get_input(hints)) *accepts_focus = 1; else *accepts_focus = 0; } - if ((xcb_wm_hints_is_state_hint(hints)) && (initial_state)) + if ((flags & XCB_WM_STATE_HINT) && (initial_state)) { - if (xcb_wm_hints_state_is_withdrawn(hints)) + if (xcb_wm_hints_get_initial_state(hints) == XCB_WM_WITHDRAWN_STATE) *initial_state = ECORE_X_WINDOW_STATE_HINT_WITHDRAWN; - else if (xcb_wm_hints_state_is_normal(hints)) + else if (xcb_wm_hints_get_initial_state(hints) == XCB_WM_NORMAL_STATE) *initial_state = ECORE_X_WINDOW_STATE_HINT_NORMAL; - else if (xcb_wm_hints_state_is_iconic(hints)) + else if (xcb_wm_hints_get_initial_state(hints) == XCB_WM_ICONIC_STATE) *initial_state = ECORE_X_WINDOW_STATE_HINT_ICONIC; } - if ((xcb_wm_hints_is_icon_pixmap_hint(hints)) && (icon_pixmap)) + if ((flags & XCB_WM_ICON_PIXMAP_HINT) && (icon_pixmap)) { *icon_pixmap = xcb_wm_hints_get_icon_pixmap(hints); } - if ((xcb_wm_hints_is_icon_mask_hint(hints)) && (icon_mask)) + if ((flags & XCB_WM_ICON_MASK_HINT) && (icon_mask)) { *icon_mask = xcb_wm_hints_get_icon_mask(hints); } - if ((xcb_wm_hints_is_icon_window_hint(hints)) && (icon_window)) + if ((flags & XCB_WM_ICON_WINDOW_HINT) && (icon_window)) { *icon_window = xcb_wm_hints_get_icon_window(hints); } - if ((xcb_wm_hints_is_window_group_hint(hints)) && (window_group)) + if ((flags & XCB_WM_WINDOW_GROUP_HINT) && (window_group)) { if (reply->value_len < XCB_NUM_WM_HINTS_ELEMENTS) *window_group = 0; else *window_group = xcb_wm_hints_get_window_group(hints); } - if ((xcb_wm_hints_is_x_urgency_hint(hints)) && (is_urgent)) + if ((flags & XCB_WM_X_URGENCY_HINT) && (is_urgent)) { *is_urgent = 1; } @@ -525,10 +513,10 @@ ecore_x_icccm_size_pos_hints_set(Ecore_X_Window window, (reply->value_len < 15)) return; - xcb_size_hints_set_flag_none(hint); + xcb_size_hints_set_flags(hint, 0); if (request_pos) { - xcb_size_hints_set_flag_us_position(hint); + xcb_size_hints_set_flags(hint, XCB_SIZE_US_POSITION_HINT); } if (gravity != ECORE_X_GRAVITY_NW) { @@ -602,6 +590,7 @@ ecore_x_icccm_size_pos_hints_get(Ecore_X_Window window __UNUSED__, { xcb_size_hints_t *hint; xcb_get_property_reply_t *reply; + uint32_t flags; int32_t minw = 0; int32_t minh = 0; int32_t maxw = 32767; @@ -637,21 +626,22 @@ ecore_x_icccm_size_pos_hints_get(Ecore_X_Window window __UNUSED__, if (!_ecore_x_icccm_size_hints_get(reply, ECORE_X_ATOM_WM_NORMAL_HINTS, hint)) return 0; - if (xcb_size_hints_is_us_position(hint) || xcb_size_hints_is_p_position(hint)) + flags = xcb_size_hints_get_flags(hint); + if ((flags & XCB_SIZE_US_POSITION_HINT) || (flags & XCB_SIZE_P_POSITION_HINT)) { if (request_pos) *request_pos = 1; } - if (xcb_size_hints_is_p_win_gravity(hint)) + if (flags & XCB_SIZE_P_WIN_GRAVITY_HINT) { if (gravity) *gravity = xcb_size_hints_get_win_gravity(hint); } - if (xcb_size_hints_is_p_min_size(hint)) + if (flags & XCB_SIZE_P_MIN_SIZE_HINT) { xcb_size_hints_get_min_size(hint, &minw, &minh); } - if (xcb_size_hints_is_p_max_size(hint)) + if (flags & XCB_SIZE_P_MAX_SIZE_HINT) { xcb_size_hints_get_max_size(hint, &maxw, &maxh); if (maxw < minw) @@ -659,7 +649,7 @@ ecore_x_icccm_size_pos_hints_get(Ecore_X_Window window __UNUSED__, if (maxh < minh) maxh = minh; } - if (xcb_size_hints_is_p_base_size(hint)) + if (flags & XCB_SIZE_BASE_SIZE_HINT) { xcb_size_hints_get_base_size(hint, &basew, &baseh); if (basew > minw) @@ -667,7 +657,7 @@ ecore_x_icccm_size_pos_hints_get(Ecore_X_Window window __UNUSED__, if (baseh > minh) minh = baseh; } - if (xcb_size_hints_is_p_resize_inc(hint)) + if (flags & XCB_SIZE_P_RESIZE_INC_HINT) { xcb_size_hints_get_increase(hint, &stepx, &stepy); if (stepx < 1) @@ -675,7 +665,7 @@ ecore_x_icccm_size_pos_hints_get(Ecore_X_Window window __UNUSED__, if (stepy < 1) stepy = 1; } - if (xcb_size_hints_is_p_aspect(hint)) + if (flags & XCB_SIZE_P_ASPECT_HINT) { int32_t min_aspect_num; int32_t min_aspect_den; diff --git a/legacy/ecore/src/lib/ecore_x/xcb/ecore_xcb_window.c b/legacy/ecore/src/lib/ecore_x/xcb/ecore_xcb_window.c index 2b9ee8dab1..b02eb7a6ad 100644 --- a/legacy/ecore/src/lib/ecore_x/xcb/ecore_xcb_window.c +++ b/legacy/ecore/src/lib/ecore_x/xcb/ecore_xcb_window.c @@ -965,7 +965,7 @@ ecore_x_window_container_manage(Ecore_X_Window window) XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT; xcb_change_window_attributes(_ecore_xcb_conn, window, XCB_CW_EVENT_MASK, &value_list); - + } /** diff --git a/legacy/ecore/src/lib/ecore_x/xcb/ecore_xcb_window_shadow.c b/legacy/ecore/src/lib/ecore_x/xcb/ecore_xcb_window_shadow.c new file mode 100644 index 0000000000..c0256731d7 --- /dev/null +++ b/legacy/ecore/src/lib/ecore_x/xcb/ecore_xcb_window_shadow.c @@ -0,0 +1,355 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +/* #include "Ecore.h" */ +#include "ecore_xcb_private.h" +#include "Ecore_X.h" + + +typedef struct _Shadow Shadow; +struct _Shadow +{ + Shadow *parent; + Shadow **children; + Ecore_X_Window win; + int children_num; + short x, y; + unsigned short w, h; +}; + +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; + Shadow **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; + int j; + + cookie_attr = xcb_get_window_attributes_unchecked(_ecore_xcb_conn, window); + cookie_geom = xcb_get_geometry_unchecked(_ecore_xcb_conn, window); + cookie_tree = xcb_query_tree_unchecked(_ecore_xcb_conn, window); + + reply_attr = xcb_get_window_attributes_reply(_ecore_xcb_conn, cookie_attr, NULL); + if (!reply_attr) + { + reply_geom = xcb_get_geometry_reply(_ecore_xcb_conn, cookie_geom, NULL); + if (reply_geom) free(reply_geom); + reply_tree = xcb_query_tree_reply(_ecore_xcb_conn, cookie_tree, NULL); + if (reply_tree) free(reply_tree); + return NULL; + } + + if (reply_attr->map_state != XCB_MAP_STATE_VIEWABLE) + { + reply_geom = xcb_get_geometry_reply(_ecore_xcb_conn, cookie_geom, NULL); + if (reply_geom) free(reply_geom); + reply_tree = xcb_query_tree_reply(_ecore_xcb_conn, cookie_tree, NULL); + if (reply_tree) free(reply_tree); + return NULL; + } + + free(reply_attr); + + s = calloc(1, sizeof(Shadow)); + if (!s) return NULL; + + reply_geom = xcb_get_geometry_reply(_ecore_xcb_conn, cookie_geom, NULL); + if (!reply_geom) + { + reply_tree = xcb_query_tree_reply(_ecore_xcb_conn, cookie_tree, NULL); + if (reply_tree) free(reply_tree); + 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); + + reply_tree = xcb_query_tree_reply(_ecore_xcb_conn, cookie_tree, NULL); + if (reply_tree) +/* if (XQueryTree(_ecore_xcb_conn, s->win, &root_win, &parent_win, */ +/* &list, &num)) */ + { + 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; + + 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; + + 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; + int i, num; + + roots = ecore_x_window_root_list(&num); + if (roots) + { + 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; + + 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; + + 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; + int i, j; + int wx, wy; + + wx = s->x + bx; + wy = s->y + by; + if (!((x >= wx) && (y >= wy) && (x < (wx + s->w)) && (y < (wy + s->h)))) + 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); +} + +/** + * 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, Ecore_X_Window win) +{ + Shadow *s; + int i; + + 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(); +}