diff --git a/src/bin/e_dnd.c b/src/bin/e_dnd.c index 8d619f703..41d995e8c 100644 --- a/src/bin/e_dnd.c +++ b/src/bin/e_dnd.c @@ -61,8 +61,11 @@ static Eina_List *_drag_list = NULL; static E_Drag *_drag_current = NULL; 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; @@ -75,8 +78,11 @@ EINTERN int e_dnd_init(void) { _type_text_uri_list = eina_stringshare_add("text/uri-list"); + _type_xds = eina_stringshare_add(XDS_ATOM); _type_text_x_moz_url = eina_stringshare_add("text/x-moz-url"); _type_enlightenment_x_file = eina_stringshare_add("enlightenment/x-file"); + _xds_atom = ecore_x_atom_get(XDS_ATOM); + _text_atom = ecore_x_atom_get("text/plain"); _drop_win_hash = eina_hash_string_superfast_new(NULL); _drop_handlers_responsives = eina_hash_string_superfast_new(NULL); @@ -137,11 +143,14 @@ e_dnd_shutdown(void) eina_hash_free(_drop_handlers_responsives); eina_stringshare_del(_type_text_uri_list); + eina_stringshare_del(_type_xds); eina_stringshare_del(_type_text_x_moz_url); eina_stringshare_del(_type_enlightenment_x_file); _type_text_uri_list = NULL; + _type_xds = NULL; _type_text_x_moz_url = NULL; _type_enlightenment_x_file = NULL; + _text_atom = _xds_atom = 0; return 1; } @@ -348,6 +357,44 @@ e_drag_xdnd_start(E_Drag *drag, int x, int y) return 1; } +EAPI void +e_drop_handler_xds_set(E_Drop_Handler *handler, Ecore_Task_Cb cb) +{ + handler->cb.xds = cb; +} + +/* should only be used for windows */ +EAPI void +e_drop_xds_update(Eina_Bool enable, const char *value) +{ + Ecore_X_Window xwin; + char buf[PATH_MAX + 8]; + char *file; + int size; + size_t len; + + enable = !!enable; + + xwin = ecore_x_selection_owner_get(ECORE_X_ATOM_SELECTION_XDND); + if (enable) + { + if (!ecore_x_window_prop_property_get(xwin, _xds_atom, _text_atom, 8, (unsigned char **)&file, &size)) + return; + len = strlen(value); + if (size + len + 8 + 1 > sizeof(buf)) + { + free(file); + return; + } + snprintf(buf, sizeof(buf), "file://%s/", value); + strncat(buf, file, size); + free(file); + ecore_x_window_prop_property_set(xwin, _xds_atom, _text_atom, 8, (void*)buf, size + len + 8); + } + else + ecore_x_window_prop_property_del(xwin, _xds_atom); +} + EAPI E_Drop_Handler * e_drop_handler_add(E_Object *obj, void *data, @@ -1360,7 +1407,19 @@ _e_dnd_cb_event_dnd_drop(void *data __UNUSED__, int type __UNUSED__, void *event if (_xdnd) { - ecore_x_selection_xdnd_request(ev->win, _xdnd->type); + E_Drop_Handler *h; + Eina_Bool req = EINA_TRUE; + Eina_List *l; + + EINA_LIST_FOREACH(_drop_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); + } + } + if (req) ecore_x_selection_xdnd_request(ev->win, _xdnd->type); _xdnd->x = ev->position.x; _xdnd->y = ev->position.y; diff --git a/src/bin/e_dnd.h b/src/bin/e_dnd.h index ac52df7bb..95373b896 100644 --- a/src/bin/e_dnd.h +++ b/src/bin/e_dnd.h @@ -67,6 +67,7 @@ struct _E_Drop_Handler void (*move)(void *data, const char *type, void *event); void (*leave)(void *data, const char *type, void *event); void (*drop)(void *data, const char *type, void *event); + Ecore_Task_Cb xds; void *data; } cb; @@ -127,6 +128,8 @@ EAPI void e_drag_key_up_cb_set(E_Drag *drag, void (*func)(E_Drag *dra 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 void e_drop_xds_update(Eina_Bool enable, const char *value); +EAPI void e_drop_handler_xds_set(E_Drop_Handler *handler, Ecore_Task_Cb cb); EAPI E_Drop_Handler *e_drop_handler_add(E_Object *obj, void *data, void (*enter_cb)(void *data, const char *type, void *event), diff --git a/src/bin/e_fm.c b/src/bin/e_fm.c index 567f33525..c3aa14da5 100644 --- a/src/bin/e_fm.c +++ b/src/bin/e_fm.c @@ -483,6 +483,14 @@ static const char *_e_fm2_mime_inode_directory = NULL; static const char *_e_fm2_mime_app_desktop = NULL; static const char *_e_fm2_mime_app_edje = NULL; static const char *_e_fm2_mime_text_uri_list = NULL; +static const char *_e_fm2_xds = NULL; + +static const char **_e_fm2_dnd_types[] = +{ + &_e_fm2_mime_text_uri_list, + &_e_fm2_xds, + NULL +}; static Ecore_Timer *_e_fm2_mime_flush = NULL; static Ecore_Timer *_e_fm2_mime_clear = NULL; @@ -787,6 +795,7 @@ e_fm2_init(void) _e_fm2_mime_app_desktop = eina_stringshare_add("application/x-desktop"); _e_fm2_mime_app_edje = eina_stringshare_add("application/x-extension-edj"); _e_fm2_mime_text_uri_list = eina_stringshare_add("text/uri-list"); + _e_fm2_xds = eina_stringshare_add("XdndDirectSave0"); _e_fm2_favorites_thread = ecore_thread_run(_e_fm2_favorites_thread_cb, _e_fm2_thread_cleanup_cb, @@ -819,6 +828,7 @@ e_fm2_shutdown(void) eina_stringshare_replace(&_e_fm2_mime_app_desktop, NULL); eina_stringshare_replace(&_e_fm2_mime_app_edje, NULL); eina_stringshare_replace(&_e_fm2_mime_text_uri_list, NULL); + eina_stringshare_replace(&_e_fm2_xds, NULL); /// DBG if (_e_fm2_op_registry_entry_add_handler) @@ -864,6 +874,16 @@ e_fm2_add(Evas *evas) return evas_object_smart_add(evas, _e_fm2_smart); } +static Eina_Bool +_e_fm2_dir_xds_update(E_Fm2_Smart_Data *sd) +{ + Eina_Bool allow; + + allow = (sd->realpath && ecore_file_can_write(sd->realpath)); + e_drop_xds_update(allow, sd->realpath); + return allow; +} + static void _e_fm2_cb_mount_ok(void *data) { @@ -1523,7 +1543,7 @@ e_fm2_view_flags_get(Evas_Object *obj) EAPI void e_fm2_window_object_set(Evas_Object *obj, E_Object *eobj) { - const char *drop[] = { "enlightenment/desktop", "enlightenment/border", "text/uri-list" }; + const char *drop[] = { "enlightenment/desktop", "enlightenment/border", "text/uri-list", "XdndDirectSave0"}; EFM_SMART_CHECK(); sd->eobj = eobj; @@ -1534,9 +1554,10 @@ e_fm2_window_object_set(Evas_Object *obj, E_Object *eobj) _e_fm2_cb_dnd_move, _e_fm2_cb_dnd_leave, _e_fm2_cb_dnd_drop, - drop, 3, + drop, 4, sd->x, sd->y, sd->w, sd->h); e_drop_handler_responsive_set(sd->drop_handler); + e_drop_handler_xds_set(sd->drop_handler, (Ecore_Task_Cb)_e_fm2_dir_xds_update); } EAPI void @@ -6016,6 +6037,16 @@ _e_fm2_dnd_drop_hide(Evas_Object *obj) } /* FIXME: prototype + reposition + implement */ +static Eina_Bool +_e_fm2_dnd_type_implemented(const char *type) +{ + const char **t; + + for (t = *_e_fm2_dnd_types; t; t++) + if (type == *t) return EINA_TRUE; + return EINA_FALSE; +} + static void _e_fm2_dnd_finish(Evas_Object *obj, int refresh) { @@ -6042,7 +6073,7 @@ _e_fm2_cb_dnd_enter(void *data __UNUSED__, const char *type, void *event) { E_Event_Dnd_Enter *ev; - if (type != _e_fm2_mime_text_uri_list) return; + if (!_e_fm2_dnd_type_implemented(type)) return; ev = (E_Event_Dnd_Enter *)event; e_drop_handler_action_set(ev->action); } @@ -6057,7 +6088,7 @@ _e_fm2_cb_dnd_move(void *data, const char *type, void *event) int dx, dy; sd = data; - if (type != _e_fm2_mime_text_uri_list) return; + if (!_e_fm2_dnd_type_implemented(type)) return; ev = (E_Event_Dnd_Move *)event; dx = ev->x - sd->x; dy = ev->y - sd->y; @@ -6160,7 +6191,7 @@ _e_fm2_cb_dnd_leave(void *data, const char *type, void *event __UNUSED__) E_Fm2_Smart_Data *sd; sd = data; - if (type != _e_fm2_mime_text_uri_list) return; + if (!_e_fm2_dnd_type_implemented(type)) return; _e_fm2_dnd_drop_hide(sd->obj); _e_fm2_dnd_drop_all_hide(sd->obj); } @@ -6330,7 +6361,7 @@ _e_fm2_cb_dnd_drop(void *data, const char *type, void *event) E_Event_Dnd_Drop *ev; E_Fm2_Icon *ic; Eina_List *fsel, *l, *ll, *il, *isel; - char buf[4096]; + char buf[PATH_MAX]; const char *fp; Evas_Object *obj; Evas_Coord ox, oy, x, y; @@ -6342,8 +6373,8 @@ _e_fm2_cb_dnd_drop(void *data, const char *type, void *event) Eina_Bool memerr = EINA_FALSE; sd = data; - if (type != _e_fm2_mime_text_uri_list) return; - ev = (E_Event_Dnd_Drop *)event; + ev = event; + if (!_e_fm2_dnd_type_implemented(type)) return; fsel = _e_fm2_uri_path_list_get(ev->data); fp = eina_list_data_get(fsel);