chore: move event loop recreation check into backends themselves
This commit is contained in:
parent
5f2c7350e9
commit
8ad016362a
12 changed files with 64 additions and 25 deletions
|
|
@ -11,7 +11,6 @@
|
|||
use std::marker::PhantomData;
|
||||
#[cfg(any(x11_platform, wayland_platform))]
|
||||
use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
use rwh_06::{DisplayHandle, HandleError, HasDisplayHandle};
|
||||
pub use winit_core::event_loop::*;
|
||||
|
|
@ -53,8 +52,6 @@ pub struct EventLoopBuilder {
|
|||
pub(crate) platform_specific: platform_impl::PlatformSpecificEventLoopAttributes,
|
||||
}
|
||||
|
||||
static EVENT_LOOP_CREATED: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
impl EventLoopBuilder {
|
||||
/// Builds a new event loop.
|
||||
///
|
||||
|
|
@ -93,10 +90,6 @@ impl EventLoopBuilder {
|
|||
pub fn build(&mut self) -> Result<EventLoop, EventLoopError> {
|
||||
let _span = tracing::debug_span!("winit::EventLoopBuilder::build").entered();
|
||||
|
||||
if EVENT_LOOP_CREATED.swap(true, Ordering::Relaxed) {
|
||||
return Err(EventLoopError::RecreationAttempt);
|
||||
}
|
||||
|
||||
// Certain platforms accept a mutable reference in their API.
|
||||
#[allow(clippy::unnecessary_mut_passed)]
|
||||
Ok(EventLoop {
|
||||
|
|
@ -104,11 +97,6 @@ impl EventLoopBuilder {
|
|||
_marker: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(web_platform)]
|
||||
pub(crate) fn allow_event_loop_recreation() {
|
||||
EVENT_LOOP_CREATED.store(false, Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
impl EventLoop {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
use winit_core::application::ApplicationHandler;
|
||||
use winit_core::error::{EventLoopError, NotSupportedError};
|
||||
use winit_core::event_loop::ActiveEventLoop as RootActiveEventLoop;
|
||||
|
|
@ -20,11 +22,22 @@ pub struct EventLoop {
|
|||
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub(crate) struct PlatformSpecificEventLoopAttributes {}
|
||||
|
||||
static EVENT_LOOP_CREATED: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
impl EventLoop {
|
||||
pub(crate) fn new(_: &PlatformSpecificEventLoopAttributes) -> Result<Self, EventLoopError> {
|
||||
if EVENT_LOOP_CREATED.swap(true, Ordering::Relaxed) {
|
||||
// For better cross-platformness.
|
||||
return Err(EventLoopError::RecreationAttempt);
|
||||
}
|
||||
|
||||
Ok(EventLoop { elw: ActiveEventLoop::new() })
|
||||
}
|
||||
|
||||
fn allow_event_loop_recreation() {
|
||||
EVENT_LOOP_CREATED.store(false, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
pub fn run_app<A: ApplicationHandler>(self, app: A) -> ! {
|
||||
let app = Box::new(app);
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ use super::super::main_thread::MainThreadMarker;
|
|||
use super::super::monitor::MonitorHandler;
|
||||
use super::proxy::EventLoopProxy;
|
||||
use super::state::State;
|
||||
use super::{backend, ActiveEventLoop};
|
||||
use super::{backend, ActiveEventLoop, EventLoop};
|
||||
use crate::platform::web::{PollStrategy, WaitUntilStrategy};
|
||||
use crate::platform_impl::platform::backend::{EventListenerHandle, SafeAreaHandle};
|
||||
use crate::platform_impl::platform::r#async::DispatchRunner;
|
||||
|
|
@ -773,7 +773,7 @@ impl Shared {
|
|||
// * The `register_redraw_request` closure.
|
||||
// * The `destroy_fn` closure.
|
||||
if self.0.event_loop_recreation.get() {
|
||||
crate::event_loop::EventLoopBuilder::allow_event_loop_recreation();
|
||||
EventLoop::allow_event_loop_recreation();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -128,6 +128,12 @@ const GLOBAL_WINDOW: WindowId = WindowId::from_raw(0);
|
|||
|
||||
impl EventLoop {
|
||||
pub fn new(attributes: &PlatformSpecificEventLoopAttributes) -> Result<Self, EventLoopError> {
|
||||
static EVENT_LOOP_CREATED: AtomicBool = AtomicBool::new(false);
|
||||
if EVENT_LOOP_CREATED.swap(true, Ordering::Relaxed) {
|
||||
// For better cross-platformness.
|
||||
return Err(EventLoopError::RecreationAttempt);
|
||||
}
|
||||
|
||||
let android_app = attributes.android_app.as_ref().expect(
|
||||
"An `AndroidApp` as passed to android_main() is required to create an `EventLoop` on \
|
||||
Android",
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ impl AppState {
|
|||
activation_policy: Option<NSApplicationActivationPolicy>,
|
||||
default_menu: bool,
|
||||
activate_ignoring_other_apps: bool,
|
||||
) -> Rc<Self> {
|
||||
) -> Option<Rc<Self>> {
|
||||
let event_loop_proxy = Arc::new(EventLoopProxy::new(mtm, move || {
|
||||
Self::get(mtm).with_handler(|app, event_loop| app.proxy_wake_up(event_loop));
|
||||
}));
|
||||
|
|
@ -85,8 +85,7 @@ impl AppState {
|
|||
pending_redraw: RefCell::new(vec![]),
|
||||
});
|
||||
|
||||
GLOBAL.get(mtm).set(this.clone()).expect("application state can only be set once");
|
||||
this
|
||||
GLOBAL.get(mtm).set(this.clone()).ok().and(Some(this))
|
||||
}
|
||||
|
||||
pub fn get(mtm: MainThreadMarker) -> Rc<Self> {
|
||||
|
|
|
|||
|
|
@ -182,7 +182,8 @@ impl EventLoop {
|
|||
activation_policy,
|
||||
attributes.default_menu,
|
||||
attributes.activate_ignoring_other_apps,
|
||||
);
|
||||
)
|
||||
.ok_or_else(|| EventLoopError::RecreationAttempt)?;
|
||||
|
||||
// Initialize the application (if it has not already been).
|
||||
let app = NSApplication::sharedApplication(mtm);
|
||||
|
|
|
|||
|
|
@ -19,7 +19,13 @@ pub enum EventLoopError {
|
|||
impl fmt::Display for EventLoopError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::RecreationAttempt => write!(f, "EventLoop can't be recreated"),
|
||||
Self::RecreationAttempt => {
|
||||
write!(
|
||||
f,
|
||||
"EventLoop can't be recreated, only a single instance of it is supported (for \
|
||||
cross-platform compatibility)"
|
||||
)
|
||||
},
|
||||
Self::Os(err) => err.fmt(f),
|
||||
Self::ExitFailure(status) => write!(f, "Exit Failure: {status}"),
|
||||
Self::NotSupported(err) => err.fmt(f),
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use std::cell::Cell;
|
||||
use std::collections::VecDeque;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{mpsc, Arc, Mutex};
|
||||
use std::time::Instant;
|
||||
use std::{iter, mem, slice};
|
||||
|
|
@ -280,6 +281,12 @@ pub struct EventLoop {
|
|||
|
||||
impl EventLoop {
|
||||
pub fn new(_: &PlatformSpecificEventLoopAttributes) -> Result<Self, EventLoopError> {
|
||||
static EVENT_LOOP_CREATED: AtomicBool = AtomicBool::new(false);
|
||||
if EVENT_LOOP_CREATED.swap(true, Ordering::Relaxed) {
|
||||
// For better cross-platformness.
|
||||
return Err(EventLoopError::RecreationAttempt);
|
||||
}
|
||||
|
||||
// NOTE: Create a channel which can hold only one event to automatically _squash_ user
|
||||
// events.
|
||||
let (user_events_sender, user_events_receiver) = mpsc::sync_channel(1);
|
||||
|
|
|
|||
|
|
@ -148,10 +148,10 @@ impl EventLoop {
|
|||
|
||||
static mut SINGLETON_INIT: bool = false;
|
||||
unsafe {
|
||||
assert!(
|
||||
!SINGLETON_INIT,
|
||||
"Only one `EventLoop` is supported on iOS. `EventLoopProxy` might be helpful"
|
||||
);
|
||||
if SINGLETON_INIT {
|
||||
// Required, AppState is global state, and event loop can only be run once.
|
||||
return Err(EventLoopError::RecreationAttempt);
|
||||
}
|
||||
SINGLETON_INIT = true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use std::io::Result as IOResult;
|
|||
use std::mem;
|
||||
use std::os::fd::OwnedFd;
|
||||
use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd};
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{Arc, Condvar, Mutex};
|
||||
use std::thread::JoinHandle;
|
||||
use std::time::{Duration, Instant};
|
||||
|
|
@ -80,6 +80,12 @@ pub struct EventLoop {
|
|||
|
||||
impl EventLoop {
|
||||
pub fn new() -> Result<EventLoop, EventLoopError> {
|
||||
static EVENT_LOOP_CREATED: AtomicBool = AtomicBool::new(false);
|
||||
if EVENT_LOOP_CREATED.swap(true, Ordering::Relaxed) {
|
||||
// For better cross-platformness.
|
||||
return Err(EventLoopError::RecreationAttempt);
|
||||
}
|
||||
|
||||
let connection = Connection::connect_to_env().map_err(|err| os_error!(err))?;
|
||||
|
||||
let (globals, mut event_queue) =
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use std::cell::Cell;
|
|||
use std::ffi::c_void;
|
||||
use std::os::windows::io::{AsRawHandle as _, FromRawHandle as _, OwnedHandle, RawHandle};
|
||||
use std::rc::Rc;
|
||||
use std::sync::atomic::{AtomicU32, Ordering};
|
||||
use std::sync::atomic::{AtomicBool, AtomicU32, Ordering};
|
||||
use std::sync::{Arc, LazyLock, Mutex, MutexGuard};
|
||||
use std::time::{Duration, Instant};
|
||||
use std::{fmt, mem, panic, ptr};
|
||||
|
|
@ -195,6 +195,12 @@ impl EventLoop {
|
|||
pub fn new(
|
||||
attributes: &mut PlatformSpecificEventLoopAttributes,
|
||||
) -> Result<Self, EventLoopError> {
|
||||
static EVENT_LOOP_CREATED: AtomicBool = AtomicBool::new(false);
|
||||
if EVENT_LOOP_CREATED.swap(true, Ordering::Relaxed) {
|
||||
// For better cross-platformness.
|
||||
return Err(EventLoopError::RecreationAttempt);
|
||||
}
|
||||
|
||||
let thread_id = unsafe { GetCurrentThreadId() };
|
||||
|
||||
if !attributes.any_thread && thread_id != main_thread_id() {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ use std::mem::MaybeUninit;
|
|||
use std::ops::Deref;
|
||||
use std::os::raw::*;
|
||||
use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::mpsc::{self, Receiver, Sender, TryRecvError};
|
||||
use std::sync::{Arc, LazyLock, Mutex, Weak};
|
||||
use std::time::{Duration, Instant};
|
||||
|
|
@ -207,6 +208,12 @@ struct EventLoopState {
|
|||
|
||||
impl EventLoop {
|
||||
pub fn new() -> Result<EventLoop, EventLoopError> {
|
||||
static EVENT_LOOP_CREATED: AtomicBool = AtomicBool::new(false);
|
||||
if EVENT_LOOP_CREATED.swap(true, Ordering::Relaxed) {
|
||||
// Required?
|
||||
return Err(EventLoopError::RecreationAttempt);
|
||||
}
|
||||
|
||||
let xconn = match X11_BACKEND.lock().unwrap_or_else(|e| e.into_inner()).as_ref() {
|
||||
Ok(xconn) => xconn.clone(),
|
||||
Err(err) => return Err(os_error!(err.clone()).into()),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue