···11open Notty
22open Lwd_utils
3344-module Focus :
55-sig
44+module Focus : sig
65 type var = int Lwd.var
76 type handle
77+88 val make : unit -> handle
99 val request : handle -> unit
1010 val request_var : var -> unit
1111 val release : handle -> unit
12121313+ (** Request the focus and add to the focus stack *)
1314 val request_reversable : handle -> unit
1414- (** Request the focus and add to the focus stack *)
15151616+ (** Release the focus (if the handle has it) and restore the last focus on the stack *)
1617 val release_reversable : handle -> unit
1717- (** Release the focus (if the handle has it) and restore the last focus on the stack *)
18181919 type status =
2020 | Empty
2121 | Handle of int * var
2222 | Conflict of int
2323- val peek_has_focus:handle->bool
24232424+ val peek_has_focus : handle -> bool
2525 val empty : status
2626+2627 (*val is_empty : status -> bool*)
2728 val status : handle -> status Lwd.t
2829 val has_focus : status -> bool
2930 val merge : status -> status -> status
3031end = struct
3132 (*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
3232- When we render the UI we go through and set anything with a focus value not matching that of the clock to 0 *)
3333+ When we render the UI we go through and set anything with a focus value not matching that of the clock to 0 *)
33343435 type var = int Lwd.var
3536···40414142 type handle = var * status Lwd.t
42434343- let make ():handle =
4444+ let make () : handle =
4445 let v = Lwd.var 0 in
4545- (v,
4646- (Lwd.get v)|> Lwd.map ~f:(fun i -> Handle (i, v))
4747- )
4646+ v, Lwd.get v |> Lwd.map ~f:(fun i -> Handle (i, v))
4747+ ;;
48484949 let empty : status = Empty
5050-5150 let status (h : handle) : status Lwd.t = snd h
52515352 let has_focus = function
5453 | Empty -> false
5554 | Handle (i, _) | Conflict i -> i > 0
5555+ ;;
56565757- let peek_has_focus (h : handle) : bool= fst h|>Lwd.peek>0
5858-5757+ let peek_has_focus (h : handle) : bool = fst h |> Lwd.peek > 0
5958 let clock = ref 0
6060-6161- let currently_focused:var ref= ref (make()|>fst)
6262-6363- let focus_stack:var Stack.t= Stack.create()
5959+ let currently_focused : var ref = ref (make () |> fst)
6060+ let focus_stack : var Stack.t = Stack.create ()
64616562 let request_var (v : var) =
6663 incr clock;
6764 Lwd.set v !clock;
6868- currently_focused := v;
6969- ;;
7070- let request ((v, _ ): handle) =
7171- request_var v;
7272- ;;
7373- let release (v, _ : handle) = incr clock; Lwd.set v 0
6565+ currently_focused := v
6666+ ;;
6767+6868+ let request ((v, _) : handle) = request_var v
74697070+ let release ((v, _) : handle) =
7171+ incr clock;
7272+ Lwd.set v 0
7373+ ;;
75747676- let request_reversable (v, _ : handle)=
7777- focus_stack|>Stack.push !currently_focused;
7878- request_var v ;
7575+ let request_reversable ((v, _) : handle) =
7676+ focus_stack |> Stack.push !currently_focused;
7777+ request_var v
7978 ;;
80798181- let release_reversable (v, _ : handle)=
8080+ let release_reversable ((v, _) : handle) =
8281 (* we should only release if we actually have the focus*)
8383- if (Lwd.peek v)>0 then
8484- focus_stack|>Stack.pop |>request_var;
8585-8282+ if Lwd.peek v > 0 then focus_stack |> Stack.pop_opt |> Option.iter request_var
8683 ;;
87848888-8989- let merge s1 s2 : status = match s1, s2 with
8585+ let merge s1 s2 : status =
8686+ match s1, s2 with
9087 | Empty, x | x, Empty -> x
9188 | _, Handle (0, _) -> s1
9289 | Handle (0, _), _ -> s2
9390 | Handle (i1, _), Handle (i2, _) when i1 = i2 -> s1
9491 | (Handle (i1, _) | Conflict i1), Conflict i2 when i1 < i2 -> s2
9595- | (Handle (i1, _) | Conflict i1), Handle (i2, _) when i1 < i2 ->
9696- Conflict i2
9292+ | (Handle (i1, _) | Conflict i1), Handle (i2, _) when i1 < i2 -> Conflict i2
9793 | Conflict _, (Handle (_, _) | Conflict _) -> s1
9894 | Handle (i1, _), (Handle (_, _) | Conflict _) -> Conflict i1
9999-100100- (*
101101- Can i get the currently focused focus handle??
102102-103103- I could modify the focus handle so that it stores the last focused thing. That way when i call focus release on it it can return us to that. In a sense this would be almost like a linked list.
104104- I have an issue that if the focus isn't stored in the UI somewhere if i have two concurrent UIs their focus control will collide. Is this a real concern? Could I store the current focus in the root node, or as part of the UI rendering?
9595+ ;;
10596106106- The renderer could store the currently focused item.
107107- When we walk the focus tree, if the items are focused we keep walking untill we hit the end and then we assign that as the focused item.
108108- When switching focus we use that focused item.
109109-110110-111111- Would could have a FocusManager module. It stores the most recently focused item and also has the focus heap. When you request focus it can either be a queue adding request or a non queue adding request. When i release focus it will always release back to the last item in the heap
112112- *)
9797+ (*
9898+ Can i get the currently focused focus handle??
11399100100+ I could modify the focus handle so that it stores the last focused thing. That way when i call focus release on it it can return us to that. In a sense this would be almost like a linked list.
101101+ I have an issue that if the focus isn't stored in the UI somewhere if i have two concurrent UIs their focus control will collide. Is this a real concern? Could I store the current focus in the root node, or as part of the UI rendering?
114102103103+ The renderer could store the currently focused item.
104104+ When we walk the focus tree, if the items are focused we keep walking untill we hit the end and then we assign that as the focused item.
105105+ When switching focus we use that focused item.
115106116116-107107+ Would could have a FocusManager module. It stores the most recently focused item and also has the focus heap. When you request focus it can either be a queue adding request or a non queue adding request. When i release focus it will always release back to the last item in the heap
108108+ *)
117109end
118110119119-120120-module Gravity :
121121-sig
122122- type direction = [
123123- | `Negative
111111+module Gravity : sig
112112+ type direction =
113113+ [ `Negative
124114 | `Neutral
125115 | `Positive
126126- ]
116116+ ]
117117+127118 val pp_direction : Format.formatter -> direction -> unit
119119+128120 type t
121121+129122 val pp : Format.formatter -> t -> unit
130123 val make : h:direction -> v:direction -> t
131124 val default : t
···133126 val v : t -> direction
134127135128 type t2
129129+136130 val pair : t -> t -> t2
137131 val p1 : t2 -> t
138132 val p2 : t2 -> t
139139-end =
140140-struct
141141- type direction = [ `Negative | `Neutral | `Positive ]
133133+end = struct
134134+ type direction =
135135+ [ `Negative
136136+ | `Neutral
137137+ | `Positive
138138+ ]
139139+142140 type t = int
143141 type t2 = int
144142···146144147145 let pack = function
148146 | `Negative -> 0
149149- | `Neutral -> 1
147147+ | `Neutral -> 1
150148 | `Positive -> 2
149149+ ;;
151150152151 let unpack = function
153152 | 0 -> `Negative
154153 | 1 -> `Neutral
155154 | _ -> `Positive
156156-157157- let make ~h ~v =
158158- (pack h lsl 2) lor pack v
155155+ ;;
159156157157+ let make ~h ~v = (pack h lsl 2) lor pack v
160158 let h x = unpack (x lsr 2)
161159 let v x = unpack (x land 3)
162160163161 let pp_direction ppf dir =
164164- let text = match dir with
162162+ let text =
163163+ match dir with
165164 | `Negative -> "`Negative"
166166- | `Neutral -> "`Neutral"
165165+ | `Neutral -> "`Neutral"
167166 | `Positive -> "`Positive"
168167 in
169168 Format.pp_print_string ppf text
169169+ ;;
170170171171 let pp ppf g =
172172 Format.fprintf ppf "{ h = %a; v = %a }" pp_direction (h g) pp_direction (v g)
173173+ ;;
173174174174- let pair t1 t2 =
175175- (t1 lsl 4) lor t2
176176-175175+ let pair t1 t2 = (t1 lsl 4) lor t2
177176 let p1 t = (t lsr 4) land 15
178177 let p2 t = t land 15
179178end
179179+180180type gravity = Gravity.t
181181182182module Interval : sig
183183 type t = private int
184184+184185 val make : int -> int -> t
185186 val shift : t -> int -> t
186187 val fst : t -> int
187188 val snd : t -> int
189189+188190 (*val size : t -> int*)
189191 val zero : t
190192end = struct
···197199 let size = y - x in
198200 (*assert (size >= 0);*)
199201 (x lsl half) lor (size land mask)
200200-201201- let shift t d =
202202- t + d lsl half
202202+ ;;
203203204204+ let shift t d = t + (d lsl half)
204205 let fst t = t asr half
205206 let size t = t land mask
206207 let snd t = fst t + size t
207207-208208 let zero = 0
209209end
210210211211-module Ui =
212212-struct
211211+module Ui = struct
212212+ type mouse_handler =
213213+ x:int
214214+ -> y:int
215215+ -> Unescape.button
216216+ -> [ `Unhandled
217217+ | `Handled
218218+ | `Grab of (x:int -> y:int -> unit) * (x:int -> y:int -> unit)
219219+ ]
213220214214- type mouse_handler = x:int -> y:int -> Unescape.button -> [
215215- | `Unhandled
216216- | `Handled
217217- | `Grab of (x:int -> y:int -> unit) * (x:int -> y:int -> unit)
221221+ type semantic_key =
222222+ [ (* Clipboard *)
223223+ `Copy
224224+ | `Paste
225225+ | (* Focus management *)
226226+ `Focus of
227227+ [ `Out | `Next | `Prev | `Left | `Right | `Up | `Down ]
218228 ]
219229220220- type semantic_key = [
221221- (* Clipboard *)
222222- | `Copy
223223- | `Paste
224224- (* Focus management *)
225225- | `Focus of [`Out| `Next | `Prev | `Left | `Right | `Up | `Down]
226226- ]
230230+ type key =
231231+ [ Unescape.special | `Uchar of Uchar.t | `ASCII of char | semantic_key ]
232232+ * Unescape.mods
227233228228- type key = [
229229- | Unescape.special | `Uchar of Uchar.t | `ASCII of char | semantic_key
230230- ] * Unescape.mods
231231- type may_handle = [ `Unhandled | `Handled | `Remap of key ]
234234+ type may_handle =
235235+ [ `Unhandled
236236+ | `Handled
237237+ | `Remap of key
238238+ ]
232239233240 type mouse = Unescape.mouse
234241235235- type event = [ `Key of key | `Mouse of mouse | `Paste of Unescape.paste ]
242242+ type event =
243243+ [ `Key of key
244244+ | `Mouse of mouse
245245+ | `Paste of Unescape.paste
246246+ ]
236247237237- type layout_spec = { w : int; h : int; sw : int; sh : int ; mw : int; mh : int}
248248+ type layout_spec =
249249+ { w : int
250250+ ; h : int
251251+ ; sw : int
252252+ ; sh : int
253253+ ; mw : int
254254+ ; mh : int
255255+ }
238256239239- let pp_layout_spec ppf { w; h; sw; sh;mw;mh } =
240240- Format.fprintf ppf "{ w = %d; h = %d; sw = %d; sh = %d; mw= %d; mh=%d; }" w h sw sh mw mh
257257+ let pp_layout_spec ppf { w; h; sw; sh; mw; mh } =
258258+ Format.fprintf
259259+ ppf
260260+ "{ w = %d; h = %d; sw = %d; sh = %d; mw= %d; mh=%d; }"
261261+ w
262262+ h
263263+ sw
264264+ sh
265265+ mw
266266+ mh
267267+ ;;
241268242269 type flags = int
270270+243271 let flags_none = 0
244272 let flag_transient_sensor = 1
245273 let flag_permanent_sensor = 2
···247275 type size_sensor = w:int -> h:int -> unit
248276 type frame_sensor = x:int -> y:int -> w:int -> h:int -> unit -> unit
249277250250- type t = {
251251- w : int; sw : int;
252252- mw : int; mh : int;
253253- h : int; sh : int;
254254- mutable desc : desc;
255255- focus : Focus.status;
256256- mutable flags : flags;
257257- mutable sensor_cache : (int * int * int * int) option;
258258- mutable cache : cache;
259259- }
260260- and cache = {
261261- vx : Interval.t; vy : Interval.t;
262262- image : image;
263263- }
278278+ type t =
279279+ { w : int
280280+ ; sw : int
281281+ ; mw : int
282282+ ; mh : int
283283+ ; h : int
284284+ ; sh : int
285285+ ; mutable desc : desc
286286+ ; focus : Focus.status
287287+ ; mutable flags : flags
288288+ ; mutable sensor_cache : (int * int * int * int) option
289289+ ; mutable cache : cache
290290+ }
291291+292292+ and cache =
293293+ { vx : Interval.t
294294+ ; vy : Interval.t
295295+ ; image : image
296296+ }
297297+264298 and desc =
265299 | Atom of image
266300 | Size_sensor of t * size_sensor
···270304 | Mouse_handler of t * mouse_handler
271305 | Focus_area of t * (key -> may_handle)
272306 | Shift_area of t * int * int
273273- | Event_filter of t * ([`Key of key | `Mouse of mouse] -> may_handle)
307307+ | Event_filter of t * ([ `Key of key | `Mouse of mouse ] -> may_handle)
274308 | X of t * t
275309 | Y of t * t
276310 | Z of t * t
277311312312+ let layout_spec t : layout_spec =
313313+ { w = t.w; h = t.h; sw = t.sw; sh = t.sh; mw = t.mw; mh = t.mh }
314314+ ;;
278315279279- let layout_spec t : layout_spec =
280280- { w = t.w; h = t.h; sw = t.sw; sh = t.sh ; mw=t.mw; mh=t.mh }
281316 let layout_width t = t.w
282317 let layout_stretch_width t = t.sw
283318 let layout_height t = t.h
284319 let layout_stretch_height t = t.sh
285320 let layout_max_width t = t.mw
286321 let layout_max_height t = t.mh
287287-288288- let cache : cache =
289289- { vx = Interval.zero; vy = Interval.zero; image = I.empty }
322322+ let cache : cache = { vx = Interval.zero; vy = Interval.zero; image = I.empty }
290323291324 let empty : t =
292292- { w = 0; sw = 0; h = 0; sh = 0; mw= 0; mh=0; flags = flags_none;
293293- focus = Focus.empty; desc = Atom I.empty;
294294- sensor_cache = None; cache }
325325+ { w = 0
326326+ ; sw = 0
327327+ ; h = 0
328328+ ; sh = 0
329329+ ; mw = 0
330330+ ; mh = 0
331331+ ; flags = flags_none
332332+ ; focus = Focus.empty
333333+ ; desc = Atom I.empty
334334+ ; sensor_cache = None
335335+ ; cache
336336+ }
337337+ ;;
295338296339 let atom img : t =
297297- { w = I.width img; sw = 0;
298298- mw=I.width img;
299299- mh=I.height img;
300300- h = I.height img; sh = 0;
301301- focus = Focus.empty; flags = flags_none;
302302- desc = Atom img;
303303- sensor_cache = None; cache; }
340340+ { w = I.width img
341341+ ; sw = 0
342342+ ; mw = I.width img
343343+ ; mh = I.height img
344344+ ; h = I.height img
345345+ ; sh = 0
346346+ ; focus = Focus.empty
347347+ ; flags = flags_none
348348+ ; desc = Atom img
349349+ ; sensor_cache = None
350350+ ; cache
351351+ }
352352+ ;;
304353305354 let space_1_0 = atom (I.void 1 0)
306355 let space_0_1 = atom (I.void 0 1)
···313362 | 0, 1 -> space_0_1
314363 | 1, 1 -> space_1_1
315364 | _ -> atom (I.void x y)
365365+ ;;
316366317317- let mouse_area f t : t =
318318- { t with desc = Mouse_handler (t, f) }
367367+ let mouse_area f t : t = { t with desc = Mouse_handler (t, f) }
319368320369 let keyboard_area ?focus f t : t =
321321- let focus = match focus with
370370+ let focus =
371371+ match focus with
322372 | None -> t.focus
323373 | Some focus -> Focus.merge focus t.focus
324374 in
325375 { t with desc = Focus_area (t, f); focus }
376376+ ;;
326377327327- let shift_area x y t : t =
328328- { t with desc = Shift_area (t, x, y) }
329329-330330- let size_sensor handler t : t =
331331- { t with desc = Size_sensor (t, handler) }
378378+ let shift_area x y t : t = { t with desc = Shift_area (t, x, y) }
379379+ let size_sensor handler t : t = { t with desc = Size_sensor (t, handler) }
332380333381 let transient_sensor frame_sensor t =
334334- { t with desc = Transient_sensor (t, frame_sensor);
335335- flags = t.flags lor flag_transient_sensor }
382382+ { t with
383383+ desc = Transient_sensor (t, frame_sensor)
384384+ ; flags = t.flags lor flag_transient_sensor
385385+ }
386386+ ;;
336387337388 let permanent_sensor frame_sensor t =
338338- { t with desc = Permanent_sensor (t, frame_sensor);
339339- flags = t.flags lor flag_permanent_sensor }
389389+ { t with
390390+ desc = Permanent_sensor (t, frame_sensor)
391391+ ; flags = t.flags lor flag_permanent_sensor
392392+ }
393393+ ;;
340394341395 let prepare_gravity = function
342396 | None, None -> Gravity.(pair default default)
343397 | Some g, None | None, Some g -> Gravity.(pair g g)
344398 | Some pad, Some crop -> Gravity.(pair pad crop)
399399+ ;;
345400346346- let resize ?w ?h ?sw ?sh ?mw ?mh ?pad ?crop ?(bg=A.empty) t : t =
401401+ let resize ?w ?h ?sw ?sh ?mw ?mh ?pad ?crop ?(bg = A.empty) t : t =
347402 let g = prepare_gravity (pad, crop) in
348348- match (w, t.w), (h, t.h), (sw, t.sw), (sh, t.sh), (mw,t.mw) ,(mh,t.mh) with
349349- | (Some w, _ | None, w), (Some h, _ | None, h),
350350- (Some sw, _ | None, sw), (Some sh, _ | None, sh), (Some mw, _ | None, mw),(Some mh, _ | None, mh) ->
351351- let mw= if w>mw then w else mw
352352- and mh= if h>mh then h else mh
353353- in
354354- {t with w; h; sw; sh; mw; mh; desc = Resize (t, g, bg)}
403403+ match (w, t.w), (h, t.h), (sw, t.sw), (sh, t.sh), (mw, t.mw), (mh, t.mh) with
404404+ | ( (Some w, _ | None, w)
405405+ , (Some h, _ | None, h)
406406+ , (Some sw, _ | None, sw)
407407+ , (Some sh, _ | None, sh)
408408+ , (Some mw, _ | None, mw)
409409+ , (Some mh, _ | None, mh) ) ->
410410+ let mw = if w > mw then w else mw
411411+ and mh = if h > mh then h else mh in
412412+ { t with w; h; sw; sh; mw; mh; desc = Resize (t, g, bg) }
413413+ ;;
355414356356- let resize_to ({w; h; sw; sh;mw;mh} : layout_spec) ?pad ?crop ?(bg=A.empty) t : t =
415415+ let resize_to ({ w; h; sw; sh; mw; mh } : layout_spec) ?pad ?crop ?(bg = A.empty) t : t =
357416 let g = prepare_gravity (pad, crop) in
358358- let mw= if w>mw then w else mw
359359- and mh= if h>mh then h else mh
360360- in
361361- {t with w; h; sw; sh; mw; mh; desc = Resize (t, g, bg)}
417417+ let mw = if w > mw then w else mw
418418+ and mh = if h > mh then h else mh in
419419+ { t with w; h; sw; sh; mw; mh; desc = Resize (t, g, bg) }
420420+ ;;
362421363422 let event_filter ?focus f t : t =
364364- let focus = match focus with
423423+ let focus =
424424+ match focus with
365425 | None -> t.focus
366426 | Some focus -> focus
367427 in
368428 { t with desc = Event_filter (t, f); focus }
429429+ ;;
369430370370- let join_x a b = {
371371- w = (a.w + b.w); sw = (a.sw + b.sw);
372372- h = (maxi a.h b.h); sh = (maxi a.sh b.sh);
373373- mw=a.mw+b.mw;
374374- mh=maxi a.mh b.mh;
375375- flags = a.flags lor b.flags;
376376- focus = Focus.merge a.focus b.focus; desc = X (a, b);
377377- sensor_cache = None; cache
378378- }
431431+ let join_x a b =
432432+ { w = a.w + b.w
433433+ ; sw = a.sw + b.sw
434434+ ; h = maxi a.h b.h
435435+ ; sh = maxi a.sh b.sh
436436+ ; mw = a.mw + b.mw
437437+ ; mh = maxi a.mh b.mh
438438+ ; flags = a.flags lor b.flags
439439+ ; focus = Focus.merge a.focus b.focus
440440+ ; desc = X (a, b)
441441+ ; sensor_cache = None
442442+ ; cache
443443+ }
444444+ ;;
379445380380- let join_y a b = {
381381- w = (maxi a.w b.w); sw = (maxi a.sw b.sw);
382382- h = (a.h + b.h); sh = (a.sh + b.sh);
383383- mw=maxi a.mw b.mw;
384384- mh=a.mh+b.mh;
385385- flags = a.flags lor b.flags;
386386- focus = Focus.merge a.focus b.focus; desc = Y (a, b);
387387- sensor_cache = None; cache;
388388- }
446446+ let join_y a b =
447447+ { w = maxi a.w b.w
448448+ ; sw = maxi a.sw b.sw
449449+ ; h = a.h + b.h
450450+ ; sh = a.sh + b.sh
451451+ ; mw = maxi a.mw b.mw
452452+ ; mh = a.mh + b.mh
453453+ ; flags = a.flags lor b.flags
454454+ ; focus = Focus.merge a.focus b.focus
455455+ ; desc = Y (a, b)
456456+ ; sensor_cache = None
457457+ ; cache
458458+ }
459459+ ;;
389460390390- let join_z a b = {
391391- w = (maxi a.w b.w); sw = (maxi a.sw b.sw);
392392- h = (maxi a.h b.h); sh = (maxi a.sh b.sh);
393393- mw=maxi a.mw b.mw;
394394- mh=maxi a.mh b.mh;
395395- flags = a.flags lor b.flags;
396396- focus = Focus.merge a.focus b.focus; desc = Z (a, b);
397397- sensor_cache = None; cache;
398398- }
461461+ let join_z a b =
462462+ { w = maxi a.w b.w
463463+ ; sw = maxi a.sw b.sw
464464+ ; h = maxi a.h b.h
465465+ ; sh = maxi a.sh b.sh
466466+ ; mw = maxi a.mw b.mw
467467+ ; mh = maxi a.mh b.mh
468468+ ; flags = a.flags lor b.flags
469469+ ; focus = Focus.merge a.focus b.focus
470470+ ; desc = Z (a, b)
471471+ ; sensor_cache = None
472472+ ; cache
473473+ }
474474+ ;;
399475400400- let pack_x = (empty, join_x)
401401- let pack_y = (empty, join_y)
402402- let pack_z = (empty, join_z)
403403-476476+ let pack_x = empty, join_x
477477+ let pack_y = empty, join_y
478478+ let pack_z = empty, join_z
404479 let hcat xs = Lwd_utils.reduce pack_x xs
405480 let vcat xs = Lwd_utils.reduce pack_y xs
406481 let zcat xs = Lwd_utils.reduce pack_z xs
407407-408482 let has_focus t = Focus.has_focus t.focus
409483410484 let rec pp ppf t =
411411- Format.fprintf ppf
485485+ Format.fprintf
486486+ ppf
412487 "@[<hov>{@ w = %d;@ h = %d;@ sw = %d;@ sh = %d;@ desc = @[%a@];@ }@]"
413413- t.w t.h t.sw t.sh pp_desc t.desc
488488+ t.w
489489+ t.h
490490+ t.sw
491491+ t.sh
492492+ pp_desc
493493+ t.desc
414494415495 and pp_desc ppf = function
416416- | Atom _ -> Format.fprintf ppf "Atom _"
417417- | Size_sensor (desc, _) ->
418418- Format.fprintf ppf "Size_sensor (@[%a,@ _@])" pp desc
496496+ | Atom _ -> Format.fprintf ppf "Atom _"
497497+ | Size_sensor (desc, _) -> Format.fprintf ppf "Size_sensor (@[%a,@ _@])" pp desc
419498 | Transient_sensor (desc, _) ->
420499 Format.fprintf ppf "Transient_sensor (@[%a,@ _@])" pp desc
421500 | Permanent_sensor (desc, _) ->
422501 Format.fprintf ppf "Permanent_sensor (@[%a,@ _@])" pp desc
423502 | Resize (desc, gravity, _bg) ->
424424- Format.fprintf ppf "Resize (@[%a,@ %a,@ %a@])" pp desc
425425- Gravity.pp (Gravity.p1 gravity)
426426- Gravity.pp (Gravity.p2 gravity)
427427- | Mouse_handler (n, _) ->
428428- Format.fprintf ppf "Mouse_handler (@[%a,@ _@])" pp n
429429- | Focus_area (n, _) ->
430430- Format.fprintf ppf "Focus_area (@[%a,@ _@])" pp n
431431- | Shift_area (n, _, _) ->
432432- Format.fprintf ppf "Shift_area (@[%a,@ _@])" pp n
433433- | Event_filter (n, _) ->
434434- Format.fprintf ppf "Event_filter (@[%a,@ _@])" pp n
503503+ Format.fprintf
504504+ ppf
505505+ "Resize (@[%a,@ %a,@ %a@])"
506506+ pp
507507+ desc
508508+ Gravity.pp
509509+ (Gravity.p1 gravity)
510510+ Gravity.pp
511511+ (Gravity.p2 gravity)
512512+ | Mouse_handler (n, _) -> Format.fprintf ppf "Mouse_handler (@[%a,@ _@])" pp n
513513+ | Focus_area (n, _) -> Format.fprintf ppf "Focus_area (@[%a,@ _@])" pp n
514514+ | Shift_area (n, _, _) -> Format.fprintf ppf "Shift_area (@[%a,@ _@])" pp n
515515+ | Event_filter (n, _) -> Format.fprintf ppf "Event_filter (@[%a,@ _@])" pp n
435516 | X (a, b) -> Format.fprintf ppf "X (@[%a,@ %a@])" pp a pp b
436517 | Y (a, b) -> Format.fprintf ppf "Y (@[%a,@ %a@])" pp a pp b
437518 | Z (a, b) -> Format.fprintf ppf "Z (@[%a,@ %a@])" pp a pp b
519519+ ;;
438520439439- let iter f ui = match ui.desc with
521521+ let iter f ui =
522522+ match ui.desc with
440523 | Atom _ -> ()
441441- | Size_sensor (u, _) | Transient_sensor (u, _) | Permanent_sensor (u, _)
442442- | Resize (u, _, _) | Mouse_handler (u, _)
443443- | Focus_area (u, _) | Shift_area (u, _, _) | Event_filter (u, _)
444444- -> f u
445445- | X (u1, u2) | Y (u1, u2) | Z (u1, u2) -> f u1; f u2
524524+ | Size_sensor (u, _)
525525+ | Transient_sensor (u, _)
526526+ | Permanent_sensor (u, _)
527527+ | Resize (u, _, _)
528528+ | Mouse_handler (u, _)
529529+ | Focus_area (u, _)
530530+ | Shift_area (u, _, _)
531531+ | Event_filter (u, _) -> f u
532532+ | X (u1, u2) | Y (u1, u2) | Z (u1, u2) ->
533533+ f u1;
534534+ f u2
535535+ ;;
446536end
537537+447538type ui = Ui.t
448539449449-module Renderer =
450450-struct
540540+module Renderer = struct
451541 open Ui
452542453543 type size = int * int
454454-455544 type grab_function = (x:int -> y:int -> unit) * (x:int -> y:int -> unit)
456456- type t = {
457457- mutable size : size;
458458- mutable view : ui;
459459- mutable mouse_grab : grab_function option;
460460- }
461545462462- let make () = {
463463- mouse_grab = None;
464464- size = (0, 0);
465465- view = Ui.empty;
466466- }
546546+ type t =
547547+ { mutable size : size
548548+ ; mutable view : ui
549549+ ; mutable mouse_grab : grab_function option
550550+ }
467551552552+ let make () = { mouse_grab = None; size = 0, 0; view = Ui.empty }
468553 let size t = t.size
469469-470554471555 let solve_focus ui i =
472556 let rec aux ui =
···477561 | Focus.Conflict _ -> Ui.iter aux ui
478562 in
479563 aux ui
564564+ ;;
480565481481-(* this generates the share of a space between two ui elements *)
566566+ (* this generates the share of a space between two ui elements *)
482567 let split ~mA:aMax ~mB:bMax ~a ~sa ~b ~sb total =
483568 (*total stretch value*)
484569 let stretch = sa + sb in
485570 (*the free space the two elements have*)
486571 let flex = total - a - b in
487572 (*if we have a stretch value and space to stretch into*)
488488- let canStretch=stretch > 0 && flex > 0 in
489489-490490- if canStretch then
491491- let ratio =
492492- if sa > sb then
493493- flex * sa / stretch
494494- else
495495- flex - flex * sb / stretch
496496-497497-498498- in
573573+ let canStretch = stretch > 0 && flex > 0 in
574574+ if canStretch
575575+ then (
576576+ let ratio = if sa > sb then flex * sa / stretch else flex - (flex * sb / stretch) in
499577 (* this is way to complex but basically:
500500- 1. stretch a, if we hit max give the leftover to b
501501- 2. stretch b give the leftover to a
502502- 3. check if a is overstretched
578578+ 1. stretch a, if we hit max give the leftover to b
579579+ 2. stretch b give the leftover to a
580580+ 3. check if a is overstretched
503581 *)
504504- let aRatio,bRatio= ref (a+ratio), ref (b+flex-ratio) in
505505-506506- let aMaxed =ref false in
507507- if !aRatio>aMax then
508508- (
509509- bRatio:=!bRatio+(!aRatio-aMax);
510510- aRatio:=aMax ;
511511- aMaxed:=true
512512- );
513513- if (!bRatio)>bMax then
514514- begin
515515- if !aMaxed then
516516- bRatio:=bMax
517517- else
518518- aRatio:=!aRatio+(!bRatio-bMax);
519519- bRatio:=bMax;
520520- end;
521521- if !aRatio>aMax then
522522- aRatio:=aMax ;
523523-524524- (!aRatio,!bRatio)
525525-526526- else
527527- (a, b)
582582+ let aRatio, bRatio = ref (a + ratio), ref (b + flex - ratio) in
583583+ let aMaxed = ref false in
584584+ if !aRatio > aMax
585585+ then (
586586+ bRatio := !bRatio + (!aRatio - aMax);
587587+ aRatio := aMax;
588588+ aMaxed := true);
589589+ if !bRatio > bMax
590590+ then (
591591+ if !aMaxed then bRatio := bMax else aRatio := !aRatio + (!bRatio - bMax);
592592+ bRatio := bMax);
593593+ if !aRatio > aMax then aRatio := aMax;
594594+ !aRatio, !bRatio)
595595+ else a, b
596596+ ;;
528597529598 let pack ~max ~fixed ~stretch total g1 g2 =
530599 (*flex is the space we should expand into if we stretch*)
531600 let flex = total - fixed in
532532- if stretch > 0 && flex >= 0 && max >total then
533533- (0, total)
534534- else
535535- (* If we can stretch and we have space to expand into and we got here we must have wanted to stretch beyond the max which means we should stretch to max and recalculate the flex*)
536536- let (fixed,flex)=if stretch > 0 && total >= max then (max,total-max) else (fixed,flex) in
537537-601601+ if stretch > 0 && flex >= 0 && max > total
602602+ then 0, total
603603+ else (
604604+ (* If we can stretch and we have space to expand into and we got here we must have wanted to stretch beyond the max which means we should stretch to max and recalculate the flex*)
605605+ let fixed, flex =
606606+ if stretch > 0 && total >= max then max, total - max else fixed, flex
607607+ in
538608 let gravity = if flex >= 0 then g1 else g2 in
539539-540609 match gravity with
541541- | `Negative -> (0, fixed)
542542- | `Neutral -> (flex / 2, fixed)
543543- | `Positive -> (flex, fixed)
610610+ | `Negative -> 0, fixed
611611+ | `Neutral -> flex / 2, fixed
612612+ | `Positive -> flex, fixed)
613613+ ;;
544614545615 let has_transient_sensor flags = flags land flag_transient_sensor <> 0
546616 let has_permanent_sensor flags = flags land flag_permanent_sensor <> 0
547617548618 let rec update_sensors ox oy sw sh mw mh ui =
549549- if has_transient_sensor ui.flags || (
550550- has_permanent_sensor ui.flags &&
551551- match ui.sensor_cache with
552552- | None -> true
553553- | Some (ox', oy', sw', sh') ->
554554- not (ox = ox' && oy = oy' && sw = sw' && sh = sh')
555555- )
619619+ if has_transient_sensor ui.flags
620620+ || (has_permanent_sensor ui.flags
621621+ &&
622622+ match ui.sensor_cache with
623623+ | None -> true
624624+ | Some (ox', oy', sw', sh') ->
625625+ not (ox = ox' && oy = oy' && sw = sw' && sh = sh'))
556626 then (
557627 ui.flags <- ui.flags land lnot flag_transient_sensor;
558558- if has_permanent_sensor ui.flags then
559559- ui.sensor_cache <- Some (ox, oy, sw, sh);
628628+ if has_permanent_sensor ui.flags then ui.sensor_cache <- Some (ox, oy, sw, sh);
560629 match ui.desc with
561630 | Atom _ -> ()
562562- | Size_sensor (t, _) | Mouse_handler (t, _)
563563- | Focus_area (t, _) | Event_filter (t, _) ->
564564- update_sensors ox oy sw sh mw mh t
631631+ | Size_sensor (t, _) | Mouse_handler (t, _) | Focus_area (t, _) | Event_filter (t, _)
632632+ -> update_sensors ox oy sw sh mw mh t
565633 | Transient_sensor (t, sensor) ->
566634 ui.desc <- t.desc;
567635 let sensor = sensor ~x:ox ~y:oy ~w:sw ~h:sh in
568568- update_sensors ox oy sw sh mw mh t;
636636+ update_sensors ox oy sw sh mw mh t;
569637 sensor ()
570638 | Permanent_sensor (t, sensor) ->
571639 let sensor = sensor ~x:ox ~y:oy ~w:sw ~h:sh in
···575643 let open Gravity in
576644 let dx, rw = pack ~max:t.mw ~fixed:t.w ~stretch:t.sw sw (h (p1 g)) (h (p2 g)) in
577645 let dy, rh = pack ~max:t.mh ~fixed:t.h ~stretch:t.sh sh (v (p1 g)) (v (p2 g)) in
578578- update_sensors (ox + dx) (oy + dy) rw rh mw mh t
579579- | Shift_area (t, sx, sy) ->
580580- update_sensors (ox - sx) (oy - sy) sw sh mw mh t
646646+ update_sensors (ox + dx) (oy + dy) rw rh mw mh t
647647+ | Shift_area (t, sx, sy) -> update_sensors (ox - sx) (oy - sy) sw sh mw mh t
581648 | X (a, b) ->
582649 let aw, bw = split ~a:a.w ~sa:a.sw ~b:b.w ~sb:b.sw ~mA:a.mw ~mB:b.mw sw in
583650 update_sensors ox oy aw sh mw mh a;
···585652 | Y (a, b) ->
586653 let ah, bh = split ~a:a.h ~sa:a.sh ~b:b.h ~sb:b.sh ~mA:a.mh ~mB:b.mh sh in
587654 update_sensors ox oy sw ah mw mh a;
588588- update_sensors ox (oy + ah) sw bh mw mh b
655655+ update_sensors ox (oy + ah) sw bh mw mh b
589656 | Z (a, b) ->
590657 update_sensors ox oy sw sh mw mh a;
591591- update_sensors ox oy sw sh mw mh b
592592- )
658658+ update_sensors ox oy sw sh mw mh b)
659659+ ;;
593660594661 (** goes through all focuses and attempts to resolve any that have changed*)
595662 let update_focus ui =
596663 match ui.focus with
597664 | Focus.Empty | Focus.Handle _ -> ()
598665 | Focus.Conflict i -> solve_focus ui i
666666+ ;;
599667600668 let update t size ui =
601669 t.size <- size;
602670 t.view <- ui;
603671 (* TODO:I think i need to do something here*)
604604- update_sensors 0 0 (fst size) (snd size) (fst size) (snd size)ui;
672672+ update_sensors 0 0 (fst size) (snd size) (fst size) (snd size) ui;
605673 update_focus ui
674674+ ;;
606675607676 let dispatch_mouse st x y btn w h t =
608677 let handle ox oy f =
609678 match f ~x:(x - ox) ~y:(y - oy) btn with
610679 | `Unhandled -> false
611680 | `Handled -> true
612612- | `Grab f -> st.mouse_grab <- Some f; true
681681+ | `Grab f ->
682682+ st.mouse_grab <- Some f;
683683+ true
613684 in
614685 let rec aux ox oy sw sh t =
615686 match t.desc with
616687 | Atom _ -> false
617688 | X (a, b) ->
618689 let aw, bw = split ~a:a.w ~sa:a.sw ~b:b.w ~sb:b.sw ~mA:a.mh ~mB:b.mh sw in
619619- if x - ox < aw
620620- then aux ox oy aw sh a
621621- else aux (ox + aw) oy bw sh b
690690+ if x - ox < aw then aux ox oy aw sh a else aux (ox + aw) oy bw sh b
622691 | Y (a, b) ->
623692 let ah, bh = split ~a:a.h ~sa:a.sh ~b:b.h ~sb:b.sh ~mA:a.mh ~mB:b.mh sh in
624624- if y - oy < ah
625625- then aux ox oy sw ah a
626626- else aux ox (oy + ah) sw bh b
627627- | Z (a, b) ->
628628- aux ox oy sw sh b || aux ox oy sw sh a
693693+ if y - oy < ah then aux ox oy sw ah a else aux ox (oy + ah) sw bh b
694694+ | Z (a, b) -> aux ox oy sw sh b || aux ox oy sw sh a
629695 | Mouse_handler (t, f) ->
630696 let _offsetx, rw = pack ~max:t.mw ~fixed:t.w ~stretch:t.sw sw `Negative `Negative
631631- and _offsety, rh = pack ~max:t.mh~fixed:t.h ~stretch:t.sh sh `Negative `Negative
697697+ and _offsety, rh =
698698+ pack ~max:t.mh ~fixed:t.h ~stretch:t.sh sh `Negative `Negative
632699 in
633700 assert (_offsetx = 0 && _offsety = 0);
634634- (x - ox >= 0 && x - ox <= rw && y - oy >= 0 && y - oy <= rh) &&
635635- (aux ox oy sw sh t || handle ox oy f)
701701+ (x - ox >= 0 && x - ox <= rw && y - oy >= 0 && y - oy <= rh)
702702+ && (aux ox oy sw sh t || handle ox oy f)
636703 | Size_sensor (desc, _)
637637- | Transient_sensor (desc, _) | Permanent_sensor (desc, _)
638638- | Focus_area (desc, _) ->
639639- aux ox oy sw sh desc
640640- | Shift_area (desc, sx, sy) ->
641641- aux (ox - sx) (oy - sy) sw sh desc
704704+ | Transient_sensor (desc, _)
705705+ | Permanent_sensor (desc, _)
706706+ | Focus_area (desc, _) -> aux ox oy sw sh desc
707707+ | Shift_area (desc, sx, sy) -> aux (ox - sx) (oy - sy) sw sh desc
642708 | Resize (t, g, _bg) ->
643709 let open Gravity in
644644- let dx, rw = pack ~max:t.mw~fixed:t.w ~stretch:t.sw sw (h (p1 g)) (h (p2 g)) in
645645- let dy, rh = pack ~max:t.mh~fixed:t.h ~stretch:t.sh sh (v (p1 g)) (v (p2 g)) in
710710+ let dx, rw = pack ~max:t.mw ~fixed:t.w ~stretch:t.sw sw (h (p1 g)) (h (p2 g)) in
711711+ let dy, rh = pack ~max:t.mh ~fixed:t.h ~stretch:t.sh sh (v (p1 g)) (v (p2 g)) in
646712 aux (ox + dx) (oy + dy) rw rh t
647713 | Event_filter (n, f) ->
648648- begin match f (`Mouse (`Press btn, (x, y), [])) with
649649- | `Handled -> true
650650- | `Unhandled -> aux ox oy sw sh n
651651- | `Remap _ -> failwith "Cannot remap mouse events"
652652- end
714714+ (match f (`Mouse (`Press btn, (x, y), [])) with
715715+ | `Handled -> true
716716+ | `Unhandled -> aux ox oy sw sh n
717717+ | `Remap _ -> failwith "Cannot remap mouse events")
653718 in
654719 aux 0 0 w h t
720720+ ;;
655721656722 let release_grab st x y =
657723 match st.mouse_grab with
···659725 | Some (_, release) ->
660726 st.mouse_grab <- None;
661727 release ~x ~y
728728+ ;;
662729663730 let dispatch_mouse t (event, (x, y), _mods) =
664664- if
665665- match event with
666666- | `Press btn ->
667667- release_grab t x y;
668668- let w, h = t.size in
669669- dispatch_mouse t x y btn w h t.view
670670- | `Drag ->
671671- begin match t.mouse_grab with
731731+ if match event with
732732+ | `Press btn ->
733733+ release_grab t x y;
734734+ let w, h = t.size in
735735+ dispatch_mouse t x y btn w h t.view
736736+ | `Drag ->
737737+ (match t.mouse_grab with
672738 | None -> false
673673- | Some (drag, _) -> drag ~x ~y; true
674674- end
675675- | `Release ->
676676- release_grab t x y; true
739739+ | Some (drag, _) ->
740740+ drag ~x ~y;
741741+ true)
742742+ | `Release ->
743743+ release_grab t x y;
744744+ true
677745 then `Handled
678746 else `Unhandled
747747+ ;;
679748680749 let resize_canvas rw rh image =
681750 let w = I.width image in
682751 let h = I.height image in
683683- if w <> rw || h <> rh
684684- then I.pad ~r:(rw - w) ~b:(rh - h) image
685685- else image
752752+ if w <> rw || h <> rh then I.pad ~r:(rw - w) ~b:(rh - h) image else image
753753+ ;;
686754687755 let resize_canvas2 ox oy rw rh image =
688756 let w = I.width image in
689757 let h = I.height image in
690758 I.pad ~l:ox ~t:oy ~r:(rw - w - ox) ~b:(rh - h - oy) image
759759+ ;;
691760692692- let same_size w h image =
693693- w = I.width image &&
694694- h = I.height image
761761+ let same_size w h image = w = I.width image && h = I.height image
695762696763 let rec render_node vx1 vy1 vx2 vy2 sw sh t : cache =
697697- if
698698- let cache = t.cache in
699699- vx1 >= Interval.fst cache.vx && vy1 >= Interval.fst cache.vy &&
700700- vx2 <= Interval.snd cache.vx && vy2 <= Interval.snd cache.vy &&
701701- same_size sw sh cache.image
764764+ if let cache = t.cache in
765765+ vx1 >= Interval.fst cache.vx
766766+ && vy1 >= Interval.fst cache.vy
767767+ && vx2 <= Interval.snd cache.vx
768768+ && vy2 <= Interval.snd cache.vy
769769+ && same_size sw sh cache.image
702770 then t.cache
703703- else if vx2 < 0 || vy2 < 0 || sw < vx1 || sh < vy1 then
704704- let vx = Interval.make vx1 vx2 and vy = Interval.make vy1 vy2 in
705705- { vx; vy; image = I.void sw sh }
706706- else
707707- let cache = match t.desc with
771771+ else if vx2 < 0 || vy2 < 0 || sw < vx1 || sh < vy1
772772+ then (
773773+ let vx = Interval.make vx1 vx2
774774+ and vy = Interval.make vy1 vy2 in
775775+ { vx; vy; image = I.void sw sh })
776776+ else (
777777+ let cache =
778778+ match t.desc with
708779 | Atom image ->
709709- { vx = Interval.make 0 sw;
710710- vy = Interval.make 0 sh;
711711- image = resize_canvas sw sh image }
780780+ { vx = Interval.make 0 sw
781781+ ; vy = Interval.make 0 sh
782782+ ; image = resize_canvas sw sh image
783783+ }
712784 | Size_sensor (desc, handler) ->
713785 handler ~w:sw ~h:sh;
714786 render_node vx1 vy1 vx2 vy2 sw sh desc
···717789 | Focus_area (desc, _) | Mouse_handler (desc, _) ->
718790 render_node vx1 vy1 vx2 vy2 sw sh desc
719791 | Shift_area (t', sx, sy) ->
720720- let cache = render_node
721721- (vx1 + sx) (vy1 + sy) (vx2 + sx) (vy2 + sy) (sx + sw) (sy + sh) t'
792792+ let cache =
793793+ render_node (vx1 + sx) (vy1 + sy) (vx2 + sx) (vy2 + sy) (sx + sw) (sy + sh) t'
722794 in
723723- let vx = Interval.make vx1 vx2 and vy = Interval.make vy1 vy2 in
795795+ let vx = Interval.make vx1 vx2
796796+ and vy = Interval.make vy1 vy2 in
724797 let image = resize_canvas sw sh (I.crop ~l:sx ~t:sy cache.image) in
725798 { vx; vy; image }
726799 | X (a, b) ->
727800 let aw, bw = split ~a:a.w ~sa:a.sw ~b:b.w ~sb:b.sw ~mA:a.mw ~mB:b.mw sw in
728801 let ca = render_node vx1 vy1 vx2 vy2 aw sh a in
729802 let cb = render_node (vx1 - aw) vy1 (vx2 - aw) vy2 bw sh b in
730730- let vx = Interval.make
803803+ let vx =
804804+ Interval.make
731805 (maxi (Interval.fst ca.vx) (Interval.fst cb.vx + aw))
732806 (mini (Interval.snd ca.vx) (Interval.snd cb.vx + aw))
733733- and vy = Interval.make
807807+ and vy =
808808+ Interval.make
734809 (maxi (Interval.fst ca.vy) (Interval.fst cb.vy))
735810 (mini (Interval.snd ca.vy) (Interval.snd cb.vy))
736736- and image = resize_canvas sw sh (I.(<|>) ca.image cb.image) in
811811+ and image = resize_canvas sw sh (I.( <|> ) ca.image cb.image) in
737812 { vx; vy; image }
738813 | Y (a, b) ->
739814 let ah, bh = split ~a:a.h ~sa:a.sh ~b:b.h ~sb:b.sh ~mA:a.mh ~mB:b.mh sh in
740815 let ca = render_node vx1 vy1 vx2 vy2 sw ah a in
741816 let cb = render_node vx1 (vy1 - ah) vx2 (vy2 - ah) sw bh b in
742742- let vx = Interval.make
817817+ let vx =
818818+ Interval.make
743819 (maxi (Interval.fst ca.vx) (Interval.fst cb.vx))
744820 (mini (Interval.snd ca.vx) (Interval.snd cb.vx))
745745- and vy = Interval.make
821821+ and vy =
822822+ Interval.make
746823 (maxi (Interval.fst ca.vy) (Interval.fst cb.vy + ah))
747824 (mini (Interval.snd ca.vy) (Interval.snd cb.vy + ah))
748748- and image = resize_canvas sw sh (I.(<->) ca.image cb.image) in
825825+ and image = resize_canvas sw sh (I.( <-> ) ca.image cb.image) in
749826 { vx; vy; image }
750827 | Z (a, b) ->
751828 let ca = render_node vx1 vy1 vx2 vy2 sw sh a in
752829 let cb = render_node vx1 vy1 vx2 vy2 sw sh b in
753753- let vx = Interval.make
830830+ let vx =
831831+ Interval.make
754832 (maxi (Interval.fst ca.vx) (Interval.fst cb.vx))
755833 (mini (Interval.snd ca.vx) (Interval.snd cb.vx))
756756- and vy = Interval.make
834834+ and vy =
835835+ Interval.make
757836 (maxi (Interval.fst ca.vy) (Interval.fst cb.vy))
758837 (mini (Interval.snd ca.vy) (Interval.snd cb.vy))
759759- and image = resize_canvas sw sh (I.(</>) cb.image ca.image) in
838838+ and image = resize_canvas sw sh (I.( </> ) cb.image ca.image) in
760839 { vx; vy; image }
761840 | Resize (t, g, bg) ->
762841 let open Gravity in
763842 let dx, rw = pack ~max:t.mw ~fixed:t.w ~stretch:t.sw sw (h (p1 g)) (h (p2 g)) in
764843 let dy, rh = pack ~max:t.mh ~fixed:t.h ~stretch:t.sh sh (v (p1 g)) (v (p2 g)) in
765765- let c =
766766- render_node (vx1 - dx) (vy1 - dy) (vx2 - dx) (vy2 - dy) rw rh t
767767- in
844844+ let c = render_node (vx1 - dx) (vy1 - dy) (vx2 - dx) (vy2 - dy) rw rh t in
768845 let image = resize_canvas2 dx dy sw sh c.image in
769769- let image =
770770- if bg != A.empty then
771771- I.(image </> char bg ' ' sw sh)
772772- else
773773- image
774774- in
846846+ let image = if bg != A.empty then I.(image </> char bg ' ' sw sh) else image in
775847 let vx = Interval.shift c.vx dx in
776848 let vy = Interval.shift c.vy dy in
777849 { vx; vy; image }
778778- | Event_filter (t, _f) ->
779779- render_node vx1 vy1 vx2 vy2 sw sh t
850850+ | Event_filter (t, _f) -> render_node vx1 vy1 vx2 vy2 sw sh t
780851 in
781852 t.cache <- cache;
782782- cache
853853+ cache)
854854+ ;;
783855784784- let image {size = (w, h); view; _} =
856856+ let image { size = w, h; view; _ } =
785857 (*There is a weird quirk in how rending works that is fixed by having an empty top level node.
786786- See when you resize you actually resize the parent node and then insert a resize node. That means that if you resize at the top level It doesn't have a parent node and the resize doesn't apply. This is a very odd quirk which can be fixed by ensuring there is always a top level node that doesn't actually do anything.
787787- Hence we wrap everything in this resize node which does nothing.
858858+ See when you resize you actually resize the parent node and then insert a resize node. That means that if you resize at the top level It doesn't have a parent node and the resize doesn't apply. This is a very odd quirk which can be fixed by ensuring there is always a top level node that doesn't actually do anything.
859859+ Hence we wrap everything in this resize node which does nothing.
788860 *)
789789- (render_node 0 0 w h w h (view|>resize)).image
861861+ (render_node 0 0 w h w h (view |> resize)).image
862862+ ;;
790863791864 let rec dispatch_raw_key st key =
792792- let rec iter (sts: ui list) : [> `Unhandled] =
865865+ let rec iter (sts : ui list) : [> `Unhandled ] =
793866 match sts with
794867 | [] -> `Unhandled
795868 | ui :: tl ->
796796- begin match ui.desc with
797797- | Atom _ -> iter tl
798798- | X (a, b) | Y (a, b) | Z (a, b) ->
799799- (* Try left/top most branch first *)
800800- let st' =
801801- if Focus.has_focus b.focus&&Focus.has_focus a.focus
802802- then b::a :: tl
803803- else if Focus.has_focus b.focus
804804- then b :: tl
805805- else if Focus.has_focus a.focus
806806- then a :: tl
807807- (*If neither branch has focus we can just go down both*)
808808- else b::a :: tl
809809- in
810810- iter st'
811811- | Focus_area (t, f) ->
812812- begin match iter [t] with
813813- | `Unhandled ->
814814- begin
815815- match f key with
816816- | `Unhandled -> iter tl
817817- |other->other
818818- end
819819- |other->other
820820- end
821821- | Mouse_handler (t, _) | Size_sensor (t, _)
822822- | Transient_sensor (t, _) | Permanent_sensor (t, _)
823823- | Shift_area (t, _, _) | Resize (t, _, _) ->
824824- iter (t :: tl)
825825- | Event_filter (t, f) ->
826826- begin match f (`Key key) with
827827- | `Unhandled -> iter (t :: tl)
828828- | `Handled -> `Handled
829829- | `Remap key ->
830830- dispatch_raw_key st key
831831- end
832832- end
869869+ (match ui.desc with
870870+ | Atom _ -> iter tl
871871+ | X (a, b) | Y (a, b) | Z (a, b) ->
872872+ (* Try left/top most branch first *)
873873+ let st' =
874874+ if Focus.has_focus b.focus && Focus.has_focus a.focus
875875+ then b :: a :: tl
876876+ else if Focus.has_focus b.focus
877877+ then b :: tl
878878+ else if Focus.has_focus a.focus
879879+ then a :: tl (*If neither branch has focus we can just go down both*)
880880+ else b :: a :: tl
881881+ in
882882+ iter st'
883883+ | Focus_area (t, f) ->
884884+ (match iter [ t ] with
885885+ | `Unhandled ->
886886+ (match f key with
887887+ | `Unhandled -> iter tl
888888+ | other -> other)
889889+ | other -> other)
890890+ | Mouse_handler (t, _)
891891+ | Size_sensor (t, _)
892892+ | Transient_sensor (t, _)
893893+ | Permanent_sensor (t, _)
894894+ | Shift_area (t, _, _)
895895+ | Resize (t, _, _) -> iter (t :: tl)
896896+ | Event_filter (t, f) ->
897897+ (match f (`Key key) with
898898+ | `Unhandled -> iter (t :: tl)
899899+ | `Handled -> `Handled
900900+ | `Remap key -> dispatch_raw_key st key))
833901 in
834834- iter [st.view]
902902+ iter [ st.view ]
903903+ ;;
835904836905 exception Acquired_focus
837906···839908 let rec aux ui =
840909 match ui.focus with
841910 | Focus.Empty -> ()
842842- | Focus.Handle (_, v) -> Focus.request_var v; raise Acquired_focus
911911+ | Focus.Handle (_, v) ->
912912+ Focus.request_var v;
913913+ raise Acquired_focus
843914 | Focus.Conflict _ -> iter aux ui
844915 in
845845- try aux ui; false with Acquired_focus -> true
846846-916916+ try
917917+ aux ui;
918918+ false
919919+ with
920920+ | Acquired_focus -> true
921921+ ;;
847922848923 let rec dispatch_focus t dir =
849924 match t.desc with
850925 | Atom _ -> false
851851- | Mouse_handler (t, _) | Size_sensor (t, _)
852852- | Transient_sensor (t, _) | Permanent_sensor (t, _)
853853- | Shift_area (t, _, _) | Resize (t, _, _) | Event_filter (t, _) ->
854854- dispatch_focus t dir
926926+ | Mouse_handler (t, _)
927927+ | Size_sensor (t, _)
928928+ | Transient_sensor (t, _)
929929+ | Permanent_sensor (t, _)
930930+ | Shift_area (t, _, _)
931931+ | Resize (t, _, _)
932932+ | Event_filter (t, _) -> dispatch_focus t dir
855933 | Focus_area (t', _) ->
856856- begin
857857- match dir with
858858- | `Out ->
859859- (*If my element doesn't have focus then I should let a child element take focus or grab focus for myself.
860860- This should drill down until an element has focus and then let the next element up take the focus *)
861861- if (Focus.has_focus t'.focus) && (Focus.has_focus t.focus)then
862862- dispatch_focus t' dir ||grab_focus t
863863- else if not (Focus.has_focus t'.focus) then
864864- false
865865- else
866866- true
867867- |_->
868868- if Focus.has_focus t'.focus then
869869- dispatch_focus t' dir || grab_focus t
870870- else if Focus.has_focus t.focus then
871871- false
872872- else
873873- grab_focus t
874874- end
934934+ (match dir with
935935+ | `Out ->
936936+ (*If my element doesn't have focus then I should let a child element take focus or grab focus for myself.
937937+ This should drill down until an element has focus and then let the next element up take the focus *)
938938+ if Focus.has_focus t'.focus && Focus.has_focus t.focus
939939+ then dispatch_focus t' dir || grab_focus t
940940+ else if not (Focus.has_focus t'.focus)
941941+ then false
942942+ else true
943943+ | _ ->
944944+ if Focus.has_focus t'.focus
945945+ then dispatch_focus t' dir || grab_focus t
946946+ else if Focus.has_focus t.focus
947947+ then false
948948+ else grab_focus t)
875949 | X (a, b) ->
876876- begin if Focus.has_focus a.focus then
877877- dispatch_focus a dir ||
878878- (match dir with
879879- | `Out|`Next | `Right -> dispatch_focus b dir
880880- | _ -> false
881881- )
882882- else if Focus.has_focus b.focus then
883883- dispatch_focus b dir ||
884884- (match dir with
885885- | `Out|`Prev | `Left -> dispatch_focus a dir
886886- | _ -> false
887887- )
888888- else
889889- match dir with
890890- | `Out|`Prev | `Left | `Up -> dispatch_focus b dir || dispatch_focus a dir
891891- | `Next | `Down | `Right -> dispatch_focus a dir || dispatch_focus b dir
892892- |_->false
893893- end
950950+ if Focus.has_focus a.focus
951951+ then
952952+ dispatch_focus a dir
953953+ ||
954954+ match dir with
955955+ | `Out | `Next | `Right -> dispatch_focus b dir
956956+ | _ -> false
957957+ else if Focus.has_focus b.focus
958958+ then
959959+ dispatch_focus b dir
960960+ ||
961961+ match dir with
962962+ | `Out | `Prev | `Left -> dispatch_focus a dir
963963+ | _ -> false
964964+ else (
965965+ match dir with
966966+ | `Out | `Prev | `Left | `Up -> dispatch_focus b dir || dispatch_focus a dir
967967+ | `Next | `Down | `Right -> dispatch_focus a dir || dispatch_focus b dir
968968+ | _ -> false)
894969 | Y (a, b) ->
895895- begin if Focus.has_focus a.focus then
896896- dispatch_focus a dir ||
897897- (match dir with
898898- | `Out|`Next | `Down -> dispatch_focus b dir
899899- | _ -> false
900900- )
901901- else if Focus.has_focus b.focus then
902902- dispatch_focus b dir ||
903903- (match dir with
904904- | `Out|`Prev | `Up -> dispatch_focus a dir
905905- | _ -> false
906906- )
907907- else match dir with
908908- |`Out| `Prev | `Up -> dispatch_focus b dir || dispatch_focus a dir
909909- | `Next | `Left | `Down | `Right -> dispatch_focus a dir || dispatch_focus b dir
910910- |_->false
911911- end
970970+ if Focus.has_focus a.focus
971971+ then
972972+ dispatch_focus a dir
973973+ ||
974974+ match dir with
975975+ | `Out | `Next | `Down -> dispatch_focus b dir
976976+ | _ -> false
977977+ else if Focus.has_focus b.focus
978978+ then
979979+ dispatch_focus b dir
980980+ ||
981981+ match dir with
982982+ | `Out | `Prev | `Up -> dispatch_focus a dir
983983+ | _ -> false
984984+ else (
985985+ match dir with
986986+ | `Out | `Prev | `Up -> dispatch_focus b dir || dispatch_focus a dir
987987+ | `Next | `Left | `Down | `Right -> dispatch_focus a dir || dispatch_focus b dir
988988+ | _ -> false)
912989 | Z (a, b) ->
913913- if Focus.has_focus a.focus then
914914- dispatch_focus a dir
915915- else
916916- dispatch_focus b dir || dispatch_focus a dir
990990+ if Focus.has_focus a.focus
991991+ then dispatch_focus a dir
992992+ else dispatch_focus b dir || dispatch_focus a dir
993993+ ;;
917994918995 let rec dispatch_key st key =
919996 match dispatch_raw_key st key, key with
920997 | `Handled, _ -> `Handled
921998 | `Remap k, _ -> dispatch_key st k
922922- | `Unhandled, (`Arrow dir, [`Meta]) ->
923923- let dir : [`Down | `Left | `Right | `Up] :>
924924- [`Down | `Left | `Right |`Out| `Up | `Next | `Prev] = dir in
925925- dispatch_key st (`Focus dir, [`Meta])
999999+ | `Unhandled, (`Arrow dir, [ `Meta ]) ->
10001000+ let dir : [ `Down | `Left | `Right | `Up ]
10011001+ :> [ `Down | `Left | `Right | `Out | `Up | `Next | `Prev ]
10021002+ =
10031003+ dir
10041004+ in
10051005+ dispatch_key st (`Focus dir, [ `Meta ])
9261006 | `Unhandled, (`Tab, mods) ->
9271007 let dir = if List.mem `Shift mods then `Prev else `Next in
9281008 dispatch_key st (`Focus dir, mods)
9291009 | `Unhandled, (`Focus dir, _) ->
9301010 if dispatch_focus st.view dir then `Handled else `Unhandled
9311011 | `Unhandled, _ -> `Unhandled
10121012+ ;;
93210139331014 let dispatch_event t = function
9341015 | `Key key -> dispatch_key t key
9351016 | `Mouse mouse -> dispatch_mouse t mouse
9361017 | `Paste _ -> `Unhandled
10181018+ ;;
9371019end
9381020939939-module Ui_loop =
940940-struct
10211021+module Ui_loop = struct
9411022 open Notty_unix
94210239431024 (* FIXME Uses of [quick_sample] and [quick_release] should be replaced by
944944- [sample] and [release] with the appropriate release management. *)
10251025+ [sample] and [release] with the appropriate release management. *)
9451026946946- let step ?(process_event=true) ?(timeout=(-1.0)) ~renderer term root =
10271027+ let step ?(process_event = true) ?(timeout = -1.0) ~renderer term root =
9471028 let size = Term.size term in
9481029 let image =
9491030 let rec stabilize () =
9501031 let tree = Lwd.quick_sample root in
9511032 Renderer.update renderer size tree;
9521033 let image = Renderer.image renderer in
953953- if Lwd.is_damaged root
954954- then stabilize ()
955955- else image
10341034+ if Lwd.is_damaged root then stabilize () else image
9561035 in
9571036 stabilize ()
9581037 in
9591038 Term.image term image;
960960- if process_event then
10391039+ if process_event
10401040+ then (
9611041 let wait_for_event () =
9621042 let i, _ = Term.fds term in
9631043 let rec select () =
964964- match Unix.select [i] [] [i] timeout with
10441044+ match Unix.select [ i ] [] [ i ] timeout with
9651045 | [], [], [] -> Term.pending term
9661046 | _ -> true
967967- | exception (Unix.Unix_error (Unix.EINTR, _, _)) -> select ()
10471047+ | exception Unix.Unix_error (Unix.EINTR, _, _) -> select ()
9681048 in
9691049 select ()
9701050 in
9711051 let has_event = timeout < 0.0 || Term.pending term || wait_for_event () in
972972- if has_event then
10521052+ if has_event
10531053+ then (
9731054 match Term.event term with
9741055 | `End -> ()
9751056 | `Resize _ -> ()
9761057 | #Unescape.event as event ->
9771058 let event = (event : Unescape.event :> Ui.event) in
978978- ignore (Renderer.dispatch_event renderer event : [`Handled | `Unhandled])
10591059+ ignore (Renderer.dispatch_event renderer event : [ `Handled | `Unhandled ])))
10601060+ ;;
9791061980980- let run_with_term term ?tick_period ?(tick=ignore) ~renderer quit t =
10621062+ let run_with_term term ?tick_period ?(tick = ignore) ~renderer quit t =
9811063 let quit = Lwd.observe (Lwd.get quit) in
9821064 let root = Lwd.observe t in
9831065 let rec loop () =
9841066 let quit = Lwd.quick_sample quit in
985985- if not quit then (
10671067+ if not quit
10681068+ then (
9861069 step ~process_event:true ?timeout:tick_period ~renderer term root;
9871070 tick ();
988988- loop ()
989989- )
10711071+ loop ())
9901072 in
9911073 loop ();
9921074 ignore (Lwd.quick_release root);
9931075 ignore (Lwd.quick_release quit)
10761076+ ;;
9941077995995- let run ?tick_period ?tick ?term ?(renderer=Renderer.make ())
996996- ?quit ?(quit_on_escape=true) ?(quit_on_ctrl_q=true) t =
997997- let quit = match quit with
10781078+ let run
10791079+ ?tick_period
10801080+ ?tick
10811081+ ?term
10821082+ ?(renderer = Renderer.make ())
10831083+ ?quit
10841084+ ?(quit_on_escape = true)
10851085+ ?(quit_on_ctrl_q = true)
10861086+ t
10871087+ =
10881088+ let quit =
10891089+ match quit with
9981090 | Some quit -> quit
9991091 | None -> Lwd.var false
10001092 in
10011001- let t = Lwd.map t ~f:(Ui.event_filter (function
10021002- | `Key (`ASCII 'Q', [`Ctrl]) when quit_on_ctrl_q ->
10031003- Lwd.set quit true; `Handled
10041004- | `Key (`Escape, []) when quit_on_escape ->
10051005- Lwd.set quit true; `Handled
10061006- | _ -> `Unhandled
10071007- ))
10931093+ let t =
10941094+ Lwd.map
10951095+ t
10961096+ ~f:
10971097+ (Ui.event_filter (function
10981098+ | `Key (`ASCII 'Q', [ `Ctrl ]) when quit_on_ctrl_q ->
10991099+ Lwd.set quit true;
11001100+ `Handled
11011101+ | `Key (`Escape, []) when quit_on_escape ->
11021102+ Lwd.set quit true;
11031103+ `Handled
11041104+ | _ -> `Unhandled))
10081105 in
10091106 match term with
10101107 | Some term -> run_with_term term ?tick_period ?tick ~renderer quit t
···10121109 let term = Term.create () in
10131110 run_with_term term ?tick_period ?tick ~renderer quit t;
10141111 Term.release term
10151015-11121112+ ;;
10161113end
+12-4
forks/nottui/lib/nottui/widgets/overlays.ml
···219219 prompt_internal ?pad_w ?pad_h ~focus ~show_prompt:prompt_args ui
220220;;
221221222222-let popup ~show_popup_var ui =
222222+let popup ?(focus = Focus.make ()) ?on_key ~show_popup_var ui =
223223 let popup_ui =
224224 let$* show_popup = Lwd.get show_popup_var in
225225 match show_popup with
226226 | Some (content, label) ->
227227- let prompt_field = content in
228228- prompt_field |>$ Ui.resize ~w:5 ~sw:1 |> BB.box ~label_top:label |> clear_bg
229229- | None -> Ui.empty |> Lwd.pure
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;
231231+ prompt_field |> Ui.resize ~w:5 ~sw:1
232232+ in
233233+ ui |> BB.focusable ~focus ~label_top:label ?on_key |> clear_bg
234234+ | None ->
235235+ let$ status = Focus.status focus in
236236+ if Focus.has_focus status then Focus.release_reversable focus;
237237+ Ui.empty
230238 in
231239 W.zbox [ ui; popup_ui |>$ Ui.resize ~crop:neutral_grav ~pad:neutral_grav ]
232240;;
+2
forks/nottui/lib/nottui/widgets/overlays.mli
···75757676 (**This is a simple popup that can show ontop of other ui elements *)
7777val popup :
7878+ ?focus:Nottui_main.Focus.handle ->
7979+ ?on_key:(Nottui_main.Ui.key->Nottui_main.Ui.may_handle)->
7880 show_popup_var:(Nottui_main.ui Lwd.t * string) option Lwd.var ->
7981 Nottui_main.ui Lwd.t -> Nottui_main.ui Lwd.t
+17-6
forks/nottui/lib/nottui/widgets/selection_list.ml
···60606161let multi_selection_list_exclusions
6262 ?(focus = Focus.make ())
6363+ ?reset_selections
6364 ?(on_selection_change = fun ~hovered ~selected -> ())
6465 ~custom_handler
6566 (items : 'a maybe_multi_selectable array Lwd.t)
···7273 4. offset by the scroll amount, apply size sensors and output final ui
7374 *)
7475 let selected_items_var = Lwd.var MyMap.empty in
7676+ (*provides a way to set this from the outside*)
7777+ reset_selections
7878+ |> Option.iter (Signal.sub (fun x -> selected_items_var $= MyMap.empty));
7979+ (*Lets external functions to reset the selection*)
7580 (*hovered var is a tuple of (id, overall_idx,selection_idx)*)
7681 (*we set it up this way so we can avoid double rendering. We sometimes wish to change the value of the hover var during rendering and that would not update till the next render and cause a re-render*)
7782 let hovered_var = ref (0, 0, 0) in
···132137 on_selection_change
133138 ~hovered:item.data
134139 ~selected:
135135- (Lwd.peek selected_items_var |> MyMap.to_list |> List.map (fun (_,a) -> a));
140140+ (Lwd.peek selected_items_var |> MyMap.to_list |> List.map (fun (_, a) -> a));
136141 items, selectable_items)
137142 else items, selectable_items
138143 and$ _ = Lwd.get hover_changed
···167172 on_selection_change
168173 ~hovered:(selectable_items.(hovered_idx) |> snd).data
169174 ~selected:
170170- (Lwd.peek selected_items_var |> MyMap.to_list |> List.map (fun (_,a) -> a));
175175+ (Lwd.peek selected_items_var |> MyMap.to_list |> List.map (fun (_, a) -> a));
171176 `Handled
172177 | `Arrow `Down, [] ->
173178 let hovered_idx =
···181186 on_selection_change
182187 ~hovered:(selectable_items.(hovered_idx) |> snd).data
183188 ~selected:
184184- (Lwd.peek selected_items_var |> MyMap.to_list |> List.map (fun (_,a) -> a));
189189+ (Lwd.peek selected_items_var |> MyMap.to_list |> List.map (fun (_, a) -> a));
185190 `Handled
186191 | `ASCII ' ', [] ->
187192 let hovered_id, _, hovered_idx = !hovered_var in
188188- let data=
189189-(selectable_items.(hovered_idx) |> snd).data in let selected = Lwd.peek selected_items_var in
193193+ let data = (selectable_items.(hovered_idx) |> snd).data in
194194+ let selected = Lwd.peek selected_items_var in
190195 if selected |> MyMap.mem hovered_id
191196 then Lwd.set selected_items_var (MyMap.remove hovered_id selected)
192197 else Lwd.set selected_items_var (MyMap.add hovered_id data selected);
···194199 on_selection_change
195200 ~hovered:data
196201 ~selected:
197197- (Lwd.peek selected_items_var |> MyMap.to_list |> List.map (fun (_,a)-> a));
202202+ (Lwd.peek selected_items_var |> MyMap.to_list |> List.map (fun (_, a) -> a));
203203+ `Handled
204204+ | `Escape, [] ->
205205+ Lwd.set selected_items_var MyMap.empty;
198206 `Handled
199207 | a -> custom_handler ~selected:(Lwd.peek selected_items_var) ~selectable_items a)
200208 in
···382390383391let multi_selection_list_custom
384392 ?(focus = Focus.make ())
393393+ ?reset_selections
385394 ?(on_selection_change = fun ~hovered ~selected -> ())
386395 ~custom_handler
387396 (items : 'a multi_selectable_item list Lwd.t)
388397 =
389398 multi_selection_list_exclusions
390399 ~focus
400400+ ?reset_selections
391401 ~on_selection_change
392402 ~custom_handler
393403 (items
···395405 let selectable_items = Array.make (List.length items) (Obj.magic ()) in
396406 items |> List.iteri (fun i x -> Array.set selectable_items i (Selectable x));
397407 selectable_items)
408408+;;
398409399410let selection_list_custom
400411 ?(focus = Focus.make ())