mirror of
https://github.com/slint-ui/slint.git
synced 2025-11-02 04:48:27 +00:00
winit backend: remove the GLOBAL_PROXY
We have a proxy in the backend, use it
This commit is contained in:
parent
42e65da8e2
commit
d2fb69c182
3 changed files with 28 additions and 137 deletions
|
|
@ -10,7 +10,6 @@
|
|||
use crate::drag_resize_window::{handle_cursor_move_for_resize, handle_resize};
|
||||
use crate::WinitWindowEventResult;
|
||||
use crate::{SharedBackendData, SlintUserEvent};
|
||||
use corelib::api::EventLoopError;
|
||||
use corelib::graphics::euclid;
|
||||
use corelib::input::{KeyEvent, KeyEventType, MouseEvent};
|
||||
use corelib::items::{ColorScheme, PointerEventButton};
|
||||
|
|
@ -32,7 +31,6 @@ pub(crate) struct NotRunningEventLoop {
|
|||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub(crate) clipboard: Rc<std::cell::RefCell<crate::clipboard::ClipboardPair>>,
|
||||
pub(crate) instance: winit::event_loop::EventLoop<SlintUserEvent>,
|
||||
event_loop_proxy: winit::event_loop::EventLoopProxy<SlintUserEvent>,
|
||||
}
|
||||
|
||||
impl NotRunningEventLoop {
|
||||
|
|
@ -72,7 +70,6 @@ impl NotRunningEventLoop {
|
|||
|
||||
let instance =
|
||||
builder.build().map_err(|e| format!("Error initializing winit event loop: {e}"))?;
|
||||
let event_loop_proxy = instance.create_proxy();
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
let clipboard = crate::clipboard::create_clipboard(
|
||||
|
|
@ -83,7 +80,6 @@ impl NotRunningEventLoop {
|
|||
|
||||
Ok(Self {
|
||||
instance,
|
||||
event_loop_proxy,
|
||||
#[cfg(not(target_family = "wasm"))]
|
||||
clipboard: Rc::new(clipboard.into()),
|
||||
})
|
||||
|
|
@ -154,53 +150,6 @@ thread_local! {
|
|||
|
||||
scoped_tls_hkt::scoped_thread_local!(static CURRENT_WINDOW_TARGET : for<'a> &'a RunningEventLoop<'a>);
|
||||
|
||||
pub(crate) enum GlobalEventLoopProxyOrEventQueue {
|
||||
Proxy(winit::event_loop::EventLoopProxy<SlintUserEvent>),
|
||||
Queue(Vec<SlintUserEvent>),
|
||||
}
|
||||
|
||||
impl GlobalEventLoopProxyOrEventQueue {
|
||||
pub(crate) fn send_event(&mut self, event: SlintUserEvent) -> Result<(), EventLoopError> {
|
||||
match self {
|
||||
GlobalEventLoopProxyOrEventQueue::Proxy(proxy) => {
|
||||
proxy.send_event(event).map_err(|_| EventLoopError::EventLoopTerminated)
|
||||
}
|
||||
GlobalEventLoopProxyOrEventQueue::Queue(queue) => {
|
||||
queue.push(event);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn set_proxy(&mut self, proxy: winit::event_loop::EventLoopProxy<SlintUserEvent>) {
|
||||
match self {
|
||||
GlobalEventLoopProxyOrEventQueue::Proxy(_) => {}
|
||||
GlobalEventLoopProxyOrEventQueue::Queue(queue) => {
|
||||
std::mem::take(queue)
|
||||
.into_iter()
|
||||
.for_each(|event| proxy.send_event(event).ok().unwrap());
|
||||
*self = GlobalEventLoopProxyOrEventQueue::Proxy(proxy);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for GlobalEventLoopProxyOrEventQueue {
|
||||
fn default() -> Self {
|
||||
Self::Queue(Vec::new())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub(crate) static GLOBAL_PROXY: std::sync::OnceLock<
|
||||
std::sync::Mutex<GlobalEventLoopProxyOrEventQueue>,
|
||||
> = std::sync::OnceLock::new();
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
thread_local! {
|
||||
pub(crate) static GLOBAL_PROXY: RefCell<Option<GlobalEventLoopProxyOrEventQueue>> = RefCell::new(None)
|
||||
}
|
||||
|
||||
pub(crate) fn with_window_target<T>(
|
||||
callback: impl FnOnce(
|
||||
&dyn EventLoopInterface,
|
||||
|
|
@ -715,21 +664,6 @@ impl EventLoopState {
|
|||
})
|
||||
.map_err(|e| format!("Error initializing winit event loop: {e}"))?;
|
||||
|
||||
let event_loop_proxy = not_running_loop_instance.event_loop_proxy;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
GLOBAL_PROXY
|
||||
.get_or_init(Default::default)
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_proxy(event_loop_proxy.clone());
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
GLOBAL_PROXY.with(|global_proxy| {
|
||||
global_proxy
|
||||
.borrow_mut()
|
||||
.get_or_insert_with(Default::default)
|
||||
.set_proxy(event_loop_proxy.clone())
|
||||
});
|
||||
|
||||
let mut winit_loop = not_running_loop_instance.instance;
|
||||
|
||||
#[cfg(all(not(target_arch = "wasm32"), not(target_os = "ios")))]
|
||||
|
|
@ -739,13 +673,10 @@ impl EventLoopState {
|
|||
.run_app_on_demand(&mut ActiveEventLoopSetterDuringEventProcessing(&mut self))
|
||||
.map_err(|e| format!("Error running winit event loop: {e}"))?;
|
||||
|
||||
*GLOBAL_PROXY.get_or_init(Default::default).lock().unwrap() = Default::default();
|
||||
|
||||
// Keep the EventLoop instance alive and re-use it in future invocations of run_event_loop().
|
||||
// Winit does not support creating multiple instances of the event loop.
|
||||
let nre = NotRunningEventLoop {
|
||||
instance: winit_loop,
|
||||
event_loop_proxy,
|
||||
clipboard: not_running_loop_instance.clipboard,
|
||||
};
|
||||
MAYBE_LOOP_INSTANCE.with(|loop_instance| *loop_instance.borrow_mut() = Some(nre));
|
||||
|
|
@ -783,13 +714,6 @@ impl EventLoopState {
|
|||
})
|
||||
.map_err(|e| format!("Error initializing winit event loop: {e}"))?;
|
||||
|
||||
let event_loop_proxy = not_running_loop_instance.event_loop_proxy;
|
||||
GLOBAL_PROXY
|
||||
.get_or_init(Default::default)
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_proxy(event_loop_proxy.clone());
|
||||
|
||||
let mut winit_loop = not_running_loop_instance.instance;
|
||||
|
||||
self.pumping_events_instantly = timeout.is_some_and(|duration| duration.is_zero());
|
||||
|
|
@ -799,13 +723,10 @@ impl EventLoopState {
|
|||
|
||||
self.pumping_events_instantly = false;
|
||||
|
||||
*GLOBAL_PROXY.get_or_init(Default::default).lock().unwrap() = Default::default();
|
||||
|
||||
// Keep the EventLoop instance alive and re-use it in future invocations of run_event_loop().
|
||||
// Winit does not support creating multiple instances of the event loop.
|
||||
let nre = NotRunningEventLoop {
|
||||
instance: winit_loop,
|
||||
event_loop_proxy,
|
||||
clipboard: not_running_loop_instance.clipboard,
|
||||
};
|
||||
MAYBE_LOOP_INSTANCE.with(|loop_instance| *loop_instance.borrow_mut() = Some(nre));
|
||||
|
|
@ -826,14 +747,6 @@ impl EventLoopState {
|
|||
})
|
||||
.map_err(|e| format!("Error initializing winit event loop: {e}"))?;
|
||||
|
||||
let event_loop_proxy = not_running_loop_instance.event_loop_proxy;
|
||||
GLOBAL_PROXY.with(|global_proxy| {
|
||||
global_proxy
|
||||
.borrow_mut()
|
||||
.get_or_insert_with(Default::default)
|
||||
.set_proxy(event_loop_proxy.clone())
|
||||
});
|
||||
|
||||
not_running_loop_instance
|
||||
.instance
|
||||
.spawn_app(ActiveEventLoopSetterDuringEventProcessing(self));
|
||||
|
|
|
|||
|
|
@ -8,8 +8,9 @@
|
|||
extern crate alloc;
|
||||
|
||||
use event_loop::{CustomEvent, EventLoopState};
|
||||
use i_slint_core::api::EventLoopError;
|
||||
use i_slint_core::graphics::{RequestedGraphicsAPI, RequestedOpenGLVersion};
|
||||
use i_slint_core::platform::EventLoopProxy;
|
||||
use i_slint_core::platform::{EventLoopProxy, PlatformError};
|
||||
use i_slint_core::window::WindowAdapter;
|
||||
use renderer::WinitCompatibleRenderer;
|
||||
use std::cell::RefCell;
|
||||
|
|
@ -21,8 +22,6 @@ use std::rc::Weak;
|
|||
mod clipboard;
|
||||
mod drag_resize_window;
|
||||
mod winitwindowadapter;
|
||||
|
||||
use i_slint_core::platform::PlatformError;
|
||||
use winitwindowadapter::*;
|
||||
pub(crate) mod event_loop;
|
||||
|
||||
|
|
@ -454,37 +453,6 @@ impl Backend {
|
|||
}
|
||||
}
|
||||
|
||||
fn send_event_via_global_event_loop_proxy(
|
||||
event: SlintUserEvent,
|
||||
) -> Result<(), i_slint_core::api::EventLoopError> {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
crate::event_loop::GLOBAL_PROXY
|
||||
.get_or_init(Default::default)
|
||||
.lock()
|
||||
.unwrap()
|
||||
.send_event(event)?;
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
{
|
||||
crate::event_loop::GLOBAL_PROXY.with(|global_proxy| {
|
||||
let mut maybe_proxy = global_proxy.borrow_mut();
|
||||
let proxy = maybe_proxy.get_or_insert_with(Default::default);
|
||||
// Calling send_event is usually done by winit at the bottom of the stack,
|
||||
// in event handlers, and thus winit might decide to process the event
|
||||
// immediately within that stack.
|
||||
// To prevent re-entrancy issues that might happen by getting the application
|
||||
// event processed on top of the current stack, set winit in Poll mode so that
|
||||
// events are queued and process on top of a clean stack during a requested animation
|
||||
// frame a few moments later.
|
||||
// This also allows batching multiple post_event calls and redraw their state changes
|
||||
// all at once.
|
||||
proxy.send_event(SlintUserEvent(CustomEvent::WakeEventLoopWorkaround))?;
|
||||
proxy.send_event(event)?;
|
||||
Ok(())
|
||||
})?
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl i_slint_core::platform::Platform for Backend {
|
||||
fn create_window_adapter(&self) -> Result<Rc<dyn WindowAdapter>, PlatformError> {
|
||||
let mut attrs = WinitWindowAdapter::window_attributes()?;
|
||||
|
|
@ -561,21 +529,38 @@ impl i_slint_core::platform::Platform for Backend {
|
|||
}
|
||||
|
||||
fn new_event_loop_proxy(&self) -> Option<Box<dyn EventLoopProxy>> {
|
||||
struct Proxy;
|
||||
struct Proxy(winit::event_loop::EventLoopProxy<SlintUserEvent>);
|
||||
impl EventLoopProxy for Proxy {
|
||||
fn quit_event_loop(&self) -> Result<(), i_slint_core::api::EventLoopError> {
|
||||
send_event_via_global_event_loop_proxy(SlintUserEvent(CustomEvent::Exit))
|
||||
fn quit_event_loop(&self) -> Result<(), EventLoopError> {
|
||||
self.0
|
||||
.send_event(SlintUserEvent(CustomEvent::Exit))
|
||||
.map_err(|_| EventLoopError::EventLoopTerminated)
|
||||
}
|
||||
|
||||
fn invoke_from_event_loop(
|
||||
&self,
|
||||
event: Box<dyn FnOnce() + Send>,
|
||||
) -> Result<(), i_slint_core::api::EventLoopError> {
|
||||
let e = SlintUserEvent(CustomEvent::UserEvent(event));
|
||||
send_event_via_global_event_loop_proxy(e)
|
||||
) -> Result<(), EventLoopError> {
|
||||
// Calling send_event is usually done by winit at the bottom of the stack,
|
||||
// in event handlers, and thus winit might decide to process the event
|
||||
// immediately within that stack.
|
||||
// To prevent re-entrancy issues that might happen by getting the application
|
||||
// event processed on top of the current stack, set winit in Poll mode so that
|
||||
// events are queued and process on top of a clean stack during a requested animation
|
||||
// frame a few moments later.
|
||||
// This also allows batching multiple post_event calls and redraw their state changes
|
||||
// all at once.
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
self.0
|
||||
.send_event(SlintUserEvent(CustomEvent::WakeEventLoopWorkaround))
|
||||
.map_err(|_| EventLoopError::EventLoopTerminated)?;
|
||||
|
||||
self.0
|
||||
.send_event(SlintUserEvent(CustomEvent::UserEvent(event)))
|
||||
.map_err(|_| EventLoopError::EventLoopTerminated)
|
||||
}
|
||||
}
|
||||
Some(Box::new(Proxy))
|
||||
Some(Box::new(Proxy(self.proxy.clone())))
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
|
|
|
|||
|
|
@ -278,15 +278,8 @@ impl WasmInputHelper {
|
|||
) {
|
||||
let closure = move |arg: Arg| {
|
||||
closure(arg);
|
||||
crate::event_loop::GLOBAL_PROXY.with(|global_proxy| {
|
||||
if let Ok(mut x) = global_proxy.try_borrow_mut() {
|
||||
if let Some(proxy) = &mut *x {
|
||||
let _ = proxy.send_event(crate::SlintUserEvent(
|
||||
crate::event_loop::CustomEvent::WakeEventLoopWorkaround,
|
||||
));
|
||||
}
|
||||
}
|
||||
});
|
||||
// wake up event loop
|
||||
i_slint_core::api::invoke_from_event_loop(|| {}).ok();
|
||||
};
|
||||
let closure = Closure::wrap(Box::new(closure) as Box<dyn Fn(_)>);
|
||||
self.input
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue