mirror of
				https://github.com/slint-ui/slint.git
				synced 2025-11-04 05:34:37 +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