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;