Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 0 additions & 12 deletions src/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::*;
Expand Down Expand Up @@ -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.
///
Expand Down Expand Up @@ -93,22 +90,13 @@ 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 {
event_loop: platform_impl::EventLoop::new(&mut self.platform_specific)?,
_marker: PhantomData,
})
}

#[cfg(web_platform)]
pub(crate) fn allow_event_loop_recreation() {
EVENT_LOOP_CREATED.store(false, Ordering::Relaxed);
}
}

impl EventLoop {
Expand Down
13 changes: 13 additions & 0 deletions src/platform_impl/web/event_loop/mod.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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);

Expand Down
4 changes: 2 additions & 2 deletions src/platform_impl/web/event_loop/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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();
}
}

Expand Down
6 changes: 6 additions & 0 deletions winit-android/src/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
5 changes: 2 additions & 3 deletions winit-appkit/src/app_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}));
Expand All @@ -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> {
Expand Down
3 changes: 2 additions & 1 deletion winit-appkit/src/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
8 changes: 7 additions & 1 deletion winit-core/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
7 changes: 7 additions & 0 deletions winit-orbital/src/event_loop.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand Down Expand Up @@ -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);
Expand Down
8 changes: 4 additions & 4 deletions winit-uikit/src/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
8 changes: 7 additions & 1 deletion winit-wayland/src/event_loop/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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) =
Expand Down
8 changes: 7 additions & 1 deletion winit-win32/src/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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() {
Expand Down
7 changes: 7 additions & 0 deletions winit-x11/src/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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()),
Expand Down
Loading