Big giant Monitor Snapping Fix when we resize or move !! ;)
authorChris Michael <cp.michael@samsung.com>
Thu, 1 Aug 2013 07:16:39 +0000 (08:16 +0100)
committerChris Michael <cp.michael@samsung.com>
Thu, 1 Aug 2013 07:25:09 +0000 (08:25 +0100)
- Add previous monitor geometry to smart data structure.
- When we set the crtc, also set the monitor current geometry.
- Add function to return the previous monitor geometry.
- On a mouse up, check for monitor location difference versus previous
geometry, if nothing changed then we have no 'move' to do.
- When we start a resize, record the previous geometry and raise the
monitor.
- When a monitor is moved/resized we call the position_update function
which already loops all monitors, so no need to loop them twice.
- Fix position_update function to allow some Snapping Fuzziness so
that on a move/resize any adjoining monitors (within tolerance) will
more reliably snap to each other.

Signed-off-by: Chris Michael <cp.michael@samsung.com>
src/modules/conf_randr/e_smart_monitor.c
src/modules/conf_randr/e_smart_randr.c

index 8814fbf..f6e399e 100644 (file)
@@ -106,6 +106,11 @@ struct _E_Smart_Data
         Eina_Bool enabled : 1;
      } current;
 
+   struct 
+     {
+        Evas_Coord x, y, w, h;
+     } prev;
+
    /* visibility flag */
    Eina_Bool visible : 1;
 
@@ -236,6 +241,11 @@ e_smart_monitor_crtc_set(Evas_Object *obj, Ecore_X_Randr_Crtc crtc, Evas_Coord c
    sd->crtc.w = cw;
    sd->crtc.h = ch;
 
+   sd->current.x = cx;
+   sd->current.y = cy;
+   sd->current.w = cw;
+   sd->current.h = ch;
+
    /* get the root window */
    root = ecore_x_window_root_first_get();
 
@@ -511,6 +521,22 @@ e_smart_monitor_current_geometry_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord
 }
 
 void 
+e_smart_monitor_previous_geometry_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
+{
+   E_Smart_Data *sd;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+   /* try to get the objects smart data */
+   if (!(sd = evas_object_smart_data_get(obj))) return;
+
+   if (x) *x = sd->prev.x;
+   if (y) *y = sd->prev.y;
+   if (w) *w = sd->prev.w;
+   if (h) *h = sd->prev.h;
+}
+
+void 
 e_smart_monitor_clone_set(Evas_Object *obj, Evas_Object *parent)
 {
    E_Smart_Data *sd, *psd = NULL;
@@ -1600,6 +1626,10 @@ _e_smart_monitor_thumb_cb_mouse_up(void *data, Evas *evas EINA_UNUSED, Evas_Obje
    /* reset mouse pointer */
    _e_smart_monitor_pointer_pop(obj, "move");
 
+   if ((sd->current.x == sd->prev.x) && 
+       (sd->current.y == sd->prev.y)) 
+     return;
+
    /* any objects below this monitor ? */
    if ((below = evas_object_below_get(mon)))
      {
@@ -1688,8 +1718,8 @@ _e_smart_monitor_thumb_cb_mouse_down(void *data, Evas *evas EINA_UNUSED, Evas_Ob
 
    /* record current size of monitor */
    evas_object_grid_pack_get(sd->grid.obj, mon, 
-                             &sd->current.x, &sd->current.y, 
-                             &sd->current.w, &sd->current.h);
+                             &sd->prev.x, &sd->prev.y, 
+                             &sd->prev.w, &sd->prev.h);
 
    /* raise the monitor */
    evas_object_raise(mon);
@@ -1797,8 +1827,16 @@ _e_smart_monitor_frame_cb_resize_start(void *data, Evas_Object *obj EINA_UNUSED,
                              &sd->current.x, &sd->current.y, 
                              &sd->current.w, &sd->current.h);
 
+   sd->prev.x = sd->current.x;
+   sd->prev.y = sd->current.y;
+   sd->prev.w = sd->current.w;
+   sd->prev.h = sd->current.h;
+
    /* set resizing flag */
    sd->resizing = EINA_TRUE;
+
+   /* raise the monitor */
+   evas_object_raise(mon);
 }
 
 static void 
@@ -1853,6 +1891,11 @@ _e_smart_monitor_frame_cb_rotate_start(void *data, Evas_Object *obj EINA_UNUSED,
                              &sd->current.x, &sd->current.y, 
                              &sd->current.w, &sd->current.h);
 
+   sd->prev.x = sd->current.x;
+   sd->prev.y = sd->current.y;
+   sd->prev.w = sd->current.w;
+   sd->prev.h = sd->current.h;
+
    /* set resizing flag */
    sd->rotating = EINA_TRUE;
 }
@@ -2234,6 +2277,9 @@ _e_smart_monitor_move_event(E_Smart_Data *sd, Evas_Object *mon, void *event)
    /* take current object position, translate to virtual */
    _e_smart_monitor_coord_canvas_to_virtual(sd, nx, ny, &px, &py);
 
+   sd->current.x = px;
+   sd->current.y = py;
+
    /* set monitor position text */
    _e_smart_monitor_position_set(sd, px, py);
 
index 5257283..7acc4f3 100644 (file)
@@ -3,6 +3,8 @@
 #include "e_smart_randr.h"
 #include "e_smart_monitor.h"
 
+#define SNAP_FUZZ 100
+
 /*
  * TODO:
  * 
@@ -653,11 +655,10 @@ _e_smart_randr_monitor_cb_changed(void *data, Evas_Object *obj EINA_UNUSED, void
 }
 
 static void 
-_e_smart_randr_monitor_cb_moved(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
+_e_smart_randr_monitor_cb_moved(void *data, Evas_Object *obj, void *event EINA_UNUSED)
 {
    E_Smart_Data *sd;
-   Evas_Object *randr, *mon;
-   Eina_List *l = NULL;
+   Evas_Object *randr;
 
    if (!(randr = data)) return;
 
@@ -671,18 +672,7 @@ _e_smart_randr_monitor_cb_moved(void *data, Evas_Object *obj EINA_UNUSED, void *
    /* move any monitors which are adjacent to this one to their new 
     * positions due to the resize, specifying this resized monitor as 
     * the one to skip */
-   _e_smart_randr_monitor_position_update(sd, randr, randr);
-
-   EINA_LIST_FOREACH(sd->monitors, l, mon)
-     {
-        /* skip the monitor which was currently resized */
-        if ((mon == randr)) continue;
-
-        /* move any monitors which are adjacent to this one to their new 
-         * positions due to the resize, specifying this resized monitor as 
-         * the one to skip */
-        _e_smart_randr_monitor_position_update(sd, mon, randr);
-     }
+   _e_smart_randr_monitor_position_update(sd, obj, obj);
 
    /* tell main dialog that something changed and to enable apply button */
    evas_object_smart_callback_call(randr, "randr_changed", NULL);
@@ -692,8 +682,7 @@ static void
 _e_smart_randr_monitor_cb_resized(void *data, Evas_Object *obj, void *event EINA_UNUSED)
 {
    E_Smart_Data *sd;
-   Evas_Object *randr, *mon;
-   Eina_List *l = NULL;
+   Evas_Object *randr;
 
    if (!(randr = data)) return;
 
@@ -705,17 +694,6 @@ _e_smart_randr_monitor_cb_resized(void *data, Evas_Object *obj, void *event EINA
     * the one to skip */
    _e_smart_randr_monitor_position_update(sd, obj, obj);
 
-   EINA_LIST_FOREACH(sd->monitors, l, mon)
-     {
-        /* skip the monitor which was currently resized */
-        if ((mon == obj)) continue;
-
-        /* move any monitors which are adjacent to this one to their new 
-         * positions due to the resize, specifying this resized monitor as 
-         * the one to skip */
-        _e_smart_randr_monitor_position_update(sd, mon, obj);
-     }
-
    /* tell main dialog that something changed and to enable apply button */
    evas_object_smart_callback_call(randr, "randr_changed", NULL);
 }
@@ -725,11 +703,13 @@ _e_smart_randr_monitor_position_update(E_Smart_Data *sd, Evas_Object *obj, Evas_
 {
    Eina_List *l = NULL;
    Evas_Object *mon;
-   Eina_Rectangle o;
+   Eina_Rectangle o, op;
 
    /* get the current geometry of the monitor we were passed in */
    e_smart_monitor_current_geometry_get(obj, &o.x, &o.y, &o.w, &o.h);
 
+   e_smart_monitor_previous_geometry_get(obj, &op.x, &op.y, &op.w, &op.h);
+
    /* loop the list of monitors */
    EINA_LIST_FOREACH(sd->monitors, l, mon)
      {
@@ -744,27 +724,28 @@ _e_smart_randr_monitor_position_update(E_Smart_Data *sd, Evas_Object *obj, Evas_
 
         /* check if this monitor is adjacent to the original one, 
          * if it is, then we need to move it */
-        if ((m.x == o.x) || (m.y == o.y))
+
+        /* check for any monitors that are on this X axis
+         * (within a certain threshold of distance) */
+        if ((m.x >= (op.x + (op.w / 3))) && 
+            (((m.x <= ((op.x + op.w) + SNAP_FUZZ)) || 
+              (m.x <= ((op.x + op.w) - SNAP_FUZZ)))))
           {
-             if ((m.x == o.x))
-               {
-                  if ((m.y >= o.y))
-                    {
-                       /* vertical positioning */
-                       e_smart_monitor_current_geometry_set(mon, m.x, 
-                                                            (o.y + o.h), 
-                                                            m.w, m.h);
-                    }
-               }
-             else if ((m.y == o.y))
-               {
-                  if ((m.x >= o.x))
-                    {
-                       /* horizontal positioning */
-                       e_smart_monitor_current_geometry_set(mon, (o.x + o.w),
-                                                            m.y, m.w, m.h);
-                    }
-               }
+             /* don't move the monitor IF this movement would place it 
+              * outside the virual grid */
+             if (((o.x + o.w) + m.w) <= sd->vw)
+               e_smart_monitor_current_geometry_set(mon, (o.x + o.w),
+                                                    m.y, m.w, m.h);
+          }
+        else if ((m.y >= (op.y + (op.h / 3))) && 
+                 (((m.y <= ((op.y + op.h) + SNAP_FUZZ)) || 
+                   (m.y <= ((op.y + op.h) - SNAP_FUZZ)))))
+          {
+             /* don't move the monitor IF this movement would place it 
+              * outside the virual grid */
+             if (((o.y + o.h) + m.h) <= sd->vh)
+               e_smart_monitor_current_geometry_set(mon, m.x, (o.y + o.h), 
+                                                    m.w, m.h);
           }
      }
 }