winit/src/platform_impl/stdweb/event_loop.rs

300 lines
9.5 KiB
Rust
Raw Normal View History

2019-03-11 22:22:21 -04:00
use super::*;
2019-03-16 18:51:11 -04:00
use dpi::LogicalPosition;
use event::{DeviceId as RootDI, ElementState, Event, KeyboardInput, StartCause, WindowEvent};
2019-03-11 22:22:21 -04:00
use event_loop::{ControlFlow, EventLoopWindowTarget as RootELW, EventLoopClosed};
2019-03-16 18:51:11 -04:00
use window::{WindowId as RootWI};
2019-03-11 22:22:21 -04:00
use stdweb::{
traits::*,
web::{
document,
event::*,
html_element::CanvasElement,
},
};
2019-03-16 18:51:11 -04:00
use std::cell::RefCell;
2019-03-11 22:22:21 -04:00
use std::collections::VecDeque;
use std::collections::vec_deque::IntoIter as VecDequeIter;
use std::marker::PhantomData;
use std::rc::Rc;
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct DeviceId(i32);
impl DeviceId {
pub unsafe fn dummy() -> Self {
DeviceId(0)
}
}
pub struct EventLoop<T: 'static> {
elw: RootELW<T>,
}
pub struct EventLoopWindowTarget<T: 'static> {
2019-03-16 18:40:35 -04:00
pub(crate) runner: EventLoopRunnerShared<T>,
2019-03-11 22:22:21 -04:00
}
impl<T> EventLoopWindowTarget<T> {
fn new() -> Self {
EventLoopWindowTarget {
2019-03-16 18:40:35 -04:00
runner: Rc::new(ELRShared {
runner: RefCell::new(None),
events: RefCell::new(VecDeque::new())
})
2019-03-11 22:22:21 -04:00
}
}
}
#[derive(Clone)]
pub struct EventLoopProxy<T> {
runner: EventLoopRunnerShared<T>
}
impl<T> EventLoopProxy<T> {
pub fn send_event(&self, event: T) -> Result<(), EventLoopClosed> {
self.runner.send_event(Event::UserEvent(event));
Ok(())
}
}
2019-03-16 18:40:35 -04:00
pub type EventLoopRunnerShared<T> = Rc<ELRShared<T>>;
2019-03-11 22:22:21 -04:00
2019-03-16 18:40:35 -04:00
pub struct ELRShared<T> {
2019-03-11 22:22:21 -04:00
runner: RefCell<Option<EventLoopRunner<T>>>,
events: RefCell<VecDeque<Event<T>>>, // TODO: this may not be necessary?
}
struct EventLoopRunner<T> {
control: ControlFlow,
2019-03-18 22:13:30 -04:00
handling: bool,
2019-03-11 22:22:21 -04:00
event_handler: Box<dyn FnMut(Event<T>, &mut ControlFlow)>,
}
impl<T> EventLoop<T> {
pub fn new() -> Self {
EventLoop {
elw: RootELW {
p: EventLoopWindowTarget::new(),
_marker: PhantomData
},
}
}
pub fn get_available_monitors(&self) -> VecDequeIter<MonitorHandle> {
VecDeque::new().into_iter()
}
pub fn get_primary_monitor(&self) -> MonitorHandle {
MonitorHandle
}
2019-03-16 18:51:11 -04:00
pub fn run<F>(self, mut event_handler: F) -> !
2019-03-18 22:13:30 -04:00
where F: 'static + FnMut(Event<T>, &RootELW<T>, &mut ControlFlow) {
2019-03-16 18:40:35 -04:00
let runner = self.elw.p.runner;
2019-03-18 22:13:30 -04:00
2019-03-11 22:22:21 -04:00
let relw = RootELW {
p: EventLoopWindowTarget::new(),
_marker: PhantomData
};
runner.set_listener(Box::new(move |evt, ctrl| event_handler(evt, &relw, ctrl)));
let document = &document();
2019-03-16 18:44:13 -04:00
add_event(&runner, document, |elrs, _: BlurEvent| {
elrs.send_event(Event::WindowEvent {
window_id: RootWI(WindowId),
event: WindowEvent::Focused(false)
});
2019-03-11 22:22:21 -04:00
});
2019-03-16 18:44:13 -04:00
add_event(&runner, document, |elrs, _: FocusEvent| {
elrs.send_event(Event::WindowEvent {
window_id: RootWI(WindowId),
event: WindowEvent::Focused(true)
});
2019-03-11 22:22:21 -04:00
});
add_event(&runner, document, |elrs, event: KeyDownEvent| {
let key = event.key();
let mut characters = key.chars();
let first = characters.next();
let second = characters.next();
if let (Some(key), None) = (first, second) {
elrs.send_event(Event::WindowEvent {
window_id: RootWI(WindowId),
event: WindowEvent::ReceivedCharacter(key)
});
}
elrs.send_event(Event::WindowEvent {
window_id: RootWI(WindowId),
event: WindowEvent::KeyboardInput {
device_id: RootDI(unsafe { DeviceId::dummy() }),
input: KeyboardInput {
scancode: scancode(&event),
state: ElementState::Pressed,
virtual_keycode: button_mapping(&event),
modifiers: keyboard_modifiers_state(&event),
}
}
});
});
add_event(&runner, document, |elrs, event: KeyUpEvent| {
elrs.send_event(Event::WindowEvent {
window_id: RootWI(WindowId),
event: WindowEvent::KeyboardInput {
device_id: RootDI(unsafe { DeviceId::dummy() }),
input: KeyboardInput {
scancode: scancode(&event),
state: ElementState::Released,
virtual_keycode: button_mapping(&event),
modifiers: keyboard_modifiers_state(&event),
}
}
});
});
stdweb::event_loop(); // TODO: this is only necessary for stdweb emscripten, should it be here?
2019-03-16 18:40:35 -04:00
// Throw an exception to break out of Rust exceution and use unreachable to tell the
// compiler this function won't return, giving it a return type of '!'
2019-03-11 22:22:21 -04:00
js! {
throw "Using exceptions for control flow, don't mind me";
}
unreachable!();
}
pub fn create_proxy(&self) -> EventLoopProxy<T> {
EventLoopProxy {
2019-03-16 18:40:35 -04:00
runner: self.elw.p.runner.clone()
2019-03-11 22:22:21 -04:00
}
}
pub fn window_target(&self) -> &RootELW<T> {
&self.elw
}
}
2019-03-16 18:40:35 -04:00
pub fn register<T: 'static>(elrs: &EventLoopRunnerShared<T>, canvas: &CanvasElement) {
2019-03-11 22:22:21 -04:00
add_event(elrs, canvas, |elrs, event: PointerOutEvent| {
elrs.send_event(Event::WindowEvent {
window_id: RootWI(WindowId),
event: WindowEvent::CursorLeft {
device_id: RootDI(DeviceId(event.pointer_id()))
}
});
});
add_event(elrs, canvas, |elrs, event: PointerOverEvent| {
elrs.send_event(Event::WindowEvent {
window_id: RootWI(WindowId),
event: WindowEvent::CursorEntered {
device_id: RootDI(DeviceId(event.pointer_id()))
}
});
});
add_event(elrs, canvas, |elrs, event: PointerMoveEvent| {
elrs.send_event(Event::WindowEvent {
window_id: RootWI(WindowId),
event: WindowEvent::CursorMoved {
device_id: RootDI(DeviceId(event.pointer_id())),
position: LogicalPosition {
x: event.offset_x(),
y: event.offset_y()
},
modifiers: mouse_modifiers_state(&event)
}
});
});
add_event(elrs, canvas, |elrs, event: PointerUpEvent| {
elrs.send_event(Event::WindowEvent {
window_id: RootWI(WindowId),
event: WindowEvent::MouseInput {
device_id: RootDI(DeviceId(event.pointer_id())),
state: ElementState::Pressed,
button: mouse_button(&event),
modifiers: mouse_modifiers_state(&event)
}
});
});
add_event(elrs, canvas, |elrs, event: PointerDownEvent| {
elrs.send_event(Event::WindowEvent {
window_id: RootWI(WindowId),
event: WindowEvent::MouseInput {
device_id: RootDI(DeviceId(event.pointer_id())),
state: ElementState::Released,
button: mouse_button(&event),
modifiers: mouse_modifiers_state(&event)
}
});
});
}
fn add_event<T: 'static, E, F>(elrs: &EventLoopRunnerShared<T>, target: &impl IEventTarget, mut handler: F)
where E: ConcreteEvent, F: FnMut(&EventLoopRunnerShared<T>, E) + 'static {
2019-03-16 18:40:35 -04:00
let elrs = elrs.clone();
2019-03-11 22:22:21 -04:00
target.add_event_listener(move |event: E| {
// Don't capture the event if the events loop has been destroyed
match &*elrs.runner.borrow() {
Some(ref runner) if runner.control == ControlFlow::Exit => return,
_ => ()
}
2019-03-11 22:22:21 -04:00
event.prevent_default();
event.stop_propagation();
event.cancel_bubble();
handler(&elrs, event);
});
}
impl<T> ELRShared<T> {
fn set_listener(&self, event_handler: Box<dyn FnMut(Event<T>, &mut ControlFlow)>) {
*self.runner.borrow_mut() = Some(EventLoopRunner {
control: ControlFlow::Poll,
handling: false,
2019-03-11 22:22:21 -04:00
event_handler
});
}
// TODO: handle event loop closures
// TODO: handle event buffer
2019-03-16 18:40:35 -04:00
pub fn send_event(&self, event: Event<T>) {
let start_cause = StartCause::Poll; // TODO: this is obviously not right
self.handle_start(start_cause);
self.handle_event(event);
self.handle_event(Event::EventsCleared);
}
fn handle_start(&self, start: StartCause) {
let is_handling = if let Some(ref runner) = *self.runner.borrow() {
runner.handling
} else {
false
};
if is_handling {
self.handle_event(Event::NewEvents(start));
}
}
fn handle_event(&self, event: Event<T>) {
2019-03-11 22:22:21 -04:00
match *self.runner.borrow_mut() {
2019-03-18 22:13:30 -04:00
Some(ref mut runner) if !runner.handling => {
runner.handling = true;
let closed = runner.control == ControlFlow::Exit;
2019-03-11 22:22:21 -04:00
// TODO: bracket this in control flow events?
(runner.event_handler)(event, &mut runner.control);
2019-03-18 22:13:30 -04:00
if closed {
runner.control = ControlFlow::Exit;
}
runner.handling = false;
2019-03-11 22:22:21 -04:00
}
2019-03-18 22:13:30 -04:00
_ => self.events.borrow_mut().push_back(event)
2019-03-11 22:22:21 -04:00
}
if self.runner.borrow().is_some() {
if let Some(event) = self.events.borrow_mut().pop_front() {
self.handle_event(event);
}
}
2019-03-11 22:22:21 -04:00
}
}