Skip to main content

goud_engine/core/events/
window.rs

1//! Window events.
2//!
3//! Contains events emitted when the window changes size, position, focus, or
4//! receives a close request.
5
6/// Emitted when the window has been resized.
7///
8/// This event fires whenever the window dimensions change, whether from
9/// user action (dragging window edges) or programmatic resize.
10///
11/// # Common Uses
12///
13/// - Update camera aspect ratios
14/// - Resize render targets and framebuffers
15/// - Adjust UI layout
16///
17/// # Example
18///
19/// ```rust
20/// use goud_engine::core::events::WindowResized;
21/// use goud_engine::core::event::Events;
22///
23/// fn handle_resize(events: &Events<WindowResized>) {
24///     let mut reader = events.reader();
25///     for event in reader.read() {
26///         let aspect = event.width as f32 / event.height as f32;
27///         println!("New size: {}x{}, aspect: {:.2}", event.width, event.height, aspect);
28///         // Update camera, resize framebuffers, etc.
29///     }
30/// }
31/// ```
32#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
33pub struct WindowResized {
34    /// New window width in pixels.
35    pub width: u32,
36    /// New window height in pixels.
37    pub height: u32,
38}
39
40impl WindowResized {
41    /// Creates a new `WindowResized` event.
42    #[must_use]
43    pub fn new(width: u32, height: u32) -> Self {
44        Self { width, height }
45    }
46
47    /// Returns the aspect ratio (width / height).
48    ///
49    /// Returns 0.0 if height is 0 to avoid division by zero.
50    #[must_use]
51    pub fn aspect_ratio(&self) -> f32 {
52        if self.height == 0 {
53            0.0
54        } else {
55            self.width as f32 / self.height as f32
56        }
57    }
58}
59
60impl Default for WindowResized {
61    fn default() -> Self {
62        Self::new(800, 600)
63    }
64}
65
66/// Emitted when the window gains or loses focus.
67///
68/// Use this to pause/resume gameplay, mute audio, or adjust input handling
69/// based on whether the window is in the foreground.
70///
71/// # Example
72///
73/// ```rust
74/// use goud_engine::core::events::WindowFocused;
75/// use goud_engine::core::event::Events;
76///
77/// fn handle_focus(events: &Events<WindowFocused>) {
78///     let mut reader = events.reader();
79///     for event in reader.read() {
80///         if event.focused {
81///             println!("Window gained focus - resuming");
82///             // Resume game, unmute audio
83///         } else {
84///             println!("Window lost focus - pausing");
85///             // Pause game, mute audio
86///         }
87///     }
88/// }
89/// ```
90#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
91pub struct WindowFocused {
92    /// `true` if the window now has focus, `false` if it lost focus.
93    pub focused: bool,
94}
95
96impl WindowFocused {
97    /// Creates a new `WindowFocused` event.
98    #[must_use]
99    pub fn new(focused: bool) -> Self {
100        Self { focused }
101    }
102
103    /// Creates an event indicating the window gained focus.
104    #[must_use]
105    pub fn gained() -> Self {
106        Self::new(true)
107    }
108
109    /// Creates an event indicating the window lost focus.
110    #[must_use]
111    pub fn lost() -> Self {
112        Self::new(false)
113    }
114}
115
116impl Default for WindowFocused {
117    fn default() -> Self {
118        Self::new(true)
119    }
120}
121
122/// Emitted when the window has been moved.
123///
124/// Contains the new position of the window's top-left corner in screen
125/// coordinates.
126///
127/// # Example
128///
129/// ```rust
130/// use goud_engine::core::events::WindowMoved;
131/// use goud_engine::core::event::Events;
132///
133/// fn handle_move(events: &Events<WindowMoved>) {
134///     let mut reader = events.reader();
135///     for event in reader.read() {
136///         println!("Window moved to ({}, {})", event.x, event.y);
137///     }
138/// }
139/// ```
140#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
141pub struct WindowMoved {
142    /// New X position of window's top-left corner in screen coordinates.
143    pub x: i32,
144    /// New Y position of window's top-left corner in screen coordinates.
145    pub y: i32,
146}
147
148impl WindowMoved {
149    /// Creates a new `WindowMoved` event.
150    #[must_use]
151    pub fn new(x: i32, y: i32) -> Self {
152        Self { x, y }
153    }
154}
155
156impl Default for WindowMoved {
157    fn default() -> Self {
158        Self::new(0, 0)
159    }
160}
161
162/// Emitted when the user requests to close the window.
163///
164/// This is a request, not a command. Games can intercept this event to
165/// show confirmation dialogs, save progress, or prevent accidental closure.
166///
167/// # Example
168///
169/// ```rust
170/// use goud_engine::core::events::WindowCloseRequested;
171/// use goud_engine::core::event::Events;
172///
173/// fn handle_close_request(events: &Events<WindowCloseRequested>) {
174///     let mut reader = events.reader();
175///     for _event in reader.read() {
176///         println!("Close requested - showing confirmation dialog");
177///         // Show "Are you sure?" dialog, save game, etc.
178///         // Only proceed with exit if user confirms
179///     }
180/// }
181/// ```
182#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
183pub struct WindowCloseRequested;