Implement WindowID on the web platform (#1177)

* Use actual numeric IDs to differentiate Windows

This is generally important to identifying which window should
recieve which event, but is also specifically crucial for fixing
RedrawRequested on web.

* Cargo fmt
This commit is contained in:
Ryan G 2019-09-19 18:40:18 -04:00 committed by GitHub
parent e87bc3db20
commit 2c47c43f47
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 38 additions and 19 deletions

View file

@ -16,6 +16,7 @@ impl<T> Clone for Shared<T> {
pub struct Execution<T> { pub struct Execution<T> {
runner: RefCell<Option<Runner<T>>>, runner: RefCell<Option<Runner<T>>>,
events: RefCell<VecDeque<Event<T>>>, events: RefCell<VecDeque<Event<T>>>,
id: RefCell<u32>,
} }
struct Runner<T> { struct Runner<T> {
@ -39,6 +40,7 @@ impl<T: 'static> Shared<T> {
Shared(Rc::new(Execution { Shared(Rc::new(Execution {
runner: RefCell::new(None), runner: RefCell::new(None),
events: RefCell::new(VecDeque::new()), events: RefCell::new(VecDeque::new()),
id: RefCell::new(0),
})) }))
} }
@ -53,6 +55,15 @@ impl<T: 'static> Shared<T> {
backend::on_unload(move || close_instance.handle_unload()); backend::on_unload(move || close_instance.handle_unload());
} }
// Generate a strictly increasing ID
// This is used to differentiate windows when handling events
pub fn generate_id(&self) -> u32 {
let mut id = self.0.id.borrow_mut();
*id += 1;
*id
}
// Add an event to the event loop runner // Add an event to the event loop runner
// //
// It will determine if the event should be immediately sent to the user or buffered for later // It will determine if the event should be immediately sent to the user or buffered for later

View file

@ -31,11 +31,16 @@ impl<T> WindowTarget<T> {
self.runner.set_listener(event_handler); self.runner.set_listener(event_handler);
} }
pub fn register(&self, canvas: &mut backend::Canvas) { pub fn generate_id(&self) -> window::Id {
window::Id(self.runner.generate_id())
}
pub fn register(&self, canvas: &mut backend::Canvas, id: window::Id) {
let runner = self.runner.clone(); let runner = self.runner.clone();
canvas.on_blur(move || { canvas.on_blur(move || {
runner.send_event(Event::WindowEvent { runner.send_event(Event::WindowEvent {
window_id: WindowId(window::Id), window_id: WindowId(id),
event: WindowEvent::Focused(false), event: WindowEvent::Focused(false),
}); });
}); });
@ -43,7 +48,7 @@ impl<T> WindowTarget<T> {
let runner = self.runner.clone(); let runner = self.runner.clone();
canvas.on_focus(move || { canvas.on_focus(move || {
runner.send_event(Event::WindowEvent { runner.send_event(Event::WindowEvent {
window_id: WindowId(window::Id), window_id: WindowId(id),
event: WindowEvent::Focused(true), event: WindowEvent::Focused(true),
}); });
}); });
@ -51,7 +56,7 @@ impl<T> WindowTarget<T> {
let runner = self.runner.clone(); let runner = self.runner.clone();
canvas.on_keyboard_press(move |scancode, virtual_keycode, modifiers| { canvas.on_keyboard_press(move |scancode, virtual_keycode, modifiers| {
runner.send_event(Event::WindowEvent { runner.send_event(Event::WindowEvent {
window_id: WindowId(window::Id), window_id: WindowId(id),
event: WindowEvent::KeyboardInput { event: WindowEvent::KeyboardInput {
device_id: DeviceId(unsafe { device::Id::dummy() }), device_id: DeviceId(unsafe { device::Id::dummy() }),
input: KeyboardInput { input: KeyboardInput {
@ -67,7 +72,7 @@ impl<T> WindowTarget<T> {
let runner = self.runner.clone(); let runner = self.runner.clone();
canvas.on_keyboard_release(move |scancode, virtual_keycode, modifiers| { canvas.on_keyboard_release(move |scancode, virtual_keycode, modifiers| {
runner.send_event(Event::WindowEvent { runner.send_event(Event::WindowEvent {
window_id: WindowId(window::Id), window_id: WindowId(id),
event: WindowEvent::KeyboardInput { event: WindowEvent::KeyboardInput {
device_id: DeviceId(unsafe { device::Id::dummy() }), device_id: DeviceId(unsafe { device::Id::dummy() }),
input: KeyboardInput { input: KeyboardInput {
@ -83,7 +88,7 @@ impl<T> WindowTarget<T> {
let runner = self.runner.clone(); let runner = self.runner.clone();
canvas.on_received_character(move |char_code| { canvas.on_received_character(move |char_code| {
runner.send_event(Event::WindowEvent { runner.send_event(Event::WindowEvent {
window_id: WindowId(window::Id), window_id: WindowId(id),
event: WindowEvent::ReceivedCharacter(char_code), event: WindowEvent::ReceivedCharacter(char_code),
}); });
}); });
@ -91,7 +96,7 @@ impl<T> WindowTarget<T> {
let runner = self.runner.clone(); let runner = self.runner.clone();
canvas.on_cursor_leave(move |pointer_id| { canvas.on_cursor_leave(move |pointer_id| {
runner.send_event(Event::WindowEvent { runner.send_event(Event::WindowEvent {
window_id: WindowId(window::Id), window_id: WindowId(id),
event: WindowEvent::CursorLeft { event: WindowEvent::CursorLeft {
device_id: DeviceId(device::Id(pointer_id)), device_id: DeviceId(device::Id(pointer_id)),
}, },
@ -101,7 +106,7 @@ impl<T> WindowTarget<T> {
let runner = self.runner.clone(); let runner = self.runner.clone();
canvas.on_cursor_enter(move |pointer_id| { canvas.on_cursor_enter(move |pointer_id| {
runner.send_event(Event::WindowEvent { runner.send_event(Event::WindowEvent {
window_id: WindowId(window::Id), window_id: WindowId(id),
event: WindowEvent::CursorEntered { event: WindowEvent::CursorEntered {
device_id: DeviceId(device::Id(pointer_id)), device_id: DeviceId(device::Id(pointer_id)),
}, },
@ -111,7 +116,7 @@ impl<T> WindowTarget<T> {
let runner = self.runner.clone(); let runner = self.runner.clone();
canvas.on_cursor_move(move |pointer_id, position, modifiers| { canvas.on_cursor_move(move |pointer_id, position, modifiers| {
runner.send_event(Event::WindowEvent { runner.send_event(Event::WindowEvent {
window_id: WindowId(window::Id), window_id: WindowId(id),
event: WindowEvent::CursorMoved { event: WindowEvent::CursorMoved {
device_id: DeviceId(device::Id(pointer_id)), device_id: DeviceId(device::Id(pointer_id)),
position, position,
@ -123,7 +128,7 @@ impl<T> WindowTarget<T> {
let runner = self.runner.clone(); let runner = self.runner.clone();
canvas.on_mouse_press(move |pointer_id, button, modifiers| { canvas.on_mouse_press(move |pointer_id, button, modifiers| {
runner.send_event(Event::WindowEvent { runner.send_event(Event::WindowEvent {
window_id: WindowId(window::Id), window_id: WindowId(id),
event: WindowEvent::MouseInput { event: WindowEvent::MouseInput {
device_id: DeviceId(device::Id(pointer_id)), device_id: DeviceId(device::Id(pointer_id)),
state: ElementState::Pressed, state: ElementState::Pressed,
@ -136,7 +141,7 @@ impl<T> WindowTarget<T> {
let runner = self.runner.clone(); let runner = self.runner.clone();
canvas.on_mouse_release(move |pointer_id, button, modifiers| { canvas.on_mouse_release(move |pointer_id, button, modifiers| {
runner.send_event(Event::WindowEvent { runner.send_event(Event::WindowEvent {
window_id: WindowId(window::Id), window_id: WindowId(id),
event: WindowEvent::MouseInput { event: WindowEvent::MouseInput {
device_id: DeviceId(device::Id(pointer_id)), device_id: DeviceId(device::Id(pointer_id)),
state: ElementState::Released, state: ElementState::Released,
@ -149,7 +154,7 @@ impl<T> WindowTarget<T> {
let runner = self.runner.clone(); let runner = self.runner.clone();
canvas.on_mouse_wheel(move |pointer_id, delta, modifiers| { canvas.on_mouse_wheel(move |pointer_id, delta, modifiers| {
runner.send_event(Event::WindowEvent { runner.send_event(Event::WindowEvent {
window_id: WindowId(window::Id), window_id: WindowId(id),
event: WindowEvent::MouseWheel { event: WindowEvent::MouseWheel {
device_id: DeviceId(device::Id(pointer_id)), device_id: DeviceId(device::Id(pointer_id)),
delta, delta,

View file

@ -13,7 +13,7 @@ use stdweb::web::event::{
}; };
use stdweb::web::html_element::CanvasElement; use stdweb::web::html_element::CanvasElement;
use stdweb::web::{ use stdweb::web::{
document, window, EventListenerHandle, IChildNode, IElement, IEventTarget, IHtmlElement, INode, document, window, EventListenerHandle, IChildNode, IElement, IEventTarget, IHtmlElement,
}; };
pub struct Canvas { pub struct Canvas {

View file

@ -15,6 +15,7 @@ pub struct Window {
canvas: backend::Canvas, canvas: backend::Canvas,
previous_pointer: RefCell<&'static str>, previous_pointer: RefCell<&'static str>,
position: RefCell<LogicalPosition>, position: RefCell<LogicalPosition>,
id: Id,
} }
impl Window { impl Window {
@ -25,19 +26,22 @@ impl Window {
) -> Result<Self, RootOE> { ) -> Result<Self, RootOE> {
let runner = target.runner.clone(); let runner = target.runner.clone();
let id = target.generate_id();
let mut canvas = backend::Canvas::create(move || { let mut canvas = backend::Canvas::create(move || {
runner.send_event(Event::WindowEvent { runner.send_event(Event::WindowEvent {
window_id: RootWI(Id), window_id: RootWI(id),
event: WindowEvent::RedrawRequested, event: WindowEvent::RedrawRequested,
}) })
})?; })?;
target.register(&mut canvas); target.register(&mut canvas, id);
let window = Window { let window = Window {
canvas, canvas,
previous_pointer: RefCell::new("auto"), previous_pointer: RefCell::new("auto"),
position: RefCell::new(LogicalPosition { x: 0.0, y: 0.0 }), position: RefCell::new(LogicalPosition { x: 0.0, y: 0.0 }),
id,
}; };
window.set_inner_size(attr.inner_size.unwrap_or(LogicalSize { window.set_inner_size(attr.inner_size.unwrap_or(LogicalSize {
@ -250,17 +254,16 @@ impl Window {
#[inline] #[inline]
pub fn id(&self) -> Id { pub fn id(&self) -> Id {
// TODO ? return self.id;
unsafe { Id::dummy() }
} }
} }
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Id; pub struct Id(pub(crate) u32);
impl Id { impl Id {
pub unsafe fn dummy() -> Id { pub unsafe fn dummy() -> Id {
Id Id(0)
} }
} }