Implement hidpi for web platform (#1233)

* fix: use a 'static lifetime for the web backend's `Event` types

* implement hidpi for stdweb (web-sys wip?)

* fix: make all canvas resizes go through backend::set_canvas_size

* update Window docs for web, make `inner/outer_position` return the position in the viewport
This commit is contained in:
Michael Tang 2019-12-31 14:39:33 -08:00 committed by Osspial
parent 28a20aec10
commit 777d9edeaa
11 changed files with 137 additions and 91 deletions

View file

@ -37,7 +37,8 @@ impl<T> EventLoop<T> {
pub fn run<F>(self, mut event_handler: F) -> !
where
F: 'static + FnMut(Event<T>, &root::EventLoopWindowTarget<T>, &mut root::ControlFlow),
F: 'static
+ FnMut(Event<'static, T>, &root::EventLoopWindowTarget<T>, &mut root::ControlFlow),
{
let target = root::EventLoopWindowTarget {
p: self.elw.p.clone(),

View file

@ -11,7 +11,7 @@ use std::{
rc::Rc,
};
pub struct Shared<T>(Rc<Execution<T>>);
pub struct Shared<T: 'static>(Rc<Execution<T>>);
impl<T> Clone for Shared<T> {
fn clone(&self) -> Self {
@ -19,21 +19,21 @@ impl<T> Clone for Shared<T> {
}
}
pub struct Execution<T> {
pub struct Execution<T: 'static> {
runner: RefCell<Option<Runner<T>>>,
events: RefCell<VecDeque<Event<T>>>,
events: RefCell<VecDeque<Event<'static, T>>>,
id: RefCell<u32>,
redraw_pending: RefCell<HashSet<WindowId>>,
}
struct Runner<T> {
struct Runner<T: 'static> {
state: State,
is_busy: bool,
event_handler: Box<dyn FnMut(Event<T>, &mut root::ControlFlow)>,
event_handler: Box<dyn FnMut(Event<'static, T>, &mut root::ControlFlow)>,
}
impl<T: 'static> Runner<T> {
pub fn new(event_handler: Box<dyn FnMut(Event<T>, &mut root::ControlFlow)>) -> Self {
pub fn new(event_handler: Box<dyn FnMut(Event<'static, T>, &mut root::ControlFlow)>) -> Self {
Runner {
state: State::Init,
is_busy: false,
@ -55,7 +55,10 @@ impl<T: 'static> Shared<T> {
// Set the event callback to use for the event loop runner
// This the event callback is a fairly thin layer over the user-provided callback that closes
// over a RootEventLoopWindowTarget reference
pub fn set_listener(&self, event_handler: Box<dyn FnMut(Event<T>, &mut root::ControlFlow)>) {
pub fn set_listener(
&self,
event_handler: Box<dyn FnMut(Event<'static, T>, &mut root::ControlFlow)>,
) {
self.0.runner.replace(Some(Runner::new(event_handler)));
self.send_event(Event::NewEvents(StartCause::Init));
@ -79,7 +82,7 @@ impl<T: 'static> Shared<T> {
// 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
pub fn send_event(&self, event: Event<T>) {
pub fn send_event(&self, event: Event<'static, T>) {
// If the event loop is closed, it should discard any new events
if self.is_closed() {
return;
@ -153,7 +156,7 @@ impl<T: 'static> Shared<T> {
// handle_event takes in events and either queues them or applies a callback
//
// It should only ever be called from send_event
fn handle_event(&self, event: Event<T>, control: &mut root::ControlFlow) {
fn handle_event(&self, event: Event<'static, T>, control: &mut root::ControlFlow) {
let is_closed = self.is_closed();
match *self.0.runner.borrow_mut() {

View file

@ -1,5 +1,5 @@
use super::{backend, device, proxy::Proxy, runner, window};
use crate::dpi::LogicalSize;
use crate::dpi::{PhysicalSize, Size};
use crate::event::{DeviceId, ElementState, Event, KeyboardInput, TouchPhase, WindowEvent};
use crate::event_loop::ControlFlow;
use crate::window::WindowId;
@ -28,7 +28,7 @@ impl<T> WindowTarget<T> {
Proxy::new(self.runner.clone())
}
pub fn run(&self, event_handler: Box<dyn FnMut(Event<T>, &mut ControlFlow)>) {
pub fn run(&self, event_handler: Box<dyn FnMut(Event<'static, T>, &mut ControlFlow)>) {
self.runner.set_listener(event_handler);
}
@ -170,25 +170,27 @@ impl<T> WindowTarget<T> {
let runner = self.runner.clone();
let raw = canvas.raw().clone();
let mut intended_size = LogicalSize {
width: raw.width() as f64,
height: raw.height() as f64,
// The size to restore to after exiting fullscreen.
let mut intended_size = PhysicalSize {
width: raw.width() as u32,
height: raw.height() as u32,
};
canvas.on_fullscreen_change(move || {
// If the canvas is marked as fullscreen, it is moving *into* fullscreen
// If it is not, it is moving *out of* fullscreen
let new_size = if backend::is_fullscreen(&raw) {
intended_size = LogicalSize {
width: raw.width() as f64,
height: raw.height() as f64,
intended_size = PhysicalSize {
width: raw.width() as u32,
height: raw.height() as u32,
};
backend::window_size()
backend::window_size().to_physical(backend::hidpi_factor())
} else {
intended_size
};
raw.set_width(new_size.width as u32);
raw.set_height(new_size.height as u32);
backend::set_canvas_size(&raw, Size::Physical(new_size));
runner.send_event(Event::WindowEvent {
window_id: WindowId(id),
event: WindowEvent::Resized(new_size),