Skip to content

Commit

Permalink
WIP: Update to glutin 0.22
Browse files Browse the repository at this point in the history
  • Loading branch information
mbrubeck committed Jan 30, 2020
1 parent c9b89f3 commit 951e620
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 52 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ path = "src/lib.rs"

[dependencies]
gl = "0.11.0"
glutin = "0.21.0"
glutin = "0.22.0"
pistoncore-input = "0.28.0"
pistoncore-window = "0.44.0"
shader_version = "0.6.0"
155 changes: 104 additions & 51 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ use window::{
UnsupportedGraphicsApiError,
};
use glutin::GlRequest;
use glutin::platform::desktop::EventLoopExtDesktop;
use std::time::Duration;
use std::thread;

Expand All @@ -45,7 +46,7 @@ pub use shader_version::OpenGL;
/// Contains stuff for game window.
pub struct GlutinWindow {
/// The window.
pub ctx: glutin::ContextWrapper<glutin::PossiblyCurrent, glutin::Window>,
pub ctx: glutin::ContextWrapper<glutin::PossiblyCurrent, glutin::window::Window>,
// The back-end does not remember the title.
title: String,
exit_on_esc: bool,
Expand All @@ -61,22 +62,24 @@ pub struct GlutinWindow {
// Used to emit cursor event after enter/leave.
cursor_pos: Option<[f64; 2]>,
// Polls events from window.
events_loop: glutin::EventsLoop,
event_loop: glutin::event_loop::EventLoop<()>,
// Stores list of events ready for processing.
events: VecDeque<glutin::Event>,
events: VecDeque<glutin::event::Event<'static, ()>>,
}

fn window_builder_from_settings(settings: &WindowSettings) -> glutin::WindowBuilder {
let size = settings.get_size();
let mut builder = glutin::WindowBuilder::new()
.with_dimensions((size.width, size.height).into())
fn window_builder_from_settings(settings: &WindowSettings) -> glutin::window::WindowBuilder {
let Size { width, height } = settings.get_size();
let size = glutin::dpi::LogicalSize { width, height };
let mut builder = glutin::window::WindowBuilder::new()
.with_inner_size(size)
.with_decorations(settings.get_decorated())
.with_multitouch()
.with_title(settings.get_title())
.with_resizable(settings.get_resizable());
if settings.get_fullscreen() {
let events_loop = glutin::EventsLoop::new();
builder = builder.with_fullscreen(Some(events_loop.get_primary_monitor()));
let event_loop = glutin::event_loop::EventLoop::new();
let monitor = event_loop.primary_monitor();
let fullscreen = glutin::window::Fullscreen::Borderless(monitor);
builder = builder.with_fullscreen(Some(fullscreen));
}
builder
}
Expand Down Expand Up @@ -111,19 +114,19 @@ impl GlutinWindow {

/// Creates a new game window for Glutin.
pub fn new(settings: &WindowSettings) -> Result<Self, Box<Error>> {
let events_loop = glutin::EventsLoop::new();
let event_loop = glutin::event_loop::EventLoop::new();
let title = settings.get_title();
let exit_on_esc = settings.get_exit_on_esc();
let window_builder = window_builder_from_settings(&settings);
let context_builder = context_builder_from_settings(&settings)?;
let ctx = context_builder.build_windowed(window_builder, &events_loop);
let ctx = context_builder.build_windowed(window_builder, &event_loop);
let ctx = match ctx {
Ok(ctx) => ctx,
Err(_) => {
let settings = settings.clone().samples(0);
let window_builder = window_builder_from_settings(&settings);
let context_builder = context_builder_from_settings(&settings)?;
let ctx = context_builder.build_windowed(window_builder, &events_loop)?;
let ctx = context_builder.build_windowed(window_builder, &event_loop)?;
ctx
}
};
Expand All @@ -142,7 +145,7 @@ impl GlutinWindow {
is_capturing_cursor: false,
last_cursor_pos: None,
mouse_relative: None,
events_loop,
event_loop,
events: VecDeque::new(),
})
}
Expand All @@ -155,9 +158,11 @@ impl GlutinWindow {
loop {
{
let ref mut events = self.events;
self.events_loop.run_forever(|ev| {
events.push_back(ev);
glutin::ControlFlow::Break
self.event_loop.run_return(|ev, _, control_flow| {
if let Some(event) = to_static_event(ev) {
events.push_back(event);
}
*control_flow = glutin::event_loop::ControlFlow::Exit;
});
}

Expand All @@ -173,26 +178,28 @@ impl GlutinWindow {
return Some(event);
}
// Schedule wake up when time is out.
let events_loop_proxy = self.events_loop.create_proxy();
let event_loop_proxy = self.event_loop.create_proxy();
thread::spawn(move || {
thread::sleep(timeout);
// Wakeup can fail only if the event loop went away.
events_loop_proxy.wakeup().ok();
// `send_event` can fail only if the event loop went away.
event_loop_proxy.send_event(()).ok();
});
{
let ref mut events = self.events;
self.events_loop.run_forever(|ev| {
events.push_back(ev);
glutin::ControlFlow::Break
self.event_loop.run_return(|ev, _, control_flow| {
if let Some(event) = to_static_event(ev) {
events.push_back(event);
}
*control_flow = glutin::event_loop::ControlFlow::Exit;
});
}

self.poll_event()
}

fn poll_event(&mut self) -> Option<Event> {
use glutin::Event as E;
use glutin::WindowEvent as WE;
use glutin::event::Event as E;
use glutin::event::WindowEvent as WE;

// Loop to skip unknown events.
loop {
Expand All @@ -201,7 +208,7 @@ impl GlutinWindow {

if self.events.len() == 0 {
let ref mut events = self.events;
self.events_loop.poll_events(|ev| events.push_back(ev));
self.event_loop.poll_events(|ev| events.push_back(ev));
}
let mut ev = self.events.pop_front();

Expand All @@ -212,11 +219,11 @@ impl GlutinWindow {
}) = ev {
// Ignore this event since mouse positions
// should not be emitted when capturing cursor.
self.last_cursor_pos = Some([position.x, position.y]);
self.last_cursor_pos = Some([position.x.into(), position.y.into()]);

if self.events.len() == 0 {
let ref mut events = self.events;
self.events_loop.poll_events(|ev| events.push_back(ev));
self.event_loop.poll_events(|ev| events.push_back(ev));
}
ev = self.events.pop_front();
}
Expand Down Expand Up @@ -255,10 +262,10 @@ impl GlutinWindow {
/// The `unknown` flag is set to `true` when the event is not recognized.
/// This is used to poll another event to make the event loop logic sound.
/// When `unknown` is `true`, the return value is `None`.
fn handle_event(&mut self, ev: Option<glutin::Event>, unknown: &mut bool) -> Option<Input> {
use glutin::Event as E;
use glutin::WindowEvent as WE;
use glutin::MouseScrollDelta;
fn handle_event(&mut self, ev: Option<glutin::event::Event<()>>, unknown: &mut bool) -> Option<Input> {
use glutin::event::Event as E;
use glutin::event::WindowEvent as WE;
use glutin::event::MouseScrollDelta;
use input::{ Key, Motion };

match ev {
Expand Down Expand Up @@ -296,8 +303,8 @@ impl GlutinWindow {
Some(Input::Focus(focused)),
Some(E::WindowEvent {
event: WE::KeyboardInput{
input: glutin::KeyboardInput{
state: glutin::ElementState::Pressed,
input: glutin::event::KeyboardInput{
state: glutin::event::ElementState::Pressed,
virtual_keycode: Some(key), scancode, ..
}, ..
}, ..
Expand All @@ -314,8 +321,8 @@ impl GlutinWindow {
},
Some(E::WindowEvent {
event: WE::KeyboardInput{
input: glutin::KeyboardInput{
state: glutin::ElementState::Released,
input: glutin::event::KeyboardInput{
state: glutin::event::ElementState::Released,
virtual_keycode: Some(key), scancode, ..
}, ..
}, ..
Expand All @@ -326,9 +333,9 @@ impl GlutinWindow {
scancode: Some(scancode as i32),
})),
Some(E::WindowEvent {
event: WE::Touch(glutin::Touch { phase, location, id, .. }), ..
event: WE::Touch(glutin::event::Touch { phase, location, id, .. }), ..
}) => {
use glutin::TouchPhase;
use glutin::event::TouchPhase;
use input::{Touch, TouchArgs};

Some(Input::Move(Motion::Touch(TouchArgs::new(
Expand Down Expand Up @@ -375,14 +382,14 @@ impl GlutinWindow {
event: WE::MouseWheel{delta: MouseScrollDelta::LineDelta(x, y), ..}, ..
}) => Some(Input::Move(Motion::MouseScroll([x as f64, y as f64]))),
Some(E::WindowEvent {
event: WE::MouseInput{state: glutin::ElementState::Pressed, button, ..}, ..
event: WE::MouseInput{state: glutin::event::ElementState::Pressed, button, ..}, ..
}) => Some(Input::Button(ButtonArgs {
state: ButtonState::Press,
button: Button::Mouse(map_mouse(button)),
scancode: None,
})),
Some(E::WindowEvent {
event: WE::MouseInput{state: glutin::ElementState::Released, button, ..}, ..
event: WE::MouseInput{state: glutin::event::ElementState::Released, button, ..}, ..
}) => Some(Input::Button(ButtonArgs {
state: ButtonState::Release,
button: Button::Mouse(map_mouse(button)),
Expand Down Expand Up @@ -484,15 +491,14 @@ impl AdvancedWindow for GlutinWindow {
Position { x: pos.x as i32, y: pos.y as i32 })
}
fn set_position<P: Into<Position>>(&mut self, pos: P) {
let pos: Position = pos.into();
self.ctx.window().set_position((pos.x, pos.y).into());
let Position { x, y }= pos.into();
let pos = glutin::dpi::LogicalPosition { x, y };
self.ctx.window().set_outer_position(pos);
}
fn set_size<S: Into<Size>>(&mut self, size: S) {
let size: Size = size.into();
self.ctx.window().set_inner_size((
size.width as f64,
size.height as f64,
).into());
let Size { width, height } = size.into();
let size = glutin::dpi::LogicalSize { width, height };
self.ctx.window().set_inner_size(size);
}
}

Expand All @@ -514,9 +520,9 @@ impl OpenGLWindow for GlutinWindow {
}

/// Maps Glutin's key to Piston's key.
pub fn map_key(keycode: glutin::VirtualKeyCode) -> keyboard::Key {
pub fn map_key(keycode: glutin::event::VirtualKeyCode) -> keyboard::Key {
use input::keyboard::Key;
use glutin::VirtualKeyCode as K;
use glutin::event::VirtualKeyCode as K;

match keycode {
K::Key0 => Key::D0,
Expand Down Expand Up @@ -644,8 +650,8 @@ pub fn map_key(keycode: glutin::VirtualKeyCode) -> keyboard::Key {
}

/// Maps Glutin's mouse button to Piston's mouse button.
pub fn map_mouse(mouse_button: glutin::MouseButton) -> MouseButton {
use glutin::MouseButton as M;
pub fn map_mouse(mouse_button: glutin::event::MouseButton) -> MouseButton {
use glutin::event::MouseButton as M;

match mouse_button {
M::Left => MouseButton::Left,
Expand All @@ -659,3 +665,50 @@ pub fn map_mouse(mouse_button: glutin::MouseButton) -> MouseButton {
_ => MouseButton::Unknown
}
}

// XXX Massive Hack XXX: `wait_event` and `wait_event_timeout` can't handle non-'static events, so
// they need to ignore events like `WindowEvent::ScaleFactorChanged` that contain references.
fn to_static_event(event: glutin::event::Event<()>) -> Option<glutin::event::Event<'static, ()>> {
use glutin::event::Event as E;
use glutin::event::WindowEvent as WE;
let event = match event {
E::NewEvents(s) => E::NewEvents(s),
E::WindowEvent { window_id, event } => E::WindowEvent {
window_id,
event: match event {
WE::Resized(size) => WE::Resized(size),
WE::Moved(pos) => WE::Moved(pos),
WE::CloseRequested => WE::CloseRequested,
WE::Destroyed => WE::Destroyed,
WE::DroppedFile(path) => WE::DroppedFile(path),
WE::HoveredFile(path) => WE::HoveredFile(path),
WE::HoveredFileCancelled => WE::HoveredFileCancelled,
WE::ReceivedCharacter(c) => WE::ReceivedCharacter(c),
WE::Focused(b) => WE::Focused(b),
WE::KeyboardInput { device_id, input, is_synthetic } => WE::KeyboardInput { device_id, input, is_synthetic },
#[allow(deprecated)]
WE::CursorMoved { device_id, position, modifiers } => WE::CursorMoved { device_id, position, modifiers },
WE::CursorEntered { device_id } => WE::CursorEntered { device_id },
WE::CursorLeft { device_id } => WE::CursorLeft { device_id },
#[allow(deprecated)]
WE::MouseWheel { device_id, delta, phase, modifiers } => WE::MouseWheel { device_id, delta, phase, modifiers },
#[allow(deprecated)]
WE::MouseInput { device_id, state, button, modifiers } => WE::MouseInput { device_id, state, button, modifiers },
WE::TouchpadPressure { device_id, pressure, stage } => WE::TouchpadPressure { device_id, pressure, stage },
WE::AxisMotion { device_id, axis, value } => WE::AxisMotion { device_id, axis, value },
WE::Touch(touch) => WE::Touch(touch),
WE::ScaleFactorChanged { scale_factor, new_inner_size } => return None,
WE::ThemeChanged(theme) => WE::ThemeChanged(theme),
},
},
E::DeviceEvent { device_id, event } => E::DeviceEvent { device_id, event },
E::UserEvent(()) => E::UserEvent(()),
E::Suspended => E::Suspended,
E::Resumed => E::Resumed,
E::MainEventsCleared => E::MainEventsCleared,
E::RedrawRequested(window_id) => E::RedrawRequested(window_id),
E::RedrawEventsCleared => E::RedrawEventsCleared,
E::LoopDestroyed => E::LoopDestroyed,
};
Some(event)
}

0 comments on commit 951e620

Please sign in to comment.