diff --git a/src/bin/e_int_menus.c b/src/bin/e_int_menus.c index b24e67d66..13a7dfd67 100644 --- a/src/bin/e_int_menus.c +++ b/src/bin/e_int_menus.c @@ -33,6 +33,8 @@ static void _e_int_menus_apps_start (void *data, E_Menu *m); static void _e_int_menus_apps_del_hook (void *obj); static void _e_int_menus_apps_free_hook (void *obj); static void _e_int_menus_apps_run (void *data, E_Menu *m, E_Menu_Item *mi); +static void _e_int_menus_apps_drag (void *data, E_Menu *m, E_Menu_Item *mi); +static void _e_int_menus_apps_drag_finished(E_Drag *drag, int dropped); static void _e_int_menus_config_pre_cb (void *data, E_Menu *m); static void _e_int_menus_config_free_hook (void *obj); static void _e_int_menus_config_item_cb (void *data, E_Menu *m, E_Menu_Item *mi); @@ -472,6 +474,7 @@ _e_int_menus_apps_scan(E_Menu *m) if (a->icon_path) e_menu_item_icon_path_set(mi, a->icon_path); } e_menu_item_callback_set(mi, _e_int_menus_apps_run, a); + e_menu_item_drag_callback_set(mi, _e_int_menus_apps_drag, a); app_count++; } else @@ -540,6 +543,41 @@ _e_int_menus_apps_run(void *data, E_Menu *m, E_Menu_Item *mi) e_exehist_add("menu/apps", a->exe); } +static void +_e_int_menus_apps_drag(void *data, E_Menu *m, E_Menu_Item *mi) +{ + E_App *a; + + a = data; + + /* start drag! */ + if (mi->icon_object) + { + E_Drag *drag; + Evas_Object *o = NULL; + Evas_Coord x, y, w, h; + const char *file = NULL, *part = NULL; + const char *drag_types[] = { "enlightenment/eapp" }; + + evas_object_geometry_get(mi->icon_object, + &x, &y, &w, &h); + drag = e_drag_new(m->zone->container, x, y, + drag_types, 1, a, -1, _e_int_menus_apps_drag_finished); + + o = e_app_icon_add(e_drag_evas_get(drag), a); + e_drag_object_set(drag, o); + e_drag_resize(drag, w, h); + e_object_ref(E_OBJECT(a)); + e_drag_start(drag, mi->drag.x + w, mi->drag.y + h); + } +} + +static void +_e_int_menus_apps_drag_finished(E_Drag *drag, int dropped) +{ + e_object_unref(E_OBJECT(drag->data)); +} + static void _e_int_menus_desktops_pre_cb(void *data, E_Menu *m) { diff --git a/src/bin/e_menu.c b/src/bin/e_menu.c index 5f182f554..2ced4db18 100644 --- a/src/bin/e_menu.c +++ b/src/bin/e_menu.c @@ -92,6 +92,8 @@ static E_Menu_Item *_e_active_menu_item = NULL; static Evas_Hash *_e_menu_categories = NULL; static Ecore_X_Time _e_menu_activate_time = 0; static int _e_menu_activate_floating = 0; +static int _e_menu_activate_maybe_drag = 0; +static int _e_menu_activate_dragging = 0; static Ecore_Timer *_e_menu_scroll_timer = NULL; static double _e_menu_scroll_start = 0.0; static int _e_menu_x = 0; @@ -778,6 +780,15 @@ e_menu_item_submenu_post_callback_set(E_Menu_Item *mi, void (*func) (void *data mi->submenu_post_cb.data = data; } +EAPI void +e_menu_item_drag_callback_set(E_Menu_Item *mi, void (*func) (void *data, E_Menu *m, E_Menu_Item *mi), void *data) +{ + E_OBJECT_CHECK(mi); + E_OBJECT_TYPE_CHECK(mi, E_MENU_ITEM_TYPE); + mi->drag_cb.func = func; + mi->drag_cb.data = data; +} + EAPI void e_menu_item_active_set(E_Menu_Item *mi, int active) { @@ -1778,6 +1789,9 @@ _e_menu_deactivate_all(void) m->parent_item = NULL; e_object_unref(E_OBJECT(m)); } + _e_menu_activate_floating = 0; + _e_menu_activate_maybe_drag = 0; + _e_menu_activate_dragging = 0; } static void @@ -2473,9 +2487,24 @@ static void _e_menu_cb_item_out(void *data, Evas *evas, Evas_Object *obj, void *event_info) { E_Menu_Item *mi; + Evas_Event_Mouse_In *ev; mi = data; + ev = event_info; e_menu_item_active_set(mi, 0); + if (_e_menu_activate_maybe_drag) + { + if (mi->drag_cb.func) + { + /* User is dragging a draggable item elsewhere. */ + mi->drag.x = ev->output.x - (ev->output.x - mi->x); + mi->drag.y = ev->output.y - (ev->output.y - mi->y); + _e_menu_deactivate_all(); + mi->drag_cb.func(mi->drag_cb.data, mi->menu, mi); + } + /* Either way, the maybe drag stops here. */ + _e_menu_activate_maybe_drag = 0; + } } static int @@ -2560,6 +2589,15 @@ _e_menu_cb_mouse_down(void *data, int type, void *event) ev = event; if (ev->win != _e_menu_win) return 1; + + /* Only allow dragging from floating menus for now. + * The reason for this is that for non floating menus, + * the mouse is already down and dragging, so the decision + * to start a drag is much more complex. + */ + if (_e_menu_activate_floating) + _e_menu_activate_maybe_drag = 1; + return 1; } @@ -2568,11 +2606,11 @@ _e_menu_cb_mouse_up(void *data, int type, void *event) { Ecore_X_Event_Mouse_Button_Up *ev; Ecore_X_Time t; - int ret; + int ret = 0; ev = event; if (ev->win != _e_menu_win) return 1; - + t = ev->time - _e_menu_activate_time; if ((_e_menu_activate_time != 0) && (t < (e_config->menus_click_drag_timeout * 1000))) @@ -2581,7 +2619,16 @@ _e_menu_cb_mouse_up(void *data, int type, void *event) return 1; } - ret = _e_menu_active_call(); + if (_e_menu_activate_dragging) + { + /* FIXME: This is a drop, which is not allowed for now. + * Once dragging is working, this will be subject to some experimenattion. + */ + } + else + ret = _e_menu_active_call(); + _e_menu_activate_maybe_drag = 0; + _e_menu_activate_dragging = 0; if (ret == 1) { /* allow mouse to pop down menu if clicked elsewhere */ @@ -2617,6 +2664,7 @@ _e_menu_cb_mouse_move(void *data, int type, void *event) is_fast = 1; // printf("d=%i dt=%3.9f fast_move_threshold=%3.3f ---> FAST=%i\n", // d, dt, fast_move_threshold, is_fast); + for (l = _e_active_menus; l; l = l->next) { tmp = evas_list_append(tmp, l->data); diff --git a/src/bin/e_menu.h b/src/bin/e_menu.h index 92da0b1a9..5aa2ea4ee 100644 --- a/src/bin/e_menu.h +++ b/src/bin/e_menu.h @@ -130,6 +130,15 @@ struct _E_Menu_Item void (*func) (void *data, E_Menu *m, E_Menu_Item *mi); } submenu_post_cb; + struct { + void *data; + void (*func) (void *data, E_Menu *m, E_Menu_Item *mi); + } drag_cb; /* Callback for menu item dragging */ + + struct { + int x, y; + } drag; + unsigned char separator : 1; unsigned char radio : 1; unsigned char check : 1; @@ -190,6 +199,7 @@ EAPI void e_menu_item_callback_set(E_Menu_Item *mi, void (*func) (void EAPI void e_menu_item_realize_callback_set(E_Menu_Item *mi, void (*func) (void *data, E_Menu *m, E_Menu_Item *mi), void *data); EAPI void e_menu_item_submenu_pre_callback_set(E_Menu_Item *mi, void (*func) (void *data, E_Menu *m, E_Menu_Item *mi), void *data); EAPI void e_menu_item_submenu_post_callback_set(E_Menu_Item *mi, void (*func) (void *data, E_Menu *m, E_Menu_Item *mi), void *data); +EAPI void e_menu_item_drag_callback_set(E_Menu_Item *mi, void (*func) (void *data, E_Menu *m, E_Menu_Item *mi), void *data); EAPI void e_menu_item_active_set(E_Menu_Item *mi, int active); EAPI void e_menu_idler_before(void);