better pager dragging

* drag windows around within pager
  * dnd when going outside of the pager
  * window placed at location in pager of drop
  * window centered under mouse when dropped off of pager


I'm not sure yet to do with original window when dragging off the pager. Right now it stays at last "on pager" location, which is a bit ugly. Should it jump back to the original position? Or disappear entirely?


SVN revision: 21555
This commit is contained in:
rephorm 2006-03-29 00:35:16 +00:00 committed by rephorm
parent 57628bfbee
commit 5f9a3d1a4f
6 changed files with 268 additions and 40 deletions

View File

@ -713,7 +713,6 @@ group {
parts {
part {
name: "overlay";
mouse_events: 0;
description {
state: "default" 0.0;
rel1 {

View File

@ -102,6 +102,28 @@ e_layout_virtual_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h)
if (h) *h = sd->vh;
}
EAPI void
e_layout_coord_canvas_to_virtual(Evas_Object *obj, Evas_Coord cx, Evas_Coord cy, Evas_Coord *vx, Evas_Coord *vy)
{
E_Smart_Data *sd;
sd = evas_object_smart_data_get(obj);
if (vx) *vx = (cx - sd->x) * ((double)(sd->vw) / sd->w);
if (vy) *vy = (cy - sd->y) * ((double)(sd->vh) / sd->h);
}
EAPI void
e_layout_coord_virtual_to_canvas(Evas_Object *obj, Evas_Coord vx, Evas_Coord vy, Evas_Coord *cx, Evas_Coord *cy)
{
E_Smart_Data *sd;
sd = evas_object_smart_data_get(obj);
if (cx) *cx = vx * ((double)(sd->w) / sd->vw) + sd->x;
if (cy) *cy = vy * ((double)(sd->h) / sd->vh) + sd->y;
}
EAPI void
e_layout_pack(Evas_Object *obj, Evas_Object *child)
{
@ -209,6 +231,20 @@ e_layout_child_raise_above(Evas_Object *obj, Evas_Object *above)
}
}
EAPI void
e_layout_child_geometry_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
{
E_Layout_Item *li;
li = evas_object_data_get(obj, "e_layout_data");
if (!li) return;
if (x) *x = li->x;
if (y) *y = li->y;
if (w) *w = li->w;
if (h) *h = li->h;
}
EAPI void
e_layout_unpack(Evas_Object *obj)
{

View File

@ -11,6 +11,10 @@ EAPI int e_layout_freeze (Evas_Object *obj);
EAPI int e_layout_thaw (Evas_Object *obj);
EAPI void e_layout_virtual_size_set (Evas_Object *obj, Evas_Coord w, Evas_Coord h);
EAPI void e_layout_virtual_size_get (Evas_Object *obj, Evas_Coord *w, Evas_Coord *h);
EAPI void e_layout_coord_canvas_to_virtual (Evas_Object *obj, Evas_Coord cx, Evas_Coord cy, Evas_Coord *vx, Evas_Coord *vy);
EAPI void e_layout_coord_virtual_to_canvas (Evas_Object *obj, Evas_Coord vx, Evas_Coord vy, Evas_Coord *cx, Evas_Coord *cy);
EAPI void e_layout_pack (Evas_Object *obj, Evas_Object *child);
EAPI void e_layout_child_move (Evas_Object *obj, Evas_Coord x, Evas_Coord y);
EAPI void e_layout_child_resize (Evas_Object *obj, Evas_Coord w, Evas_Coord h);
@ -18,6 +22,7 @@ EAPI void e_layout_child_raise (Evas_Object *obj);
EAPI void e_layout_child_lower (Evas_Object *obj);
EAPI void e_layout_child_raise_above (Evas_Object *obj, Evas_Object *above);
EAPI void e_layout_child_lower_below (Evas_Object *obj, Evas_Object *below);
EAPI void e_layout_child_geometry_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h);
EAPI void e_layout_unpack (Evas_Object *obj);
#endif

View File

@ -9,6 +9,7 @@ struct _E_Config_Dialog_Data
int name_pos;
int show_popup;
double popup_speed;
int drag_resist;
};
/* Protos */
@ -55,6 +56,7 @@ _fill_data(Pager *p, E_Config_Dialog_Data *cfdata)
cfdata->show_popup = p->conf->popup;
cfdata->popup_speed = p->conf->popup_speed;
cfdata->drag_resist = p->conf->drag_resist;
}
static void *
@ -141,6 +143,10 @@ _advanced_create_widgets(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data
e_widget_framelist_object_append(of, ob);
ob = e_widget_check_add(evas, _("Show Desktop Name"), &(cfdata->show_name));
e_widget_framelist_object_append(of, ob);
ob = e_widget_label_add(evas, _("Resistance to Dragging Windows:"));
e_widget_framelist_object_append(of, ob);
ob = e_widget_slider_add(evas, 1, 0, _("%.0f px"), 0.0, 10.0, 1.0, 0, NULL, &(cfdata->drag_resist), 200);
e_widget_framelist_object_append(of, ob);
e_widget_list_object_append(o, of, 1, 1, 0.5);
of = e_widget_framelist_add(evas, _("Desktop Name Position"), 0);
@ -181,6 +187,7 @@ _advanced_apply_data(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata)
if (!cfdata->show_name)
p->conf->deskname_pos = PAGER_DESKNAME_NONE;
p->conf->popup_speed = cfdata->popup_speed;
p->conf->drag_resist = cfdata->drag_resist;
e_border_button_bindings_grab_all();
e_config_save_queue();

View File

@ -34,6 +34,7 @@ static void _pager_window_move(Pager_Face *face, Pager_Win *pw);
static Pager_Win *_pager_face_border_find(Pager_Face *face, E_Border *border);
static Pager_Win *_pager_desk_border_find(Pager_Desk *pd, E_Border *border);
static Pager_Desk *_pager_face_desk_find(Pager_Face *face, E_Desk *desk);
static Pager_Desk *_pager_face_desk_at_coord(Pager_Face *face, Evas_Coord x, Evas_Coord y);
static void _pager_face_desk_select(Pager_Desk *pd);
static void _pager_popup_free(Pager_Popup *pp);
@ -223,6 +224,7 @@ _pager_new(void)
E_CONFIG_VAL(D, T, deskname_pos, UINT);
E_CONFIG_VAL(D, T, popup_speed, DOUBLE);
E_CONFIG_VAL(D, T, popup, UINT);
E_CONFIG_VAL(D, T, drag_resist, UINT);
pager->conf = e_config_domain_load("module.pager", _conf_edd);
@ -232,6 +234,7 @@ _pager_new(void)
pager->conf->deskname_pos = PAGER_DESKNAME_NONE;
pager->conf->popup_speed = 1.0;
pager->conf->popup = 1;
pager->conf->drag_resist = 3;
}
E_CONFIG_LIMIT(pager->conf->deskname_pos, PAGER_DESKNAME_NONE, PAGER_DESKNAME_RIGHT);
E_CONFIG_LIMIT(pager->conf->popup_speed, 0.1, 10.0);
@ -830,6 +833,29 @@ _pager_face_desk_find(Pager_Face *face, E_Desk *desk)
return NULL;
}
/**
* Return Pager_Desk at canvas coord x, y
*/
static Pager_Desk *
_pager_face_desk_at_coord(Pager_Face *face, Evas_Coord x, Evas_Coord y)
{
Evas_List *l;
for (l = face->desks; l; l = l->next)
{
Pager_Desk *pd;
Evas_Coord dx, dy, dw, dh;
pd = l->data;
evas_object_geometry_get(pd->desk_object, &dx, &dy, &dw, &dh);
if (E_INSIDE(x, y, dx, dy, dw, dh))
{
return pd;
}
}
return NULL;
}
static void
_pager_face_desk_select(Pager_Desk *pd)
{
@ -1784,9 +1810,16 @@ _pager_window_cb_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_i
/* make this configurable */
if (ev->button == 1)
{
Evas_Coord ox, oy;
evas_object_geometry_get(pw->window_object, &ox, &oy, NULL, NULL);
pw->drag.in_pager = 1;
pw->drag.x = ev->canvas.x;
pw->drag.y = ev->canvas.y;
pw->drag.dx = ox - ev->canvas.x;
pw->drag.dy = oy - ev->canvas.y;
pw->drag.start = 1;
pw->drag.x = -1;
pw->drag.y = -1;
}
}
@ -1800,7 +1833,9 @@ _pager_window_cb_mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_inf
pw = data;
if (!pw) return;
pw->drag.in_pager = 0;
pw->drag.start = 0;
pw->desk->face->dragging = 0;
}
static void
@ -1813,9 +1848,92 @@ _pager_window_cb_mouse_move(void *data, Evas *e, Evas_Object *obj, void *event_i
pw = data;
if (!pw) return;
/* prevent drag for a few pixels */
if (pw->drag.start)
{
#if 1
Evas_Coord dx, dy;
unsigned int resist = 0;
dx = pw->drag.x - ev->cur.output.x;
dy = pw->drag.y - ev->cur.output.y;
if (pw->desk && pw->desk->face && pw->desk->face->pager)
resist = pw->desk->face->pager->conf->drag_resist;
if (((dx * dx) + (dy * dy)) <= (resist * resist)) return;
pw->desk->face->dragging = 1;
pw->drag.start = 0;
}
/* dragging this win around inside the pager */
if (pw->drag.in_pager)
{
Evas_Coord mx, my, vx, vy;
Pager_Desk *desk;
/* m for mouse */
mx = ev->cur.canvas.x;
my = ev->cur.canvas.y;
/* find desk at pointer */
desk = _pager_face_desk_at_coord(pw->desk->face, mx, my);
if (desk)
{
e_layout_coord_canvas_to_virtual(desk->layout_object, mx + pw->drag.dx, my + pw->drag.dy, &vx, &vy);
if (desk != pw->desk) e_border_desk_set(pw->border, desk->desk);
e_border_move(pw->border, vx + desk->desk->zone->x, vy + desk->desk->zone->y);
}
else
{
/* not over a desk, start dnd drag */
if (pw->window_object)
{
E_Drag *drag;
Evas_Object *o, *oo;
Evas_Coord x, y, w, h;
const char *file, *part;
const char *drag_types[] = { "enlightenment/pager_win" };
evas_object_geometry_get(pw->window_object,
&x, &y, &w, &h);
/* XXX this relies on screen and canvas coords matching. is this a valid assumption? */
drag = e_drag_new(pw->desk->face->zone->container, x, y,
drag_types, 1, pw, -1,
_pager_window_cb_drag_finished);
o = edje_object_add(drag->evas);
edje_object_file_get(pw->window_object, &file, &part);
edje_object_file_set(o, file, part);
oo = o;
o = edje_object_add(drag->evas);
edje_object_file_get(pw->icon_object, &file, &part);
edje_object_file_set(o, file, part);
edje_object_part_swallow(oo, "icon", o);
e_drag_object_set(drag, oo);
e_drag_resize(drag, w, h);
e_drag_start(drag, x - pw->drag.dx, y - pw->drag.dy);
/* this prevents the desk from switching on drags */
pw->drag.from_face = pw->desk->face;
pw->drag.from_face->dragging = 1;
evas_event_feed_mouse_up(pw->desk->face->evas, 1,
EVAS_BUTTON_NONE, ecore_time_get(), NULL);
}
pw->drag.in_pager = 0;
}
}
#if 0
{
// printf("DRAG: %d\n", pw);
if ((pw->drag.x == -1) && (pw->drag.y == -1))
{
@ -1873,9 +1991,8 @@ _pager_window_cb_mouse_move(void *data, Evas *e, Evas_Object *obj, void *event_i
}
}
#endif
}
#endif
}
static void
@ -1885,7 +2002,55 @@ _pager_window_cb_drag_finished(E_Drag *drag, int dropped)
pw = drag->data;
if (pw && pw->desk && pw->desk->face)
if (!pw) return;
if (!dropped)
{
/* wasn't dropped (on pager). move it to position of mouse on screen */
int x, y, dx, dy;
E_Container *cont;
E_Zone *zone;
E_Desk *desk;
cont = e_container_current_get(e_manager_current_get());
zone = e_zone_current_get(cont);
desk = e_desk_current_get(zone);
e_border_zone_set(pw->border, zone);
e_border_desk_set(pw->border, desk);
ecore_x_pointer_last_xy_get(&x, &y);
x = x + zone->x;
y = y + zone->y;
dx = (pw->border->w / 2);
dy = (pw->border->h / 2);
/* offset so that center of window is on mouse, but keep within desk bounds */
if (dx < x)
{
x -= dx;
if ((pw->border->w < zone->w) && (x + pw->border->w > zone->x + zone->w))
{
x -= x + pw->border->w - (zone->x + zone->w);
}
}
else x = 0;
if (dy < y)
{
y -= dy;
if ((pw->border->h < zone->h) && (y + pw->border->h > zone->y + zone->h))
{
y -= y + pw->border->h - (zone->y + zone->h);
}
}
else y = 0;
e_border_move(pw->border, x, y);
}
if (pw && pw->drag.from_face)
{
pw->drag.from_face->dragging = 0;
}
@ -2011,48 +2176,60 @@ _pager_face_cb_drop(void *data, const char *type, void *event_info)
{
E_Event_Dnd_Drop *ev;
Pager_Face *face;
E_Desk *desk;
Pager_Desk *desk;
E_Border *bd;
Evas_List *l;
int x, y;
double w, h;
int dx = 0, dy = 0;
ev = event_info;
face = data;
w = (face->fw - (face->inset.l + face->inset.r)) / (double) face->xnum;
h = (face->fh - (face->inset.t + face->inset.b)) / (double) face->ynum;
x = (ev->x - (face->fx + face->inset.l)) / w;
y = (ev->y - (face->fy + face->inset.t)) / h;
desk = e_desk_at_xy_get(face->zone, x, y);
if (!strcmp(type, "enlightenment/pager_win"))
/* XXX convert screen -> evas coords? */
desk = _pager_face_desk_at_coord(face, ev->x, ev->y);
if (desk)
{
bd = ((Pager_Win *)(ev->data))->border;
}
else if (!strcmp(type, "enlightenment/border"))
{
bd = ev->data;
}
else
{
return;
if (!strcmp(type, "enlightenment/pager_win"))
{
Pager_Win *pw;
pw = (Pager_Win *)(ev->data);
if (pw)
{
bd = pw->border;
dx = pw->drag.dx;
dy = pw->drag.dy;
}
}
else if (!strcmp(type, "enlightenment/border"))
{
Evas_Coord wx, wy, wx2, wy2;
bd = ev->data;
e_layout_coord_virtual_to_canvas(desk->layout_object, bd->x, bd->y, &wx, &wy);
e_layout_coord_virtual_to_canvas(desk->layout_object, bd->x + bd->w, bd->y + bd->h, &wx2, &wy2);
dx = (wx - wx2) / 2;
dy = (wy - wy2) / 2;
}
else
{
return;
}
if ((bd) && (desk))
{
Evas_Coord nx, ny;
e_border_desk_set(bd, desk->desk);
e_layout_coord_canvas_to_virtual(desk->layout_object, ev->x + dx, ev->y + dy, &nx, &ny);
e_border_move(bd, nx + desk->desk->zone->x, ny + desk->desk->zone->y);
}
}
if ((bd) && (desk))
{
e_border_desk_set(bd, desk);
}
for (l = face->desks; l; l = l->next)
{
Pager_Desk *pd;
pd = l->data;
edje_object_signal_emit(pd->desk_object, "drag", "out");
}
for (l = face->desks; l; l = l->next)
{
Pager_Desk *pd;
pd = l->data;
edje_object_signal_emit(pd->desk_object, "drag", "out");
}
}
static void

View File

@ -33,6 +33,7 @@ struct _Config
/* Show popup? */
unsigned int popup;
unsigned int drag_resist;
};
struct _Config_Face
@ -130,7 +131,10 @@ struct _Pager_Win
struct {
Pager_Face *from_face;
unsigned char start : 1;
unsigned char in_pager : 1;
unsigned char dnd : 1;
int x, y;
int dx, dy;
} drag;
};