improve xdnd performance by thousdands of times. it was HORRID. note the
comments in the code. SVN revision: 32694
This commit is contained in:
parent
0c97103851
commit
c9c3ca7f1d
|
@ -1090,6 +1090,7 @@ 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 Ecore_X_Window ecore_x_window_shadow_parent_get(Ecore_X_Window root, Ecore_X_Window win);
|
||||
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);
|
||||
|
|
|
@ -43,6 +43,14 @@ static Ecore_X_DND_Source *_source = NULL;
|
|||
static Ecore_X_DND_Target *_target = NULL;
|
||||
static int _ecore_x_dnd_init_count = 0;
|
||||
|
||||
typedef struct _Version_Cache_Item
|
||||
{
|
||||
Ecore_X_Window win;
|
||||
int ver;
|
||||
} Version_Cache_Item;
|
||||
static Version_Cache_Item *_version_cache = NULL;
|
||||
static int _version_cache_num = 0, _version_cache_alloc = 0;
|
||||
|
||||
void
|
||||
_ecore_x_dnd_init(void)
|
||||
{
|
||||
|
@ -163,15 +171,50 @@ ecore_x_dnd_version_get(Ecore_X_Window win)
|
|||
unsigned char *prop_data;
|
||||
int num;
|
||||
|
||||
// this looks hacky - and it is, but we need a way of caching info about
|
||||
// a window while dragging, because we literally query this every mouse
|
||||
// move and going to and from x multiple times per move is EXPENSIVE
|
||||
// and slows things down, puts lots of load on x etc.
|
||||
if (_source->state == ECORE_X_DND_SOURCE_DRAGGING)
|
||||
{
|
||||
if (_version_cache)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < _version_cache_num; i++)
|
||||
{
|
||||
if (_version_cache[i].win == win)
|
||||
return _version_cache[i].ver;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ecore_x_window_prop_property_get(win, ECORE_X_ATOM_XDND_AWARE,
|
||||
XA_ATOM, 32, &prop_data, &num))
|
||||
{
|
||||
int version = (int) *prop_data;
|
||||
free(prop_data);
|
||||
if (_source->state == ECORE_X_DND_SOURCE_DRAGGING)
|
||||
{
|
||||
_version_cache_num++;
|
||||
if (_version_cache_num > _version_cache_alloc)
|
||||
_version_cache_alloc += 16;
|
||||
_version_cache = realloc(_version_cache, _version_cache_alloc * sizeof(Version_Cache_Item));
|
||||
_version_cache[_version_cache_num - 1].win = win;
|
||||
_version_cache[_version_cache_num - 1].ver = version;
|
||||
}
|
||||
return version;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
if (_source->state == ECORE_X_DND_SOURCE_DRAGGING)
|
||||
{
|
||||
_version_cache_num++;
|
||||
if (_version_cache_num > _version_cache_alloc)
|
||||
_version_cache_alloc += 16;
|
||||
_version_cache = realloc(_version_cache, _version_cache_alloc * sizeof(Version_Cache_Item));
|
||||
_version_cache[_version_cache_num - 1].win = win;
|
||||
_version_cache[_version_cache_num - 1].ver = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
EAPI int
|
||||
|
@ -331,6 +374,15 @@ ecore_x_dnd_begin(Ecore_X_Window source, unsigned char *data, int size)
|
|||
if (!ecore_x_selection_xdnd_set(source, data, size))
|
||||
return 0;
|
||||
|
||||
if (_version_cache)
|
||||
{
|
||||
free(_version_cache);
|
||||
_version_cache = NULL;
|
||||
_version_cache_num = 0;
|
||||
_version_cache_alloc = 0;
|
||||
}
|
||||
ecore_x_window_shadow_tree_flush();
|
||||
|
||||
_source->win = source;
|
||||
ecore_x_window_ignore_set(_source->win, 1);
|
||||
_source->state = ECORE_X_DND_SOURCE_DRAGGING;
|
||||
|
@ -462,7 +514,7 @@ ecore_x_dnd_send_finished(void)
|
|||
}
|
||||
|
||||
void
|
||||
_ecore_x_dnd_drag(int x, int y)
|
||||
_ecore_x_dnd_drag(Ecore_X_Window root, int x, int y)
|
||||
{
|
||||
XEvent xev;
|
||||
Ecore_X_Window win;
|
||||
|
@ -480,9 +532,17 @@ _ecore_x_dnd_drag(int x, int y)
|
|||
|
||||
/* Attempt to find a DND-capable window under the cursor */
|
||||
skip = ecore_x_window_ignore_list(&num);
|
||||
win = ecore_x_window_at_xy_with_skip_get(x, y, skip, num);
|
||||
// WARNING - this function is HEAVY. it goes to and from x a LOT walking the
|
||||
// window tree - use the SHADOW version - makes a 1-off tree copy, then uses
|
||||
// that instead.
|
||||
// win = ecore_x_window_at_xy_with_skip_get(x, y, skip, num);
|
||||
win = ecore_x_window_shadow_tree_at_xy_with_skip_get(root, x, y, skip, num);
|
||||
|
||||
// NOTE: This now uses the shadow version to find parent windows
|
||||
// while ((win) && !(ecore_x_dnd_version_get(win)))
|
||||
// win = ecore_x_window_parent_get(win);
|
||||
while ((win) && !(ecore_x_dnd_version_get(win)))
|
||||
win = ecore_x_window_parent_get(win);
|
||||
win = ecore_x_window_shadow_parent_get(root, win);
|
||||
|
||||
/* Send XdndLeave to current destination window if we have left it */
|
||||
if ((_source->dest) && (win != _source->dest))
|
||||
|
|
|
@ -568,7 +568,7 @@ _ecore_x_event_handle_motion_notify(XEvent *xevent)
|
|||
_ecore_x_event_last_root_y = e->root.y;
|
||||
|
||||
/* Xdnd handling */
|
||||
_ecore_x_dnd_drag(e->root.x, e->root.y);
|
||||
_ecore_x_dnd_drag(xevent->xmotion.root, e->root.x, e->root.y);
|
||||
|
||||
ecore_event_add(ECORE_X_EVENT_MOUSE_MOVE, e, NULL, NULL);
|
||||
}
|
||||
|
|
|
@ -217,7 +217,7 @@ void _ecore_x_key_grab_remove(Ecore_X_Window win);
|
|||
void _ecore_x_dnd_init(void);
|
||||
Ecore_X_DND_Source *_ecore_x_dnd_source_get(void);
|
||||
Ecore_X_DND_Target *_ecore_x_dnd_target_get(void);
|
||||
void _ecore_x_dnd_drag(int x, int y);
|
||||
void _ecore_x_dnd_drag(Ecore_X_Window root, int x, int y);
|
||||
void _ecore_x_dnd_shutdown(void);
|
||||
|
||||
/* from netwm */
|
||||
|
|
|
@ -713,6 +713,7 @@ ecore_x_window_visible_get(Ecore_X_Window win)
|
|||
typedef struct _Shadow Shadow;
|
||||
struct _Shadow
|
||||
{
|
||||
Shadow *parent;
|
||||
Shadow **children;
|
||||
Window win;
|
||||
int children_num;
|
||||
|
@ -753,7 +754,10 @@ _ecore_x_window_tree_walk(Window win)
|
|||
{
|
||||
s->children_num = num;
|
||||
for (i = 0; i < num; i++)
|
||||
s->children[i] = _ecore_x_window_tree_walk(list[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++)
|
||||
|
@ -935,8 +939,11 @@ _ecore_x_window_shadow_tree_at_xy_get(Window base, int bx, int by, int x, int y,
|
|||
{
|
||||
Shadow *s;
|
||||
|
||||
if (!shadow_base) _ecore_x_window_tree_shadow_populate();
|
||||
if (!shadow_base) return 0;
|
||||
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);
|
||||
|
@ -960,6 +967,38 @@ ecore_x_window_shadow_tree_at_xy_with_skip_get(Ecore_X_Window base, int x, int y
|
|||
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
|
||||
|
|
|
@ -611,7 +611,8 @@ ecore_x_dnd_send_finished(void)
|
|||
}
|
||||
|
||||
void
|
||||
_ecore_x_dnd_drag(int x,
|
||||
_ecore_x_dnd_drag(Ecore_X_Window root,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
xcb_client_message_event_t ev;
|
||||
|
@ -627,7 +628,8 @@ _ecore_x_dnd_drag(int x,
|
|||
|
||||
/* Attempt to find a DND-capable window under the cursor */
|
||||
skip = ecore_x_window_ignore_list(&num);
|
||||
win = ecore_x_window_at_xy_with_skip_get(x, y, skip, num);
|
||||
// win = ecore_x_window_at_xy_with_skip_get(x, y, skip, num);
|
||||
win = ecore_x_window_shadow_tree_at_xy_with_skip_get(root, x, y, skip, num);
|
||||
while (win)
|
||||
{
|
||||
xcb_query_tree_cookie_t cookie_tree;
|
||||
|
|
Loading…
Reference in New Issue