From 5f9a3d1a4f7af0331b5013c4faa575322f72c27c Mon Sep 17 00:00:00 2001 From: rephorm Date: Wed, 29 Mar 2006 00:35:16 +0000 Subject: [PATCH] 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 --- data/themes/default_pager.edc | 1 - src/bin/e_layout.c | 36 +++++ src/bin/e_layout.h | 5 + src/modules/pager/e_mod_config.c | 7 + src/modules/pager/e_mod_main.c | 255 ++++++++++++++++++++++++++----- src/modules/pager/e_mod_main.h | 4 + 6 files changed, 268 insertions(+), 40 deletions(-) diff --git a/data/themes/default_pager.edc b/data/themes/default_pager.edc index ee4bb48b7..7542ba38b 100644 --- a/data/themes/default_pager.edc +++ b/data/themes/default_pager.edc @@ -713,7 +713,6 @@ group { parts { part { name: "overlay"; - mouse_events: 0; description { state: "default" 0.0; rel1 { diff --git a/src/bin/e_layout.c b/src/bin/e_layout.c index 5ddc9d698..f01d7ad1c 100644 --- a/src/bin/e_layout.c +++ b/src/bin/e_layout.c @@ -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) { diff --git a/src/bin/e_layout.h b/src/bin/e_layout.h index de02326e6..2ea9cf5ab 100644 --- a/src/bin/e_layout.h +++ b/src/bin/e_layout.h @@ -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 diff --git a/src/modules/pager/e_mod_config.c b/src/modules/pager/e_mod_config.c index 327889a11..236b2b011 100644 --- a/src/modules/pager/e_mod_config.c +++ b/src/modules/pager/e_mod_config.c @@ -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(); diff --git a/src/modules/pager/e_mod_main.c b/src/modules/pager/e_mod_main.c index 3c30a8d5c..5d0ec2df7 100644 --- a/src/modules/pager/e_mod_main.c +++ b/src/modules/pager/e_mod_main.c @@ -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 diff --git a/src/modules/pager/e_mod_main.h b/src/modules/pager/e_mod_main.h index 55785c545..b04b8f0e9 100644 --- a/src/modules/pager/e_mod_main.h +++ b/src/modules/pager/e_mod_main.h @@ -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; };