From b2a2ec91aea2365b7c92ef2fd11023d5d298eddb Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Wed, 25 Oct 2023 15:58:31 +0400 Subject: [PATCH 1/5] Fix unused import warnings on nightly --- src/platform_impl/linux/x11/ffi.rs | 4 +--- src/platform_impl/linux/x11/util/mod.rs | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/platform_impl/linux/x11/ffi.rs b/src/platform_impl/linux/x11/ffi.rs index 58abdb7247..1561803a69 100644 --- a/src/platform_impl/linux/x11/ffi.rs +++ b/src/platform_impl/linux/x11/ffi.rs @@ -1,7 +1,5 @@ use x11_dl::xmd::CARD32; -pub use x11_dl::{ - error::OpenError, keysym::*, xcursor::*, xinput::*, xinput2::*, xlib::*, xlib_xcb::*, -}; +pub use x11_dl::{error::OpenError, xcursor::*, xinput2::*, xlib::*, xlib_xcb::*}; // Isn't defined by x11_dl #[allow(non_upper_case_globals)] diff --git a/src/platform_impl/linux/x11/util/mod.rs b/src/platform_impl/linux/x11/util/mod.rs index 851e65bc51..f806b0825c 100644 --- a/src/platform_impl/linux/x11/util/mod.rs +++ b/src/platform_impl/linux/x11/util/mod.rs @@ -13,9 +13,7 @@ mod randr; mod window_property; mod wm; -pub use self::{ - client_msg::*, geometry::*, hint::*, icon::*, input::*, randr::*, window_property::*, wm::*, -}; +pub use self::{geometry::*, hint::*, input::*, window_property::*, wm::*}; use std::{ mem::{self, MaybeUninit}, From 62ed51a138aeb2dc7d64950e6f9877ba9d57646e Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Wed, 25 Oct 2023 18:32:16 +0400 Subject: [PATCH 2/5] On Winows, Fix deedlock with `WM_MOUSEMOVE` The lock was still present in `None` path. Fixes: d37d1a03b(On Windows, fix deadlock during `Cursor{Enter,Leave}`) --- src/platform_impl/windows/event_loop.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index 14080e8bc0..2bedd9a4be 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -1496,7 +1496,7 @@ unsafe fn public_window_callback_inner( }, }); } - PointerMoveKind::None => (), + PointerMoveKind::None => drop(w), } // handle spurious WM_MOUSEMOVE messages From f4e71a1d9c193b1b509fe731d3b0c7b696dbee27 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Wed, 25 Oct 2023 17:13:44 +0200 Subject: [PATCH 3/5] On macOS, fix deadlock during nested event loops (e.g. rfd) --- CHANGELOG.md | 1 + src/platform_impl/macos/app_state.rs | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 53caaba58d..1a68d11157 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ Unreleased` header. # Unreleased - On Windows, fix deadlock when accessing the state during `Cursor{Enter,Leave}`. +- On macOS, fix deadlock when entering a nested event loop from an event handler. # 0.29.2 diff --git a/src/platform_impl/macos/app_state.rs b/src/platform_impl/macos/app_state.rs index a18ffebd8e..114c124f5e 100644 --- a/src/platform_impl/macos/app_state.rs +++ b/src/platform_impl/macos/app_state.rs @@ -494,9 +494,9 @@ impl AppState { // Return when in callback due to https://github.com/rust-windowing/winit/issues/1779 if panic_info.is_panicking() + || HANDLER.get_in_callback() || !HANDLER.have_callback() || !HANDLER.is_running() - || HANDLER.get_in_callback() { return; } @@ -601,9 +601,9 @@ impl AppState { // XXX: how does it make sense that `get_in_callback()` can ever return `true` here if we're // about to return to the `CFRunLoop` to poll for new events? if panic_info.is_panicking() + || HANDLER.get_in_callback() || !HANDLER.have_callback() || !HANDLER.is_running() - || HANDLER.get_in_callback() { return; } From c235bd154adb080b876913bbbf556be4e95572c3 Mon Sep 17 00:00:00 2001 From: Marijn Suijten Date: Wed, 25 Oct 2023 17:42:51 +0200 Subject: [PATCH 4/5] On wasm, provide intradoc-link for `spawn()` function in `EventLoop` docs (#3178) --- src/event_loop.rs | 12 +++++++-- src/lib.rs | 46 ++++++++++++++++++++++++----------- src/platform/run_on_demand.rs | 15 ++++++++---- src/platform/web.rs | 19 +++++++++++++-- 4 files changed, 69 insertions(+), 23 deletions(-) diff --git a/src/event_loop.rs b/src/event_loop.rs index 3d334a79b6..13e7488e80 100644 --- a/src/event_loop.rs +++ b/src/event_loop.rs @@ -224,14 +224,22 @@ impl EventLoop { /// (that Rust doesn't see) that will also mean that the rest of the function is never executed /// and any values not passed to this function will *not* be dropped. /// - /// Web applications are recommended to use `spawn()` instead of `run()` to avoid the need + /// Web applications are recommended to use + #[cfg_attr( + wasm_platform, + doc = "[`EventLoopExtWebSys::spawn()`][crate::platform::web::EventLoopExtWebSys::spawn()]" + )] + #[cfg_attr(not(wasm_platform), doc = "`EventLoopExtWebSys::spawn()`")] + /// [^1] instead of [`run()`] to avoid the need /// for the Javascript exception trick, and to make it clearer that the event loop runs /// asynchronously (via the browser's own, internal, event loop) and doesn't block the /// current thread of execution like it does on other platforms. /// /// This function won't be available with `target_feature = "exception-handling"`. /// - /// [`set_control_flow()`]: EventLoopWindowTarget::set_control_flow + /// [`set_control_flow()`]: EventLoopWindowTarget::set_control_flow() + /// [`run()`]: Self::run() + /// [^1]: `EventLoopExtWebSys::spawn()` is only available on WASM. #[inline] #[cfg(not(all(wasm_platform, target_feature = "exception-handling")))] pub fn run(self, event_handler: F) -> Result<(), EventLoopError> diff --git a/src/lib.rs b/src/lib.rs index 54b43cd4f5..7438d6e221 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,16 +26,36 @@ //! window or a key getting pressed while the window is focused. Devices can generate //! [`DeviceEvent`]s, which contain unfiltered event data that isn't specific to a certain window. //! Some user activity, like mouse movement, can generate both a [`WindowEvent`] *and* a -//! [`DeviceEvent`]. You can also create and handle your own custom [`UserEvent`]s, if desired. +//! [`DeviceEvent`]. You can also create and handle your own custom [`Event::UserEvent`]s, if desired. //! -//! You can retrieve events by calling [`EventLoop::run`][event_loop_run]. This function will +//! You can retrieve events by calling [`EventLoop::run()`]. This function will //! dispatch events for every [`Window`] that was created with that particular [`EventLoop`], and -//! will run until [`exit()`] is used, at which point [`Event`]`::`[`LoopExiting`]. +//! will run until [`exit()`] is used, at which point [`Event::LoopExiting`]. //! //! Winit no longer uses a `EventLoop::poll_events() -> impl Iterator`-based event loop //! model, since that can't be implemented properly on some platforms (e.g web, iOS) and works poorly on //! most other platforms. However, this model can be re-implemented to an extent with -//! [`EventLoopExtPumpEvents::pump_events`]. See that method's documentation for more reasons about why +#![cfg_attr( + any( + windows_platform, + macos_platform, + android_platform, + x11_platform, + wayland_platform + ), + doc = "[`EventLoopExtPumpEvents::pump_events()`][platform::pump_events::EventLoopExtPumpEvents::pump_events()]" +)] +#![cfg_attr( + not(any( + windows_platform, + macos_platform, + android_platform, + x11_platform, + wayland_platform + )), + doc = "`EventLoopExtPumpEvents::pump_events()`" +)] +//! [^1]. See that method's documentation for more reasons about why //! it's discouraged, beyond compatibility reasons. //! //! @@ -92,8 +112,8 @@ //! }); //! ``` //! -//! [`Event`]`::`[`WindowEvent`] has a [`WindowId`] member. In multi-window environments, it should be -//! compared to the value returned by [`Window::id()`][window_id_fn] to determine which [`Window`] +//! [`WindowEvent`] has a [`WindowId`] member. In multi-window environments, it should be +//! compared to the value returned by [`Window::id()`] to determine which [`Window`] //! dispatched the event. //! //! # Drawing on the window @@ -101,7 +121,7 @@ //! Winit doesn't directly provide any methods for drawing on a [`Window`]. However it allows you to //! retrieve the raw handle of the window and display (see the [`platform`] module and/or the //! [`raw_window_handle`] and [`raw_display_handle`] methods), which in turn allows -//! you to create an OpenGL/Vulkan/DirectX/Metal/etc. context that can be used to render graphics. +//! you to create an OpenGL/Vulkan/DirectX/Metal/etc. context that can be used to render graphics. //! //! Note that many platforms will display garbage data in the window's client area if the //! application doesn't render anything to the window by the time the desktop compositor is ready to @@ -110,9 +130,8 @@ //! window visible only once you're ready to render into it. //! //! [`EventLoop`]: event_loop::EventLoop -//! [`EventLoopExtPumpEvents::pump_events`]: ./platform/pump_events/trait.EventLoopExtPumpEvents.html#tymethod.pump_events //! [`EventLoop::new()`]: event_loop::EventLoop::new -//! [event_loop_run]: event_loop::EventLoop::run +//! [`EventLoop::run()`]: event_loop::EventLoop::run //! [`exit()`]: event_loop::EventLoopWindowTarget::exit //! [`Window`]: window::Window //! [`WindowId`]: window::WindowId @@ -120,15 +139,14 @@ //! [window_new]: window::Window::new //! [window_builder_new]: window::WindowBuilder::new //! [window_builder_build]: window::WindowBuilder::build -//! [window_id_fn]: window::Window::id -//! [`Event`]: event::Event +//! [`Window::id()`]: window::Window::id //! [`WindowEvent`]: event::WindowEvent //! [`DeviceEvent`]: event::DeviceEvent -//! [`UserEvent`]: event::Event::UserEvent -//! [`LoopExiting`]: event::Event::LoopExiting -//! [`platform`]: platform +//! [`Event::UserEvent`]: event::Event::UserEvent +//! [`Event::LoopExiting`]: event::Event::LoopExiting //! [`raw_window_handle`]: ./window/struct.Window.html#method.raw_window_handle //! [`raw_display_handle`]: ./window/struct.Window.html#method.raw_display_handle +//! [^1]: `EventLoopExtPumpEvents::pump_events()` is only available on Windows, macOS, Android, X11 and Wayland. #![deny(rust_2018_idioms)] #![deny(rustdoc::broken_intra_doc_links)] diff --git a/src/platform/run_on_demand.rs b/src/platform/run_on_demand.rs index 7443c2bd92..5326e92c74 100644 --- a/src/platform/run_on_demand.rs +++ b/src/platform/run_on_demand.rs @@ -35,9 +35,9 @@ pub trait EventLoopExtRunOnDemand { /// See the [`set_control_flow()`] docs on how to change the event loop's behavior. /// /// # Caveats - /// - This extension isn't available on all platforms, since it's not always possible to - /// return to the caller (specifically this is impossible on iOS and Web - though with - /// the Web backend it is possible to use `spawn()` more than once instead). + /// - This extension isn't available on all platforms, since it's not always possible to return + /// to the caller (specifically this is impossible on iOS and Web - though with the Web + /// backend it is possible to use `EventLoopExtWebSys::spawn()`[^1] more than once instead). /// - No [`Window`] state can be carried between separate runs of the event loop. /// /// You are strongly encouraged to use [`EventLoop::run()`] for portability, unless you specifically need @@ -57,8 +57,13 @@ pub trait EventLoopExtRunOnDemand { /// on an event loop that is internal to the browser itself. /// - **iOS:** It's not possible to stop and start an `NSApplication` repeatedly on iOS. /// - /// [`exit()`]: EventLoopWindowTarget::exit - /// [`set_control_flow()`]: EventLoopWindowTarget::set_control_flow + #[cfg_attr( + not(wasm_platform), + doc = "[^1]: `spawn()` is only available on `wasm` platforms." + )] + /// + /// [`exit()`]: EventLoopWindowTarget::exit() + /// [`set_control_flow()`]: EventLoopWindowTarget::set_control_flow() fn run_on_demand(&mut self, event_handler: F) -> Result<(), EventLoopError> where F: FnMut(Event, &EventLoopWindowTarget); diff --git a/src/platform/web.rs b/src/platform/web.rs index 8a9a3d01ff..06e3f682a4 100644 --- a/src/platform/web.rs +++ b/src/platform/web.rs @@ -109,13 +109,28 @@ pub trait EventLoopExtWebSys { /// Initializes the winit event loop. /// - /// Unlike `run`, this returns immediately, and doesn't throw an exception in order to - /// satisfy its `!` return type. + /// Unlike + #[cfg_attr( + all(wasm_platform, target_feature = "exception-handling"), + doc = "`run()`" + )] + #[cfg_attr( + not(all(wasm_platform, target_feature = "exception-handling")), + doc = "[`run()`]" + )] + /// [^1], this returns immediately, and doesn't throw an exception in order to + /// satisfy its [`!`] return type. /// /// Once the event loop has been destroyed, it's possible to reinitialize another event loop /// by calling this function again. This can be useful if you want to recreate the event loop /// while the WebAssembly module is still loaded. For example, this can be used to recreate the /// event loop when switching between tabs on a single page application. + /// + #[cfg_attr( + not(all(wasm_platform, target_feature = "exception-handling")), + doc = "[`run()`]: EventLoop::run()" + )] + /// [^1]: `run()` is _not_ available on WASM when the target supports `exception-handling`. fn spawn(self, event_handler: F) where F: 'static + FnMut(Event, &EventLoopWindowTarget); From 53ca5af48ff5cf17ca0fa0012f1860e582fa9402 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Wed, 25 Oct 2023 20:59:39 +0400 Subject: [PATCH 5/5] On Wayland, fix `RedrawRequsted` loop The `dirty` is never cleared when decorations are hidden without `sctk-adwaita`. Fixes #3177. --- CHANGELOG.md | 1 + src/platform_impl/linux/wayland/window/state.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a68d11157..85f30ae569 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ Unreleased` header. # Unreleased +- On Wayland, fix `RedrawRequsted` being always sent without decorations and `sctk-adwaita` feature. - On Windows, fix deadlock when accessing the state during `Cursor{Enter,Leave}`. - On macOS, fix deadlock when entering a nested event loop from an event handler. diff --git a/src/platform_impl/linux/wayland/window/state.rs b/src/platform_impl/linux/wayland/window/state.rs index 67b705ab4d..ea2ff5aec1 100644 --- a/src/platform_impl/linux/wayland/window/state.rs +++ b/src/platform_impl/linux/wayland/window/state.rs @@ -537,7 +537,7 @@ impl WindowState { /// Refresh the decorations frame if it's present returning whether the client should redraw. pub fn refresh_frame(&mut self) -> bool { if let Some(frame) = self.frame.as_mut() { - if frame.is_dirty() { + if !frame.is_hidden() && frame.is_dirty() { return frame.draw(); } }