dnd overhaul

* use separate list for active handlers to avoid unnecessary iterating

* use similar function to efm for detecting supported dnd types
This commit is contained in:
Mike Blumenkrantz 2013-05-29 09:15:21 +01:00
parent 76ed05375d
commit db20c24837
1 changed files with 90 additions and 104 deletions

View File

@ -38,6 +38,7 @@ struct _XDnd
static Eina_List *_event_handlers = NULL;
static Eina_List *_drop_handlers = NULL;
static Eina_List *_active_handlers = NULL;
static Eina_Hash *_drop_win_hash = NULL;
static Ecore_X_Window _drag_win = 0;
@ -50,10 +51,20 @@ static XDnd *_xdnd = NULL;
#define XDS_ATOM "XdndDirectSave0"
static Ecore_X_Atom _xds_atom = 0;
static Ecore_X_Atom _text_atom = 0;
static const char *_type_text_uri_list = NULL;
static const char *_type_xds = NULL;
static const char *_type_text_x_moz_url = NULL;
static const char *_type_enlightenment_x_file = NULL;
static Eina_Stringshare *_type_text_uri_list = NULL;
static Eina_Stringshare *_type_xds = NULL;
static Eina_Stringshare *_type_text_x_moz_url = NULL;
static Eina_Stringshare *_type_enlightenment_x_file = NULL;
static Eina_Stringshare **_e_dnd_types[] =
{
&_type_text_uri_list,
&_type_xds,
//&_type_text_x_moz_url,
//&_type_enlightenment_x_file,
NULL
};
static Eina_Hash *_drop_handlers_responsives;
static Ecore_X_Atom _action;
@ -94,6 +105,7 @@ e_dnd_shutdown(void)
{
E_FREE_LIST(_drag_list, e_object_del);
_active_handlers = eina_list_free(_active_handlers);
E_FREE_LIST(_drop_handlers, e_drop_handler_del);
E_FREE_LIST(_event_handlers, ecore_event_handler_del);
@ -239,13 +251,14 @@ e_drag_start(E_Drag *drag, int x, int y)
drag->dx = x - drag->x;
drag->dy = y - drag->y;
_active_handlers = eina_list_free(_active_handlers);
EINA_LIST_FOREACH(_drop_handlers, l, h)
{
unsigned int i, j;
Eina_Bool active = h->active;
h->active = 0;
eina_stringshare_del(h->active_type);
h->active_type = NULL;
eina_stringshare_replace(&h->active_type, NULL);
for (i = 0; i < h->num_types; i++)
{
for (j = 0; j < drag->num_types; j++)
@ -259,6 +272,13 @@ e_drag_start(E_Drag *drag, int x, int y)
}
if (h->active) break;
}
if (h->active != active)
{
if (h->active)
_active_handlers = eina_list_append(_active_handlers, h);
else
_active_handlers = eina_list_remove(_active_handlers, h);
}
h->entered = 0;
}
@ -295,14 +315,14 @@ e_drag_xdnd_start(E_Drag *drag, int x, int y)
drag->dx = x - drag->x;
drag->dy = y - drag->y;
_active_handlers = eina_list_free(_active_handlers);
EINA_LIST_FOREACH(_drop_handlers, l, h)
{
unsigned int i, j;
Eina_Bool active = h->active;
h->active = 0;
eina_stringshare_del(h->active_type);
h->active_type = NULL;
eina_stringshare_replace(&h->active_type, NULL);
for (i = 0; i < h->num_types; i++)
{
for (j = 0; j < drag->num_types; j++)
@ -316,6 +336,13 @@ e_drag_xdnd_start(E_Drag *drag, int x, int y)
}
if (h->active) break;
}
if (h->active != active)
{
if (h->active)
_active_handlers = eina_list_append(_active_handlers, h);
else
_active_handlers = eina_list_remove(_active_handlers, h);
}
h->entered = 0;
}
@ -431,6 +458,8 @@ e_drop_handler_del(E_Drop_Handler *handler)
return;
_drop_handlers = eina_list_remove(_drop_handlers, handler);
if (handler->active)
_active_handlers = eina_list_remove(_active_handlers, handler);
for (i = 0; i < handler->num_types; i++)
eina_stringshare_del(handler->types[i]);
eina_stringshare_del(handler->active_type);
@ -544,6 +573,19 @@ e_dnd_util_text_uri_list_convert(char *data, int size)
/* local subsystem functions */
static Eina_Stringshare *
_e_dnd_type_implemented(const char *type)
{
const char ***t;
for (t = _e_dnd_types; *t; t++)
{
if (!strcmp(type, **t))
return **t;
}
return NULL;
}
static void
_e_drag_move(E_Drag *drag, int x, int y)
{
@ -777,9 +819,8 @@ _e_drag_update(Ecore_X_Window root, int x, int y, Ecore_X_Atom action)
else e_popup_hide(_drag_current->pop);
_e_drag_move(_drag_current, x, y);
}
EINA_LIST_FOREACH(_drop_handlers, l, h)
EINA_LIST_FOREACH(_active_handlers, l, h)
{
if (!h->active) continue;
_e_drag_coords_update(h, &dx, &dy);
enter_ev.x = x - dx;
enter_ev.y = y - dy;
@ -937,10 +978,8 @@ _e_drag_end(int x, int y)
leave_ev.x = 0;
leave_ev.y = 0;
EINA_LIST_FOREACH(_drop_handlers, l, h)
EINA_LIST_FOREACH(_active_handlers, l, h)
{
if (!h->active) continue;
if (h->entered)
{
if (h->cb.leave)
@ -950,9 +989,8 @@ _e_drag_end(int x, int y)
}
}
EINA_LIST_FOREACH(_drop_handlers, l, h)
EINA_LIST_FOREACH(_active_handlers, l, h)
{
if (!h->active) continue;
_e_drag_coords_update(h, &dx, &dy);
ev.x = x - dx;
ev.y = y - dy;
@ -1022,9 +1060,8 @@ _e_drag_xdnd_end(Ecore_X_Window win, int x, int y)
{
E_Drop_Handler *h;
EINA_LIST_FOREACH(_drop_handlers, l, h)
EINA_LIST_FOREACH(_active_handlers, l, h)
{
if (!h->active) continue;
_e_drag_coords_update(h, &dx, &dy);
ev.x = x - dx;
ev.y = y - dy;
@ -1045,10 +1082,8 @@ _e_drag_xdnd_end(Ecore_X_Window win, int x, int y)
leave_ev.x = 0;
leave_ev.y = 0;
EINA_LIST_FOREACH(_drop_handlers, l, h)
EINA_LIST_FOREACH(_active_handlers, l, h)
{
if (!h->active) continue;
if (h->entered)
{
if (h->cb.leave)
@ -1077,9 +1112,9 @@ _e_drag_free(E_Drag *drag)
leave_ev.x = 0;
leave_ev.y = 0;
EINA_LIST_FOREACH(_drop_handlers, l, h)
EINA_LIST_FOREACH(_active_handlers, l, h)
{
if ((h->active) && (h->entered))
if (h->entered)
{
if (h->cb.leave)
h->cb.leave(h->cb.data, h->active_type, &leave_ev);
@ -1105,9 +1140,8 @@ _e_drag_free(E_Drag *drag)
static Eina_Bool
_e_dnd_cb_key_down(void *data __UNUSED__, int type __UNUSED__, void *event)
{
Ecore_Event_Key *ev;
Ecore_Event_Key *ev = event;
ev = event;
if (ev->window != _drag_win) return ECORE_CALLBACK_PASS_ON;
if (!_drag_current) return ECORE_CALLBACK_PASS_ON;
@ -1121,9 +1155,8 @@ _e_dnd_cb_key_down(void *data __UNUSED__, int type __UNUSED__, void *event)
static Eina_Bool
_e_dnd_cb_key_up(void *data __UNUSED__, int type __UNUSED__, void *event)
{
Ecore_Event_Key *ev;
Ecore_Event_Key *ev = event;
ev = event;
if (ev->window != _drag_win) return ECORE_CALLBACK_PASS_ON;
if (!_drag_current) return ECORE_CALLBACK_PASS_ON;
@ -1137,9 +1170,8 @@ _e_dnd_cb_key_up(void *data __UNUSED__, int type __UNUSED__, void *event)
static Eina_Bool
_e_dnd_cb_mouse_up(void *data __UNUSED__, int type __UNUSED__, void *event)
{
Ecore_Event_Mouse_Button *ev;
Ecore_Event_Mouse_Button *ev = event;
ev = event;
if (ev->window != _drag_win) return ECORE_CALLBACK_PASS_ON;
_e_drag_end(ev->x, ev->y);
@ -1150,9 +1182,8 @@ _e_dnd_cb_mouse_up(void *data __UNUSED__, int type __UNUSED__, void *event)
static Eina_Bool
_e_dnd_cb_mouse_move(void *data __UNUSED__, int type __UNUSED__, void *event)
{
Ecore_Event_Mouse_Move *ev;
Ecore_Event_Mouse_Move *ev = event;
ev = event;
if (ev->window != _drag_win) return ECORE_CALLBACK_PASS_ON;
if (!_xdnd)
@ -1165,69 +1196,46 @@ _e_dnd_cb_mouse_move(void *data __UNUSED__, int type __UNUSED__, void *event)
static Eina_Bool
_e_dnd_cb_event_dnd_enter(void *data __UNUSED__, int type __UNUSED__, void *event)
{
Ecore_X_Event_Xdnd_Enter *ev;
Ecore_X_Event_Xdnd_Enter *ev = event;
E_Drop_Handler *h;
const char *id;
const Eina_List *l;
unsigned int j;
int i;
ev = event;
id = e_util_winid_str_get(ev->win);
if (!eina_hash_find(_drop_win_hash, id)) return ECORE_CALLBACK_PASS_ON;
EINA_LIST_FOREACH(_drop_handlers, l, h)
EINA_LIST_FREE(_active_handlers, h)
{
h->active = 0;
eina_stringshare_del(h->active_type);
h->active_type = NULL;
eina_stringshare_replace(&h->active_type, NULL);
h->entered = 0;
}
for (i = 0; i < ev->num_types; i++)
{
const char *t = NULL;
/* FIXME: Maybe we want to get something else then files dropped? */
if (!strcmp(_type_text_uri_list, ev->types[i]))
t = eina_stringshare_ref(_type_text_uri_list);
else if (!strcmp(_type_xds, ev->types[i]))
t = eina_stringshare_ref(_type_xds);
if (t)
{
_xdnd = E_NEW(XDnd, 1);
_xdnd->type = t;
EINA_LIST_FOREACH(_drop_handlers, l, h)
{
h->active = 0;
eina_stringshare_del(h->active_type);
h->active_type = NULL;
for (j = 0; j < h->num_types; j++)
{
if (h->types[j] == _xdnd->type)
{
h->active = 1;
h->active_type = eina_stringshare_ref(_xdnd->type);
break;
}
}
Eina_Stringshare *t;
h->entered = 0;
}
break;
}
#if 0
else if ((_type_text_x_moz_url == ev->types[i]) ||
(!strcmp(_type_text_x_moz_url, ev->types[i]))) /* not sure it is stringshared */
t = eina_stringshare_ref(_e_dnd_type_implemented(ev->types[i]));
if (!t) continue;
_xdnd = E_NEW(XDnd, 1);
_xdnd->type = t;
EINA_LIST_FOREACH(_drop_handlers, l, h)
{
_xdnd = E_NEW(XDnd, 1);
_xdnd->type = eina_stringshare_ref(_type_text_x_moz_url);
EINA_LIST_FOREACH(_drop_handlers, l, h)
for (j = 0; j < h->num_types; j++)
{
h->active = (h->type == _type_enlightenment_x_file);
h->entered = 0;
if (h->types[j] == _xdnd->type)
{
h->active = 1;
h->active_type = eina_stringshare_ref(_xdnd->type);
_active_handlers = eina_list_append(_active_handlers, h);
break;
}
}
break;
h->entered = 0;
}
#endif
break;
}
return ECORE_CALLBACK_PASS_ON;
}
@ -1235,13 +1243,11 @@ _e_dnd_cb_event_dnd_enter(void *data __UNUSED__, int type __UNUSED__, void *even
static Eina_Bool
_e_dnd_cb_event_dnd_leave(void *data __UNUSED__, int type __UNUSED__, void *event)
{
Ecore_X_Event_Xdnd_Leave *ev;
Ecore_X_Event_Xdnd_Leave *ev = event;
E_Event_Dnd_Leave leave_ev;
const char *id;
const Eina_List *l;
ev = event;
id = e_util_winid_str_get(ev->win);
if (!eina_hash_find(_drop_win_hash, id)) return ECORE_CALLBACK_PASS_ON;
@ -1252,10 +1258,8 @@ _e_dnd_cb_event_dnd_leave(void *data __UNUSED__, int type __UNUSED__, void *even
{
E_Drop_Handler *h;
EINA_LIST_FOREACH(_drop_handlers, l, h)
EINA_LIST_FOREACH(_active_handlers, l, h)
{
if (!h->active) continue;
if (h->entered)
{
if (h->cb.leave)
@ -1273,16 +1277,11 @@ _e_dnd_cb_event_dnd_leave(void *data __UNUSED__, int type __UNUSED__, void *even
static Eina_Bool
_e_dnd_cb_event_dnd_position(void *data __UNUSED__, int type __UNUSED__, void *event)
{
Ecore_X_Event_Xdnd_Position *ev;
Ecore_X_Event_Xdnd_Position *ev = event;
Ecore_X_Rectangle rect;
const char *id;
const Eina_List *l;
E_Drop_Handler *h;
int active;
int responsive;
ev = event;
// double t1 = ecore_time_get(); ////
id = e_util_winid_str_get(ev->win);
if (!eina_hash_find(_drop_win_hash, id))
@ -1297,16 +1296,7 @@ _e_dnd_cb_event_dnd_position(void *data __UNUSED__, int type __UNUSED__, void *e
rect.width = 0;
rect.height = 0;
active = 0;
EINA_LIST_FOREACH(_drop_handlers, l, h)
{
if (h->active)
{
active = 1;
break;
}
}
if (!active)
if (!_active_handlers)
ecore_x_dnd_send_status(0, 0, rect, ECORE_X_DND_ACTION_PRIVATE);
else
{
@ -1324,9 +1314,8 @@ _e_dnd_cb_event_dnd_position(void *data __UNUSED__, int type __UNUSED__, void *e
static Eina_Bool
_e_dnd_cb_event_dnd_status(void *data __UNUSED__, int type __UNUSED__, void *event)
{
Ecore_X_Event_Xdnd_Status *ev;
Ecore_X_Event_Xdnd_Status *ev = event;
ev = event;
if (ev->win != _drag_win) return ECORE_CALLBACK_PASS_ON;
return ECORE_CALLBACK_PASS_ON;
}
@ -1364,10 +1353,9 @@ _e_dnd_cb_event_dnd_finished(void *data __UNUSED__, int type __UNUSED__, void *e
static Eina_Bool
_e_dnd_cb_event_dnd_drop(void *data __UNUSED__, int type __UNUSED__, void *event)
{
Ecore_X_Event_Xdnd_Drop *ev;
Ecore_X_Event_Xdnd_Drop *ev = event;
const char *id;
ev = event;
id = e_util_winid_str_get(ev->win);
if (!eina_hash_find(_drop_win_hash, id)) return ECORE_CALLBACK_PASS_ON;
@ -1377,9 +1365,8 @@ _e_dnd_cb_event_dnd_drop(void *data __UNUSED__, int type __UNUSED__, void *event
Eina_Bool req = EINA_TRUE;
Eina_List *l;
EINA_LIST_FOREACH(_drop_handlers, l, h)
EINA_LIST_FOREACH(_active_handlers, l, h)
{
if (!h->active) continue;
if (_e_drag_win_matches(h, ev->win, 1) && h->entered && h->cb.xds)
{
req = h->cb.xds(h->cb.data, _xdnd->type);
@ -1404,11 +1391,10 @@ _e_dnd_cb_event_dnd_drop(void *data __UNUSED__, int type __UNUSED__, void *event
static Eina_Bool
_e_dnd_cb_event_dnd_selection(void *data __UNUSED__, int type __UNUSED__, void *event)
{
Ecore_X_Event_Selection_Notify *ev;
Ecore_X_Event_Selection_Notify *ev = event;
const char *id;
int i;
ev = event;
id = e_util_winid_str_get(ev->win);
if (!eina_hash_find(_drop_win_hash, id)) return ECORE_CALLBACK_PASS_ON;
if (ev->selection != ECORE_X_SELECTION_XDND) return ECORE_CALLBACK_PASS_ON;