aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Letan <lthms@soap.coffee>2022-10-02 13:59:36 +0200
committerThomas Letan <lthms@soap.coffee>2022-10-02 13:59:36 +0200
commite44014c12d50277ff29088afdaaa507f650c54b1 (patch)
treed38478867fae6a10b8058aad05984ec5614a6592
parentSignal waybar before rearranging windows (diff)
Drop the infinite loop in favor of a line of windows
This might be revert in the future, but the current intuition is that it leads to a better UX.
-rw-r--r--bin/spatial/ribbon.ml180
-rw-r--r--bin/spatial/state.ml6
2 files changed, 101 insertions, 85 deletions
diff --git a/bin/spatial/ribbon.ml b/bin/spatial/ribbon.ml
index 830dc98..a7297c7 100644
--- a/bin/spatial/ribbon.ml
+++ b/bin/spatial/ribbon.ml
@@ -3,13 +3,20 @@ open Sway_ipc_types
type t = {
full_view : bool;
maximum_visible_size : int;
+ hidden_left : int64 list;
visible : (int * int64 list) option;
- hidden : int64 list;
+ hidden_right : int64 list;
}
let empty full_view maximum_visible_size =
assert (0 < maximum_visible_size);
- { full_view; maximum_visible_size; visible = None; hidden = [] }
+ {
+ full_view;
+ maximum_visible_size;
+ hidden_left = [];
+ visible = None;
+ hidden_right = [];
+ }
let visible_windows_count = function
| { visible = None; _ } -> 0
@@ -56,7 +63,7 @@ let shrink_left ribbon =
{
ribbon with
visible = Some (f - 1, l);
- hidden = push_back w ribbon.hidden;
+ hidden_left = push_front w ribbon.hidden_left;
}
| _ -> ribbon
@@ -69,7 +76,11 @@ let shrink_right ribbon =
| Some (f, l) when ribbon.maximum_visible_size < visible_windows_count ribbon
->
let w, l = pop_back_exn l in
- { ribbon with visible = Some (f, l); hidden = push_front w ribbon.hidden }
+ {
+ ribbon with
+ visible = Some (f, l);
+ hidden_right = push_front w ribbon.hidden_right;
+ }
| _ -> ribbon
let shrink ribbon =
@@ -105,12 +116,20 @@ let remove_if_present window =
let fill_space ribbon =
if visible_windows_count ribbon < ribbon.maximum_visible_size then
- match (pop_front ribbon.hidden, ribbon.visible) with
- | Some (x, hidden), Some (f, l) ->
- { ribbon with visible = Some (f, push_back x l); hidden }
- | Some (x, hidden), None ->
- { ribbon with visible = Some (0, [ x ]); hidden }
- | None, _ -> ribbon
+ match
+ ( pop_front ribbon.hidden_right,
+ pop_front ribbon.hidden_left,
+ ribbon.visible )
+ with
+ | Some (x, hidden_right), _, Some (f, l) ->
+ { ribbon with visible = Some (f, push_back x l); hidden_right }
+ | Some (x, hidden_right), _, None ->
+ { ribbon with visible = Some (0, [ x ]); hidden_right }
+ | None, Some (x, hidden_left), Some (f, l) ->
+ { ribbon with visible = Some (f + 1, push_front x l); hidden_left }
+ | None, Some (x, hidden_left), None ->
+ { ribbon with visible = Some (0, [ x ]); hidden_left }
+ | None, None, _ -> ribbon
else ribbon
let incr_maximum_visible ribbon =
@@ -133,8 +152,18 @@ let remove_window window ribbon =
| Some (_, l) ->
let f' = if f < List.length l then f else f - 1 in
{ ribbon with visible = Some (f', l) }
- | None -> { ribbon with hidden = remove_if_present window ribbon.hidden })
- | None -> { ribbon with hidden = remove_if_present window ribbon.hidden }
+ | None ->
+ {
+ ribbon with
+ hidden_left = remove_if_present window ribbon.hidden_left;
+ hidden_right = remove_if_present window ribbon.hidden_right;
+ })
+ | None ->
+ {
+ ribbon with
+ hidden_left = remove_if_present window ribbon.hidden_left;
+ hidden_right = remove_if_present window ribbon.hidden_right;
+ }
let toggle_full_view ribbon = { ribbon with full_view = not ribbon.full_view }
@@ -142,13 +171,11 @@ let move_focus_left ribbon =
match ribbon.visible with
| None -> ribbon
| Some (0, l) -> (
- match pop_back ribbon.hidden with
- | Some (x, hidden) ->
+ match pop_front ribbon.hidden_left with
+ | Some (x, hidden_left) ->
shrink_right
- { ribbon with visible = Some (0, push_front x l); hidden }
- | None ->
- let x, l = pop_back_exn l in
- { ribbon with visible = Some (0, push_front x l) })
+ { ribbon with visible = Some (0, push_front x l); hidden_left }
+ | None -> ribbon)
| Some (f, l) -> { ribbon with visible = Some (f - 1, l) }
let move_focus_right ribbon =
@@ -157,22 +184,31 @@ let move_focus_right ribbon =
| Some (f, l) when f < List.length l - 1 ->
{ ribbon with visible = Some (f + 1, l) }
| Some (f, l) -> (
- match pop_front ribbon.hidden with
- | Some (x, hidden) ->
+ match pop_front ribbon.hidden_right with
+ | Some (x, hidden_right) ->
shrink_left
- { ribbon with visible = Some (f + 1, push_back x l); hidden }
- | None ->
- let x, l = pop_front_exn l in
- { ribbon with visible = Some (f, push_back x l) })
-
-let rec focus_index ribbon index =
- match ribbon.visible with
- | Some (_, l) when index < List.length l ->
- { ribbon with visible = Some (index, l) }
- | Some (_, l) when index < List.length l + List.length ribbon.hidden ->
- let ribbon = move_focus_right ribbon in
- focus_index ribbon (index - 1)
- | _ -> ribbon
+ { ribbon with visible = Some (f + 1, push_back x l); hidden_right }
+ | None -> ribbon)
+
+let focus_index ribbon index =
+ let index = index - List.length ribbon.hidden_left in
+ let rec aux ribbon index =
+ match ribbon.visible with
+ | Some (_, l) ->
+ let visible_len = List.length l in
+ if index < 0 then
+ aux (move_focus_left { ribbon with visible = Some (0, l) }) (index + 1)
+ else if index < visible_len then
+ { ribbon with visible = Some (index, l) }
+ else if index < visible_len + List.length ribbon.hidden_right then
+ aux
+ (move_focus_right
+ { ribbon with visible = Some (visible_len - 1, l) })
+ (index - 1)
+ else ribbon
+ | _ -> ribbon
+ in
+ aux ribbon index
let split_at l i =
let rec split_visible acc i = function
@@ -190,39 +226,28 @@ let move_window_left ribbon =
| Some (left, focus, right) -> (
match pop_back left with
| Some (x, left) ->
- (* Case: [|a b {f} ..| ..]
- Result: [|a {f} b ..| ..] *)
+ (* Case: [.. |a b {f} ..| ..]
+ Result: [.. |a {f} b ..| ..] *)
{
ribbon with
visible =
Some (List.length left, left @ [ focus ] @ push_front x right);
}
| None -> (
- (* Case: [|{f} ..| ..] *)
- match pop_back ribbon.hidden with
- | Some (x, hidden) ->
- (* Case: [|{f} ..| a b] *)
- (* Result: [|{f} b ..| a] *)
+ (* Case: [.. |{f} ..| ..] *)
+ match pop_front ribbon.hidden_left with
+ | Some (x, hidden_left) ->
+ (* Case: [.. a |{f} ..| ..] *)
+ (* Result: [.. |{f} a ..| ..] *)
{
ribbon with
visible = Some (0, focus :: push_front x right);
- hidden;
+ hidden_left;
}
|> shrink_right
- | None -> (
- (* Case: [|{f} ..|] *)
- match pop_back right with
- | Some (x, right) ->
- (* Case: [|{f} a b c|]
- Result: [|{f} c a b|] *)
- {
- ribbon with
- visible = Some (0, focus :: push_front x right);
- }
- | None ->
- (* Case: [|{f}|]
- Result: [|{f}|] *)
- ribbon)))
+ | None ->
+ (* Case: [|{f} ..| ..] *)
+ ribbon))
(* Case: [||]
Result: [||] *)
| None -> ribbon
@@ -233,40 +258,27 @@ let move_window_right ribbon =
let f = List.length left + 1 in
match pop_front right with
| Some (x, right) ->
- (* Case: [|.. {f} a b| ..]
- Result: [|.. a {f} b| ..] *)
+ (* Case: [.. |.. {f} a b| ..]
+ Result: [.. |.. a {f} b| ..] *)
{
ribbon with
visible = Some (f, push_back x left @ [ focus ] @ right);
}
| None -> (
- (* Case: [|.. {f}| ..] *)
- match pop_front ribbon.hidden with
- | Some (x, hidden) ->
- (* Case: [|.. {f}| a b] *)
- (* Result: [|.. a {f}| b] *)
+ (* Case: [.. |.. {f}| ..] *)
+ match pop_front ribbon.hidden_right with
+ | Some (x, hidden_right) ->
+ (* Case: [ |.. {f}| a b] *)
+ (* Result: [ |.. a {f}| b] *)
{
ribbon with
visible = Some (f, push_back x left @ [ focus ] @ right);
- hidden;
+ hidden_right;
}
|> shrink_left
- | None -> (
- (* Case: [|.. {f}|] *)
- match pop_front left with
- | Some (x, left) ->
- (* Case: [|a b {f}|]
- Result: [|b a {f}|]
- In this case, focus remains in the same place, so
- [f - 1] *)
- {
- ribbon with
- visible = Some (f - 1, push_back x left @ [ focus ] @ right);
- }
- | None ->
- (* Case: [|{f}|]
- Result: [|{f}|] *)
- ribbon)))
+ | None ->
+ (* Case: [.. |.. {f}|] *)
+ ribbon))
(* Case: [||]
Result: [||] *)
| None -> ribbon
@@ -289,7 +301,9 @@ let visible_windows ribbon =
| None -> []
let all_windows ribbon =
- ribbon.hidden @ visible_windows { ribbon with full_view = false }
+ List.rev ribbon.hidden_left
+ @ visible_windows { ribbon with full_view = false }
+ @ ribbon.hidden_right
let focused_window ribbon =
match ribbon.visible with Some (f, l) -> List.nth_opt l f | None -> None
@@ -336,5 +350,7 @@ let pp fmt ribbon =
match split_visible ribbon with
| None -> Format.fprintf fmt "[]"
| Some (left, x, right) ->
- Format.fprintf fmt "[|%a{%Ld}%a|%a]" Pp_helpers.pp_windows_seq left x
- Pp_helpers.pp_windows_seq right Pp_helpers.pp_windows_seq ribbon.hidden
+ Format.fprintf fmt "[%a|%a{%Ld}%a|%a]" Pp_helpers.pp_windows_seq
+ (List.rev ribbon.hidden_left)
+ Pp_helpers.pp_windows_seq left x Pp_helpers.pp_windows_seq right
+ Pp_helpers.pp_windows_seq ribbon.hidden_right
diff --git a/bin/spatial/state.ml b/bin/spatial/state.ml
index 71d2427..e6fd29d 100644
--- a/bin/spatial/state.ml
+++ b/bin/spatial/state.ml
@@ -254,13 +254,13 @@ let client_command_handle :
| None -> { focus = None; windows = [] }
| Some ribbon -> (
match ribbon.visible with
- | Some (f, l) ->
+ | Some (f, _) ->
{
- focus = Some f;
+ focus = Some (f + List.length ribbon.hidden_left);
windows =
List.map
(fun id -> Windows_registry.find id state.windows)
- (l @ ribbon.hidden);
+ (Ribbon.all_windows ribbon);
}
| None -> { focus = None; windows = [] }) ))
: _ * a)