fix up dnd to handle stacked windows and move the burden of window offset

handling etc. to dnd not the objects that create dnd zones. they onyl need to
now worry about the dnd zone withint heir canvas/window/whatever


SVN revision: 25903
This commit is contained in:
Carsten Haitzler 2006-09-17 06:12:48 +00:00
parent 947396a983
commit 8497432eca
5 changed files with 157 additions and 104 deletions

View File

@ -18,6 +18,8 @@
static void _e_drag_show(E_Drag *drag);
static void _e_drag_hide(E_Drag *drag);
static void _e_drag_move(E_Drag *drag, int x, int y);
static void _e_drag_coords_update(E_Drop_Handler *h, int *dx, int *dy, int *dw, int *dh);
static int _e_drag_win_matches(E_Drop_Handler *h, Ecore_X_Window win);
static void _e_drag_update(int x, int y);
static void _e_drag_end(int x, int y);
static void _e_drag_xdnd_end(int x, int y);
@ -299,7 +301,8 @@ e_drag_xdnd_start(E_Drag *drag, int x, int y)
}
EAPI E_Drop_Handler *
e_drop_handler_add(void *data,
e_drop_handler_add(E_Object *obj,
void *data,
void (*enter_cb)(void *data, const char *type, void *event),
void (*move_cb)(void *data, const char *type, void *event),
void (*leave_cb)(void *data, const char *type, void *event),
@ -329,6 +332,8 @@ e_drop_handler_add(void *data,
handler->w = w;
handler->h = h;
handler->obj = obj;
_drop_handlers = evas_list_append(_drop_handlers, handler);
return handler;
@ -485,6 +490,89 @@ _e_drag_move(E_Drag *drag, int x, int y)
drag->y);
}
static void
_e_drag_coords_update(E_Drop_Handler *h, int *dx, int *dy, int *dw, int *dh)
{
int px = 0, py = 0;
*dx = h->x;
*dy = h->y;
*dw = h->w;
*dh = h->h;
if (h->obj)
{
switch (h->obj->type)
{
case E_GADCON_TYPE:
e_gadcon_canvas_zone_geometry_get((E_Gadcon *)(h->obj), &px, &py, NULL, NULL);
break;
case E_WIN_TYPE:
px = ((E_Win *)(h->obj))->x;
py = ((E_Win *)(h->obj))->y;
if ((((E_Win *)(h->obj))->border) &&
(((E_Win *)(h->obj))->border->zone))
{
px -= ((E_Win *)(h->obj))->border->zone->x;
py -= ((E_Win *)(h->obj))->border->zone->y;
}
break;
case E_BORDER_TYPE:
px = ((E_Border *)(h->obj))->x + ((E_Border *)(h->obj))->fx.x;
py = ((E_Border *)(h->obj))->y + ((E_Border *)(h->obj))->fx.y;
if (((E_Border *)(h->obj))->zone)
{
px -= ((E_Border *)(h->obj))->zone->x;
py -= ((E_Border *)(h->obj))->zone->y;
}
break;
case E_POPUP_TYPE:
px = ((E_Popup *)(h->obj))->x;
py = ((E_Popup *)(h->obj))->y;
if (((E_Popup *)(h->obj))->zone)
{
px -= ((E_Popup *)(h->obj))->zone->x;
py -= ((E_Popup *)(h->obj))->zone->y;
}
break;
/* FIXME: add mroe types as needed */
default:
break;
}
}
*dx += px;
*dy += py;
}
static int
_e_drag_win_matches(E_Drop_Handler *h, Ecore_X_Window win)
{
Ecore_X_Window hwin = 0;
if (h->obj)
{
switch (h->obj->type)
{
case E_GADCON_TYPE:
hwin = ecore_evas_software_x11_window_get(((E_Gadcon *)(h->obj))->ecore_evas);
break;
case E_WIN_TYPE:
hwin = ((E_Win *)(h->obj))->evas_win;
break;
case E_BORDER_TYPE:
hwin = ((E_Border *)(h->obj))->event_win;
break;
case E_POPUP_TYPE:
hwin = ((E_Popup *)(h->obj))->evas_win;
break;
/* FIXME: add mroe types as needed */
default:
break;
}
}
if (win == hwin) return 1;
return 0;
}
static void
_e_drag_update(int x, int y)
{
@ -492,7 +580,19 @@ _e_drag_update(int x, int y)
E_Event_Dnd_Enter *enter_ev;
E_Event_Dnd_Move *move_ev;
E_Event_Dnd_Leave *leave_ev;
int dx, dy, dw, dh;
Ecore_X_Window win, ignore_win[2];
if (_drag_current)
{
ignore_win[0] = _drag_current->evas_win;
ignore_win[1] = _drag_win;
/* this is nasty - but necessary to get the window stacking */
win = ecore_x_window_at_xy_with_skip_get(x, y, &ignore_win, 2);
}
else
win = ecore_x_window_at_xy_with_skip_get(x, y, NULL, 0);
if (_drag_current)
{
_e_drag_show(_drag_current);
@ -518,11 +618,10 @@ _e_drag_update(int x, int y)
E_Drop_Handler *h;
h = l->data;
if (!h->active)
continue;
if (E_INSIDE(x, y, h->x, h->y, h->w, h->h))
if (!h->active) continue;
_e_drag_coords_update(h, &dx, &dy, &dw, &dh);
if ((_e_drag_win_matches(h, win)) &&
(E_INSIDE(x, y, dx, dy, dw, dh)))
{
if (!h->entered)
{
@ -551,11 +650,10 @@ _e_drag_update(int x, int y)
E_Drop_Handler *h;
h = l->data;
if (!h->active)
continue;
if (E_INSIDE(x, y, h->x, h->y, h->w, h->h))
if (!h->active) continue;
_e_drag_coords_update(h, &dx, &dy, &dw, &dh);
if ((_e_drag_win_matches(h, win)) &&
(E_INSIDE(x, y, dx, dy, dw, dh)))
{
if (!h->entered)
{
@ -589,8 +687,14 @@ _e_drag_end(int x, int y)
Evas_List *l;
E_Event_Dnd_Drop *ev;
const char *type = NULL;
int dx, dy, dw, dh;
Ecore_X_Window win, ignore_win[2];
if (!_drag_current) return;
ignore_win[0] = _drag_current->evas_win;
ignore_win[1] = _drag_win;
/* this is nasty - but necessary to get the window stacking */
win = ecore_x_window_at_xy_with_skip_get(x, y, &ignore_win, 2);
zone = e_container_zone_at_point_get(_drag_current->container, x, y);
/* Pass -1, -1, so that it is possible to drop at the edge. */
if (zone) e_zone_flip_coords_handle(zone, -1, -1);
@ -627,14 +731,13 @@ _e_drag_end(int x, int y)
for (l = _drop_handlers; l; l = l->next)
{
E_Drop_Handler *h;
h = l->data;
if (!h->active)
continue;
if ((h->cb.drop) &&
E_INSIDE(x, y, h->x, h->y, h->w, h->h))
if (!h->active) continue;
_e_drag_coords_update(h, &dx, &dy, &dw, &dh);
if ((_e_drag_win_matches(h, win)) &&
((h->cb.drop) &&
(E_INSIDE(x, y, dx, dy, dw, dh))))
{
h->cb.drop(h->cb.data, type, ev);
dropped = 1;
@ -682,8 +785,19 @@ _e_drag_xdnd_end(int x, int y)
Evas_List *l;
E_Event_Dnd_Drop *ev;
const char *type = NULL;
int dx, dy, dw, dh;
Ecore_X_Window win, ignore_win[2];
if (!_xdnd) return;
if (_drag_current)
{
ignore_win[0] = _drag_current->evas_win;
ignore_win[1] = _drag_win;
/* this is nasty - but necessary to get the window stacking */
win = ecore_x_window_at_xy_with_skip_get(x, y, &ignore_win, 2);
}
else
win = ecore_x_window_at_xy_with_skip_get(x, y, NULL, 0);
ev = E_NEW(E_Event_Dnd_Drop, 1);
ev->data = _xdnd->data;
@ -699,14 +813,13 @@ _e_drag_xdnd_end(int x, int y)
for (l = _drop_handlers; l; l = l->next)
{
E_Drop_Handler *h;
h = l->data;
if (!h->active)
continue;
if ((h->cb.drop) &&
E_INSIDE(x, y, h->x, h->y, h->w, h->h))
if (!h->active) continue;
_e_drag_coords_update(h, &dx, &dy, &dw, &dh);
if ((_e_drag_win_matches(h, win)) &&
((h->cb.drop) &&
(E_INSIDE(x, y, dx, dy, dw, dh))))
{
h->cb.drop(h->cb.data, type, ev);
dropped = 1;

View File

@ -4,7 +4,12 @@
#ifdef E_TYPEDEFS
typedef enum _E_Drag_Type E_Drag_Type;
typedef enum _E_Drag_Type
{
E_DRAG_NONE,
E_DRAG_INTERNAL,
E_DRAG_XDND
} E_Drag_Type;
typedef struct _E_Drag E_Drag;
typedef struct _E_Drop_Handler E_Drop_Handler;
@ -19,13 +24,6 @@ typedef struct _E_Event_Dnd_Drop E_Event_Dnd_Drop;
#define E_DRAG_TYPE 0xE0b0100f
enum _E_Drag_Type
{
E_DRAG_NONE,
E_DRAG_INTERNAL,
E_DRAG_XDND
};
struct _E_Drag
{
E_Object e_obj_inherit;
@ -69,6 +67,7 @@ struct _E_Drop_Handler
void *data;
} cb;
E_Object *obj;
char **types;
unsigned int num_types;
@ -117,7 +116,8 @@ EAPI void e_drag_idler_before(void);
EAPI int e_drag_start(E_Drag *drag, int x, int y);
EAPI int e_drag_xdnd_start(E_Drag *drag, int x, int y);
EAPI E_Drop_Handler *e_drop_handler_add(void *data,
EAPI E_Drop_Handler *e_drop_handler_add(E_Object *obj,
void *data,
void (*enter_cb)(void *data, const char *type, void *event),
void (*move_cb)(void *data, const char *type, void *event),
void (*leave_cb)(void *data, const char *type, void *event),

View File

@ -40,8 +40,7 @@ struct _Instance
Evas_Object *o_ibar;
IBar *ibar;
E_Drop_Handler *drop_handler;
Ecore_Timer *drop_recalc_timer;
const char *dir;
const char *dir;
};
struct _IBar
@ -93,7 +92,6 @@ static void _ibar_icon_fill(IBar_Icon *ic);
static void _ibar_icon_empty(IBar_Icon *ic);
static void _ibar_icon_signal_emit(IBar_Icon *ic, char *sig, char *src);
static void _ibar_cb_app_change(void *data, E_App *a, E_App_Change ch);
static int _ibar_cb_timer_drop_recalc(void *data);
static void _ibar_cb_obj_moveresize(void *data, Evas *e, Evas_Object *obj, void *event_info);
static void _ibar_cb_menu_icon_properties(void *data, E_Menu *m, E_Menu_Item *mi);
static void _ibar_cb_menu_icon_remove(void *data, E_Menu *m, E_Menu_Item *mi);
@ -125,7 +123,6 @@ _gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style)
E_Gadcon_Client *gcc;
Instance *inst;
Evas_Coord x, y, w, h;
int cx, cy, cw, ch;
const char *drop[] = { "enlightenment/eapp", "enlightenment/border", "text/uri-list" };
Config_Item *ci;
@ -146,21 +143,17 @@ _gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style)
inst->gcc = gcc;
inst->o_ibar = o;
e_gadcon_canvas_zone_geometry_get(inst->gcc->gadcon, &cx, &cy, &cw, &ch);
evas_object_geometry_get(o, &x, &y, &w, &h);
inst->drop_handler =
e_drop_handler_add(inst,
e_drop_handler_add(inst->gcc->gadcon, inst,
_ibar_inst_cb_enter, _ibar_inst_cb_move,
_ibar_inst_cb_leave, _ibar_inst_cb_drop,
drop, 3, cx + x, cy + y, w, h);
drop, 3, x, y, w, h);
evas_object_event_callback_add(o, EVAS_CALLBACK_MOVE,
_ibar_cb_obj_moveresize, inst);
evas_object_event_callback_add(o, EVAS_CALLBACK_RESIZE,
_ibar_cb_obj_moveresize, inst);
ibar_config->instances = evas_list_append(ibar_config->instances, inst);
/* FIXME: HACK!!!! */
inst->drop_recalc_timer = ecore_timer_add(1.0, _ibar_cb_timer_drop_recalc,
inst);
return gcc;
}
@ -171,7 +164,6 @@ _gc_shutdown(E_Gadcon_Client *gcc)
inst = gcc->data;
evas_stringshare_del(inst->dir);
ecore_timer_del(inst->drop_recalc_timer);
ibar_config->instances = evas_list_remove(ibar_config->instances, inst);
e_drop_handler_del(inst->drop_handler);
_ibar_free(inst->ibar);
@ -425,11 +417,9 @@ static void
_ibar_instance_drop_zone_recalc(Instance *inst)
{
Evas_Coord x, y, w, h;
int cx, cy, cw, ch;
evas_object_geometry_get(inst->o_ibar, &x, &y, &w, &h);
e_gadcon_canvas_zone_geometry_get(inst->gcc->gadcon, &cx, &cy, &cw, &ch);
e_drop_handler_geometry_set(inst->drop_handler, cx + x, cy + y, w, h);
e_drop_handler_geometry_set(inst->drop_handler, x, y, w, h);
}
static Config_Item *
@ -774,16 +764,6 @@ _ibar_cb_app_change(void *data, E_App *a, E_App_Change ch)
}
}
static int
_ibar_cb_timer_drop_recalc(void *data)
{
Instance *inst;
inst = data;
_ibar_instance_drop_zone_recalc(inst);
return 1;
}
static void
_ibar_cb_obj_moveresize(void *data, Evas *e, Evas_Object *obj, void *event_info)
{

View File

@ -40,7 +40,6 @@ struct _Instance
Evas_Object *o_ibox;
IBox *ibox;
E_Drop_Handler *drop_handler;
Ecore_Timer *drop_recalc_timer;
};
struct _IBox
@ -94,7 +93,6 @@ static void _ibox_icon_empty(IBox_Icon *ic);
static void _ibox_icon_signal_emit(IBox_Icon *ic, char *sig, char *src);
//static IBox *_ibox_zone_find(E_Zone *zone);
static Evas_List *_ibox_zone_find(E_Zone *zone);
static int _ibox_cb_timer_drop_recalc(void *data);
static void _ibox_cb_obj_moveresize(void *data, Evas *e, Evas_Object *obj, void *event_info);
static void _ibox_cb_menu_post(void *data, E_Menu *m);
static void _ibox_cb_menu_configuration(void *data, E_Menu *m, E_Menu_Item *mi);
@ -132,7 +130,6 @@ _gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style)
E_Gadcon_Client *gcc;
Instance *inst;
Evas_Coord x, y, w, h;
int cx, cy, cw, ch;
const char *drop[] = { "enlightenment/border" };
Config_Item *ci;
@ -156,21 +153,17 @@ _gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style)
inst->gcc = gcc;
inst->o_ibox = o;
e_gadcon_canvas_zone_geometry_get(inst->gcc->gadcon, &cx, &cy, &cw, &ch);
evas_object_geometry_get(o, &x, &y, &w, &h);
inst->drop_handler =
e_drop_handler_add(inst,
e_drop_handler_add(inst->gcc->gadcon, inst,
_ibox_inst_cb_enter, _ibox_inst_cb_move,
_ibox_inst_cb_leave, _ibox_inst_cb_drop,
drop, 1, cx + x, cy + y, w, h);
drop, 1, x, y, w, h);
evas_object_event_callback_add(o, EVAS_CALLBACK_MOVE,
_ibox_cb_obj_moveresize, inst);
evas_object_event_callback_add(o, EVAS_CALLBACK_RESIZE,
_ibox_cb_obj_moveresize, inst);
ibox_config->instances = evas_list_append(ibox_config->instances, inst);
/* FIXME: HACK!!!! */
inst->drop_recalc_timer = ecore_timer_add(1.0, _ibox_cb_timer_drop_recalc,
inst);
return gcc;
}
@ -180,7 +173,6 @@ _gc_shutdown(E_Gadcon_Client *gcc)
Instance *inst;
inst = gcc->data;
ecore_timer_del(inst->drop_recalc_timer);
ibox_config->instances = evas_list_remove(ibox_config->instances, inst);
e_drop_handler_del(inst->drop_handler);
_ibox_free(inst->ibox);
@ -436,11 +428,9 @@ static void
_ibox_instance_drop_zone_recalc(Instance *inst)
{
Evas_Coord x, y, w, h;
int cx, cy, cw, ch;
evas_object_geometry_get(inst->o_ibox, &x, &y, &w, &h);
e_gadcon_canvas_zone_geometry_get(inst->gcc->gadcon, &cx, &cy, &cw, &ch);
e_drop_handler_geometry_set(inst->drop_handler, cx + x, cy + y, w, h);
e_drop_handler_geometry_set(inst->drop_handler, x, y, w, h);
}
static IBox_Icon *
@ -608,16 +598,6 @@ _ibox_zone_find(E_Zone *zone)
return ibox;
}
static int
_ibox_cb_timer_drop_recalc(void *data)
{
Instance *inst;
inst = data;
_ibox_instance_drop_zone_recalc(inst);
return 1;
}
static void
_ibox_cb_obj_moveresize(void *data, Evas *e, Evas_Object *obj, void *event_info)
{

View File

@ -42,7 +42,6 @@ struct _Instance
Evas_Object *o_pager; // table
Pager *pager;
E_Drop_Handler *drop_handler;
Ecore_Timer *drop_recalc_timer;
};
struct _Pager
@ -94,7 +93,6 @@ struct _Pager_Popup
Ecore_Timer *timer;
};
static int _pager_cb_timer_drop_recalc(void *data);
static void _pager_cb_obj_moveresize(void *data, Evas *e, Evas_Object *obj, void *event_info);
static void _button_cb_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info);
static void _menu_cb_post(void *data, E_Menu *m);
@ -159,7 +157,6 @@ _gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style)
E_Gadcon_Client *gcc;
Instance *inst;
Evas_Coord x, y, w, h;
int cx, cy, cw, ch;
const char *drop[] = { "enlightenment/border", "enlightenment/pager_win" };
inst = E_NEW(Instance, 1);
@ -174,13 +171,12 @@ _gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style)
inst->gcc = gcc;
inst->o_pager = o;
e_gadcon_canvas_zone_geometry_get(inst->gcc->gadcon, &cx, &cy, &cw, &ch);
evas_object_geometry_get(o, &x, &y, &w, &h);
inst->drop_handler =
e_drop_handler_add(inst,
e_drop_handler_add(inst->gcc->gadcon, inst,
_pager_inst_cb_enter, _pager_inst_cb_move,
_pager_inst_cb_leave, _pager_inst_cb_drop,
drop, 2, cx + x, cy + y, w, h);
drop, 2, x, y, w, h);
evas_object_event_callback_add(o, EVAS_CALLBACK_MOVE,
_pager_cb_obj_moveresize, inst);
evas_object_event_callback_add(o, EVAS_CALLBACK_RESIZE,
@ -188,9 +184,6 @@ _gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style)
evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN,
_button_cb_mouse_down, inst);
pager_config->instances = evas_list_append(pager_config->instances, inst);
/* FIXME: HACK!!!! */
inst->drop_recalc_timer = ecore_timer_add(1.0, _pager_cb_timer_drop_recalc,
inst);
return gcc;
}
@ -200,7 +193,6 @@ _gc_shutdown(E_Gadcon_Client *gcc)
Instance *inst;
inst = gcc->data;
ecore_timer_del(inst->drop_recalc_timer);
pager_config->instances = evas_list_remove(pager_config->instances, inst);
e_drop_handler_del(inst->drop_handler);
_pager_free(inst->pager);
@ -600,16 +592,6 @@ _pager_popup_free(Pager_Popup *pp)
free(pp);
}
static int
_pager_cb_timer_drop_recalc(void *data)
{
Instance *inst;
inst = data;
_pager_instance_drop_zone_recalc(inst);
return 1;
}
static void
_pager_cb_obj_moveresize(void *data, Evas *e, Evas_Object *obj, void *event_info)
{
@ -676,11 +658,9 @@ static void
_pager_instance_drop_zone_recalc(Instance *inst)
{
Evas_Coord x, y, w, h;
int cx, cy, cw, ch;
evas_object_geometry_get(inst->o_pager, &x, &y, &w, &h);
e_gadcon_canvas_zone_geometry_get(inst->gcc->gadcon, &cx, &cy, &cw, &ch);
e_drop_handler_geometry_set(inst->drop_handler, cx + x, cy + y, w, h);
e_drop_handler_geometry_set(inst->drop_handler, x, y, w, h);
}
void