zng_wgt_window/
events.rs

1//! Window events, [`on_window_open`](fn@on_window_open) and [`on_window_close_requested`](fn@on_window_close_requested).
2//!
3//! These events are re-exported by [`Window!`](struct@crate::Window) as `on_open` and `on_close_requested`, but you can
4//! attach then in any widget inside a window using the property full name.
5//!
6//! There is no event property for the [`WINDOW_CLOSE_EVENT`] because that event notifies
7//! after the window is deinited. You can use [`on_deinit`](fn@zng_wgt::on_deinit) in the
8//! [`Window!`](struct@crate::Window) widget to handle a window closing, or create an app level handler for the
9//! event using [`EVENTS`](zng_app::event::EVENTS).
10//!
11//! [`WINDOW_CLOSE_EVENT`]: zng_ext_window::WINDOW_CLOSE_EVENT
12
13use zng_ext_window::*;
14use zng_wgt::prelude::*;
15
16event_property! {
17    /// On window opened.
18    ///
19    /// This event notifies once per window, after the window content is inited.
20    #[property(EVENT)]
21    pub fn on_window_open<on_pre_window_open>(child: impl IntoUiNode, handler: Handler<WindowOpenArgs>) -> UiNode {
22        const PRE: bool;
23        EventNodeBuilder::new(WINDOW_OPEN_EVENT)
24            .filter(|| {
25                let id = WINDOW.id();
26                move |args| args.window_id == id
27            })
28            .build::<PRE>(child, handler)
29    }
30
31    /// On window loaded.
32    ///
33    /// This event notifies once per window, after the first layout and all [`WindowLoadingHandle`]
34    /// have expired or dropped.
35    ///
36    /// [`WindowLoadingHandle`]: zng_ext_window::WindowLoadingHandle
37    #[property(EVENT)]
38    pub fn on_window_load<on_pre_window_load>(child: impl IntoUiNode, handler: Handler<WindowOpenArgs>) -> UiNode {
39        const PRE: bool;
40        EventNodeBuilder::new(WINDOW_LOAD_EVENT)
41            .filter(|| {
42                let id = WINDOW.id();
43                move |args| args.window_id == id
44            })
45            .build::<PRE>(child, handler)
46    }
47
48    /// On window moved, resized or other state changed.
49    ///
50    /// This event aggregates events moves, resizes and other state changes into a
51    /// single event to simplify tracking composite changes, for example, the window changes size and position
52    /// when maximized, this can be trivially observed with this event.
53    #[property(EVENT)]
54    pub fn on_window_changed<on_pre_window_changed>(child: impl IntoUiNode, handler: Handler<WindowChangedArgs>) -> UiNode {
55        const PRE: bool;
56        EventNodeBuilder::new(WINDOW_CHANGED_EVENT)
57            .filter(|| {
58                let id = WINDOW.id();
59                move |args| args.window_id == id
60            })
61            .build::<PRE>(child, handler)
62    }
63
64    /// On window position changed.
65    #[property(EVENT)]
66    pub fn on_window_moved<on_pre_window_moved>(child: impl IntoUiNode, handler: Handler<WindowChangedArgs>) -> UiNode {
67        const PRE: bool;
68        EventNodeBuilder::new(WINDOW_CHANGED_EVENT)
69            .filter(|| {
70                let id = WINDOW.id();
71                move |args| args.window_id == id && args.is_moved()
72            })
73            .build::<PRE>(child, handler)
74    }
75
76    /// On window size changed.
77    #[property(EVENT)]
78    pub fn on_window_resized<on_pre_window_resized>(child: impl IntoUiNode, handler: Handler<WindowChangedArgs>) -> UiNode {
79        const PRE: bool;
80        EventNodeBuilder::new(WINDOW_CHANGED_EVENT)
81            .filter(|| {
82                let id = WINDOW.id();
83                move |args| args.window_id == id && args.is_resized()
84            })
85            .build::<PRE>(child, handler)
86    }
87
88    /// On window close requested.
89    ///
90    /// Calling `propagation().stop()` on this event cancels the window close.
91    #[property(EVENT)]
92    pub fn on_window_close_requested<on_pre_window_close_requested>(
93        child: impl IntoUiNode,
94        handler: Handler<WindowCloseRequestedArgs>,
95    ) -> UiNode {
96        const PRE: bool;
97        EventNodeBuilder::new(WINDOW_CLOSE_REQUESTED_EVENT)
98            .filter(|| {
99                let id = WINDOW.id();
100                move |args| args.windows.contains(&id)
101            })
102            .build::<PRE>(child, handler)
103    }
104
105    /// On window closed.
106    ///
107    /// See [`WINDOW_CLOSE_EVENT`] for more details of when this event notifies.
108    #[property(EVENT)]
109    pub fn on_window_close<on_pre_window_close>(child: impl IntoUiNode, handler: Handler<WindowCloseArgs>) -> UiNode {
110        const PRE: bool;
111        EventNodeBuilder::new(WINDOW_CLOSE_EVENT)
112            .filter(|| {
113                let id = WINDOW.id();
114                move |args| args.windows.contains(&id)
115            })
116            .build::<PRE>(child, handler)
117    }
118
119    /// On window state changed.
120    ///
121    /// This event notifies every time the user or the app changes the [`WindowVars::state`].
122    ///
123    /// [`WindowVars::state`]: zng_ext_window::WindowVars
124    #[property(EVENT)]
125    pub fn on_window_state_changed<on_pre_window_state_changed>(child: impl IntoUiNode, handler: Handler<WindowChangedArgs>) -> UiNode {
126        const PRE: bool;
127        EventNodeBuilder::new(WINDOW_CHANGED_EVENT)
128            .filter(|| {
129                let id = WINDOW.id();
130                move |args| args.window_id == id && args.is_state_changed()
131            })
132            .build::<PRE>(child, handler)
133    }
134
135    /// On window state changed to [`WindowState::Maximized`].
136    ///
137    /// [`WindowState::Maximized`]: zng_ext_window::WindowState::Maximized
138    #[property(EVENT)]
139    pub fn on_window_maximized<on_pre_window_maximized>(child: impl IntoUiNode, handler: Handler<WindowChangedArgs>) -> UiNode {
140        const PRE: bool;
141        EventNodeBuilder::new(WINDOW_CHANGED_EVENT)
142            .filter(|| {
143                let id = WINDOW.id();
144                move |args| args.window_id == id && args.entered_state(WindowState::Maximized)
145            })
146            .build::<PRE>(child, handler)
147    }
148
149    /// On window state changed from [`WindowState::Maximized`].
150    ///
151    /// [`WindowState::Maximized`]: zng_ext_window::WindowState::Maximized
152    #[property(EVENT)]
153    pub fn on_window_unmaximized<on_pre_window_unmaximized>(child: impl IntoUiNode, handler: Handler<WindowChangedArgs>) -> UiNode {
154        const PRE: bool;
155        EventNodeBuilder::new(WINDOW_CHANGED_EVENT)
156            .filter(|| {
157                let id = WINDOW.id();
158                move |args| args.window_id == id && args.exited_state(WindowState::Maximized)
159            })
160            .build::<PRE>(child, handler)
161    }
162
163    /// On window state changed to [`WindowState::Minimized`].
164    ///
165    /// [`WindowState::Minimized`]: zng_ext_window::WindowState::Minimized
166    #[property(EVENT)]
167    pub fn on_window_minimized<on_pre_window_minimized>(child: impl IntoUiNode, handler: Handler<WindowChangedArgs>) -> UiNode {
168        const PRE: bool;
169        EventNodeBuilder::new(WINDOW_CHANGED_EVENT)
170            .filter(|| {
171                let id = WINDOW.id();
172                move |args| args.window_id == id && args.entered_state(WindowState::Minimized)
173            })
174            .build::<PRE>(child, handler)
175    }
176
177    /// On window state changed from [`WindowState::Minimized`].
178    ///
179    /// [`WindowState::Minimized`]: zng_ext_window::WindowState::Minimized
180    #[property(EVENT)]
181    pub fn on_window_unminimized<on_pre_window_unminimized>(child: impl IntoUiNode, handler: Handler<WindowChangedArgs>) -> UiNode {
182        const PRE: bool;
183        EventNodeBuilder::new(WINDOW_CHANGED_EVENT)
184            .filter(|| {
185                let id = WINDOW.id();
186                move |args| args.window_id == id && args.exited_state(WindowState::Minimized)
187            })
188            .build::<PRE>(child, handler)
189    }
190
191    /// On window state changed to [`WindowState::Normal`].
192    ///
193    /// [`WindowState::Normal`]: zng_ext_window::WindowState::Normal
194    #[property(EVENT)]
195    pub fn on_window_restored<on_pre_window_restored>(child: impl IntoUiNode, handler: Handler<WindowChangedArgs>) -> UiNode {
196        const PRE: bool;
197        EventNodeBuilder::new(WINDOW_CHANGED_EVENT)
198            .filter(|| {
199                let id = WINDOW.id();
200                move |args| args.window_id == id && args.entered_state(WindowState::Normal)
201            })
202            .build::<PRE>(child, handler)
203    }
204
205    /// On window state changed to [`WindowState::is_fullscreen`].
206    ///
207    /// [`WindowState::is_fullscreen`]: zng_ext_window::WindowState::is_fullscreen
208    #[property(EVENT)]
209    pub fn on_window_fullscreen<on_pre_window_fullscreen>(child: impl IntoUiNode, handler: Handler<WindowChangedArgs>) -> UiNode {
210        const PRE: bool;
211        EventNodeBuilder::new(WINDOW_CHANGED_EVENT)
212            .filter(|| {
213                let id = WINDOW.id();
214                move |args| args.window_id == id && args.entered_fullscreen()
215            })
216            .build::<PRE>(child, handler)
217    }
218
219    /// On window state changed from [`WindowState::is_fullscreen`].
220    ///
221    /// [`WindowState::is_fullscreen`]: zng_ext_window::WindowState::is_fullscreen
222    #[property(EVENT)]
223    pub fn on_window_exited_fullscreen<on_pre_window_exited_fullscreen>(
224        child: impl IntoUiNode,
225        handler: Handler<WindowChangedArgs>,
226    ) -> UiNode {
227        const PRE: bool;
228        EventNodeBuilder::new(WINDOW_CHANGED_EVENT)
229            .filter(|| {
230                let id = WINDOW.id();
231                move |args| args.window_id == id && args.exited_fullscreen()
232            })
233            .build::<PRE>(child, handler)
234    }
235
236    /// On Input Method Editor event.
237    #[property(EVENT)]
238    pub fn on_ime<on_pre_ime>(child: impl IntoUiNode, handler: Handler<ImeArgs>) -> UiNode {
239        const PRE: bool;
240        EventNodeBuilder::new(IME_EVENT)
241            .filter(|| {
242                let id = WIDGET.id();
243                move |args| args.target.widget_id() == id
244            })
245            .build::<PRE>(child, handler)
246    }
247}
248
249#[cfg(feature = "image")]
250event_property! {
251    /// On window frame rendered.
252    #[property(EVENT)]
253    pub fn on_frame_image_ready<on_pre_frame_image_ready>(child: impl IntoUiNode, handler: Handler<FrameImageReadyArgs>) -> UiNode {
254        const PRE: bool;
255        EventNodeBuilder::new(FRAME_IMAGE_READY_EVENT)
256            .filter(|| {
257                let id = WINDOW.id();
258                move |args| args.window_id == id
259            })
260            .build::<PRE>(child, handler)
261    }
262}