1use std::cell::{Cell, RefCell};
15
16use day_reactive::Signal;
17use day_spec::Edges;
18
19use crate::tree::{has_tree, with_tree};
20
21day_reactive::tls_slots! {
22 shield;
23 static DEFERRALS: RefCell<Vec<(u64, Edges)>> = const { RefCell::new(Vec::new()) };
24 static DISMISS_DISABLED: RefCell<Vec<u64>> = const { RefCell::new(Vec::new()) };
25 static STATUS_BAR: RefCell<Vec<(u64, bool)>> = const { RefCell::new(Vec::new()) };
28 static NEXT: Cell<u64> = const { Cell::new(1) };
29 static CHANGED: Cell<Option<Signal<u64>>> = const { Cell::new(None) };
32}
33
34fn changed_signal() -> Signal<u64> {
35 CHANGED.with(|c| match c.get() {
36 Some(s) => s,
37 None => {
38 let s = Signal::global(0);
39 c.set(Some(s));
40 s
41 }
42 })
43}
44
45fn next_token() -> u64 {
46 NEXT.with(|c| {
47 let t = c.get();
48 c.set(t + 1);
49 t
50 })
51}
52
53fn notify_changed() {
54 changed_signal().update(|v| *v = v.wrapping_add(1));
55}
56
57fn apply_deferral() {
58 let union = deferred_edges();
59 if has_tree() {
60 with_tree(|t| t.defer_system_gestures(union));
61 }
62 notify_changed();
63}
64
65pub fn push_gesture_deferral(edges: Edges) -> u64 {
68 let token = next_token();
69 DEFERRALS.with(|d| d.borrow_mut().push((token, edges)));
70 apply_deferral();
71 token
72}
73
74pub fn pop_gesture_deferral(token: u64) {
75 DEFERRALS.with(|d| d.borrow_mut().retain(|(t, _)| *t != token));
76 apply_deferral();
77}
78
79pub fn deferred_edges() -> Edges {
81 DEFERRALS.with(|d| {
82 d.borrow()
83 .iter()
84 .fold(Edges::NONE, |acc, (_, e)| acc.union(*e))
85 })
86}
87
88fn apply_status_bar() {
89 let hidden = status_bar_hidden();
90 if has_tree() {
91 with_tree(|t| t.set_status_bar_hidden(hidden));
92 }
93}
94
95pub fn push_status_bar_request(hidden: bool) -> u64 {
99 let token = next_token();
100 STATUS_BAR.with(|s| s.borrow_mut().push((token, hidden)));
101 apply_status_bar();
102 token
103}
104
105pub fn set_status_bar_request(token: u64, hidden: bool) {
107 let changed = STATUS_BAR.with(|s| {
108 let mut s = s.borrow_mut();
109 match s.iter_mut().find(|(t, _)| *t == token) {
110 Some((_, h)) if *h != hidden => {
111 *h = hidden;
112 true
113 }
114 _ => false,
115 }
116 });
117 if changed {
118 apply_status_bar();
119 }
120}
121
122pub fn pop_status_bar_request(token: u64) {
123 STATUS_BAR.with(|s| s.borrow_mut().retain(|(t, _)| *t != token));
124 apply_status_bar();
125}
126
127pub fn status_bar_hidden() -> bool {
129 STATUS_BAR.with(|s| s.borrow().iter().any(|(_, hidden)| *hidden))
130}
131
132pub fn push_dismiss_disabled() -> u64 {
135 let token = next_token();
136 DISMISS_DISABLED.with(|d| d.borrow_mut().push(token));
137 notify_changed();
138 token
139}
140
141pub fn pop_dismiss_disabled(token: u64) {
142 DISMISS_DISABLED.with(|d| d.borrow_mut().retain(|t| *t != token));
143 notify_changed();
144}
145
146pub fn dismiss_disabled() -> bool {
149 changed_signal().track();
150 DISMISS_DISABLED.with(|d| !d.borrow().is_empty())
151}