-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathmod.rs
More file actions
235 lines (207 loc) · 5.93 KB
/
mod.rs
File metadata and controls
235 lines (207 loc) · 5.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
//! Winit wrapper to easily construct cross platform windows
use winit::{
dpi::{
LogicalSize,
PhysicalSize,
},
event::Event,
event_loop::{
ControlFlow,
EventLoop,
EventLoopBuilder,
EventLoopProxy,
EventLoopWindowTarget,
},
monitor::MonitorHandle,
window::{
Window,
WindowBuilder,
},
};
/// Embedded module for exporting data/types from winit as minimally/controlled
/// as possible. The exports from this module are not guaranteed to be stable.
pub mod winit_exports {
pub use winit::{
event::{
ElementState,
Event,
KeyEvent,
MouseButton,
WindowEvent,
},
event_loop::{
ControlFlow,
EventLoop,
EventLoopProxy,
EventLoopWindowTarget,
},
keyboard::{
KeyCode,
PhysicalKey,
},
};
}
/// LoopBuilder - Putting this here for consistency.
pub struct LoopBuilder;
impl LoopBuilder {
pub fn new() -> Self {
return Self;
}
pub fn build<Events: 'static + std::fmt::Debug>(self) -> Loop<Events> {
let event_loop = EventLoopBuilder::<Events>::with_user_event()
.build()
.expect("Failed to build event loop");
return Loop { event_loop };
}
}
/// Loop wrapping for the winit event loop.
pub struct Loop<E: 'static + std::fmt::Debug> {
event_loop: EventLoop<E>,
}
/// Structure that contains properties needed for building a window.
pub struct WindowProperties {
pub name: String,
pub dimensions: (u32, u32),
pub monitor_handle: MonitorHandle,
}
/// Metadata for Lambda window sizing that supports Copy and Move operations.
#[derive(Clone, Copy)]
pub struct WindowSize {
pub width: u32,
pub height: u32,
pub logical: LogicalSize<u32>,
pub physical: PhysicalSize<u32>,
}
/// Aggregated window handle with cached sizing and monitor metadata.
pub struct WindowHandle {
pub window_handle: Window,
pub size: WindowSize,
pub monitor_handle: MonitorHandle,
}
// Should we take the loop as a field right here? Probably a ref or something? IDK
/// Builder for constructing a `WindowHandle` from window properties.
pub struct WindowHandleBuilder {
window_handle: Option<Window>,
size: WindowSize,
monitor_handle: Option<MonitorHandle>,
}
impl WindowHandleBuilder {
/// Instantiate an empty builder
pub fn new() -> Self {
// Initialize the window size with some default values.
let logical: LogicalSize<u32> = [0, 0].into();
let physical = logical.to_physical(1.0);
let size = WindowSize {
width: 0,
height: 0,
logical,
physical,
};
return Self {
window_handle: None,
size,
monitor_handle: None,
};
}
/// Set the window size for the WindowHandle
fn with_window_size(
mut self,
window_size: (u32, u32),
scale_factor: f64,
) -> Self {
let logical: LogicalSize<u32> = window_size.into();
let physical: PhysicalSize<u32> = logical.to_physical(scale_factor);
let (width, height) = window_size;
let window_size = WindowSize {
width,
height,
logical,
physical,
};
self.size = window_size;
return self;
}
/// Probably the function that'll be used the most
pub fn with_window_properties<E: 'static + std::fmt::Debug>(
mut self,
window_properties: WindowProperties,
lambda_loop: &Loop<E>,
) -> Self {
let WindowProperties {
name,
dimensions,
monitor_handle,
} = window_properties;
// TODO(ahlawat) = Find out if there's a better way to do this. Looks kinda ugly.
self = self.with_window_size(dimensions, monitor_handle.scale_factor());
let window_handle = WindowBuilder::new()
.with_title(name)
.with_inner_size(self.size.logical)
.build(&lambda_loop.event_loop)
.expect("Failed creation of window handle");
self.monitor_handle = Some(monitor_handle);
self.window_handle = Some(window_handle);
return self;
}
/// Build the WindowHandle
pub fn build(self) -> WindowHandle {
return WindowHandle {
monitor_handle: self
.monitor_handle
.expect("Unable to find a MonitorHandle."),
size: self.size,
window_handle: self.window_handle.expect("Unable to find WindowHandle."),
};
}
}
/// Event loop publisher wrapper for pushing events into a winit event loop.
pub struct LoopPublisher<E: 'static> {
winit_proxy: EventLoopProxy<E>,
}
impl<E: 'static + std::fmt::Debug> LoopPublisher<E> {
/// New LoopPublishers are created from a lambda_loop directly and don't need
#[inline]
pub fn new(lambda_loop: &Loop<E>) -> Self {
let winit_proxy = lambda_loop.event_loop.create_proxy();
return LoopPublisher { winit_proxy };
}
/// Publishes an event into the event loop that created this publisher.
#[inline]
pub fn publish_event(&self, event: E) {
self
.winit_proxy
.send_event(event)
.expect("Failed to send event");
}
}
impl<E: 'static + std::fmt::Debug> Loop<E> {
/// Create an event publisher for this Loop.
pub fn create_event_publisher(&mut self) -> LoopPublisher<E> {
return LoopPublisher::new(&self);
}
/// Returns the primary monitor for the current OS if detectable.
pub fn get_primary_monitor(&self) -> Option<MonitorHandle> {
return self.event_loop.primary_monitor();
}
/// Get all monitors available on the system.
pub fn get_all_monitors(&self) -> impl Iterator<Item = MonitorHandle> {
return self.event_loop.available_monitors();
}
/// Gets the first available monitor or panics.
pub fn get_any_available_monitors(&self) -> Option<MonitorHandle> {
return self.event_loop.available_monitors().next();
}
/// Uses the winit event loop to run forever
pub fn run_forever<Callback>(self, mut callback: Callback)
where
Callback: 'static + FnMut(Event<E>, &EventLoopWindowTarget<E>),
{
self
.event_loop
.run(move |event, target| {
target.set_control_flow(ControlFlow::Poll);
callback(event, target);
})
.expect("Event loop terminated unexpectedly");
}
}