Hello.

First of two attached patches brings an API that allows one to handle
key pressing while DND using two functions:

EAPI void e_drag_key_down_cb_set(E_Drag *drag, void (*func)(E_Drag *drag, 
Ecore_X_Event_Key_Down *e));
EAPI void e_drag_key_up_cb_set(E_Drag *drag, void (*func)(E_Drag *drag, 
Ecore_X_Event_Key_Up *e));

Both callbacks are called when a key is down/up while drag.

Second patch uses this API to use modifiers in EFM drag. If you hold
Control while drag the action is Copy, Alt -- action is Ask, Shift --
action is Move. The icons get signals 'e,state,move', 'e,state,copy',
'e,state,ask' with source 'e', so one can modify a theme to show which
action would be performed. Note that you need a modified Ecore_X for
this to work, see my previous mail.

-- 
King regards,
Fedor Gusev.
diff --git a/src/bin/e_dnd.c b/src/bin/e_dnd.c
index c5d002b..4038426 100644
--- a/src/bin/e_dnd.c
+++ b/src/bin/e_dnd.c
@@ -30,6 +30,8 @@ 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_key_down(void *data, int type, void *event);
+static int  _e_dnd_cb_key_up(void *data, int type, void *event);
 static int  _e_dnd_cb_mouse_up(void *data, int type, void *event);
 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);
@@ -102,6 +104,12 @@ 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));
+   _event_handlers = evas_list_append(_event_handlers,
+                                      ecore_event_handler_add(ECORE_X_EVENT_KEY_DOWN,
+                                                              _e_dnd_cb_key_down, NULL));
+   _event_handlers = evas_list_append(_event_handlers,
+                                      ecore_event_handler_add(ECORE_X_EVENT_KEY_UP,
+                                                              _e_dnd_cb_key_up, NULL));
 
    _action = ECORE_X_ATOM_XDND_ACTION_PRIVATE;
    return 1;
@@ -205,6 +213,9 @@ e_drag_new(E_Container *container, int x, int y,
    ecore_x_window_shadow_tree_flush();
    
    _drag_win_root = drag->container->manager->root;
+
+   drag->cb.key_down = NULL;
+   drag->cb.key_up = NULL;
    
    return drag;
 }
@@ -529,6 +540,18 @@ e_drop_handler_action_get()
    return _action;
 }
 
+EAPI void
+e_drag_key_down_cb_set(E_Drag *drag, void (*func)(E_Drag *drag, Ecore_X_Event_Key_Down *e))
+{
+   drag->cb.key_down = func;
+}
+
+EAPI void
+e_drag_key_up_cb_set(E_Drag *drag, void (*func)(E_Drag *drag, Ecore_X_Event_Key_Up *e))
+{
+   drag->cb.key_up = func;
+}
+
 /* local subsystem functions */
 
 static void
@@ -717,6 +740,10 @@ _e_drag_update(Ecore_X_Window root, int x, int y, Ecore_X_Atom action)
    int dx, dy, dw, dh;
    Ecore_X_Window win, ignore_win[2];
    int responsive = 0;
+   static struct 
+     {
+	Ecore_X_Window root, win;
+     } cache = {0, 0};
 
 //   double t1 = ecore_time_get(); ////
    if (_drag_current)
@@ -726,7 +753,13 @@ _e_drag_update(Ecore_X_Window root, int x, int y, Ecore_X_Atom action)
 	/* FIXME: this is nasty. every x mouse event we go back to x and do
 	 * a whole bunch of round-trips narrowing down the toplevel window
 	 * which contains the mouse */
-	win = ecore_x_window_shadow_tree_at_xy_with_skip_get(root, x, y, ignore_win, 2);
+	if (cache.win != root)
+	  {
+	     /* A little bit of caching to void trips to X. */
+	     cache.win = root;
+	     cache.root = ecore_x_window_root_get(root);
+	  }
+	win = ecore_x_window_shadow_tree_at_xy_with_skip_get(cache.root, x, y, ignore_win, 2);
 //	win = ecore_x_window_at_xy_with_skip_get(x, y, ignore_win, 2);
      }
    else
@@ -1049,6 +1082,38 @@ _e_dnd_cb_window_shape(void *data, int ev_type, void *ev)
 }
 
 static int
+_e_dnd_cb_key_down(void *data, int type, void *event)
+{
+   Ecore_X_Event_Key_Down *ev;
+
+   ev = event;
+   if (ev->win != _drag_win) return 1;
+
+   if (!_drag_current) return 1;
+
+   if (_drag_current->cb.key_down)
+     _drag_current->cb.key_down(_drag_current, ev);
+   
+   return 1;
+}
+
+static int
+_e_dnd_cb_key_up(void *data, int type, void *event)
+{
+   Ecore_X_Event_Key_Up *ev;
+
+   ev = event;
+   if (ev->win != _drag_win) return 1;
+
+   if (!_drag_current) return 1;
+
+   if (_drag_current->cb.key_up)
+     _drag_current->cb.key_up(_drag_current, ev);
+   
+   return 1;
+}
+
+static int
 _e_dnd_cb_mouse_up(void *data, int type, void *event)
 {
    Ecore_X_Event_Mouse_Button_Up *ev;
diff --git a/src/bin/e_dnd.h b/src/bin/e_dnd.h
index 069d0da..84734cd 100644
--- a/src/bin/e_dnd.h
+++ b/src/bin/e_dnd.h
@@ -38,6 +38,8 @@ struct _E_Drag
    struct {
 	void *(*convert)(E_Drag *drag, const char *type);
 	void  (*finished)(E_Drag *drag, int dropped);
+	void  (*key_down)(E_Drag *drag, Ecore_X_Event_Key_Down *e);
+	void  (*key_up)(E_Drag *drag, Ecore_X_Event_Key_Up *e);
    } cb;
 
    E_Container       *container;
@@ -120,6 +122,8 @@ EAPI void    e_drag_object_set(E_Drag *drag, Evas_Object *object);
 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);
+EAPI void    e_drag_key_down_cb_set(E_Drag *drag, void (*func)(E_Drag *drag, Ecore_X_Event_Key_Down *e));
+EAPI void    e_drag_key_up_cb_set(E_Drag *drag, void (*func)(E_Drag *drag, Ecore_X_Event_Key_Up *e));
 
 /* x and y are the coords where the mouse is when dragging starts */
 EAPI int  e_drag_start(E_Drag *drag, int x, int y);
diff --git a/src/bin/e_fm.c b/src/bin/e_fm.c
index b444d1f..c43a906 100644
--- a/src/bin/e_fm.c
+++ b/src/bin/e_fm.c
@@ -5247,6 +5247,47 @@ _e_fm2_cb_drag_finished(E_Drag *drag, int dropped)
    free(drag->data);
 }
 
+void
+_e_fm_drag_key_down_cb(E_Drag *drag, Ecore_X_Event_Key_Down *e)
+{
+   if (!strncmp(e->keyname, "Alt", 3))
+     {
+	ecore_x_dnd_source_action_set(ECORE_X_ATOM_XDND_ACTION_ASK);
+	edje_object_signal_emit(drag->object, "e,state,ask", "e");
+     }
+   else if (!strncmp(e->keyname, "Shift", 5))
+     {
+	ecore_x_dnd_source_action_set(ECORE_X_ATOM_XDND_ACTION_MOVE);
+	edje_object_signal_emit(drag->object, "e,state,move", "e");
+     }
+   else if (!strncmp(e->keyname, "Control", 7))
+     {
+	ecore_x_dnd_source_action_set(ECORE_X_ATOM_XDND_ACTION_COPY);	
+	edje_object_signal_emit(drag->object, "e,state,copy", "e");
+     }
+}
+
+void
+_e_fm_drag_key_up_cb(E_Drag *drag, Ecore_X_Event_Key_Up *e)
+{
+   /* Default action would be move. ;) */
+
+   if (!strncmp(e->keyname, "Alt", 3))
+     {
+	ecore_x_dnd_source_action_set(ECORE_X_ATOM_XDND_ACTION_MOVE);
+     }
+   else if (!strncmp(e->keyname, "Shift", 5))
+     {
+	ecore_x_dnd_source_action_set(ECORE_X_ATOM_XDND_ACTION_MOVE);
+     }
+   else if (!strncmp(e->keyname, "Control", 7))
+     {
+	ecore_x_dnd_source_action_set(ECORE_X_ATOM_XDND_ACTION_MOVE);
+     }
+
+   edje_object_signal_emit(drag->object, "e,state,move", "e");
+}
+
 static void
 _e_fm2_cb_icon_mouse_move(void *data, Evas *e, Evas_Object *obj, void *event_info)
 {
@@ -5384,8 +5425,12 @@ _e_fm2_cb_icon_mouse_move(void *data, Evas *e, Evas_Object *obj, void *event_inf
 	     edje_object_signal_emit(o, "e,state,selected", "e");
 	     edje_object_signal_emit(o2, "e,state,selected", "e");
 	     e_drag_object_set(d, o);
+	     edje_object_signal_emit(o, "e,state,move", "e");
 	     e_drag_resize(d, w, h);
 
+	     e_drag_key_down_cb_set(d, _e_fm_drag_key_down_cb);
+	     e_drag_key_up_cb_set(d, _e_fm_drag_key_up_cb);
+
 	     e_drag_xdnd_start(d,
 			       ic->drag.x + ic->x + ic->sd->x - ic->sd->pos.x,
 			       ic->drag.y + ic->y + ic->sd->y - ic->sd->pos.y);
-------------------------------------------------------------------------
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