diff --git a/src/bin/e_gadcon.c b/src/bin/e_gadcon.c index 5e576a742..7c1d7c2f2 100644 --- a/src/bin/e_gadcon.c +++ b/src/bin/e_gadcon.c @@ -43,7 +43,6 @@ static void _e_gadcon_cb_signal_resize_left_go(void *data, E static void _e_gadcon_cb_signal_resize_right_start(void *data, Evas_Object *obj, const char *emission, const char *source); static void _e_gadcon_cb_signal_resize_right_stop(void *data, Evas_Object *obj, const char *emission, const char *source); static void _e_gadcon_cb_signal_resize_right_go(void *data, Evas_Object *obj, const char *emission, const char *source); -static void _e_gadcon_cb_drag_finished(E_Drag *drag, int dropped); static void _e_gadcon_cb_dnd_enter(void *data, const char *type, void *event); static void _e_gadcon_cb_dnd_move(void *data, const char *type, void *event); static void _e_gadcon_cb_dnd_leave(void *data, const char *type, void *event); @@ -974,6 +973,28 @@ _e_gadcon_client_frame_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UN gcc->o_frame = NULL; } +EAPI void +e_gadcon_drag_finished_cb(E_Drag *drag, int dropped) +{ + E_Gadcon_Client *gcc; + + gcc = drag->data; + gcc->drag.drag = NULL; + if (!dropped) + { + /* free client config */ + e_gadcon_client_config_del(NULL, gcc->cf); + gcc->cf = NULL; + /* delete the gadcon client */ + /* TODO: Clean up module config too? */ + e_object_del(E_OBJECT(gcc)); + } + if (!gcc->gadcon->custom) + e_gadcon_client_drag_set(NULL); + gcc->gadcon->new_gcc = NULL; + e_object_unref(E_OBJECT(gcc)); +} + /** * Creates a new gadget * @@ -1941,6 +1962,16 @@ e_gadcon_site_is_not_toolbar(E_Gadcon_Site site) return EINA_TRUE; } +EAPI void +e_gadcon_client_drag_set(E_Gadcon_Client *gcc) +{ + Eina_List *l; + E_Gadcon *gc; + + EINA_LIST_FOREACH(gadcons, l, gc) + gc->drag_gcc = gcc; +} + /* local subsystem functions */ static void _e_gadcon_free(E_Gadcon *gc) @@ -2186,15 +2217,12 @@ _e_gadcon_client_drag_begin(E_Gadcon_Client *gcc, int x, int y) E_Drag *drag; Evas_Object *o = NULL; Evas_Coord w = 0, h = 0; - Eina_List *l; - E_Gadcon *gc; const char *drag_types[] = { "enlightenment/gadcon_client" }; if ((gcc->gadcon->drag_gcc) || (!gcc->gadcon->zone) || (!gcc->gadcon->zone->container)) return; - EINA_LIST_FOREACH(gadcons, l, gc) - gc->drag_gcc = gcc; + e_gadcon_client_drag_set(gcc); e_object_ref(E_OBJECT(gcc)); /* Remove this config from the current gadcon */ @@ -2210,7 +2238,7 @@ _e_gadcon_client_drag_begin(E_Gadcon_Client *gcc, int x, int y) gcc->drag.drag = drag = e_drag_new(gcc->gadcon->zone->container, x, y, drag_types, 1, gcc, -1, NULL, - _e_gadcon_cb_drag_finished); + e_gadcon_drag_finished_cb); if (!drag) return; o = gcc->client_class->func.icon((E_Gadcon_Client_Class *)gcc->client_class, @@ -2770,30 +2798,6 @@ _e_gadcon_cb_signal_resize_right_go(void *data, Evas_Object *obj __UNUSED__, con gcc->dy += y; } -static void -_e_gadcon_cb_drag_finished(E_Drag *drag, int dropped) -{ - E_Gadcon_Client *gcc; - Eina_List *l; - E_Gadcon *gc; - - gcc = drag->data; - gcc->drag.drag = NULL; - if (!dropped) - { - /* free client config */ - e_gadcon_client_config_del(NULL, gcc->cf); - gcc->cf = NULL; - /* delete the gadcon client */ - /* TODO: Clean up module config too? */ - e_object_del(E_OBJECT(gcc)); - } - EINA_LIST_FOREACH(gadcons, l, gc) - gc->drag_gcc = NULL; - gcc->gadcon->new_gcc = NULL; - e_object_unref(E_OBJECT(gcc)); -} - static void _e_gadcon_cb_dnd_enter(void *data, const char *type __UNUSED__, void *event) { @@ -2804,8 +2808,11 @@ _e_gadcon_cb_dnd_enter(void *data, const char *type __UNUSED__, void *event) ev = event; gc = data; //INF("DND ENTER"); - e_gadcon_layout_freeze(gc->o_container); gcc = gc->drag_gcc; + if ((!gcc->hidden) && (gcc->gadcon == gc)) return; + if (gcc->gadcon != gc) + e_gadcon_client_hide(gc->drag_gcc); + e_gadcon_layout_freeze(gc->o_container); if (gc->new_gcc) { @@ -2838,6 +2845,10 @@ _e_gadcon_cb_dnd_enter(void *data, const char *type __UNUSED__, void *event) gc->new_gcc->config.res = gcc->config.res; gc->new_gcc->state_info.seq = gcc->state_info.seq; gc->new_gcc->state_info.flags = gcc->state_info.flags; + gc->new_gcc->config.pos_x = gcc->config.pos_x; + gc->new_gcc->config.pos_y = gcc->config.pos_y; + gc->new_gcc->config.size_w = gcc->config.size_w; + gc->new_gcc->config.size_h = gcc->config.size_h; if (gc->new_gcc->client_class->func.orient) { if (gc->orient == E_GADCON_ORIENT_FLOAT) @@ -2862,11 +2873,22 @@ _e_gadcon_cb_dnd_enter(void *data, const char *type __UNUSED__, void *event) w = gc->zone->w; h = gc->zone->h; - gc->new_gcc->config.pos_x = (double)ev->x / (double)w; - gc->new_gcc->config.pos_y = (double)ev->y / (double)h; - evas_object_geometry_get(gcc->o_frame ?: gcc->o_base, NULL, NULL, &gw, &gh); - gc->new_gcc->config.size_w = (double)gw / (double)w; - gc->new_gcc->config.size_h = (double)gh / (double)h; + if ((!gc->new_gcc->config.pos_x) && (!gc->new_gcc->config.pos_y)) + { + gc->new_gcc->config.pos_x = (double)ev->x / (double)w; + gc->new_gcc->config.pos_y = (double)ev->y / (double)h; + } + if ((!gc->new_gcc->config.size_w) && (!gc->new_gcc->config.size_h)) + { + evas_object_geometry_get(gcc->o_frame ?: gcc->o_base, NULL, NULL, &gw, &gh); + gc->new_gcc->config.size_w = (double)gw / (double)w; + gc->new_gcc->config.size_h = (double)gh / (double)h; + } + else + { + gw = gc->new_gcc->config.size_w * w; + gh = gc->new_gcc->config.size_h * h; + } evas_object_resize(gc->new_gcc->o_base, gw, gh); evas_object_move(gc->new_gcc->o_base, ev->x, ev->y); } @@ -2968,11 +2990,12 @@ _e_gadcon_cb_drop(void *data, const char *type __UNUSED__, void *event __UNUSED_ gc = data; //INF("DND DROP"); + gc->cf->clients = eina_list_append(gc->cf->clients, gc->drag_gcc->cf); /* still has refcount from drag */ + if (!gc->new_gcc) return; e_object_del(E_OBJECT(gc->drag_gcc)); gcc = gc->new_gcc; - gc->cf->clients = eina_list_append(gc->cf->clients, gcc->cf); if (!gc->o_container) { /* FIXME: gadman sucks and should probably use a regular gadcon layout, but it doesn't diff --git a/src/bin/e_gadcon.h b/src/bin/e_gadcon.h index 6a6125525..53b4bfc16 100644 --- a/src/bin/e_gadcon.h +++ b/src/bin/e_gadcon.h @@ -353,6 +353,8 @@ EAPI void e_gadcon_location_register(E_Gadcon_Location *loc); EAPI void e_gadcon_location_unregister(E_Gadcon_Location *loc); EAPI void e_gadcon_location_set_icon_name(E_Gadcon_Location *loc, const char *name); EAPI void e_gadcon_client_add_location_menu(E_Gadcon_Client *gcc, E_Menu *menu); +EAPI void e_gadcon_drag_finished_cb(E_Drag *drag, int dropped); +EAPI void e_gadcon_client_drag_set(E_Gadcon_Client *gcc); #define GADCON_CLIENT_CONFIG_GET(_type, _items, _gc_class, _id) \ if (!_id) \ diff --git a/src/modules/gadman/e_mod_gadman.c b/src/modules/gadman/e_mod_gadman.c index 7ca06930e..66dad7987 100644 --- a/src/modules/gadman/e_mod_gadman.c +++ b/src/modules/gadman/e_mod_gadman.c @@ -64,7 +64,8 @@ gadman_reset(void) unsigned int layer; const Eina_List *l; E_Zone *zone; - + + E_FREE_LIST(Man->drag_handlers, ecore_event_handler_del); for (layer = 0; layer < GADMAN_LAYER_COUNT; layer++) { EINA_LIST_FREE(Man->gadcons[layer], gc) @@ -177,6 +178,7 @@ gadman_shutdown(void) eina_hash_free_cb_set(_gadman_gadgets, EINA_FREE_CB(eina_list_free)); eina_hash_free(_gadman_gadgets); } + E_FREE_LIST(Man->drag_handlers, ecore_event_handler_del); _gadman_gadgets = NULL; free(Man); Man = NULL; @@ -390,9 +392,11 @@ gadman_gadget_edit_start(E_Gadcon_Client *gcc) { E_Gadcon *gc; Evas_Object *mover; - Eina_List *l; int x, y, w, h; + /* this gets an unref in e_gadcon_drag_finished_cb() */ + e_object_ref(E_OBJECT(gcc)); + gc = gcc->gadcon; gc->editing = 1; @@ -405,10 +409,10 @@ gadman_gadget_edit_start(E_Gadcon_Client *gcc) evas_object_resize(mover, w, h); evas_object_raise(mover); evas_object_show(mover); + gcc->gadcon->cf->clients = eina_list_remove(gcc->gadcon->cf->clients, gcc->cf); evas_object_event_callback_del(mover, EVAS_CALLBACK_HIDE, gadman_edit); evas_object_event_callback_add(mover, EVAS_CALLBACK_HIDE, gadman_edit, gcc); - EINA_LIST_FOREACH(Man->gadcons[gcc->gadcon->id - ID_GADMAN_LAYER_BASE], l, gc) - gc->drag_gcc = gcc; + e_gadcon_client_drag_set(gcc); } void @@ -429,10 +433,9 @@ gadman_gadget_edit_end(void *data __UNUSED__, Evas_Object *obj __UNUSED__, const { gc->editing = 0; drag_gcc = gc->drag_gcc; - gc->drag_gcc = NULL; } } - + e_gadcon_client_drag_set(NULL); if (drag_gcc) _save_widget_position(drag_gcc); } @@ -793,6 +796,8 @@ _save_widget_position(E_Gadcon_Client *gcc) { int x, y, w, h; + if (!gcc->cf) return; + evas_object_geometry_get(gcc->o_frame, &x, &y, &w, &h); gcc->config.pos_x = gcc->cf->geom.pos_x = (double)x / (double)gcc->gadcon->zone->w; gcc->config.pos_y = gcc->cf->geom.pos_y = (double)y / (double)gcc->gadcon->zone->h; @@ -1419,6 +1424,70 @@ on_left(void *data, Evas_Object *o __UNUSED__, const char *em __UNUSED__, const } } +static Eina_Bool +_on_mouse_up_cb(void *data, int type __UNUSED__, void *event) +{ + E_Gadcon_Client *gcc = data; + Ecore_Event_Mouse_Button *ev = event; + E_Config_Gadcon_Client *cf; + E_Zone *dst_zone = NULL; + E_Gadcon *dst_gadcon; + int gx, gy; + + if (ev->buttons != 1) return ECORE_CALLBACK_RENEW; + + gcc->moving = 0; + gcc->dx = gcc->dy = 0; + + /* checking if zone was changed for dragged gadget */ + evas_object_geometry_get(gcc->o_frame, &gx, &gy, NULL, NULL); + dst_zone = e_container_zone_at_point_get(e_container_current_get(e_manager_current_get()), gx, gy); + if (dst_zone && (gcc->gadcon->zone != dst_zone)) + { + unsigned int layer = gcc->gadcon->id - ID_GADMAN_LAYER_BASE; + cf = gcc->cf; + + gcc->gadcon->cf->clients = eina_list_remove(gcc->gadcon->cf->clients, cf); + dst_gadcon = gadman_gadcon_get(dst_zone, layer); + if (dst_gadcon) + { + dst_gadcon->cf->clients = eina_list_append(dst_gadcon->cf->clients, cf); + e_config_save_queue(); + } + } + else + _save_widget_position(gcc); + E_FREE_LIST(Man->drag_handlers, ecore_event_handler_del); + return ECORE_CALLBACK_RENEW; +} + +static Eina_Bool +_on_move_cb(void *data, int type __UNUSED__, void *event) +{ + Ecore_Event_Mouse_Move *ev = event; + E_Gadcon_Client *gcc = data; + Evas_Object *mover; + int x, y; + int ox, oy, ow, oh; + + mover = _get_mover(gcc); + evas_object_geometry_get(mover, &ox, &oy, &ow, &oh); + + x = ev->x - gcc->dx; + y = ev->y - gcc->dy; + /* don't go out of the screen */ + if (x < 0) x = 0; + if (x > (Man->width - ow)) x = Man->width - ow; + if (y < 0) y = 0; + if (y > (Man->height - oh)) y = Man->height - oh; + + evas_object_move(gcc->o_frame, x, y); + evas_object_move(mover, x, y); + evas_object_raise(gcc->o_frame); + evas_object_raise(mover); + return ECORE_CALLBACK_RENEW; +} + static void on_move(void *data, Evas_Object *o __UNUSED__, const char *em __UNUSED__, const char *src __UNUSED__) { @@ -1436,6 +1505,9 @@ on_move(void *data, Evas_Object *o __UNUSED__, const char *em __UNUSED__, const /* DRAG_START */ if (action == DRAG_START) { + E_Drag *drag; + const char *drag_types[] = { "enlightenment/gadcon_client" }; + gc->drag_gcc->moving = 1; evas_pointer_output_xy_get(gc->drag_gcc->gadcon->evas, &mx, &my); evas_object_geometry_get(mover, &ox, &oy, &ow, &oh); @@ -1443,6 +1515,26 @@ on_move(void *data, Evas_Object *o __UNUSED__, const char *em __UNUSED__, const gc->drag_gcc->dx = mx - ox; gc->drag_gcc->dy = my - oy; + gc->drag_gcc->drag.drag = drag = e_drag_new(gc->drag_gcc->gadcon->zone->container, mx, my, + drag_types, 1, gc->drag_gcc, -1, NULL, + e_gadcon_drag_finished_cb); + if (!drag) return; + + o = gc->drag_gcc->client_class->func.icon((E_Gadcon_Client_Class *)gc->drag_gcc->client_class, + e_drag_evas_get(drag)); + if (!o) + { + /* FIXME: fallback icon for drag */ + o = evas_object_rectangle_add(e_drag_evas_get(drag)); + evas_object_color_set(o, 255, 255, 255, 100); + } + + E_LIST_HANDLERS_APPEND(Man->drag_handlers, ECORE_EVENT_MOUSE_MOVE, _on_move_cb, gc->drag_gcc); + E_LIST_HANDLERS_APPEND(Man->drag_handlers, ECORE_EVENT_MOUSE_BUTTON_UP, _on_mouse_up_cb, gc->drag_gcc); + e_drag_object_set(drag, o); + e_drag_resize(drag, ow, oh); + evas_object_hide(o); + e_drag_start(drag, mx, my); return; } @@ -1487,7 +1579,6 @@ on_move(void *data, Evas_Object *o __UNUSED__, const char *em __UNUSED__, const x = mx - gc->drag_gcc->dx; y = my - gc->drag_gcc->dy; - /* don't go out of the screen */ if (x < 0) x = 0; if (x > (Man->width - ow)) x = Man->width - ow; diff --git a/src/modules/gadman/e_mod_gadman.h b/src/modules/gadman/e_mod_gadman.h index 5c2455277..8a9240781 100644 --- a/src/modules/gadman/e_mod_gadman.h +++ b/src/modules/gadman/e_mod_gadman.h @@ -51,6 +51,8 @@ struct _Manager Evas_Object *movers[GADMAN_LAYER_COUNT]; Evas_Object *full_bg; const char *icon_name; + + Eina_List *drag_handlers; int visible; int use_composite;