From 8497432eca6fc88007c79c1fbd762efc453abc24 Mon Sep 17 00:00:00 2001 From: Carsten Haitzler Date: Sun, 17 Sep 2006 06:12:48 +0000 Subject: [PATCH] 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 --- src/bin/e_dnd.c | 163 ++++++++++++++++++++++++++++----- src/bin/e_dnd.h | 18 ++-- src/modules/ibar/e_mod_main.c | 28 +----- src/modules/ibox/e_mod_main.c | 26 +----- src/modules/pager/e_mod_main.c | 26 +----- 5 files changed, 157 insertions(+), 104 deletions(-) diff --git a/src/bin/e_dnd.c b/src/bin/e_dnd.c index e9d8697d7..7d941d4cc 100644 --- a/src/bin/e_dnd.c +++ b/src/bin/e_dnd.c @@ -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; diff --git a/src/bin/e_dnd.h b/src/bin/e_dnd.h index ac67cb4f2..276243d93 100644 --- a/src/bin/e_dnd.h +++ b/src/bin/e_dnd.h @@ -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), diff --git a/src/modules/ibar/e_mod_main.c b/src/modules/ibar/e_mod_main.c index 1909317a9..56c847500 100644 --- a/src/modules/ibar/e_mod_main.c +++ b/src/modules/ibar/e_mod_main.c @@ -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) { diff --git a/src/modules/ibox/e_mod_main.c b/src/modules/ibox/e_mod_main.c index 207cb780e..95e9d897f 100644 --- a/src/modules/ibox/e_mod_main.c +++ b/src/modules/ibox/e_mod_main.c @@ -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) { diff --git a/src/modules/pager/e_mod_main.c b/src/modules/pager/e_mod_main.c index 8075bf9fd..82a785e33 100644 --- a/src/modules/pager/e_mod_main.c +++ b/src/modules/pager/e_mod_main.c @@ -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