From c08bdf97c6715a5a3b26e3c515cc21a0e5f5b072 Mon Sep 17 00:00:00 2001 From: sebastid Date: Sat, 8 Oct 2005 13:10:20 +0000 Subject: [PATCH] Working on xdnd from E. SVN revision: 17319 --- src/bin/e_dnd.c | 518 ++++++++++++++++++++++++++++++++++++-------------------- src/bin/e_dnd.h | 19 ++- 2 files changed, 350 insertions(+), 187 deletions(-) diff --git a/src/bin/e_dnd.c b/src/bin/e_dnd.c index 40b62e6..7c7e2c2 100644 --- a/src/bin/e_dnd.c +++ b/src/bin/e_dnd.c @@ -5,12 +5,21 @@ /* * TODO: - * Better system to let a drop target support several drop types + * - Let an internal drag work with several types. + * - Let a drag be both internal and external, or allow internal xdnd + * (internal xdnd is unecessary load) */ /* local subsystem functions */ +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_update(int x, int y); +static void _e_drag_end(int x, int y); +static void _e_drag_xdnd_end(int x, int y); static void _e_drag_free(E_Drag *drag); + static int _e_dnd_cb_window_shape(void *data, int type, void *event); static int _e_dnd_cb_mouse_up(void *data, int type, void *event); @@ -18,6 +27,8 @@ static int _e_dnd_cb_mouse_move(void *data, int type, void *event); static int _e_dnd_cb_event_dnd_enter(void *data, int type, void *event); static int _e_dnd_cb_event_dnd_leave(void *data, int type, void *event); static int _e_dnd_cb_event_dnd_position(void *data, int type, void *event); +static int _e_dnd_cb_event_dnd_status(void *data, int type, void *event); +static int _e_dnd_cb_event_dnd_finished(void *data, int type, void *event); static int _e_dnd_cb_event_dnd_drop(void *data, int type, void *event); static int _e_dnd_cb_event_dnd_selection(void *data, int type, void *event); @@ -83,6 +94,14 @@ e_dnd_init(void) _e_dnd_cb_event_dnd_position, con)); _event_handlers = evas_list_append(_event_handlers, + ecore_event_handler_add(ECORE_X_EVENT_XDND_STATUS, + _e_dnd_cb_event_dnd_status, + con)); + _event_handlers = evas_list_append(_event_handlers, + ecore_event_handler_add(ECORE_X_EVENT_XDND_FINISHED, + _e_dnd_cb_event_dnd_finished, + con)); + _event_handlers = evas_list_append(_event_handlers, ecore_event_handler_add(ECORE_X_EVENT_XDND_DROP, _e_dnd_cb_event_dnd_drop, con)); @@ -168,6 +187,7 @@ e_drag_new(E_Container *container, int x, int y, ecore_x_window_shape_events_select(drag->evas_win, 1); ecore_evas_name_class_set(drag->ecore_evas, "E", "_e_drag_window"); ecore_evas_title_set(drag->ecore_evas, "E Drag"); + ecore_evas_ignore_events_set(drag->ecore_evas, 1); ecore_evas_shaped_set(drag->ecore_evas, 1); @@ -179,6 +199,8 @@ e_drag_new(E_Container *container, int x, int y, evas_object_resize(drag->object, drag->w, drag->h); ecore_evas_resize(drag->ecore_evas, drag->w, drag->h); + drag->type = E_DRAG_NONE; + drag->types = malloc(num_types * sizeof(char *)); for (i = 0; i < num_types; i++) drag->types[i] = strdup(types[i]); @@ -207,40 +229,6 @@ e_drag_object_set(E_Drag *drag, Evas_Object *object) } void -e_drag_show(E_Drag *drag) -{ - if (drag->visible) return; - drag->visible = 1; - evas_object_show(drag->object); - ecore_evas_show(drag->ecore_evas); - e_container_shape_show(drag->shape); -} - -void -e_drag_hide(E_Drag *drag) -{ - if (!drag->visible) return; - drag->visible = 0; - evas_object_hide(drag->object); - ecore_evas_hide(drag->ecore_evas); - e_container_shape_hide(drag->shape); -} - -void -e_drag_move(E_Drag *drag, int x, int y) -{ - if (((drag->x + drag->dx) == x) && ((drag->y + drag->dy) == y)) return; - drag->x = x - drag->dx; - drag->y = y - drag->dy; - ecore_evas_move(drag->ecore_evas, - drag->x, - drag->y); - e_container_shape_move(drag->shape, - drag->x, - drag->y); -} - -void e_drag_resize(E_Drag *drag, int w, int h) { if ((drag->w == w) && (drag->h == h)) return; @@ -257,12 +245,13 @@ e_dnd_active(void) return (_drag_win != 0); } -void +int e_drag_start(E_Drag *drag, int x, int y) { Evas_List *l; int i; + if (_drag_win) return 0; _drag_win = ecore_x_window_input_new(drag->container->win, drag->container->x, drag->container->y, drag->container->w, drag->container->h); @@ -270,6 +259,8 @@ e_drag_start(E_Drag *drag, int x, int y) ecore_x_pointer_confine_grab(_drag_win); ecore_x_keyboard_grab(_drag_win); + drag->type = E_DRAG_INTERNAL; + drag->dx = x - drag->x; drag->dy = y - drag->y; @@ -289,10 +280,195 @@ e_drag_start(E_Drag *drag, int x, int y) } _drag_current = drag; + return 1; +} + +int +e_drag_xdnd_start(E_Drag *drag, int x, int y) +{ + if (_drag_win) return 0; + _drag_win = ecore_x_window_input_new(drag->container->win, + drag->container->x, drag->container->y, + drag->container->w, drag->container->h); + ecore_x_window_show(_drag_win); + ecore_x_pointer_confine_grab(_drag_win); + ecore_x_keyboard_grab(_drag_win); + + drag->type = E_DRAG_XDND; + + drag->dx = x - drag->x; + drag->dy = y - drag->y; + + ecore_x_dnd_aware_set(_drag_win, 1); + ecore_x_dnd_types_set(_drag_win, drag->types, drag->num_types); + ecore_x_dnd_begin(_drag_win, drag->data, drag->data_size); + + _drag_current = drag; + return 1; +} + +E_Drop_Handler * +e_drop_handler_add(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), + void (*drop_cb)(void *data, const char *type, void *event), + const char **types, unsigned int num_types, int x, int y, int w, int h) +{ + E_Drop_Handler *handler; + int i; + + handler = E_NEW(E_Drop_Handler, 1); + if (!handler) return NULL; + + handler->cb.data = data; + handler->cb.enter = enter_cb; + handler->cb.move = move_cb; + handler->cb.leave = leave_cb; + handler->cb.drop = drop_cb; + handler->num_types = num_types; + if (num_types) + { + handler->types = malloc(num_types * sizeof(char *)); + for (i = 0; i < num_types; i++) + handler->types[i] = strdup(types[i]); + } + handler->x = x; + handler->y = y; + handler->w = w; + handler->h = h; + + _drop_handlers = evas_list_append(_drop_handlers, handler); + + return handler; +} + +void +e_drop_handler_geometry_set(E_Drop_Handler *handler, int x, int y, int w, int h) +{ + handler->x = x; + handler->y = y; + handler->w = w; + handler->h = h; +} + +void +e_drop_handler_del(E_Drop_Handler *handler) +{ + int i; + + _drop_handlers = evas_list_remove(_drop_handlers, handler); + if (handler->types) + { + for (i = 0; i < handler->num_types; i++) + free(handler->types[i]); + free(handler->types); + } + free(handler); } + void -e_drag_update(int x, int y) +e_drag_idler_before(void) +{ + Evas_List *l; + + for (l = _drag_list; l; l = l->next) + { + E_Drag *drag; + + drag = l->data; + if (drag->need_shape_export) + { + Ecore_X_Rectangle *rects, *orects; + int num; + + rects = ecore_x_window_shape_rectangles_get(drag->evas_win, &num); + if (rects) + { + int changed; + + changed = 1; + if ((num == drag->shape_rects_num) && (drag->shape_rects)) + { + int i; + + orects = drag->shape_rects; + for (i = 0; i < num; i++) + { + if ((orects[i].x != rects[i].x) || + (orects[i].y != rects[i].y) || + (orects[i].width != rects[i].width) || + (orects[i].height != rects[i].height)) + { + changed = 1; + break; + } + } + changed = 0; + } + if (changed) + { + E_FREE(drag->shape_rects); + drag->shape_rects = rects; + drag->shape_rects_num = num; + e_container_shape_rects_set(drag->shape, rects, num); + } + else + free(rects); + } + else + { + E_FREE(drag->shape_rects); + drag->shape_rects = NULL; + drag->shape_rects_num = 0; + e_container_shape_rects_set(drag->shape, NULL, 0); + } + drag->need_shape_export = 0; + if (drag->visible) + e_container_shape_show(drag->shape); + } + } +} + +/* local subsystem functions */ + +static void +_e_drag_show(E_Drag *drag) +{ + if (drag->visible) return; + drag->visible = 1; + evas_object_show(drag->object); + ecore_evas_show(drag->ecore_evas); + e_container_shape_show(drag->shape); +} + +static void +_e_drag_hide(E_Drag *drag) +{ + if (!drag->visible) return; + drag->visible = 0; + evas_object_hide(drag->object); + ecore_evas_hide(drag->ecore_evas); + e_container_shape_hide(drag->shape); +} + +static void +_e_drag_move(E_Drag *drag, int x, int y) +{ + if (((drag->x + drag->dx) == x) && ((drag->y + drag->dy) == y)) return; + drag->x = x - drag->dx; + drag->y = y - drag->dy; + ecore_evas_move(drag->ecore_evas, + drag->x, + drag->y); + e_container_shape_move(drag->shape, + drag->x, + drag->y); +} + +static void +_e_drag_update(int x, int y) { Evas_List *l; E_Event_Dnd_Enter *enter_ev; @@ -301,8 +477,8 @@ e_drag_update(int x, int y) if (_drag_current) { - e_drag_show(_drag_current); - e_drag_move(_drag_current, x, y); + _e_drag_show(_drag_current); + _e_drag_move(_drag_current, x, y); } enter_ev = E_NEW(E_Event_Dnd_Enter, 1); @@ -353,34 +529,37 @@ e_drag_update(int x, int y) free(leave_ev); } -void -e_drag_end(int x, int y) +static void +_e_drag_end(int x, int y) { Evas_List *l; E_Event_Dnd_Drop *ev; const char *type = NULL; - if (_drag_current) - { - e_drag_hide(_drag_current); + if (!_drag_current) return; - ecore_x_pointer_ungrab(); - ecore_x_keyboard_ungrab(); - ecore_x_window_del(_drag_win); - _drag_win = 0; - } + _e_drag_hide(_drag_current); - ev = E_NEW(E_Event_Dnd_Drop, 1); - if (_drag_current) - { - ev->data = _drag_current->data; - type = _drag_current->types[0]; - } - else if (_xdnd) + ecore_x_pointer_ungrab(); + ecore_x_keyboard_ungrab(); + if (_drag_current->type == E_DRAG_XDND) { - ev->data = _xdnd->data; - type = _xdnd->type; + e_object_del(E_OBJECT(_drag_current)); + _drag_current = NULL; + if (!ecore_x_dnd_drop()) + { + ecore_x_window_del(_drag_win); + _drag_win = 0; + } + return; } + + ecore_x_window_del(_drag_win); + _drag_win = 0; + + ev = E_NEW(E_Event_Dnd_Drop, 1); + ev->data = _drag_current->data; + type = _drag_current->types[0]; ev->x = x; ev->y = y; @@ -398,20 +577,17 @@ e_drag_end(int x, int y) if (!h->active) continue; - if ((h->cb.drop) - && E_INSIDE(x, y, h->x, h->y, h->w, h->h)) + if ((h->cb.drop) && + E_INSIDE(x, y, h->x, h->y, h->w, h->h)) { h->cb.drop(h->cb.data, type, ev); dropped = 1; } } - if (_drag_current) - { - if (_drag_current->cb.finished) - _drag_current->cb.finished(_drag_current, dropped); - e_object_del(E_OBJECT(_drag_current)); - _drag_current = NULL; - } + if (_drag_current->cb.finished) + _drag_current->cb.finished(_drag_current, dropped); + e_object_del(E_OBJECT(_drag_current)); + _drag_current = NULL; } else { @@ -444,131 +620,73 @@ e_drag_end(int x, int y) free(ev); } -E_Drop_Handler * -e_drop_handler_add(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), - void (*drop_cb)(void *data, const char *type, void *event), - const char **types, unsigned int num_types, int x, int y, int w, int h) +static void +_e_drag_xdnd_end(int x, int y) { - E_Drop_Handler *handler; - int i; + Evas_List *l; + E_Event_Dnd_Drop *ev; + const char *type = NULL; - handler = E_NEW(E_Drop_Handler, 1); - if (!handler) return NULL; + if (!_xdnd) return; - handler->cb.data = data; - handler->cb.enter = enter_cb; - handler->cb.move = move_cb; - handler->cb.leave = leave_cb; - handler->cb.drop = drop_cb; - handler->num_types = num_types; - if (num_types) - { - handler->types = malloc(num_types * sizeof(char *)); - for (i = 0; i < num_types; i++) - handler->types[i] = strdup(types[i]); - } - handler->x = x; - handler->y = y; - handler->w = w; - handler->h = h; + ev = E_NEW(E_Event_Dnd_Drop, 1); + ev->data = _xdnd->data; + type = _xdnd->type; + ev->x = x; + ev->y = y; - _drop_handlers = evas_list_append(_drop_handlers, handler); + if (ev->data) + { + int dropped; - return handler; -} + dropped = 0; + for (l = _drop_handlers; l; l = l->next) + { + E_Drop_Handler *h; -void -e_drop_handler_geometry_set(E_Drop_Handler *handler, int x, int y, int w, int h) -{ - handler->x = x; - handler->y = y; - handler->w = w; - handler->h = h; -} + h = l->data; -void -e_drop_handler_del(E_Drop_Handler *handler) -{ - int i; + if (!h->active) + continue; - _drop_handlers = evas_list_remove(_drop_handlers, handler); - if (handler->types) - { - for (i = 0; i < handler->num_types; i++) - free(handler->types[i]); - free(handler->types); + if ((h->cb.drop) && + E_INSIDE(x, y, h->x, h->y, h->w, h->h)) + { + h->cb.drop(h->cb.data, type, ev); + dropped = 1; + } + } } - free(handler); -} + else + { + /* Just leave */ + E_Event_Dnd_Leave *leave_ev; + leave_ev = E_NEW(E_Event_Dnd_Leave, 1); + /* FIXME: We don't need x and y in leave */ + leave_ev->x = 0; + leave_ev->y = 0; -void -e_drag_idler_before(void) -{ - Evas_List *l; - - for (l = _drag_list; l; l = l->next) - { - E_Drag *drag; - - drag = l->data; - if (drag->need_shape_export) + for (l = _drop_handlers; l; l = l->next) { - Ecore_X_Rectangle *rects, *orects; - int num; - - rects = ecore_x_window_shape_rectangles_get(drag->evas_win, &num); - if (rects) - { - int changed; - - changed = 1; - if ((num == drag->shape_rects_num) && (drag->shape_rects)) - { - int i; - - orects = drag->shape_rects; - for (i = 0; i < num; i++) - { - if ((orects[i].x != rects[i].x) || - (orects[i].y != rects[i].y) || - (orects[i].width != rects[i].width) || - (orects[i].height != rects[i].height)) - { - changed = 1; - break; - } - } - changed = 0; - } - if (changed) - { - E_FREE(drag->shape_rects); - drag->shape_rects = rects; - drag->shape_rects_num = num; - e_container_shape_rects_set(drag->shape, rects, num); - } - else - free(rects); - } - else + E_Drop_Handler *h; + + h = l->data; + + if (!h->active) + continue; + + if (h->entered) { - E_FREE(drag->shape_rects); - drag->shape_rects = NULL; - drag->shape_rects_num = 0; - e_container_shape_rects_set(drag->shape, NULL, 0); + if (h->cb.leave) + h->cb.leave(h->cb.data, type, leave_ev); + h->entered = 0; } - drag->need_shape_export = 0; - if (drag->visible) - e_container_shape_show(drag->shape); } } -} -/* local subsystem functions */ + free(ev); +} static void _e_drag_free(E_Drag *drag) @@ -618,7 +736,7 @@ _e_dnd_cb_mouse_up(void *data, int type, void *event) ev = event; if (ev->win != _drag_win) return 1; - e_drag_end(ev->x, ev->y); + _e_drag_end(ev->x, ev->y); return 1; } @@ -631,7 +749,7 @@ _e_dnd_cb_mouse_move(void *data, int type, void *event) ev = event; if (ev->win != _drag_win) return 1; - e_drag_update(ev->x, ev->y); + _e_drag_update(ev->x, ev->y); return 1; } @@ -646,6 +764,7 @@ _e_dnd_cb_event_dnd_enter(void *data, int type, void *event) ev = event; con = data; if (con->bg_win != ev->win) return 1; + if (ev->source == _drag_win) return 1; printf("Xdnd enter\n"); for (l = _drop_handlers; l; l = l->next) { @@ -712,6 +831,7 @@ _e_dnd_cb_event_dnd_leave(void *data, int type, void *event) ev = event; con = data; if (con->bg_win != ev->win) return 1; + if (ev->source == _drag_win) return 1; printf("Xdnd leave\n"); leave_ev = E_NEW(E_Event_Dnd_Leave, 1); @@ -759,6 +879,7 @@ _e_dnd_cb_event_dnd_position(void *data, int type, void *event) ev = event; con = data; if (con->bg_win != ev->win) return 1; + if (ev->source == _drag_win) return 1; rect.x = 0; rect.y = 0; @@ -780,7 +901,7 @@ _e_dnd_cb_event_dnd_position(void *data, int type, void *event) } else { - e_drag_update(ev->position.x, ev->position.y); + _e_drag_update(ev->position.x, ev->position.y); ecore_x_dnd_send_status(1, 0, rect, ECORE_X_DND_ACTION_PRIVATE); } @@ -788,6 +909,40 @@ _e_dnd_cb_event_dnd_position(void *data, int type, void *event) } static int +_e_dnd_cb_event_dnd_status(void *data, int type, void *event) +{ + Ecore_X_Event_Xdnd_Status *ev; + + ev = event; + if (ev->win != _drag_win) return 1; + + return 1; +} + +static int +_e_dnd_cb_event_dnd_finished(void *data, int type, void *event) +{ + Ecore_X_Event_Xdnd_Finished *ev; + + /* + * TODO: + * - Check action + * - Do something if not completed + */ + + ev = event; + if (ev->win != _drag_win) return 1; + printf("Xdnd finished\n"); + + if (!ev->completed) + printf("FIXME: XDnd not completed, need to delay deleting _drag_win!!\n"); + + ecore_x_window_del(_drag_win); + _drag_win = 0; + return 1; +} + +static int _e_dnd_cb_event_dnd_drop(void *data, int type, void *event) { Ecore_X_Event_Xdnd_Drop *ev; @@ -796,6 +951,7 @@ _e_dnd_cb_event_dnd_drop(void *data, int type, void *event) ev = event; con = data; if (con->bg_win != ev->win) return 1; + if (ev->source == _drag_win) return 1; printf("Xdnd drop\n"); ecore_x_selection_xdnd_request(ev->win, _xdnd->type); @@ -827,7 +983,7 @@ _e_dnd_cb_event_dnd_selection(void *data, int type, void *event) for (i = 0; i < files->num_files; i++) l = evas_list_append(l, files->files[i]), printf("file: %s\n", files->files[i]); _xdnd->data = l; - e_drag_end(_xdnd->x, _xdnd->y); + _e_drag_xdnd_end(_xdnd->x, _xdnd->y); evas_list_free(l); } else if (!strcmp("text/x-moz-url", _xdnd->type)) @@ -866,12 +1022,12 @@ _e_dnd_cb_event_dnd_selection(void *data, int type, void *event) l = evas_list_append(l, file); _xdnd->data = l; - e_drag_end(_xdnd->x, _xdnd->y); + _e_drag_xdnd_end(_xdnd->x, _xdnd->y); evas_list_free(l); } else { - e_drag_end(_xdnd->x, _xdnd->y); + _e_drag_xdnd_end(_xdnd->x, _xdnd->y); } /* FIXME: When to execute this? It could be executed in ecore_x after getting * the drop property... */ diff --git a/src/bin/e_dnd.h b/src/bin/e_dnd.h index 232ae55..84e9407 100644 --- a/src/bin/e_dnd.h +++ b/src/bin/e_dnd.h @@ -4,6 +4,8 @@ #ifdef E_TYPEDEFS +typedef enum _E_Drag_Type E_Drag_Type; + typedef struct _E_Drag E_Drag; typedef struct _E_Drop_Handler E_Drop_Handler; typedef struct _E_Event_Dnd_Enter E_Event_Dnd_Enter; @@ -17,6 +19,13 @@ 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; @@ -26,6 +35,8 @@ struct _E_Drag void *data; int data_size; + E_Drag_Type type; + struct { void (*finished)(E_Drag *drag, int dropped); } cb; @@ -99,16 +110,12 @@ EAPI E_Drag *e_drag_new(E_Container *container, int x, int y, void (*finished_cb)(E_Drag *drag, int dropped)); EAPI Evas *e_drag_evas_get(E_Drag *drag); EAPI void e_drag_object_set(E_Drag *drag, Evas_Object *object); -EAPI void e_drag_show(E_Drag *drag); -EAPI void e_drag_hide(E_Drag *drag); -EAPI void e_drag_move(E_Drag *drag, int x, int y); EAPI void e_drag_resize(E_Drag *drag, int w, int h); EAPI void e_drag_idler_before(void); /* x and y are the coords where the mouse is when dragging starts */ -EAPI void e_drag_start(E_Drag *drag, int x, int y); -EAPI void e_drag_update(int x, int y); -EAPI void e_drag_end(int x, int y); +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, void (*enter_cb)(void *data, const char *type, void *event), -- 2.7.4