Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(4/5) Multiple Issues: Fix intersections after mouse button release #183

Merged
merged 46 commits into from
Oct 6, 2019
Merged
Changes from 1 commit
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
6fcd6ad
(1/5) Multiple issues: Prep
felix-andreas Aug 27, 2019
c96e543
snap widgets after mouse button release
felix-andreas Aug 27, 2019
f37971b
close gaps after mouse button release
felix-andreas Aug 27, 2019
27fa510
check intersections after mouse button release
felix-andreas Aug 27, 2019
b4adae3
Merge branch 'master' into 1_of_5_prep_for_multiple_issues
Sep 24, 2019
00053df
Merge branch 'master' into 3_of_5_close_gaps_after_mouse_button_release
Sep 24, 2019
c627436
Merge branch 'master' into 4_of_5_fix_intersections_after_mouse_butto…
Sep 24, 2019
4310d3d
don't pass event as parameter
felix-andreas Sep 24, 2019
bacaf98
simplify event connection
felix-andreas Sep 24, 2019
87edff8
Merge branch 'master' into 2_of_5_snap_monitors_after_mouse_button_re…
felix-andreas Sep 24, 2019
70aaaa0
Merge branch '1_of_5_prep_for_multiple_issues' into 2_of_5_snap_monit…
felix-andreas Sep 24, 2019
99b3969
Merge branch '2_of_5_snap_monitors_after_mouse_button_release' of git…
felix-andreas Sep 24, 2019
3a29a0f
spelling: snapping
felix-andreas Sep 24, 2019
1c9e8ea
Merge branch '2_of_5_snap_monitors_after_mouse_button_release' into 3…
felix-andreas Sep 24, 2019
c471a5b
add blank line for linter
felix-andreas Sep 24, 2019
f4f6d57
Merge branch '3_of_5_close_gaps_after_mouse_button_release' of github…
felix-andreas Sep 24, 2019
05c535f
Merge branch '3_of_5_close_gaps_after_mouse_button_release' into 4_of…
felix-andreas Sep 24, 2019
2ef6b0e
add geometry label
felix-andreas Sep 24, 2019
5ad0884
Revert "add geometry label"
felix-andreas Sep 24, 2019
832bcae
add spaces for struct initialization
felix-andreas Sep 24, 2019
a159dd7
Merge branch '3_of_5_close_gaps_after_mouse_button_release' into 4_of…
felix-andreas Sep 24, 2019
7e86ebf
Merge branch 'master' into 2_of_5_snap_monitors_after_mouse_button_re…
felix-andreas Sep 24, 2019
b666631
Merge branch 'master' into 3_of_5_close_gaps_after_mouse_button_release
felix-andreas Sep 24, 2019
66c509f
Merge branch 'master' into 4_of_5_fix_intersections_after_mouse_butto…
felix-andreas Sep 24, 2019
1e07fea
remove space in comment
felix-andreas Sep 25, 2019
f92d8d1
Merge branch 'master' into 2_of_5_snap_monitors_after_mouse_button_re…
felix-andreas Sep 25, 2019
0a91ba9
Merge branch 'master' into 4_of_5_fix_intersections_after_mouse_butto…
Sep 26, 2019
f4b3b6c
Merge branch 'master' into 2_of_5_snap_monitors_after_mouse_button_re…
Sep 26, 2019
f383ba1
Merge branch 'master' into 3_of_5_close_gaps_after_mouse_button_release
Sep 26, 2019
ded0d2a
lint: add empty line
felix-andreas Sep 27, 2019
df9efcb
rename variable to be more explanatory
felix-andreas Sep 27, 2019
5052fa1
make minimum widget offset a const
felix-andreas Sep 27, 2019
07436e2
Merge branch '2_of_5_snap_monitors_after_mouse_button_release' of git…
felix-andreas Sep 27, 2019
86d962f
Merge branch '3_of_5_close_gaps_after_mouse_button_release' of github…
felix-andreas Sep 27, 2019
bd766f2
Merge branch '2_of_5_snap_monitors_after_mouse_button_release' into 3…
felix-andreas Sep 27, 2019
3460154
rename variables for clarity
felix-andreas Sep 27, 2019
b52624d
Merge branch '2_of_5_snap_monitors_after_mouse_button_release' into 3…
felix-andreas Sep 27, 2019
451352c
lint
felix-andreas Sep 28, 2019
78a6f4c
Merge branch '2_of_5_snap_monitors_after_mouse_button_release' into 3…
felix-andreas Sep 28, 2019
84675dd
lint: add space
felix-andreas Sep 28, 2019
def3390
lint: add correct space
felix-andreas Sep 28, 2019
20b9006
Merge branch '3_of_5_close_gaps_after_mouse_button_release' into 4_of…
felix-andreas Sep 28, 2019
59f7aab
Merge branch 'master' into 4_of_5_fix_intersections_after_mouse_butto…
Sep 29, 2019
4ded1a8
Revert "Merge branch 'master' into 4_of_5_fix_intersections_after_mou…
felix-andreas Sep 29, 2019
43c9fb8
Merge branch 'master' into 4_of_5_fix_intersections_after_mouse_butto…
kgrubb Oct 3, 2019
c53a39b
Merge branch 'master' into 4_of_5_fix_intersections_after_mouse_butto…
Oct 6, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
snap widgets after mouse button release
- a more concise widget snapping algorithm
- also fixes some issues when the widgets were
  perfectly aligned
  • Loading branch information
felix-andreas committed Aug 27, 2019
commit c96e5430a26b27d94487b3923ac734061edef029
138 changes: 42 additions & 96 deletions src/Widgets/DisplaysOverlay.vala
Original file line number Diff line number Diff line change
Expand Up @@ -384,116 +384,62 @@ public class Display.DisplaysOverlay : Gtk.Overlay {
}

/******************************************************************************************
* Widget snaping is done by trying to snap a child to other widgets called Anchors. *
* It first calculates the distance between each anchor and the child, and afterwards *
* snaps the child to the closest edge *
* Widget snaping is done by trying to snap a widget to other widgets called Anchors. *
* It first calculates the distance between each anchor and the widget, and afterwards *
* snaps the widget to the closest edge/corner *
* *
* Cases: C = child, A = current anchor *
* Cases: W = widget, A = current anchor *
* *
* 1. 2. 3. 4. *
* A C C A A C *
* C A *
* 1. 2. 3. 4. 5. 6. 7. 8. *
* A W W A A W W W A A *
* W A A A W W *
* *
******************************************************************************************/
private void snap_widget (Display.DisplayWidget child, List<Display.DisplayWidget> anchors) {
if (anchors.length () == 0) return;
int child_x, child_y, child_width, child_height;
child.get_geometry (out child_x, out child_y, out child_width, out child_height);
debug ("Child: %d %d %d %d\n", child_x, child_y, child_width, child_height);

bool snap_y = false, snap_x = false, move = false, diagonally = false;
int case_1 = int.MAX, case_2 = int.MAX, case_3 = int.MAX, case_4 = int.MAX;
private void snap_widget (Display.DisplayWidget widget, List<Display.DisplayWidget> anchors) {
if (anchors.length () == 0) {
return;
}

foreach (var anchor in anchors) {
if (child.equals (anchor)) continue;
int widget_x, widget_y, widget_width, widget_height;
widget.get_geometry (out widget_x, out widget_y, out widget_width, out widget_height);
widget_x += widget.delta_x;
widget_y += widget.delta_y;

int distance = int.MAX, distance_x = 0, distance_y = 0;
foreach (var anchor in anchors) {
int anchor_x, anchor_y, anchor_width, anchor_height;
anchor.get_geometry (out anchor_x, out anchor_y, out anchor_width, out anchor_height);
debug ("Anchor: %d %d %d %d\n", anchor_x, anchor_y, anchor_width, anchor_height);

int case_1_t = child_x - anchor_x - anchor_width;
int case_2_t = child_x - anchor_x + child_width;
int case_3_t = child_y - anchor_y - anchor_height;
int case_4_t = child_height + child_y - anchor_y;

// Check projections
if (is_projected (child_y, child_height, anchor_y, anchor_height)) {
debug ("Child is on the X axis of Anchor %s\n", anchor.virtual_monitor.get_display_name ());
case_1 = is_x_smaller_absolute (case_1, case_1_t) && !diagonally ? case_1 : case_1_t;
case_2 = is_x_smaller_absolute (case_2, case_2_t) && !diagonally ? case_2 : case_2_t;
snap_x = true;
move = true;
} else if (is_projected (child_x, child_width, anchor_x, anchor_width)) {
debug ("Child is on the Y axis of Anchor %s\n", anchor.virtual_monitor.get_display_name ());
case_3 = is_x_smaller_absolute (case_3, case_3_t) && !diagonally ? case_3 : case_3_t;
case_4 = is_x_smaller_absolute (case_4, case_4_t) && !diagonally ? case_4 : case_4_t;
snap_y = true;
move = true;
} else {
debug ("Child is diagonally of Anchor %s\n", anchor.virtual_monitor.get_display_name ());
if (!move) {
diagonally = true;
case_1 = is_x_smaller_absolute (case_1, case_1_t) ? case_1 : case_1_t;
case_2 = is_x_smaller_absolute (case_2, case_2_t) ? case_2 : case_2_t;
case_3 = is_x_smaller_absolute (case_3, case_3_t) ? case_3 : case_3_t;
case_4 = is_x_smaller_absolute (case_4, case_4_t) ? case_4 : case_4_t;
}
}
}

int shortest_x = is_x_smaller_absolute (case_1, case_2) ? case_1 : case_2;
int shortest_y = is_x_smaller_absolute (case_3, case_4) ? case_3 : case_4;

// X Snapping
if (!snap_y || is_x_smaller_absolute (shortest_x, shortest_y)) {
if (snap_x & move) {
debug ("moving child %d on X\n", shortest_x);
if (shortest_x < SNAP_LIMIT) ((DisplayWidget) child).set_geometry (child_x - shortest_x, child_y , child_width, child_height);
}
}

// Y Snapping
if (!snap_x || is_x_smaller_absolute (shortest_y, shortest_x)) {
if (snap_y & move) {
debug ("moving child %d on Y\n", shortest_y);
if (shortest_y < SNAP_LIMIT) ((DisplayWidget) child).set_geometry (child_x , child_y - shortest_y, child_width, child_height);
var diff_x = anchor_x - widget_x;
var diff_y = anchor_y - widget_y;
var distance_left = diff_x + anchor_width;
var distance_right = diff_x - widget_width;
var distance_top = diff_y + anchor_height;
var distance_bottom = diff_y - widget_height;
var test_distance_x = distance_right > -distance_left ? distance_right : distance_left;
var test_distance_y = distance_bottom > -distance_top ? distance_bottom : distance_top;

if (distance_left > 0 && distance_right < 0) {
test_distance_x = 0;
} else if (distance_top > 0 && distance_bottom < 0) {
test_distance_y = 0;
} else { // As diagonal monitors are not allowed, offset by 50px
if (test_distance_x.abs () >= test_distance_y.abs ()) {
test_distance_x += diff_x > 0 ? 50 : -50;
} else {
test_distance_y += diff_y > 0 ? 50 : -50;
}
}
}

// X & Y Snapping
if (!snap_x && !snap_y) {
if (shortest_x < SNAP_LIMIT && shortest_y < SNAP_LIMIT) {
((DisplayWidget) child).set_geometry (child_x - shortest_x, child_y - shortest_y , child_width, child_height);
debug ("moving child %d on X & %d on Y\n", shortest_x, shortest_y);
} else {
debug ("too large");
var test_distance = test_distance_x * test_distance_x + test_distance_y * test_distance_y;
if (test_distance < distance) {
distance_x = test_distance_x;
distance_y = test_distance_y;
distance = test_distance;
}
}
}

static bool equals = false;
private bool is_projected (int child_x, int child_length, int anchor_x, int anchor_length) {
var numberline = new List<int> ();

equals = false;
CompareFunc<int> intcmp = (a, b) => {
if (a == b) equals = true;
return (int) (a > b) - (int) (a < b);
};

var child_x2 = child_x + child_length;
var anchor_x2 = anchor_x + anchor_length;

numberline.insert_sorted (child_x, intcmp);
numberline.insert_sorted (child_x2, intcmp);
numberline.insert_sorted (anchor_x, intcmp);
numberline.insert_sorted (anchor_x2, intcmp);

if (equals) return false;
return !((numberline.index (child_x) - numberline.index (child_x2)).abs () == 1 && (numberline.index (anchor_x) - numberline.index (anchor_x2)).abs () == 1);
}

private bool is_x_smaller_absolute (int x, int y) {
return x.abs () < y.abs ();
widget.set_geometry (widget_x + distance_x, widget_y + distance_y, widget_width, widget_height);
}
}