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
|
use crate::*;
use std::num::NonZeroU32;
use winit::dpi::{Size, PhysicalSize};
use winit::event_loop::EventLoopWindowTarget;
use winit::window::WindowId;
pub struct Window {
pub controller: Box<dyn WindowController>,
window: winit::window::Window,
buffer: Buffer,
dimensions: Dimensions,
#[allow(dead_code)] context: softbuffer::Context,
surface: softbuffer::Surface,
current_render_hint: RenderHint,
previous_cursor_position: Option<Point>,
}
impl Window {
pub fn new(event_loop: &EventLoopWindowTarget<()>, controller: Box<dyn WindowController>) -> Self {
let window = winit::window::WindowBuilder::new()
.with_title(controller.title())
.with_resizable(controller.is_resizable())
.with_inner_size(dim_to_size(controller.initial_size()))
.build(event_loop)
.unwrap();
let context = unsafe { softbuffer::Context::new(&window) }.unwrap();
let surface = unsafe { softbuffer::Surface::new(&context, &window) }.unwrap();
Self {
controller,
window,
buffer: Buffer::new(Dimensions::ZERO),
dimensions: Dimensions::ZERO,
context,
surface,
previous_cursor_position: None,
current_render_hint: RenderHint::Redraw,
}
}
pub fn id(&self) -> WindowId {
self.window.id()
}
pub fn update_title(&mut self) {
self.window.set_title(&self.controller.title());
}
pub fn update_cursor_icon(&mut self) {
let icon = self.controller.cursor_icon().unwrap_or(CursorIcon::Default);
self.window.set_cursor_icon(icon);
}
pub fn update_minimum_size(&mut self) {
let size = self.controller.minimum_size().map(|d| dim_to_size(d));
self.window.set_min_inner_size(size);
}
pub fn update_maximum_size(&mut self) {
let size = self.controller.maximum_size().map(|d| dim_to_size(d));
self.window.set_max_inner_size(size);
}
pub fn update_cursor_visible(&mut self) {
self.window.set_cursor_visible(self.controller.is_cursor_visible());
}
pub fn update_resizable(&mut self) {
let is_resizable = self.controller.is_resizable();
self.window.set_resizable(is_resizable);
// Hack to force window to be impossible to resize on DWM, where the
// 'is_resizable' window attribute isn't respected.
if !is_resizable {
self.window.set_min_inner_size(Some(self.window.inner_size()));
self.window.set_max_inner_size(Some(self.window.inner_size()));
}
}
/// Resize the frame buffer to be the new size of the window.
pub fn resize(&mut self, dimensions: Dimensions) {
if self.dimensions == dimensions { return }
self.dimensions = dimensions;
self.buffer.resize(dimensions);
if let Some((width, height)) = dim_to_nonzero_size(dimensions) {
self.surface.resize(width, height).unwrap();
};
self.controller.on_resize(dimensions);
self.current_render_hint = RenderHint::Redraw;
}
pub fn move_cursor(&mut self, position: Point) {
// The cursor position is rounded to i32 from f64, so we need to ignore
// duplicate consecutive cursor positions.
if self.previous_cursor_position != Some(position) {
self.previous_cursor_position = Some(position);
self.controller.on_cursor_move(position);
}
}
pub fn handle_render_request(&mut self) {
if let RenderRequest::Render(hint) = self.controller.render_request() {
self.current_render_hint &= hint;
self.window.request_redraw();
}
}
pub fn render(&mut self) {
let size = self.window.inner_size();
let dim = Dimensions::new(size.width, size.height);
self.resize(dim);
self.controller.on_render(&mut self.buffer, self.current_render_hint);
let buffer = self.buffer.as_u32_slice();
let mut surface = self.surface.buffer_mut().unwrap();
let buffer_len = buffer.len();
let surface_len = surface.len();
surface[..buffer_len].copy_from_slice(&buffer[..surface_len]);
surface.present().unwrap();
// Reset current_render_hint back to the lowest variant for the next frame.
self.current_render_hint = RenderHint::Update;
}
}
fn dim_to_size(dimensions: Dimensions) -> Size {
Size::Physical( PhysicalSize { width:dimensions.width, height:dimensions.height })
}
fn dim_to_nonzero_size(dimensions: Dimensions) -> Option<(NonZeroU32, NonZeroU32)> {
let width = NonZeroU32::new(dimensions.width)?;
let height = NonZeroU32::new(dimensions.height)?;
return Some((width, height));
}
|