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
|
mod x11;
use crate::*;
use raw_window_handle::{HasRawWindowHandle, RawWindowHandle};
use winit::dpi::{Size, PhysicalSize};
use winit::event_loop::EventLoopWindowTarget;
use winit::window::{WindowId, Window as WinitWindow, WindowBuilder as WinitWindowBuilder};
// use raw_gl_context::{GlConfig, GlContext};
pub struct Window {
pub controller: Box<dyn WindowController>,
cursor_position: Option<Point>,
winit_window: WinitWindow,
buffer: Buffer,
dimensions: Dimensions,
/// The most recent render request for this window.
render_hint: RenderHint,
graphics_context: Box<dyn GraphicsContext>,
// gl_context: GlContext,
}
impl Window {
pub unsafe fn new(event_loop: &EventLoopWindowTarget<()>, controller: Box<dyn WindowController>) -> Self {
let mut builder = WinitWindowBuilder::new();
builder = builder.with_resizable(controller.resizable());
builder = builder.with_inner_size({
let dim = controller.initial_dimensions();
Size::Physical(PhysicalSize::new(dim.width, dim.height))
});
if let Some(dim) = controller.minimum_dimensions() {
let size = Size::Physical(PhysicalSize { width: dim.width, height: dim.height });
builder = builder.with_min_inner_size(size);
}
if let Some(dim) = controller.maximum_dimensions() {
let size = Size::Physical(PhysicalSize { width: dim.width, height: dim.height });
builder = builder.with_max_inner_size(size);
}
let winit_window = builder.build(event_loop).unwrap();
let graphics_context: Box<dyn GraphicsContext> = match winit_window.raw_window_handle() {
RawWindowHandle::Xlib(xlib_handle) => Box::new(x11::X11GraphicsContext::new(xlib_handle)),
_ => panic!("Unknown window handle type"),
};
// let gl_context = GlContext::create(&winit_window, GlConfig::default()).unwrap();
// gl_context.make_current();
// gl::load_with(|symbol| {
// println!("Loaded '{}'", symbol);
// gl_context.get_proc_address(symbol) as *const _
// });
Self {
winit_window,
controller,
graphics_context,
render_hint: RenderHint::Redraw,
// gl_context,
buffer: Buffer::new(Dimensions::ZERO),
dimensions: Dimensions::ZERO,
cursor_position: None,
}
}
pub fn id(&self) -> WindowId {
self.winit_window.id()
}
pub fn set_minimum_dimensions(&mut self, dimensions: Option<Dimensions>) {
self.winit_window.set_min_inner_size(dimensions.map(|dim| {
Size::Physical(PhysicalSize { width:dim.width, height:dim.height })
}))
}
pub fn set_maximum_dimensions(&mut self, dimensions: Option<Dimensions>) {
self.winit_window.set_max_inner_size(dimensions.map(|dim| {
Size::Physical(PhysicalSize { width:dim.width, height:dim.height })
}))
}
pub fn set_title(&mut self, title: &str) {
self.winit_window.set_title(title);
}
/// Call to update the frame buffer to the new size of the window.
pub fn resize_buffer(&mut self, dimensions: Dimensions) {
if self.dimensions == dimensions { return }
self.dimensions = dimensions;
self.buffer.resize(dimensions);
self.controller.on_resize(dimensions);
self.render_hint = RenderHint::Redraw;
}
pub fn set_cursor_icon(&mut self, icon: Option<CursorIcon>) {
match icon {
Some(icon) => self.winit_window.set_cursor_icon(icon),
None => self.winit_window.set_cursor_icon(CursorIcon::Default),
};
}
/// Call this after a mouse click so that the cursor-hovering callbacks are
/// rerun. This is useful where a click changes the UI layout and a new
/// element that has an on-hover effect appears beneath the cursor.
pub fn bump_mouse(&mut self) {
if let Some(position) = self.cursor_position {
self.controller.on_mouse_move(position)
}
}
pub fn move_mouse(&mut self, position: Point) {
if self.cursor_position != Some(position) {
self.cursor_position = Some(position);
self.controller.on_mouse_move(position);
}
}
pub fn check_render_request(&mut self) {
if let RenderRequest::Render(hint) = self.controller.render_request() {
self.render_hint &= hint;
self.winit_window.request_redraw();
}
}
pub fn render(&mut self) {
self.controller.render(&mut self.buffer, self.render_hint);
unsafe { self.graphics_context.blit(&self.buffer); }
// Reset the render_hint back to the lowest variant.
self.render_hint = RenderHint::Update;
}
// pub fn render_gl(&mut self) {
// self.gl_context.make_current();
// self.controller.render_gl(&mut self.gl_context);
// self.gl_context.swap_buffers();
// self.gl_context.make_not_current();
// }
}
trait GraphicsContext {
/// Fill the graphics context with the contents of the provided buffer.
unsafe fn blit(&mut self, buffer: &Buffer);
}
|