···11open Notty
22open Lwd_utils
33+module Log = (val Logs.src_log (Logs.Src.create "nottui"))
3445module Focus : sig
56 type var = int Lwd.var
···2930 val has_focus : status -> bool
3031 val merge : status -> status -> status
3132end = struct
3333+ let () = ()
3434+3235 (*The focus system works by having a clock which changes each time the focus changes. An item has focus so long as its `var` is greater than 0
3336 When we render the UI we go through and set anything with a focus value not matching that of the clock to 0 *)
3437···5760 let peek_has_focus (h : handle) : bool = fst h |> Lwd.peek > 0
5861 let clock = ref 0
5962 let currently_focused : var ref = ref (make () |> fst)
6060- let focus_stack : var Stack.t = Stack.create ()
6363+ let focus_stack : var list ref = ref []
61646265 let request_var (v : var) =
6366 incr clock;
···7275 Lwd.set v 0
7376 ;;
74777878+ let var_equal a b = Lwd.peek a = Lwd.peek b
7979+7580 let request_reversable ((v, _) : handle) =
7676- focus_stack |> Stack.push !currently_focused;
7777- request_var v
8181+ Log.debug (fun m -> m "Maybe requesting revesable focus %d" (Lwd.peek v));
8282+ if not @@ var_equal !currently_focused v
8383+ then (
8484+ focus_stack := !currently_focused :: !focus_stack;
8585+ request_var v;
8686+ Log.debug (fun m -> m "Requested reversable focus %d" (Lwd.peek v)))
7887 ;;
79888089 let release_reversable ((v, _) : handle) =
9090+ Log.debug (fun m -> m "Maybe release or remove %d from reversable focus stack" (Lwd.peek v));
8191 (* we should only release if we actually have the focus*)
8282- if Lwd.peek v > 0 then focus_stack |> Stack.pop_opt |> Option.iter request_var
9292+ if var_equal !currently_focused v
9393+ then (
9494+ (*just load the last item in the stack *)
9595+ match !focus_stack with
9696+ | hd :: tl ->
9797+ request_var hd;
9898+ Log.debug (fun m -> m "Released reversable focus %d in echange form %d" (Lwd.peek v) (Lwd.peek v));
9999+ focus_stack := tl
100100+ | _ -> ())
101101+ else (
102102+ (*we might be in the stack and we should be removed*)
103103+ let rec loop start stack =
104104+ match stack with
105105+ | hd :: tl ->
106106+ if hd == v
107107+ then (
108108+ (* we find an instance of the handle we are trying to release in our focus stack
109109+ *)
110110+ (*request focus for the next item in the stack if it's at the head*)
111111+ (*update the stack with the new focus*)
112112+ Log.debug (fun m -> m "Removed %d from reversable focus stack" (Lwd.peek v));
113113+ focus_stack := List.rev start @ tl)
114114+ else loop (hd :: start) tl
115115+ | _ -> ()
116116+ in
117117+ loop [] !focus_stack)
83118 ;;
8411985120 let merge s1 s2 : status =
+3-1
forks/nottui/lib/nottui/nottui_main.mli
···4848 "more". *)
49495050 (** Request the focus and add to the focus stack.
5151- WARNING: The focus stack is global, if you render multiple nottui ui's you may not want to use this *)
5151+ WARNING: The focus stack is global, if you render multiple nottui ui's you may not want to use this
5252+ NOTE: Calling this twice has the same result as calling it once. Trying to focus the currently focused item will not add to the stack*)
5353+5254 val request_reversable : handle -> unit
53555456 (** Release the focus (if the handle has it) and restore the last focus on the stack *)
+4-6
forks/nottui/lib/nottui/widgets/overlays.ml
···225225 match show_popup with
226226 | Some (content, label) ->
227227 let ui =
228228- let$ status = Focus.status focus
229229- and$ prompt_field = content in
230230- if not (Focus.has_focus status) then Focus.request_reversable focus;
228228+ let$ prompt_field = content in
229229+ Focus.request_reversable focus;
231230 prompt_field |> Ui.resize ~w:5 ~sw:1
232231 in
233232 ui |> BB.focusable ~focus ~label_top:label ?on_key |> clear_bg
234233 | None ->
235235- let$ status = Focus.status focus in
236236- if Focus.has_focus status then Focus.release_reversable focus;
237237- Ui.empty
234234+ Focus.release_reversable focus;
235235+ Ui.empty |> Lwd.pure
238236 in
239237 W.zbox [ ui; popup_ui |>$ Ui.resize ~crop:neutral_grav ~pad:neutral_grav ]
240238;;