[gnome-control-center/wip/benzea/display: 49/49] display: Implement major/minor axis snapping and infinit for edges



commit 495b58976774b3216dc26f049bb2d6dee41eaaf9
Author: Benjamin Berg <bberg redhat com>
Date:   Wed Apr 25 18:16:26 2018 +0200

    display: Implement major/minor axis snapping and infinit for edges
    
    This improves the snapping behaviour in a number of ways. It allows
    increasing the snapping distance while still helping the user to align
    monitors by snapping a different distance for the minor axis. The patch
    also allows setting this distance to infinity so that we get the correct
    behaviour in the case of two monitors for the corners.

 panels/display/cc-display-arrangement.c | 99 ++++++++++++++++++++++-----------
 1 file changed, 68 insertions(+), 31 deletions(-)
---
diff --git a/panels/display/cc-display-arrangement.c b/panels/display/cc-display-arrangement.c
index e4f9fbe16..1d1d52170 100644
--- a/panels/display/cc-display-arrangement.c
+++ b/panels/display/cc-display-arrangement.c
@@ -43,7 +43,7 @@ struct _CcDisplayArrangement
   gdouble           drag_anchor_x;
   gdouble           drag_anchor_y;
 
-  guint             max_snap_distance;
+  guint             major_snap_distance;
 };
 
 typedef struct _CcDisplayArrangement CcDisplayArrangement;
@@ -72,7 +72,8 @@ struct SnapData {
 
 #define MARGIN_PX  0
 #define MARGIN_MON  0.66
-#define MAX_SNAP_DISTANCE 10
+#define MAJOR_SNAP_DISTANCE 25
+#define MINOR_SNAP_DISTANCE 5
 #define MIN_OVERLAP 25
 
 G_DEFINE_TYPE (CcDisplayArrangement, cc_display_arrangement, GTK_TYPE_DRAWING_AREA)
@@ -216,7 +217,9 @@ maybe_update_snap (CcDisplayArrangement *arr,
                   gint                  mon_y,
                   gint                  new_x,
                   gint                  new_y,
-                  gboolean              snapped)
+                  enum SnapDirection    snapped,
+                  enum SnapDirection    major_axis,
+                  gint                  minor_unlimited)
 {
   enum SnapDirection update_snap = SNAP_DIR_NONE;
   gdouble dist_x, dist_y;
@@ -225,18 +228,52 @@ maybe_update_snap (CcDisplayArrangement *arr,
   get_snap_distance (arr, mon_x, mon_y, new_x, new_y, &dist_x, &dist_y);
   dist = MAX (dist_x, dist_y);
 
-  if (dist > arr->max_snap_distance)
-    return;
+  /* Snap by the variable max snap distance on the major axis, ensure the
+   * minor axis is below the minimum snapping distance (often just zero). */
+  switch (major_axis)
+    {
+      case SNAP_DIR_X:
+        if (dist_x > arr->major_snap_distance)
+          return;
+        if (dist_y > MINOR_SNAP_DISTANCE)
+          {
+            if (new_y > mon_y && minor_unlimited <= 0)
+              return;
+            if (new_y < mon_y && minor_unlimited >= 0)
+              return;
+          }
+        break;
+
+      case SNAP_DIR_Y:
+        if (dist_y > arr->major_snap_distance)
+          return;
+        if (dist_x > MINOR_SNAP_DISTANCE)
+          {
+            if (new_x > mon_x && minor_unlimited <= 0)
+              return;
+            if (new_x < mon_x && minor_unlimited >= 0)
+              return;
+          }
+        break;
+
+      default:
+        g_assert_not_reached();
+    }
 
   if (snapped == SNAP_DIR_BOTH)
     {
       if (snap_data->snapped == SNAP_DIR_NONE)
         update_snap = SNAP_DIR_BOTH;
 
-      if (dist < MAX(snap_data->dist_x, snap_data->dist_y))
+      /* Update, if this is closer on the main axis. */
+      if (((major_axis == SNAP_DIR_X) && (dist_x < snap_data->dist_x)) ||
+          ((major_axis == SNAP_DIR_Y) && (dist_y < snap_data->dist_y)))
         update_snap = SNAP_DIR_BOTH;
 
-      if (dist == MAX(snap_data->dist_x, snap_data->dist_y) && (dist_x < snap_data->dist_x || dist_y < 
snap_data->dist_y))
+      /* Also update if we were only snapping in one direction earlier and it
+       * is better or equally good. */
+      if ((snap_data->snapped == SNAP_DIR_X && (dist <= snap_data->dist_x)) ||
+          (snap_data->snapped == SNAP_DIR_Y && (dist <= snap_data->dist_y)))
         update_snap = SNAP_DIR_BOTH;
     }
   else if (snapped == SNAP_DIR_X)
@@ -334,52 +371,52 @@ find_best_snapping (CcDisplayArrangement *arr,
       /* We only snap horizontally or vertically to an edge of the same monitor */
       if (dist_y < dist_x)
         {
-          maybe_update_snap (arr, snap_data, x1, y1, x1, top_snap_pos, SNAP_DIR_Y);
-          maybe_update_snap (arr, snap_data, x1, y1, x1, bottom_snap_pos, SNAP_DIR_Y);
+          maybe_update_snap (arr, snap_data, x1, y1, x1, top_snap_pos, SNAP_DIR_Y, SNAP_DIR_Y, 0);
+          maybe_update_snap (arr, snap_data, x1, y1, x1, bottom_snap_pos, SNAP_DIR_Y, SNAP_DIR_Y, 0);
         }
       else if (dist_x < 9999)
         {
-          maybe_update_snap (arr, snap_data, x1, y1, left_snap_pos, y1, SNAP_DIR_X);
-          maybe_update_snap (arr, snap_data, x1, y1, right_snap_pos, y1, SNAP_DIR_X);
+          maybe_update_snap (arr, snap_data, x1, y1, left_snap_pos, y1, SNAP_DIR_X, SNAP_DIR_X, 0);
+          maybe_update_snap (arr, snap_data, x1, y1, right_snap_pos, y1, SNAP_DIR_X, SNAP_DIR_X, 0);
         }
 
       /* Left/right edge identical on the top */
-      maybe_update_snap (arr, snap_data, x1, y1, _x1, top_snap_pos, SNAP_DIR_BOTH);
-      maybe_update_snap (arr, snap_data, x1, y1, _x2 - w, top_snap_pos, SNAP_DIR_BOTH);
+      maybe_update_snap (arr, snap_data, x1, y1, _x1, top_snap_pos, SNAP_DIR_BOTH, SNAP_DIR_Y, 0);
+      maybe_update_snap (arr, snap_data, x1, y1, _x2 - w, top_snap_pos, SNAP_DIR_BOTH, SNAP_DIR_Y, 0);
 
       /* Left/right edge identical on the bottom */
-      maybe_update_snap (arr, snap_data, x1, y1, _x1, bottom_snap_pos, SNAP_DIR_BOTH);
-      maybe_update_snap (arr, snap_data, x1, y1, _x2 - w, bottom_snap_pos, SNAP_DIR_BOTH);
+      maybe_update_snap (arr, snap_data, x1, y1, _x1, bottom_snap_pos, SNAP_DIR_BOTH, SNAP_DIR_Y, 0);
+      maybe_update_snap (arr, snap_data, x1, y1, _x2 - w, bottom_snap_pos, SNAP_DIR_BOTH, SNAP_DIR_Y, 0);
 
       /* Top/bottom edge identical on the left */
-      maybe_update_snap (arr, snap_data, x1, y1, left_snap_pos, _y1, SNAP_DIR_BOTH);
-      maybe_update_snap (arr, snap_data, x1, y1, left_snap_pos, _y2 - h, SNAP_DIR_BOTH);
+      maybe_update_snap (arr, snap_data, x1, y1, left_snap_pos, _y1, SNAP_DIR_BOTH, SNAP_DIR_X, 0);
+      maybe_update_snap (arr, snap_data, x1, y1, left_snap_pos, _y2 - h, SNAP_DIR_BOTH, SNAP_DIR_X, 0);
 
       /* Top/bottom edge identical on the right */
-      maybe_update_snap (arr, snap_data, x1, y1, right_snap_pos, _y1, SNAP_DIR_BOTH);
-      maybe_update_snap (arr, snap_data, x1, y1, right_snap_pos, _y2 - h, SNAP_DIR_BOTH);
+      maybe_update_snap (arr, snap_data, x1, y1, right_snap_pos, _y1, SNAP_DIR_BOTH, SNAP_DIR_X, 0);
+      maybe_update_snap (arr, snap_data, x1, y1, right_snap_pos, _y2 - h, SNAP_DIR_BOTH, SNAP_DIR_X, 0);
 
       /* If snapping is infinite, then add snapping points with minimal overlap
        * to prevent detachment.
        * This is similar to the above but simply re-defines the snapping pos
        * to have only minimal overlap */
-      if (arr->max_snap_distance == G_MAXUINT)
+      if (arr->major_snap_distance == G_MAXUINT)
         {
           /* Hanging over the left/right edge on the top */
-          maybe_update_snap (arr, snap_data, x1, y1, _x1 - w + MIN_OVERLAP, top_snap_pos, SNAP_DIR_BOTH);
-          maybe_update_snap (arr, snap_data, x1, y1, _x2 - MIN_OVERLAP, top_snap_pos, SNAP_DIR_BOTH);
+          maybe_update_snap (arr, snap_data, x1, y1, _x1 - w + MIN_OVERLAP, top_snap_pos, SNAP_DIR_BOTH, 
SNAP_DIR_Y, 1);
+          maybe_update_snap (arr, snap_data, x1, y1, _x2 - MIN_OVERLAP, top_snap_pos, SNAP_DIR_BOTH, 
SNAP_DIR_Y, -1);
 
           /* Left/right edge identical on the bottom */
-          maybe_update_snap (arr, snap_data, x1, y1, _x1 - w + MIN_OVERLAP, bottom_snap_pos, SNAP_DIR_BOTH);
-          maybe_update_snap (arr, snap_data, x1, y1, _x2 - MIN_OVERLAP, bottom_snap_pos, SNAP_DIR_BOTH);
+          maybe_update_snap (arr, snap_data, x1, y1, _x1 - w + MIN_OVERLAP, bottom_snap_pos, SNAP_DIR_BOTH, 
SNAP_DIR_Y, 1);
+          maybe_update_snap (arr, snap_data, x1, y1, _x2 - MIN_OVERLAP, bottom_snap_pos, SNAP_DIR_BOTH, 
SNAP_DIR_Y, -1);
 
           /* Top/bottom edge identical on the left */
-          maybe_update_snap (arr, snap_data, x1, y1, left_snap_pos, _y1 - h + MIN_OVERLAP, SNAP_DIR_BOTH);
-          maybe_update_snap (arr, snap_data, x1, y1, left_snap_pos, _y2 - MIN_OVERLAP, SNAP_DIR_BOTH);
+          maybe_update_snap (arr, snap_data, x1, y1, left_snap_pos, _y1 - h + MIN_OVERLAP, SNAP_DIR_BOTH, 
SNAP_DIR_X, 1);
+          maybe_update_snap (arr, snap_data, x1, y1, left_snap_pos, _y2 - MIN_OVERLAP, SNAP_DIR_BOTH, 
SNAP_DIR_X, -1);
 
           /* Top/bottom edge identical on the right */
-          maybe_update_snap (arr, snap_data, x1, y1, right_snap_pos, _y1 - h + MIN_OVERLAP, SNAP_DIR_BOTH);
-          maybe_update_snap (arr, snap_data, x1, y1, right_snap_pos, _y2 - MIN_OVERLAP, SNAP_DIR_BOTH);
+          maybe_update_snap (arr, snap_data, x1, y1, right_snap_pos, _y1 - h + MIN_OVERLAP, SNAP_DIR_BOTH, 
SNAP_DIR_X, 1);
+          maybe_update_snap (arr, snap_data, x1, y1, right_snap_pos, _y2 - MIN_OVERLAP, SNAP_DIR_BOTH, 
SNAP_DIR_X, -1);
         }
     }
 }
@@ -468,9 +505,9 @@ static void
 output_changed_cb (CcDisplayArrangement *arr, CcDisplayMonitor *output)
 {
   if (cc_display_config_count_useful_monitors (arr->config) > 2) {
-    arr->max_snap_distance = MAX_SNAP_DISTANCE;
+    arr->major_snap_distance = MAJOR_SNAP_DISTANCE;
   } else {
-    arr->max_snap_distance = G_MAXUINT;
+    arr->major_snap_distance = G_MAXUINT;
   }
 
   gtk_widget_queue_draw (GTK_WIDGET (arr));
@@ -855,7 +892,7 @@ cc_display_arrangement_init (CcDisplayArrangement *arr)
   gtk_widget_add_events (GTK_WIDGET (arr),
                         GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK);
 
-  arr->max_snap_distance = MAX_SNAP_DISTANCE;
+  arr->major_snap_distance = MAJOR_SNAP_DISTANCE;
 }
 
 CcDisplayArrangement*


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]