Compare commits

...

9 Commits

Author SHA1 Message Date
Ryan G
d5609729cc Bump version to 0.22.1 (#1537)
There are a few relatively important bugfixes with no API impact in the
master branch. We might as well release this as a non-breaking change.
2020-04-17 13:36:42 -04:00
Jurgis
1f24a09570 Implement requestAnimationFrame for web (#1519)
* Use requestAnimationFrame for polling wasm

* Implement `requestAnimationFrame` for stdweb

Co-authored-by: Ryan G <ryanisaacg@users.noreply.github.com>
2020-04-11 15:49:07 -04:00
Ryan G
a8e777a5df Fix a possible double-borrow during event handling (#1512) 2020-04-11 15:20:38 -04:00
Murarth
0bc58f695b Fix warnings (#1530) 2020-04-10 11:29:33 -07:00
Matthew Russo
28023d9f5b upgrades x11-dl to 2.18.5 to fix #376 (#1517)
x11-dl was using std::mem::uninitialized incorrectly and when
rustlang added MaybeUninit and intrinsic panics on UB caused
by improper use of uninitialized (see rust-lang/rust/pull/69922)
it caused issues with X11 initialization. x11-dl pr
erlepereira/x11-rs/pull/101 updated x11-dl to use MaybeUninit
correctly
2020-03-25 22:38:25 -07:00
Murarth
c2aed1979d X11: Fix ResumeTimeReached being fired early (#1505)
* X11: Fix `ResumeTimeReached` being fired early

* Update CHANGELOG.md

Co-authored-by: Osspial <osspial@gmail.com>
2020-03-11 21:54:23 -07:00
Osspial
7e04273719 Replace Travis and Appveyor CI badges with GitHub Actions CI badge 2020-03-09 18:23:03 -04:00
Osspial
0683bdcd42 Add Unreleased category back to changelog 2020-03-09 17:01:34 -04:00
Osspial
29ab0bb629 Correct 0.22.0 date 2020-03-09 16:59:39 -04:00
12 changed files with 128 additions and 50 deletions

View File

@@ -1,4 +1,12 @@
# 0.22.0 (2020-03-07)
# Unreleased
# 0.22.1 (2020-04-16)
- On X11, fix `ResumeTimeReached` being fired too early.
- On Web, replaced zero timeout for `ControlFlow::Poll` with `requestAnimationFrame`
- On Web, fix a possible panic during event handling
# 0.22.0 (2020-03-09)
- On Windows, fix minor timing issue in wait_until_time_or_msg
- On Windows, rework handling of request_redraw() to address panics.

View File

@@ -1,6 +1,6 @@
[package]
name = "winit"
version = "0.22.0"
version = "0.22.1"
authors = ["The winit contributors", "Pierre Krieger <pierre.krieger1708@gmail.com>"]
description = "Cross-platform window creation library."
edition = "2018"
@@ -78,7 +78,7 @@ wayland-client = { version = "0.23.0", features = [ "dlopen", "egl", "cursor", "
mio = "0.6"
mio-extras = "2.0"
smithay-client-toolkit = "^0.6.6"
x11-dl = "2.18.3"
x11-dl = "2.18.5"
percent-encoding = "2.0"
[target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd", target_os = "windows"))'.dependencies.parking_lot]

View File

@@ -2,12 +2,11 @@
[![Crates.io](https://img.shields.io/crates/v/winit.svg)](https://crates.io/crates/winit)
[![Docs.rs](https://docs.rs/winit/badge.svg)](https://docs.rs/winit)
[![Build Status](https://travis-ci.org/rust-windowing/winit.svg?branch=master)](https://travis-ci.org/rust-windowing/winit)
[![Build status](https://ci.appveyor.com/api/projects/status/hr89but4x1n3dphq/branch/master?svg=true)](https://ci.appveyor.com/project/Osspial/winit/branch/master)
[![CI Status](https://github.com/rust-windowing/winit/workflows/CI/badge.svg)](https://github.com/rust-windowing/winit/actions)
```toml
[dependencies]
winit = "0.22.0"
winit = "0.22.1"
```
## [Documentation](https://docs.rs/winit)

View File

@@ -72,7 +72,8 @@ impl<T> fmt::Debug for EventLoopWindowTarget<T> {
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum ControlFlow {
/// When the current loop iteration finishes, immediately begin a new iteration regardless of
/// whether or not new events are available to process.
/// whether or not new events are available to process. For web, events are sent when
/// `requestAnimationFrame` fires.
Poll,
/// When the current loop iteration finishes, suspend the thread until another event arrives.
Wait,

View File

@@ -63,7 +63,7 @@ impl Default for PlatformSpecificWindowBuilderAttributes {
lazy_static! {
pub static ref X11_BACKEND: Mutex<Result<Arc<XConnection>, XNotSupported>> =
{ Mutex::new(XConnection::new(Some(x_error_callback)).map(Arc::new)) };
Mutex::new(XConnection::new(Some(x_error_callback)).map(Arc::new));
}
#[derive(Debug, Clone)]

View File

@@ -268,14 +268,16 @@ impl<T: 'static> EventLoop<T> {
{
let mut control_flow = ControlFlow::default();
let mut events = Events::with_capacity(8);
callback(
crate::event::Event::NewEvents(crate::event::StartCause::Init),
&self.target,
&mut control_flow,
);
let mut cause = StartCause::Init;
loop {
sticky_exit_callback(
crate::event::Event::NewEvents(cause),
&self.target,
&mut control_flow,
&mut callback,
);
// Process all pending events
self.drain_events(&mut callback, &mut control_flow);
@@ -326,7 +328,7 @@ impl<T: 'static> EventLoop<T> {
}
let start = Instant::now();
let (mut cause, deadline, timeout);
let (deadline, timeout);
match control_flow {
ControlFlow::Exit => break,
@@ -357,38 +359,20 @@ impl<T: 'static> EventLoop<T> {
}
}
if self.event_processor.poll() {
// If the XConnection already contains buffered events, we don't
// need to wait for data on the socket.
// However, we still need to check for user events.
self.poll
.poll(&mut events, Some(Duration::from_millis(0)))
.unwrap();
events.clear();
callback(
crate::event::Event::NewEvents(cause),
&self.target,
&mut control_flow,
);
} else {
// If the XConnection already contains buffered events, we don't
// need to wait for data on the socket.
if !self.event_processor.poll() {
self.poll.poll(&mut events, timeout).unwrap();
events.clear();
}
let wait_cancelled = deadline.map_or(false, |deadline| Instant::now() < deadline);
let wait_cancelled = deadline.map_or(false, |deadline| Instant::now() < deadline);
if wait_cancelled {
cause = StartCause::WaitCancelled {
start,
requested_resume: deadline,
};
}
callback(
crate::event::Event::NewEvents(cause),
&self.target,
&mut control_flow,
);
if wait_cancelled {
cause = StartCause::WaitCancelled {
start,
requested_resume: deadline,
};
}
}

View File

@@ -202,7 +202,6 @@ impl<T: 'static> Shared<T> {
// It should only ever be called from send_event
fn handle_event(&self, event: Event<'static, T>, control: &mut root::ControlFlow) {
let is_closed = self.is_closed();
match *self.0.runner.borrow_mut() {
Some(ref mut runner) => {
// An event is being processed, so the runner should be marked busy
@@ -227,7 +226,9 @@ impl<T: 'static> Shared<T> {
// If the runner doesn't exist and this method recurses, it will recurse infinitely
if !is_closed && self.0.runner.borrow().is_some() {
// Take an event out of the queue and handle it
if let Some(event) = self.0.events.borrow_mut().pop_front() {
// Make sure not to let the borrow_mut live during the next handle_event
let event = { self.0.events.borrow_mut().pop_front() };
if let Some(event) = event {
self.handle_event(event, control);
}
}
@@ -240,7 +241,7 @@ impl<T: 'static> Shared<T> {
root::ControlFlow::Poll => {
let cloned = self.clone();
State::Poll {
timeout: backend::Timeout::new(move || cloned.poll(), Duration::from_millis(0)),
request: backend::AnimationFrameRequest::new(move || cloned.poll()),
}
}
root::ControlFlow::Wait => State::Wait {

View File

@@ -15,7 +15,7 @@ pub enum State {
start: Instant,
},
Poll {
timeout: backend::Timeout,
request: backend::AnimationFrameRequest,
},
Exit,
}

View File

@@ -3,7 +3,7 @@ mod event;
mod timeout;
pub use self::canvas::Canvas;
pub use self::timeout::Timeout;
pub use self::timeout::{AnimationFrameRequest, Timeout};
use crate::dpi::{LogicalSize, Size};
use crate::platform::web::WindowExtStdweb;

View File

@@ -1,5 +1,7 @@
use std::cell::Cell;
use std::rc::Rc;
use std::time::Duration;
use stdweb::web::{window, IWindowOrWorker, TimeoutHandle};
use stdweb::web::{window, IWindowOrWorker, RequestAnimationFrameHandle, TimeoutHandle};
#[derive(Debug)]
pub struct Timeout {
@@ -23,3 +25,39 @@ impl Drop for Timeout {
handle.clear();
}
}
#[derive(Debug)]
pub struct AnimationFrameRequest {
handle: Option<RequestAnimationFrameHandle>,
// track callback state, because `cancelAnimationFrame` is slow
fired: Rc<Cell<bool>>,
}
impl AnimationFrameRequest {
pub fn new<F>(mut f: F) -> AnimationFrameRequest
where
F: 'static + FnMut(),
{
let fired = Rc::new(Cell::new(false));
let c_fired = fired.clone();
let handle = window().request_animation_frame(move |_| {
(*c_fired).set(true);
f();
});
AnimationFrameRequest {
handle: Some(handle),
fired,
}
}
}
impl Drop for AnimationFrameRequest {
fn drop(&mut self) {
if !(*self.fired).get() {
if let Some(handle) = self.handle.take() {
handle.cancel();
}
}
}
}

View File

@@ -3,7 +3,7 @@ mod event;
mod timeout;
pub use self::canvas::Canvas;
pub use self::timeout::Timeout;
pub use self::timeout::{AnimationFrameRequest, Timeout};
use crate::dpi::{LogicalSize, Size};
use crate::platform::web::WindowExtWebSys;

View File

@@ -1,3 +1,5 @@
use std::cell::Cell;
use std::rc::Rc;
use std::time::Duration;
use wasm_bindgen::closure::Closure;
use wasm_bindgen::JsCast;
@@ -38,3 +40,48 @@ impl Drop for Timeout {
window.clear_timeout_with_handle(self.handle);
}
}
#[derive(Debug)]
pub struct AnimationFrameRequest {
handle: i32,
// track callback state, because `cancelAnimationFrame` is slow
fired: Rc<Cell<bool>>,
_closure: Closure<dyn FnMut()>,
}
impl AnimationFrameRequest {
pub fn new<F>(mut f: F) -> AnimationFrameRequest
where
F: 'static + FnMut(),
{
let window = web_sys::window().expect("Failed to obtain window");
let fired = Rc::new(Cell::new(false));
let c_fired = fired.clone();
let closure = Closure::wrap(Box::new(move || {
(*c_fired).set(true);
f();
}) as Box<dyn FnMut()>);
let handle = window
.request_animation_frame(&closure.as_ref().unchecked_ref())
.expect("Failed to request animation frame");
AnimationFrameRequest {
handle,
fired,
_closure: closure,
}
}
}
impl Drop for AnimationFrameRequest {
fn drop(&mut self) {
if !(*self.fired).get() {
let window = web_sys::window().expect("Failed to obtain window");
window
.cancel_animation_frame(self.handle)
.expect("Failed to cancel animation frame");
}
}
}