better pager dragging
authorrephorm <rephorm>
Wed, 29 Mar 2006 00:35:16 +0000 (00:35 +0000)
committerrephorm <rephorm@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Wed, 29 Mar 2006 00:35:16 +0000 (00:35 +0000)
  * 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
src/bin/e_layout.c
src/bin/e_layout.h
src/modules/pager/e_mod_config.c
src/modules/pager/e_mod_main.c
src/modules/pager/e_mod_main.h

index ee4bb48..7542ba3 100644 (file)
@@ -713,7 +713,6 @@ group {
    parts {
       part {
         name:          "overlay";
-        mouse_events:  0;
         description {
            state:    "default" 0.0;
            rel1 {
index 5ddc9d6..f01d7ad 100644 (file)
@@ -103,6 +103,28 @@ 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)
+{
+   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)
 {
    E_Smart_Data *sd;
@@ -210,6 +232,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)
 {
    E_Layout_Item *li;
index de02326..2ea9cf5 100644 (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
index 327889a..236b2b0 100644 (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();
index 3c30a8d..5d0ec2d 100644 (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);
+   /* XXX convert screen -> evas coords? */ 
+   desk = _pager_face_desk_at_coord(face, ev->x, ev->y);
+   if (desk)
+     {
+       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);
 
-   if (!strcmp(type, "enlightenment/pager_win"))
-     {
-       bd = ((Pager_Win *)(ev->data))->border;
-     }
-   else if (!strcmp(type, "enlightenment/border"))
-     {
-       bd = ev->data;
-     }
-   else
-     {
-       return;
-     }
+            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
index 55785c5..b04b8f0 100644 (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;
 };