Skip to main content

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    /// If the window has a renderer this event notifies only after the window is loaded with renderer in the view-process.
37    ///
38    /// [`WindowLoadingHandle`]: zng_ext_window::WindowLoadingHandle
39    #[property(EVENT)]
40    pub fn on_window_load<on_pre_window_load>(child: impl IntoUiNode, handler: Handler<WindowOpenArgs>) -> UiNode {
41        const PRE: bool;
42        EventNodeBuilder::new(WINDOW_LOAD_EVENT)
43            .filter(|| {
44                let id = WINDOW.id();
45                move |args| args.window_id == id
46            })
47            .build::<PRE>(child, handler)
48    }
49
50    /// On window moved, resized or other state changed.
51    ///
52    /// This event aggregates events moves, resizes and other state changes into a
53    /// single event to simplify tracking composite changes, for example, the window changes size and position
54    /// when maximized, this can be trivially observed with this event.
55    #[property(EVENT)]
56    pub fn on_window_changed<on_pre_window_changed>(child: impl IntoUiNode, handler: Handler<WindowChangedArgs>) -> UiNode {
57        const PRE: bool;
58        EventNodeBuilder::new(WINDOW_CHANGED_EVENT)
59            .filter(|| {
60                let id = WINDOW.id();
61                move |args| args.window_id == id
62            })
63            .build::<PRE>(child, handler)
64    }
65
66    /// On window position changed.
67    #[property(EVENT)]
68    pub fn on_window_moved<on_pre_window_moved>(child: impl IntoUiNode, handler: Handler<WindowChangedArgs>) -> UiNode {
69        const PRE: bool;
70        EventNodeBuilder::new(WINDOW_CHANGED_EVENT)
71            .filter(|| {
72                let id = WINDOW.id();
73                move |args| args.window_id == id && args.is_moved()
74            })
75            .build::<PRE>(child, handler)
76    }
77
78    /// On window size changed.
79    #[property(EVENT)]
80    pub fn on_window_resized<on_pre_window_resized>(child: impl IntoUiNode, handler: Handler<WindowChangedArgs>) -> UiNode {
81        const PRE: bool;
82        EventNodeBuilder::new(WINDOW_CHANGED_EVENT)
83            .filter(|| {
84                let id = WINDOW.id();
85                move |args| args.window_id == id && args.is_resized()
86            })
87            .build::<PRE>(child, handler)
88    }
89
90    /// On window close requested.
91    ///
92    /// Calling `propagation().stop()` on this event cancels the window close.
93    #[property(EVENT)]
94    pub fn on_window_close_requested<on_pre_window_close_requested>(
95        child: impl IntoUiNode,
96        handler: Handler<WindowCloseRequestedArgs>,
97    ) -> UiNode {
98        const PRE: bool;
99        EventNodeBuilder::new(WINDOW_CLOSE_REQUESTED_EVENT)
100            .filter(|| {
101                let id = WINDOW.id();
102                move |args| args.windows.contains(&id)
103            })
104            .build::<PRE>(child, handler)
105    }
106
107    /// On window closed.
108    ///
109    /// See [`WINDOW_CLOSE_EVENT`] for more details of when this event notifies.
110    #[property(EVENT)]
111    pub fn on_window_close<on_pre_window_close>(child: impl IntoUiNode, handler: Handler<WindowCloseArgs>) -> UiNode {
112        const PRE: bool;
113        EventNodeBuilder::new(WINDOW_CLOSE_EVENT)
114            .filter(|| {
115                let id = WINDOW.id();
116                move |args| args.windows.contains(&id)
117            })
118            .build::<PRE>(child, handler)
119    }
120
121    /// On window state changed.
122    ///
123    /// This event notifies every time the user or the app changes the [`WindowVars::state`].
124    ///
125    /// [`WindowVars::state`]: zng_ext_window::WindowVars
126    #[property(EVENT)]
127    pub fn on_window_state_changed<on_pre_window_state_changed>(child: impl IntoUiNode, handler: Handler<WindowChangedArgs>) -> UiNode {
128        const PRE: bool;
129        EventNodeBuilder::new(WINDOW_CHANGED_EVENT)
130            .filter(|| {
131                let id = WINDOW.id();
132                move |args| args.window_id == id && args.is_state_changed()
133            })
134            .build::<PRE>(child, handler)
135    }
136
137    /// On window state changed to [`WindowState::Maximized`].
138    ///
139    /// [`WindowState::Maximized`]: zng_ext_window::WindowState::Maximized
140    #[property(EVENT)]
141    pub fn on_window_maximized<on_pre_window_maximized>(child: impl IntoUiNode, handler: Handler<WindowChangedArgs>) -> UiNode {
142        const PRE: bool;
143        EventNodeBuilder::new(WINDOW_CHANGED_EVENT)
144            .filter(|| {
145                let id = WINDOW.id();
146                move |args| args.window_id == id && args.entered_state(WindowState::Maximized)
147            })
148            .build::<PRE>(child, handler)
149    }
150
151    /// On window state changed from [`WindowState::Maximized`].
152    ///
153    /// [`WindowState::Maximized`]: zng_ext_window::WindowState::Maximized
154    #[property(EVENT)]
155    pub fn on_window_unmaximized<on_pre_window_unmaximized>(child: impl IntoUiNode, handler: Handler<WindowChangedArgs>) -> UiNode {
156        const PRE: bool;
157        EventNodeBuilder::new(WINDOW_CHANGED_EVENT)
158            .filter(|| {
159                let id = WINDOW.id();
160                move |args| args.window_id == id && args.exited_state(WindowState::Maximized)
161            })
162            .build::<PRE>(child, handler)
163    }
164
165    /// On window state changed to [`WindowState::Minimized`].
166    ///
167    /// [`WindowState::Minimized`]: zng_ext_window::WindowState::Minimized
168    #[property(EVENT)]
169    pub fn on_window_minimized<on_pre_window_minimized>(child: impl IntoUiNode, handler: Handler<WindowChangedArgs>) -> UiNode {
170        const PRE: bool;
171        EventNodeBuilder::new(WINDOW_CHANGED_EVENT)
172            .filter(|| {
173                let id = WINDOW.id();
174                move |args| args.window_id == id && args.entered_state(WindowState::Minimized)
175            })
176            .build::<PRE>(child, handler)
177    }
178
179    /// On window state changed from [`WindowState::Minimized`].
180    ///
181    /// [`WindowState::Minimized`]: zng_ext_window::WindowState::Minimized
182    #[property(EVENT)]
183    pub fn on_window_unminimized<on_pre_window_unminimized>(child: impl IntoUiNode, handler: Handler<WindowChangedArgs>) -> UiNode {
184        const PRE: bool;
185        EventNodeBuilder::new(WINDOW_CHANGED_EVENT)
186            .filter(|| {
187                let id = WINDOW.id();
188                move |args| args.window_id == id && args.exited_state(WindowState::Minimized)
189            })
190            .build::<PRE>(child, handler)
191    }
192
193    /// On window state changed to [`WindowState::Normal`].
194    ///
195    /// [`WindowState::Normal`]: zng_ext_window::WindowState::Normal
196    #[property(EVENT)]
197    pub fn on_window_restored<on_pre_window_restored>(child: impl IntoUiNode, handler: Handler<WindowChangedArgs>) -> UiNode {
198        const PRE: bool;
199        EventNodeBuilder::new(WINDOW_CHANGED_EVENT)
200            .filter(|| {
201                let id = WINDOW.id();
202                move |args| args.window_id == id && args.entered_state(WindowState::Normal)
203            })
204            .build::<PRE>(child, handler)
205    }
206
207    /// On window state changed to [`WindowState::is_fullscreen`].
208    ///
209    /// [`WindowState::is_fullscreen`]: zng_ext_window::WindowState::is_fullscreen
210    #[property(EVENT)]
211    pub fn on_window_fullscreen<on_pre_window_fullscreen>(child: impl IntoUiNode, handler: Handler<WindowChangedArgs>) -> UiNode {
212        const PRE: bool;
213        EventNodeBuilder::new(WINDOW_CHANGED_EVENT)
214            .filter(|| {
215                let id = WINDOW.id();
216                move |args| args.window_id == id && args.entered_fullscreen()
217            })
218            .build::<PRE>(child, handler)
219    }
220
221    /// On window state changed from [`WindowState::is_fullscreen`].
222    ///
223    /// [`WindowState::is_fullscreen`]: zng_ext_window::WindowState::is_fullscreen
224    #[property(EVENT)]
225    pub fn on_window_exited_fullscreen<on_pre_window_exited_fullscreen>(
226        child: impl IntoUiNode,
227        handler: Handler<WindowChangedArgs>,
228    ) -> UiNode {
229        const PRE: bool;
230        EventNodeBuilder::new(WINDOW_CHANGED_EVENT)
231            .filter(|| {
232                let id = WINDOW.id();
233                move |args| args.window_id == id && args.exited_fullscreen()
234            })
235            .build::<PRE>(child, handler)
236    }
237
238    /// On Input Method Editor event.
239    #[property(EVENT)]
240    pub fn on_ime<on_pre_ime>(child: impl IntoUiNode, handler: Handler<ImeArgs>) -> UiNode {
241        const PRE: bool;
242        EventNodeBuilder::new(IME_EVENT)
243            .filter(|| {
244                let id = WIDGET.id();
245                move |args| args.target.widget_id() == id
246            })
247            .build::<PRE>(child, handler)
248    }
249}
250
251#[cfg(feature = "image")]
252event_property! {
253    /// On window frame rendered and captured.
254    #[property(EVENT)]
255    pub fn on_frame_image_ready<on_pre_frame_image_ready>(child: impl IntoUiNode, handler: Handler<FrameImageReadyArgs>) -> UiNode {
256        const PRE: bool;
257        EventNodeBuilder::new(FRAME_IMAGE_READY_EVENT)
258            .filter(|| {
259                let id = WINDOW.id();
260                move |args| args.window_id == id
261            })
262            .build::<PRE>(child, handler)
263    }
264}