add a shadowed window tree that allows you to fetch all the window tree in 1

hit (well a series of round trips) then keep it stored to find what window a
co-ordinate is in to avoid later round-trips.


SVN revision: 31976
This commit is contained in:
Carsten Haitzler 2007-10-05 12:11:45 +00:00
parent 869d6c468b
commit 34afff4284
2 changed files with 283 additions and 22 deletions

View File

@ -1089,6 +1089,9 @@ EAPI int ecore_x_window_depth_get(Ecore_X_Window win);
EAPI void ecore_x_window_cursor_show(Ecore_X_Window win, int show);
EAPI void ecore_x_window_defaults_set(Ecore_X_Window win);
EAPI int ecore_x_window_visible_get(Ecore_X_Window win);
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);
EAPI void ecore_x_window_shadow_tree_flush(void);
EAPI Ecore_X_Window ecore_x_window_root_get(Ecore_X_Window win);
EAPI Ecore_X_Window ecore_x_window_at_xy_get(int x, int y);
EAPI Ecore_X_Window ecore_x_window_at_xy_with_skip_get(int x, int y, Ecore_X_Window *skip, int skip_num);
EAPI Ecore_X_Window ecore_x_window_at_xy_begin_get(Ecore_X_Window begin, int x, int y);

View File

@ -708,6 +708,267 @@ ecore_x_window_visible_get(Ecore_X_Window win)
(attr.map_state == IsViewable));
}
typedef struct _Shadow Shadow;
struct _Shadow
{
Shadow **children;
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;
static Shadow *
_ecore_x_window_tree_walk(Window win)
{
Window *list = NULL;
Window parent_win = 0, root_win = 0;
int i;
unsigned int num;
Shadow *s;
XWindowAttributes att;
printf("_ecore_x_window_tree_walk(%x)\n", win);
if (!XGetWindowAttributes(_ecore_x_disp, win, &att)) return NULL;
// if (att.class == InputOnly) return NULL;
if (att.map_state != IsViewable) return NULL;
s = calloc(1, sizeof(Shadow));
if (!s) return NULL;
s->win = win;
s->x = att.x;
s->y = att.y;
s->w = att.width;
s->h = att.height;
if (XQueryTree(_ecore_x_disp, s->win, &root_win, &parent_win,
&list, &num))
{
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]);
}
}
printf("ADD SHADOW %x %ix%i %i %i\n", s->win, s->w, s->h, s->x, s->y);
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, 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(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 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)
{
Window child;
int i, j;
int wx, wy;
wx = s->x + bx;
wy = s->y + by;
printf("is %i %i in [%x][%ix%i %i %i]\n",
x, y, s->win, s->w, s->h, wx, wy);
if (!((x >= wx) && (y >= wy) && (x < (wx + s->w)) && (y < (wy + s->h))))
return 0;
printf(" check children...\n");
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;
}
}
}
}
printf(" IS IN %x\n", s->win);
return s->win;
}
static Window
_ecore_x_window_shadow_tree_at_xy_get(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);
}
/**
* 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();
}
/**
* Retrieves the root window a given window is on.
* @param win The window to get the root window of
* @return The root window of @p win
* @ingroup Ecore_X_Window_Geometry_Group
*/
EAPI Ecore_X_Window
ecore_x_window_root_get(Ecore_X_Window win)
{
XWindowAttributes att;
if (!XGetWindowAttributes(_ecore_x_disp, win, &att)) return 0;
return att.root;
}
static Window
_ecore_x_window_at_xy_get(Window base, int bx, int by, int x, int y,
Ecore_X_Window *skip, int skip_num)
@ -728,42 +989,39 @@ _ecore_x_window_at_xy_get(Window base, int bx, int by, int x, int y,
return 0;
if (!XQueryTree(_ecore_x_disp, base, &root_win, &parent_win, &list, &num))
{
if (skip)
{
for (i = 0; i < skip_num; i++)
if (base == skip[i])
return 0;
}
return base;
}
return base;
if (list)
{
int skipit = 0;
for (i = num - 1; i >= 0; --i)
{
skipit = 0;
if (skip)
{
for (j = 0; j < skip_num; j++)
if (list[i] == skip[j])
continue;
{
if (list[i] == skip[j])
{
skipit = 1;
goto onward;
}
}
}
if ((child = _ecore_x_window_at_xy_get(list[i], wx, wy, x, y, skip, skip_num)))
onward:
if (!skipit)
{
XFree(list);
return child;
if ((child = _ecore_x_window_at_xy_get(list[i], wx, wy, x, y, skip, skip_num)))
{
XFree(list);
return child;
}
}
}
XFree(list);
}
if (skip)
{
for (i = 0; i < skip_num; i++)
if (base == skip[i])
return 0;
}
return base;
}