use crate::workspace::WorkspaceId;
#[must_use]
pub fn workspace_y_offset(
target_id: WorkspaceId,
active_id: WorkspaceId,
monitor_height: i32,
window_gap: i32,
) -> i32 {
let id_diff = i64::from(target_id.0) - i64::from(active_id.0);
let direction = id_diff.signum() as i32;
direction * (monitor_height + window_gap)
}
#[cfg(test)]
mod tests {
use super::*;
const MONITOR_H: i32 = 1080;
const GAP: i32 = 4;
const Y_UNIT: i32 = MONITOR_H + GAP;
#[test]
fn offset_for_previous_workspace_is_negative() {
let off = workspace_y_offset(WorkspaceId(3), WorkspaceId(5), MONITOR_H, GAP);
assert_eq!(off, -Y_UNIT);
}
#[test]
fn offset_for_next_workspace_is_positive() {
let off = workspace_y_offset(WorkspaceId(7), WorkspaceId(5), MONITOR_H, GAP);
assert_eq!(off, Y_UNIT);
}
#[test]
fn offset_for_active_workspace_is_zero() {
let off = workspace_y_offset(WorkspaceId(5), WorkspaceId(5), MONITOR_H, GAP);
assert_eq!(off, 0);
}
#[test]
fn offset_does_not_scale_with_id_distance() {
let off_to_3 = workspace_y_offset(WorkspaceId(2), WorkspaceId(3), MONITOR_H, GAP);
let off_to_4 = workspace_y_offset(WorkspaceId(2), WorkspaceId(4), MONITOR_H, GAP);
let off_to_8 = workspace_y_offset(WorkspaceId(2), WorkspaceId(8), MONITOR_H, GAP);
assert_eq!(off_to_3, -Y_UNIT);
assert_eq!(off_to_4, -Y_UNIT);
assert_eq!(off_to_8, -Y_UNIT);
}
#[test]
fn offset_independent_of_direction_of_switch() {
let ws5_below_6 = workspace_y_offset(WorkspaceId(5), WorkspaceId(6), MONITOR_H, GAP);
let ws6_above_5 = workspace_y_offset(WorkspaceId(6), WorkspaceId(5), MONITOR_H, GAP);
assert_eq!(ws5_below_6, -Y_UNIT);
assert_eq!(ws6_above_5, Y_UNIT);
assert_eq!(ws5_below_6.abs(), ws6_above_5.abs());
}
#[test]
fn offset_smallest_id_above_active_two() {
let off = workspace_y_offset(WorkspaceId(1), WorkspaceId(2), MONITOR_H, GAP);
assert_eq!(off, -Y_UNIT);
}
#[test]
fn offset_handles_zero_gap() {
let off = workspace_y_offset(WorkspaceId(2), WorkspaceId(1), 1080, 0);
assert_eq!(off, 1080);
}
#[test]
fn offset_same_id_returns_zero_regardless_of_inputs() {
assert_eq!(workspace_y_offset(WorkspaceId(1), WorkspaceId(1), 0, 0), 0);
assert_eq!(
workspace_y_offset(WorkspaceId(1), WorkspaceId(1), 9999, 999),
0
);
}
#[test]
fn offset_does_not_underflow_when_target_much_smaller() {
let off = workspace_y_offset(WorkspaceId(1), WorkspaceId(10), MONITOR_H, GAP);
assert_eq!(off, -Y_UNIT);
}
#[test]
fn offset_does_not_overflow_when_target_much_larger() {
let off = workspace_y_offset(WorkspaceId(10), WorkspaceId(1), MONITOR_H, GAP);
assert_eq!(off, Y_UNIT);
}
#[test]
fn offset_at_u32_extremes_uses_i64_widening_correctly() {
assert_eq!(
workspace_y_offset(WorkspaceId(u32::MAX), WorkspaceId(1), MONITOR_H, GAP),
Y_UNIT,
);
assert_eq!(
workspace_y_offset(WorkspaceId(1), WorkspaceId(u32::MAX), MONITOR_H, GAP),
-Y_UNIT,
);
assert_eq!(
workspace_y_offset(WorkspaceId(u32::MAX), WorkspaceId(u32::MAX), MONITOR_H, GAP),
0,
);
}
}