First attached patch adds a way to use DND actions in API that E provides.
Each window have a handler (named responsive), which you can set/get
with e_drop_handler_responsive_set() and
e_drop_handler_responsive_get(). You should set desired action in your
callbacks using e_drop_handler_action_set() and you can see the one
sent with XdndPosition in the event data.

If a handler callback was called and the handler is responsive for the
window, then action set with e_drop_handler_action_set() is sent in
XdndStatus message, otherwise XdndActionPrivate is sent.

I've used this API to customize drags from external apptications to
EFM. If you drag files and the source sends XdndPosition with
different actions, then EFM understands them. ( But not XdndActionLink
for now). Apply on top of my previuos patch.

-- 
King regards,
Fedor Gusev.
diff --git a/src/bin/e_dnd.c b/src/bin/e_dnd.c
index 1f757c3..c5d002b 100644
--- a/src/bin/e_dnd.c
+++ b/src/bin/e_dnd.c
@@ -19,10 +19,11 @@ 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 Ecore_X_Window _e_drag_win_get(E_Drop_Handler *h, int xdnd);
 static int  _e_drag_win_matches(E_Drop_Handler *h, Ecore_X_Window win, int xdnd);
 static void _e_drag_win_show(E_Drop_Handler *h);
 static void _e_drag_win_hide(E_Drop_Handler *h);
-static void _e_drag_update(Ecore_X_Window root, int x, int y);
+static int _e_drag_update(Ecore_X_Window root, int x, int y, Ecore_X_Atom action);
 static void _e_drag_end(Ecore_X_Window root, int x, int y);
 static void _e_drag_xdnd_end(Ecore_X_Window root, int x, int y);
 static void _e_drag_free(E_Drag *drag);
@@ -62,6 +63,9 @@ static E_Drag    *_drag_current = NULL;
 
 static XDnd *_xdnd = NULL;
 
+static Evas_Hash *_drop_handlers_responsives;
+static Ecore_X_Atom _action;
+
 /* externally accessible functions */
 
 EAPI int
@@ -98,6 +102,8 @@ e_dnd_init(void)
    _event_handlers = evas_list_append(_event_handlers,
 				      ecore_event_handler_add(ECORE_X_EVENT_SELECTION_NOTIFY,
 							      _e_dnd_cb_event_dnd_selection, NULL));
+
+   _action = ECORE_X_ATOM_XDND_ACTION_PRIVATE;
    return 1;
 }
 
@@ -128,6 +134,8 @@ e_dnd_shutdown(void)
    evas_list_free(_drop_handlers);
    _drop_handlers = NULL;
 
+   evas_hash_free(_drop_handlers_responsives);
+
    return 1;
 }
 
@@ -491,6 +499,36 @@ e_drag_idler_before(void)
      }
 }
 
+EAPI void
+e_drop_handler_responsive_set(E_Drop_Handler *handler)
+{
+   Ecore_X_Window hwin = _e_drag_win_get(handler, 1);
+   const char *wid = e_util_winid_str_get(hwin);
+
+   _drop_handlers_responsives = evas_hash_add(_drop_handlers_responsives, wid, (void *)handler);
+}
+
+EAPI int
+e_drop_handler_responsive_get(E_Drop_Handler *handler)
+{
+   Ecore_X_Window hwin = _e_drag_win_get(handler, 1);
+   const char *wid = e_util_winid_str_get(hwin);
+
+   return evas_hash_find(_drop_handlers_responsives, wid) == (void *)handler;
+}
+
+EAPI void
+e_drop_handler_action_set(Ecore_X_Atom action)
+{
+   _action = action;
+}
+
+EAPI Ecore_X_Atom
+e_drop_handler_action_get()
+{
+   return _action;
+}
+
 /* local subsystem functions */
 
 static void
@@ -574,8 +612,8 @@ _e_drag_coords_update(E_Drop_Handler *h, int *dx, int *dy, int *dw, int *dh)
    *dy += py;
 }
 
-static int
-_e_drag_win_matches(E_Drop_Handler *h, Ecore_X_Window win, int xdnd)
+static Ecore_X_Window
+_e_drag_win_get(E_Drop_Handler *h, int xdnd)
 {
    Ecore_X_Window hwin = 0;
    
@@ -608,6 +646,15 @@ _e_drag_win_matches(E_Drop_Handler *h, Ecore_X_Window win, int xdnd)
 	     break;
 	  }
      }
+
+   return hwin;
+}
+
+static int
+_e_drag_win_matches(E_Drop_Handler *h, Ecore_X_Window win, int xdnd)
+{
+   Ecore_X_Window hwin = _e_drag_win_get(h, xdnd);
+
    if (win == hwin) return 1;
    return 0;
 }
@@ -660,8 +707,8 @@ _e_drag_win_hide(E_Drop_Handler *h)
      }
 }
 
-static void
-_e_drag_update(Ecore_X_Window root, int x, int y)
+static int
+_e_drag_update(Ecore_X_Window root, int x, int y, Ecore_X_Atom action)
 {
    Evas_List *l;
    E_Event_Dnd_Enter enter_ev;
@@ -669,6 +716,7 @@ _e_drag_update(Ecore_X_Window root, int x, int y)
    E_Event_Dnd_Leave leave_ev;
    int dx, dy, dw, dh;
    Ecore_X_Window win, ignore_win[2];
+   int responsive = 0;
 
 //   double t1 = ecore_time_get(); ////
    if (_drag_current)
@@ -702,12 +750,16 @@ _e_drag_update(Ecore_X_Window root, int x, int y)
 	     enter_ev.x = x - dx;
 	     enter_ev.y = y - dy;
 	     enter_ev.data = NULL;
+	     enter_ev.action = action;
 	     move_ev.x = x - dx;
 	     move_ev.y = y - dy;
+	     move_ev.action = action;
 	     leave_ev.x = x - dx;
 	     leave_ev.y = y - dy;
 	     if (E_INSIDE(x, y, dx, dy, dw, dh) && _e_drag_win_matches(h, win, 0))
 	       {
+		  if(e_drop_handler_responsive_get(h)) responsive = 1;
+
 		  if (!h->entered)
 		    {
 		       _e_drag_win_show(h);
@@ -750,12 +802,16 @@ _e_drag_update(Ecore_X_Window root, int x, int y)
 	     _e_drag_coords_update(h, &dx, &dy, &dw, &dh);
 	     enter_ev.x = x - dx;
 	     enter_ev.y = y - dy;
+	     enter_ev.action = action;
 	     move_ev.x = x - dx;
 	     move_ev.y = y - dy;
+	     move_ev.action = action;
 	     leave_ev.x = x - dx;
 	     leave_ev.y = y - dy;
 	     if (E_INSIDE(x, y, dx, dy, dw, dh) && _e_drag_win_matches(h, win, 1))
 	       {
+		  if(e_drop_handler_responsive_get(h)) responsive = 1;
+
 		  if (!h->entered)
 		    {
 		       if (h->cb.enter)
@@ -776,6 +832,10 @@ _e_drag_update(Ecore_X_Window root, int x, int y)
 	       }
 	  }
      }
+
+   if(action == ECORE_X_ATOM_ATOM) responsive = 0;
+
+   return responsive;
 //   double t2 = ecore_time_get() - t1; ////
 //   printf("DND UPDATE %3.7f\n", t2); ////
 }
@@ -1009,7 +1069,7 @@ _e_dnd_cb_mouse_move(void *data, int type, void *event)
    ev = event;
    if (ev->win != _drag_win) return 1;
 
-   _e_drag_update(_drag_win_root, ev->x, ev->y);
+   _e_drag_update(_drag_win_root, ev->x, ev->y, ECORE_X_ATOM_ATOM);
    
    return 1;
 }
@@ -1133,10 +1193,13 @@ _e_dnd_cb_event_dnd_position(void *data, int type, void *event)
 {
    Ecore_X_Event_Xdnd_Position *ev;
    Ecore_X_Rectangle rect;
+   Ecore_X_Action action;
    const char *id;
+   const char *description = NULL;
    Evas_List *l;
 
    int active;
+   int responsive;
 
    ev = event;
 //   double t1 = ecore_time_get(); ////
@@ -1153,6 +1216,8 @@ _e_dnd_cb_event_dnd_position(void *data, int type, void *event)
    rect.width = 0;
    rect.height = 0;
 
+   action = ev->action;
+
    active = 0;
    for (l = _drop_handlers; l; l = l->next)
      {
@@ -1171,8 +1236,15 @@ _e_dnd_cb_event_dnd_position(void *data, int type, void *event)
      }
    else
      {
-	_e_drag_update(ev->win, ev->position.x, ev->position.y);
-	ecore_x_dnd_send_status(1, 0, rect, ECORE_X_DND_ACTION_PRIVATE);
+	responsive = _e_drag_update(ev->win, ev->position.x, ev->position.y, ev->action);
+	if(responsive)
+	  {
+	     ecore_x_dnd_send_status(1, 0, rect, _action);
+	  }
+	else
+	  {
+	     ecore_x_dnd_send_status(1, 0, rect, ECORE_X_ATOM_XDND_ACTION_PRIVATE);
+	  }
      }
 //   double t2 = ecore_time_get() - t1; ////
 //   printf("DND POS EV 2 %3.7f\n", t2); ////
diff --git a/src/bin/e_dnd.h b/src/bin/e_dnd.h
index 3659523..069d0da 100644
--- a/src/bin/e_dnd.h
+++ b/src/bin/e_dnd.h
@@ -84,11 +84,13 @@ struct _E_Event_Dnd_Enter
 {
    void *data;
    int x, y;
+   Ecore_X_Atom action;
 };
 
 struct _E_Event_Dnd_Move
 {
    int x, y;
+   Ecore_X_Atom action;
 };
 
 struct _E_Event_Dnd_Leave
@@ -135,6 +137,10 @@ EAPI void e_drop_handler_geometry_set(E_Drop_Handler *handler, int x, int y, int
 EAPI int  e_drop_inside(E_Drop_Handler *handler, int x, int y);
 EAPI void e_drop_handler_del(E_Drop_Handler *handler);
 EAPI int  e_drop_xdnd_register_set(Ecore_X_Window win, int reg);
+EAPI void e_drop_handler_responsive_set(E_Drop_Handler *handler);
+EAPI int  e_drop_handler_responsive_get(E_Drop_Handler *handler);
+EAPI void e_drop_handler_action_set(Ecore_X_Atom action);
+EAPI Ecore_X_Atom e_drop_handler_action_get();
 
 #endif
 #endif
diff --git a/src/bin/e_fm.c b/src/bin/e_fm.c
index 0715ae7..0493c05 100644
--- a/src/bin/e_fm.c
+++ b/src/bin/e_fm.c
@@ -984,6 +984,7 @@ e_fm2_window_object_set(Evas_Object *obj, E_Object *eobj)
 					 _e_fm2_cb_dnd_leave,
 					 _e_fm2_cb_dnd_drop,
 					 drop, 3, sd->x, sd->y, sd->w, sd->h);
+   e_drop_handler_responsive_set(sd->drop_handler);
 }
 
 EAPI void
@@ -4502,6 +4503,7 @@ _e_fm2_cb_dnd_enter(void *data, const char *type, void *event)
    if (strcmp(type, "text/uri-list")) return;
    ev = (E_Event_Dnd_Enter *)event;
    printf("DND IN %i %i\n", ev->x, ev->y);
+   e_drop_handler_action_set(ev->action);
 }
  
 static void
@@ -4517,6 +4519,7 @@ _e_fm2_cb_dnd_move(void *data, const char *type, void *event)
    if (strcmp(type, "text/uri-list")) return;
    ev = (E_Event_Dnd_Move *)event;
    printf("DND MOVE %i %i\n", ev->x, ev->y);
+   e_drop_handler_action_set(ev->action);
    for (l = sd->icons; l; l = l->next) /* FIXME: should only walk regions and skip non-visible ones */
      {
 	ic = l->data;
@@ -4677,6 +4680,105 @@ _e_fm_icon_save_position(const char *file, Evas_Coord x, Evas_Coord y, Evas_Coor
 }
 
 static void
+_e_fm_drop_menu_copy_cb(void *data, E_Menu *m, E_Menu_Item *mi)
+{
+   char *args = data;
+
+   if(!data) return;
+
+   _e_fm_client_file_copy(args);
+}
+
+static void
+_e_fm_drop_menu_move_cb(void *data, E_Menu *m, E_Menu_Item *mi)
+{
+   char *args = data;
+
+   if(!data) return;
+
+   _e_fm_client_file_move(args);
+}
+
+static void
+_e_fm_drop_menu_abort_cb(void *data, E_Menu *m, E_Menu_Item *mi)
+{
+   char *args = data;
+
+   if(!data) return;
+}
+
+static void
+_e_fm_drop_menu_post_cb(void *data, E_Menu *m)
+{
+   char *args = data;
+
+   if(!data) return;
+
+   free(args);
+}
+
+static void
+_e_fm_drop_menu(char *args)
+{
+   E_Menu *menu = e_menu_new();
+   E_Menu_Item *item = NULL;
+   E_Manager *man = NULL;
+   E_Container *con = NULL;
+   E_Zone *zone = NULL;
+   int x, y;
+
+   if(!menu) return;
+
+   item = e_menu_item_new(menu);
+   e_menu_item_label_set(item, _("Copy"));
+   e_menu_item_callback_set(item, _e_fm_drop_menu_copy_cb, args);
+   e_menu_item_icon_edje_set(item,
+	 e_theme_edje_file_get("base/theme/fileman",
+	    "e/fileman/default/button/copy"),
+	 "e/fileman/default/button/copy");
+
+   item = e_menu_item_new(menu);
+   e_menu_item_label_set(item, _("Move"));
+   e_menu_item_callback_set(item, _e_fm_drop_menu_move_cb, args);
+   e_menu_item_icon_edje_set(item,
+	 e_theme_edje_file_get("base/theme/fileman",
+	    "e/fileman/default/button/move"),
+	 "e/fileman/default/button/move");
+
+   item = e_menu_item_new(menu);
+   e_menu_item_label_set(item, _("Abort"));
+   e_menu_item_callback_set(item, _e_fm_drop_menu_abort_cb, args);
+   e_menu_item_icon_edje_set(item,
+	 e_theme_edje_file_get("base/theme/fileman",
+	    "e/fileman/default/button/abort"),
+	 "e/fileman/default/button/abort");
+
+   man = e_manager_current_get();
+   if (!man)
+     {
+	e_object_del(E_OBJECT(menu));
+	return;
+     }
+   con = e_container_current_get(man);
+   if (!con)
+     {
+	e_object_del(E_OBJECT(menu));
+	return;
+     }
+   ecore_x_pointer_xy_get(con->win, &x, &y);
+   zone = e_util_zone_current_get(man);
+   if (!zone)
+     {
+	e_object_del(E_OBJECT(menu));
+	return;
+     }
+   e_menu_post_deactivate_callback_set(menu, _e_fm_drop_menu_post_cb, args);
+   e_menu_activate_mouse(menu, zone, 
+			 x, y, 1, 1, 
+			 E_MENU_POP_DIRECTION_DOWN, 0);
+}
+
+static void
 _e_fm2_cb_dnd_drop(void *data, const char *type, void *event)
 {
    E_Fm2_Smart_Data *sd;
@@ -4794,8 +4896,6 @@ _e_fm2_cb_dnd_drop(void *data, const char *type, void *event)
 	  }
 	
 	args = _e_fm_string_append_quoted(args, &size, &length, sd->realpath);
-	_e_fm_client_file_move(args);
-	free(args);
      }
    else if (sd->drop_icon) /* inot or before/after an icon */
      {
@@ -4821,8 +4921,6 @@ _e_fm2_cb_dnd_drop(void *data, const char *type, void *event)
 
 	     snprintf(dirpath, sizeof(dirpath), "%s/%s", sd->realpath, sd->drop_icon->info.file);
 	     args = _e_fm_string_append_quoted(args, &size, &length, dirpath);
-	     _e_fm_client_file_move(args);
-	     free(args);
 	  }
 	else
 	  {
@@ -4852,8 +4950,6 @@ _e_fm2_cb_dnd_drop(void *data, const char *type, void *event)
 		    }
 
 		  args = _e_fm_string_append_quoted(args, &size, &length, sd->realpath);
-		  _e_fm_client_file_move(args);
-		  free(args);
 	       }
 	     else
 	       {
@@ -4869,12 +4965,25 @@ _e_fm2_cb_dnd_drop(void *data, const char *type, void *event)
 		       evas_stringshare_del(fp);
 		    }
 		  args = _e_fm_string_append_quoted(args, &size, &length, sd->realpath);
-		  _e_fm_client_file_move(args);
-		  free(args);
 	       }
 	  }
      }
 
+   if(e_drop_handler_action_get() == ECORE_X_ATOM_XDND_ACTION_COPY)
+     {
+	_e_fm_client_file_copy(args);
+	free(args);
+     }
+   else if(e_drop_handler_action_get() == ECORE_X_ATOM_XDND_ACTION_MOVE)
+     {
+	_e_fm_client_file_move(args);
+	free(args);
+     }
+   else if(e_drop_handler_action_get() == ECORE_X_ATOM_XDND_ACTION_ASK)
+     {
+	_e_fm_drop_menu(args);
+     }
+
    _e_fm2_dnd_drop_hide(sd->obj);
    _e_fm2_dnd_drop_all_hide(sd->obj);
    _e_fm2_list_walking++;
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
enlightenment-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel

Reply via email to