Merge pull request #1508 from ahesford/follow_the_white_rabbit

Refinements to edge behavior
This commit is contained in:
Andrew J. Hesford 2024-02-07 15:44:42 -05:00 committed by GitHub
commit 2c4f7e86dc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 37 additions and 30 deletions

View file

@ -66,6 +66,7 @@ struct edge {
* @target: position to which the moving edge will be moved * @target: position to which the moving edge will be moved
* @oppose: opposing edge of encountered region * @oppose: opposing edge of encountered region
* @align: aligned edge of encountered region * @align: aligned edge of encountered region
* @lesser: true if the moving edge is top or left, false otherwise
* *
* This function will be used by edge_find_neighbors and edge_find_outputs to * This function will be used by edge_find_neighbors and edge_find_outputs to
* validate and select the "best" output or neighbor edge against which a * validate and select the "best" output or neighbor edge against which a
@ -92,7 +93,7 @@ struct edge {
* update the value of *best accordingly. * update the value of *best accordingly.
*/ */
typedef void (*edge_validator_t)(int *best, struct edge current, typedef void (*edge_validator_t)(int *best, struct edge current,
struct edge target, struct edge oppose, struct edge align); struct edge target, struct edge oppose, struct edge align, bool lesser);
void edges_initialize(struct border *edges); void edges_initialize(struct border *edges);

View file

@ -90,11 +90,13 @@ validate_single_region_edge(int *valid_edge,
* the region borders for aligned edges only. * the region borders for aligned edges only.
*/ */
bool lesser = direction == VIEW_EDGE_LEFT || direction == VIEW_EDGE_UP;
validator(valid_edge, validator(valid_edge,
build_edge(view, direction, 0), build_edge(view, direction, 0),
build_edge(target, direction, 0), build_edge(target, direction, 0),
build_edge(region, view_edge_invert(direction), 0), build_edge(region, view_edge_invert(direction), 0),
build_edge(region, direction, rc.gap)); build_edge(region, direction, rc.gap), lesser);
} }
static void static void
@ -132,11 +134,13 @@ validate_single_output_edge(int *valid_edge,
.left = INT_MIN, .left = INT_MIN,
}; };
bool lesser = direction == VIEW_EDGE_LEFT || direction == VIEW_EDGE_UP;
validator(valid_edge, validator(valid_edge,
build_edge(view, direction, 0), build_edge(view, direction, 0),
build_edge(target, direction, 0), build_edge(target, direction, 0),
build_edge(region, direction, 0), build_edge(region, direction, 0),
build_edge(unbounded, direction, 0)); build_edge(unbounded, direction, 0), lesser);
} }
static void static void
@ -446,7 +450,7 @@ edges_traverse_edge(struct edge current, struct edge target, struct edge obstacl
current.offset, current.min, target.offset, target.min); current.offset, current.min, target.offset, target.min);
/* Motion misses when obstacle ends above start of quad segment */ /* Motion misses when obstacle ends above start of quad segment */
if (obstacle.max < lo) { if (obstacle.max <= lo) {
return false; return false;
} }
@ -455,5 +459,5 @@ edges_traverse_edge(struct edge current, struct edge target, struct edge obstacl
current.offset, current.max, target.offset, target.max); current.offset, current.max, target.offset, target.max);
/* Motion hits when obstacle starts above the end of quad segment */ /* Motion hits when obstacle starts above the end of quad segment */
return obstacle.min <= hi; return obstacle.min < hi;
} }

View file

@ -11,12 +11,11 @@
static void static void
check_edge(int *next, struct edge current, struct edge target, check_edge(int *next, struct edge current, struct edge target,
struct edge oppose, struct edge align, int tolerance) struct edge oppose, struct edge align, int tolerance, bool lesser)
{ {
int cur = current.offset; int cur = current.offset;
int tgt = target.offset; int tgt = target.offset;
int opp = oppose.offset; int opp = oppose.offset;
int aln = align.offset;
/* Ignore non-moving edges */ /* Ignore non-moving edges */
if (cur == tgt) { if (cur == tgt) {
@ -39,54 +38,57 @@ check_edge(int *next, struct edge current, struct edge target,
/* Direction of motion for the edge */ /* Direction of motion for the edge */
const bool decreasing = tgt < cur; const bool decreasing = tgt < cur;
/*
* Motion resists "entry" into the space of another window, but never
* resist leaving it. Without edge attraction, this only happens when
* the "leading" edge of a motion (top edge upward, bottom edge
* downward, left edge leftward, right edge rightward) encounters an
* opposing edge. If the motion is not of a leading edge, there is no
* need to check for any resistance.
*
* However, if there is attraction, a "trailing" edge of a motion (top
* edge downward, bottom edge upward, left edge rightward, right edge
* leftward) may be grabbed by the opposing edge of another window as
* it passes. Hence, trailing edges still need to be tested in
* attractive cases.
*/
if (tolerance >= 0 && lesser != decreasing) {
return;
}
/* Check the opposing edge */ /* Check the opposing edge */
bool valid = false; bool valid = false;
if (decreasing) { if (decreasing) {
/* Check for decreasing movement across opposing edge */
const int lo = clipped_sub(opp, abs(tolerance)); const int lo = clipped_sub(opp, abs(tolerance));
const int hi = clipped_sub(opp, MIN(tolerance, 0)); const int hi = clipped_sub(opp, MIN(tolerance, 0));
valid = tgt >= lo && tgt < hi; valid = tgt >= lo && tgt < hi && cur >= opp;
} else { } else {
/* Check for increasing movement across opposing edge */ /* Check for increasing movement across opposing edge */
const int lo = clipped_add(opp, MIN(tolerance, 0)); const int lo = clipped_add(opp, MIN(tolerance, 0));
const int hi = clipped_add(opp, abs(tolerance)); const int hi = clipped_add(opp, abs(tolerance));
valid = tgt > lo && tgt <= hi; valid = tgt > lo && tgt <= hi && cur <= opp;
} }
if (valid && edges_traverse_edge(current, target, oppose)) { if (valid && edges_traverse_edge(current, target, oppose)) {
*next = edge_get_best(*next, opp, decreasing); *next = edge_get_best(*next, opp, decreasing);
} }
/* Check the aligned edge */
valid = false;
if (decreasing) {
const int lo = clipped_sub(aln, abs(tolerance));
const int hi = clipped_sub(aln, MIN(tolerance, 0));
valid = tgt >= lo && tgt < hi;
} else {
const int lo = clipped_add(aln, MIN(tolerance, 0));
const int hi = clipped_add(aln, abs(tolerance));
valid = tgt > lo && tgt <= hi;
}
if (valid && edges_traverse_edge(current, target, align)) {
*next = edge_get_best(*next, aln, decreasing);
}
} }
static void static void
check_edge_output(int *next, struct edge current, struct edge target, check_edge_output(int *next, struct edge current, struct edge target,
struct edge oppose, struct edge align) struct edge oppose, struct edge align, bool lesser)
{ {
check_edge(next, current, target, check_edge(next, current, target,
oppose, align, rc.screen_edge_strength); oppose, align, rc.screen_edge_strength, lesser);
} }
static void static void
check_edge_window(int *next, struct edge current, struct edge target, check_edge_window(int *next, struct edge current, struct edge target,
struct edge oppose, struct edge align) struct edge oppose, struct edge align, bool lesser)
{ {
check_edge(next, current, target, check_edge(next, current, target,
oppose, align, rc.window_edge_strength); oppose, align, rc.window_edge_strength, lesser);
} }
void void

View file

@ -13,7 +13,7 @@
static void static void
check_edge(int *next, struct edge current, struct edge target, check_edge(int *next, struct edge current, struct edge target,
struct edge oppose, struct edge align) struct edge oppose, struct edge align, bool lesser)
{ {
int cur = current.offset; int cur = current.offset;
int tgt = target.offset; int tgt = target.offset;