with massive hacks and huge other hacks, it's finally possible to seamlessly drag icons from the desktop to a shelf and vice versa

ticket #113


SVN revision: 76765
This commit is contained in:
Mike Blumenkrantz 2012-09-17 14:49:48 +00:00
parent 3f9ccd5176
commit 03dda786da
4 changed files with 162 additions and 44 deletions

View File

@ -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

View File

@ -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) \

View File

@ -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;

View File

@ -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;