mirror of
https://github.com/slint-ui/slint.git
synced 2025-11-12 00:43:51 +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::drag_resize_window::{handle_cursor_move_for_resize, handle_resize};
|
||||||
use crate::WinitWindowEventResult;
|
use crate::WinitWindowEventResult;
|
||||||
use crate::{SharedBackendData, SlintUserEvent};
|
use crate::{SharedBackendData, SlintUserEvent};
|
||||||
use corelib::api::EventLoopError;
|
|
||||||
use corelib::graphics::euclid;
|
use corelib::graphics::euclid;
|
||||||
use corelib::input::{KeyEvent, KeyEventType, MouseEvent};
|
use corelib::input::{KeyEvent, KeyEventType, MouseEvent};
|
||||||
use corelib::items::{ColorScheme, PointerEventButton};
|
use corelib::items::{ColorScheme, PointerEventButton};
|
||||||
|
|
@ -32,7 +31,6 @@ pub(crate) struct NotRunningEventLoop {
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
pub(crate) clipboard: Rc<std::cell::RefCell<crate::clipboard::ClipboardPair>>,
|
pub(crate) clipboard: Rc<std::cell::RefCell<crate::clipboard::ClipboardPair>>,
|
||||||
pub(crate) instance: winit::event_loop::EventLoop<SlintUserEvent>,
|
pub(crate) instance: winit::event_loop::EventLoop<SlintUserEvent>,
|
||||||
event_loop_proxy: winit::event_loop::EventLoopProxy<SlintUserEvent>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NotRunningEventLoop {
|
impl NotRunningEventLoop {
|
||||||
|
|
@ -72,7 +70,6 @@ impl NotRunningEventLoop {
|
||||||
|
|
||||||
let instance =
|
let instance =
|
||||||
builder.build().map_err(|e| format!("Error initializing winit event loop: {e}"))?;
|
builder.build().map_err(|e| format!("Error initializing winit event loop: {e}"))?;
|
||||||
let event_loop_proxy = instance.create_proxy();
|
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
let clipboard = crate::clipboard::create_clipboard(
|
let clipboard = crate::clipboard::create_clipboard(
|
||||||
|
|
@ -83,7 +80,6 @@ impl NotRunningEventLoop {
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
instance,
|
instance,
|
||||||
event_loop_proxy,
|
|
||||||
#[cfg(not(target_family = "wasm"))]
|
#[cfg(not(target_family = "wasm"))]
|
||||||
clipboard: Rc::new(clipboard.into()),
|
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>);
|
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>(
|
pub(crate) fn with_window_target<T>(
|
||||||
callback: impl FnOnce(
|
callback: impl FnOnce(
|
||||||
&dyn EventLoopInterface,
|
&dyn EventLoopInterface,
|
||||||
|
|
@ -715,21 +664,6 @@ impl EventLoopState {
|
||||||
})
|
})
|
||||||
.map_err(|e| format!("Error initializing winit event loop: {e}"))?;
|
.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;
|
let mut winit_loop = not_running_loop_instance.instance;
|
||||||
|
|
||||||
#[cfg(all(not(target_arch = "wasm32"), not(target_os = "ios")))]
|
#[cfg(all(not(target_arch = "wasm32"), not(target_os = "ios")))]
|
||||||
|
|
@ -739,13 +673,10 @@ impl EventLoopState {
|
||||||
.run_app_on_demand(&mut ActiveEventLoopSetterDuringEventProcessing(&mut self))
|
.run_app_on_demand(&mut ActiveEventLoopSetterDuringEventProcessing(&mut self))
|
||||||
.map_err(|e| format!("Error running winit event loop: {e}"))?;
|
.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().
|
// 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.
|
// Winit does not support creating multiple instances of the event loop.
|
||||||
let nre = NotRunningEventLoop {
|
let nre = NotRunningEventLoop {
|
||||||
instance: winit_loop,
|
instance: winit_loop,
|
||||||
event_loop_proxy,
|
|
||||||
clipboard: not_running_loop_instance.clipboard,
|
clipboard: not_running_loop_instance.clipboard,
|
||||||
};
|
};
|
||||||
MAYBE_LOOP_INSTANCE.with(|loop_instance| *loop_instance.borrow_mut() = Some(nre));
|
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}"))?;
|
.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;
|
let mut winit_loop = not_running_loop_instance.instance;
|
||||||
|
|
||||||
self.pumping_events_instantly = timeout.is_some_and(|duration| duration.is_zero());
|
self.pumping_events_instantly = timeout.is_some_and(|duration| duration.is_zero());
|
||||||
|
|
@ -799,13 +723,10 @@ impl EventLoopState {
|
||||||
|
|
||||||
self.pumping_events_instantly = false;
|
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().
|
// 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.
|
// Winit does not support creating multiple instances of the event loop.
|
||||||
let nre = NotRunningEventLoop {
|
let nre = NotRunningEventLoop {
|
||||||
instance: winit_loop,
|
instance: winit_loop,
|
||||||
event_loop_proxy,
|
|
||||||
clipboard: not_running_loop_instance.clipboard,
|
clipboard: not_running_loop_instance.clipboard,
|
||||||
};
|
};
|
||||||
MAYBE_LOOP_INSTANCE.with(|loop_instance| *loop_instance.borrow_mut() = Some(nre));
|
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}"))?;
|
.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
|
not_running_loop_instance
|
||||||
.instance
|
.instance
|
||||||
.spawn_app(ActiveEventLoopSetterDuringEventProcessing(self));
|
.spawn_app(ActiveEventLoopSetterDuringEventProcessing(self));
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,9 @@
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
use event_loop::{CustomEvent, EventLoopState};
|
use event_loop::{CustomEvent, EventLoopState};
|
||||||
|
use i_slint_core::api::EventLoopError;
|
||||||
use i_slint_core::graphics::{RequestedGraphicsAPI, RequestedOpenGLVersion};
|
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 i_slint_core::window::WindowAdapter;
|
||||||
use renderer::WinitCompatibleRenderer;
|
use renderer::WinitCompatibleRenderer;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
|
@ -21,8 +22,6 @@ use std::rc::Weak;
|
||||||
mod clipboard;
|
mod clipboard;
|
||||||
mod drag_resize_window;
|
mod drag_resize_window;
|
||||||
mod winitwindowadapter;
|
mod winitwindowadapter;
|
||||||
|
|
||||||
use i_slint_core::platform::PlatformError;
|
|
||||||
use winitwindowadapter::*;
|
use winitwindowadapter::*;
|
||||||
pub(crate) mod event_loop;
|
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 {
|
impl i_slint_core::platform::Platform for Backend {
|
||||||
fn create_window_adapter(&self) -> Result<Rc<dyn WindowAdapter>, PlatformError> {
|
fn create_window_adapter(&self) -> Result<Rc<dyn WindowAdapter>, PlatformError> {
|
||||||
let mut attrs = WinitWindowAdapter::window_attributes()?;
|
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>> {
|
fn new_event_loop_proxy(&self) -> Option<Box<dyn EventLoopProxy>> {
|
||||||
struct Proxy;
|
struct Proxy(winit::event_loop::EventLoopProxy<SlintUserEvent>);
|
||||||
impl EventLoopProxy for Proxy {
|
impl EventLoopProxy for Proxy {
|
||||||
fn quit_event_loop(&self) -> Result<(), i_slint_core::api::EventLoopError> {
|
fn quit_event_loop(&self) -> Result<(), EventLoopError> {
|
||||||
send_event_via_global_event_loop_proxy(SlintUserEvent(CustomEvent::Exit))
|
self.0
|
||||||
|
.send_event(SlintUserEvent(CustomEvent::Exit))
|
||||||
|
.map_err(|_| EventLoopError::EventLoopTerminated)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn invoke_from_event_loop(
|
fn invoke_from_event_loop(
|
||||||
&self,
|
&self,
|
||||||
event: Box<dyn FnOnce() + Send>,
|
event: Box<dyn FnOnce() + Send>,
|
||||||
) -> Result<(), i_slint_core::api::EventLoopError> {
|
) -> Result<(), EventLoopError> {
|
||||||
let e = SlintUserEvent(CustomEvent::UserEvent(event));
|
// Calling send_event is usually done by winit at the bottom of the stack,
|
||||||
send_event_via_global_event_loop_proxy(e)
|
// 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")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
|
|
||||||
|
|
@ -278,15 +278,8 @@ impl WasmInputHelper {
|
||||||
) {
|
) {
|
||||||
let closure = move |arg: Arg| {
|
let closure = move |arg: Arg| {
|
||||||
closure(arg);
|
closure(arg);
|
||||||
crate::event_loop::GLOBAL_PROXY.with(|global_proxy| {
|
// wake up event loop
|
||||||
if let Ok(mut x) = global_proxy.try_borrow_mut() {
|
i_slint_core::api::invoke_from_event_loop(|| {}).ok();
|
||||||
if let Some(proxy) = &mut *x {
|
|
||||||
let _ = proxy.send_event(crate::SlintUserEvent(
|
|
||||||
crate::event_loop::CustomEvent::WakeEventLoopWorkaround,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
let closure = Closure::wrap(Box::new(closure) as Box<dyn Fn(_)>);
|
let closure = Closure::wrap(Box::new(closure) as Box<dyn Fn(_)>);
|
||||||
self.input
|
self.input
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue