summaryrefslogtreecommitdiff
path: root/panels/display/cc-display-arrangement.c
diff options
context:
space:
mode:
Diffstat (limited to 'panels/display/cc-display-arrangement.c')
-rw-r--r--panels/display/cc-display-arrangement.c99
1 files changed, 68 insertions, 31 deletions
diff --git a/panels/display/cc-display-arrangement.c b/panels/display/cc-display-arrangement.c
index 3b489f4b1..0bc5fcd33 100644
--- a/panels/display/cc-display-arrangement.c
+++ b/panels/display/cc-display-arrangement.c
@@ -38,7 +38,7 @@ struct _CcDisplayArrangement
gdouble drag_anchor_x;
gdouble drag_anchor_y;
- guint max_snap_distance;
+ guint major_snap_distance;
};
typedef struct _CcDisplayArrangement CcDisplayArrangement;
@@ -67,7 +67,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);
}
}
}
@@ -469,9 +506,9 @@ on_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));
@@ -857,7 +894,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*