From 3f2e8502594afaf84fe21b613c7825fea0219579 Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Thu, 1 Aug 2013 08:16:39 +0100 Subject: [PATCH] Big giant Monitor Snapping Fix when we resize or move !! ;) - 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 --- src/modules/conf_randr/e_smart_monitor.c | 50 ++++++++++++++- src/modules/conf_randr/e_smart_randr.c | 79 +++++++++--------------- 2 files changed, 78 insertions(+), 51 deletions(-) diff --git a/src/modules/conf_randr/e_smart_monitor.c b/src/modules/conf_randr/e_smart_monitor.c index 8814fbffe..f6e399e4a 100644 --- a/src/modules/conf_randr/e_smart_monitor.c +++ b/src/modules/conf_randr/e_smart_monitor.c @@ -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(); @@ -510,6 +520,22 @@ e_smart_monitor_current_geometry_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord if (h) *h = sd->current.h; } +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) { @@ -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); diff --git a/src/modules/conf_randr/e_smart_randr.c b/src/modules/conf_randr/e_smart_randr.c index 52572830d..7acc4f357 100644 --- a/src/modules/conf_randr/e_smart_randr.c +++ b/src/modules/conf_randr/e_smart_randr.c @@ -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); } } }