From 12dbbf8012524e6f1420f19062acd6ab17252e27 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Fri, 27 Oct 2023 00:56:23 +0400 Subject: [PATCH 1/8] On Wayland, improve initial user size handling Keep the user provided size in the original values and convert only when we're getting a `configure` event. On some compositors will have a scale available, so it'll work, however with some we'll still have old 'pick 1` as default. Also configure_bounds when compositor tells the user to pick the size, that will ensure that initial `with_inner_size` won't grow beyond the working area. Fixes #3187. --- CHANGELOG.md | 3 + .../linux/wayland/event_loop/mod.rs | 2 +- src/platform_impl/linux/wayland/window/mod.rs | 16 ++-- .../linux/wayland/window/state.rs | 95 ++++++++++++++++--- src/platform_impl/linux/x11/monitor.rs | 2 +- 5 files changed, 92 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 85f30ae569..282a4f2d6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,10 @@ Unreleased` header. # Unreleased +- On Wayland, apply correct scale to `PhysicalSize` passed in `WindowBuilder::with_inner_size` when possible. - On Wayland, fix `RedrawRequsted` being always sent without decorations and `sctk-adwaita` feature. +- On Wayland, ignore resize requests when the window is fully tiled. +- On Wayland, use `configure_bounds` to constrain `with_inner_size` when compositor wants users to pick size. - 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/event_loop/mod.rs b/src/platform_impl/linux/wayland/event_loop/mod.rs index cfdc870ae3..e0d6a36d78 100644 --- a/src/platform_impl/linux/wayland/event_loop/mod.rs +++ b/src/platform_impl/linux/wayland/event_loop/mod.rs @@ -393,7 +393,7 @@ impl EventLoop { self.with_state(|state| { let windows = state.windows.get_mut(); let mut window = windows.get(&window_id).unwrap().lock().unwrap(); - window.resize(new_logical_size); + window.request_inner_size(new_logical_size.into()); }); } diff --git a/src/platform_impl/linux/wayland/window/mod.rs b/src/platform_impl/linux/wayland/window/mod.rs index 96c6931e77..ae6558a810 100644 --- a/src/platform_impl/linux/wayland/window/mod.rs +++ b/src/platform_impl/linux/wayland/window/mod.rs @@ -97,11 +97,9 @@ impl Window { .map(|activation_state| activation_state.global().clone()); let display = event_loop_window_target.connection.display(); - // XXX The initial scale factor must be 1, but it might cause sizing issues on HiDPI. - let size: LogicalSize = attributes + let size: Size = attributes .inner_size - .map(|size| size.to_logical::(1.)) - .unwrap_or((800, 600).into()); + .unwrap_or(LogicalSize::new(800., 600.).into()); // We prefer server side decorations, however to not have decorations we ask for client // side decorations instead. @@ -141,7 +139,8 @@ impl Window { // Set the window title. window_state.set_title(attributes.title); - // Set the min and max sizes. + // Set the min and max sizes. We must set the hints upon creating a window, so + // we use the default `1.` scaling... let min_size = attributes.min_inner_size.map(|size| size.to_logical(1.)); let max_size = attributes.max_inner_size.map(|size| size.to_logical(1.)); window_state.set_min_inner_size(min_size); @@ -315,12 +314,9 @@ impl Window { #[inline] pub fn request_inner_size(&self, size: Size) -> Option> { let mut window_state = self.window_state.lock().unwrap(); - let scale_factor = window_state.scale_factor(); - window_state.resize(size.to_logical::(scale_factor)); - + let new_size = window_state.request_inner_size(size); self.request_redraw(); - - Some(window_state.inner_size().to_physical(scale_factor)) + Some(new_size) } /// Set the minimum inner size for the window. diff --git a/src/platform_impl/linux/wayland/window/state.rs b/src/platform_impl/linux/wayland/window/state.rs index ea2ff5aec1..f9f3187efe 100644 --- a/src/platform_impl/linux/wayland/window/state.rs +++ b/src/platform_impl/linux/wayland/window/state.rs @@ -28,7 +28,7 @@ use sctk::shm::Shm; use sctk::subcompositor::SubcompositorState; use wayland_protocols_plasma::blur::client::org_kde_kwin_blur::OrgKdeKwinBlur; -use crate::dpi::{LogicalPosition, LogicalSize}; +use crate::dpi::{LogicalPosition, LogicalSize, PhysicalSize, Size}; use crate::error::{ExternalError, NotSupportedError}; use crate::event::WindowEvent; use crate::platform_impl::wayland::event_loop::sink::EventSink; @@ -133,6 +133,10 @@ pub struct WindowState { /// sends `None` for the new size in the configure. stateless_size: LogicalSize, + /// Initial window size provided by the user. Removed on the first + /// configure. + initial_size: Option, + /// The state of the frame callback. frame_callback_state: FrameCallbackState, @@ -153,7 +157,7 @@ impl WindowState { connection: Connection, queue_handle: &QueueHandle, winit_state: &WinitState, - size: LogicalSize, + initial_size: Size, window: Window, theme: Option, ) -> Self { @@ -194,8 +198,9 @@ impl WindowState { resizable: true, scale_factor: 1., shm: winit_state.shm.wl_shm().clone(), - size, - stateless_size: size, + size: initial_size.to_logical(1.), + stateless_size: initial_size.to_logical(1.), + initial_size: Some(initial_size), text_inputs: Vec::new(), theme, title: String::default(), @@ -253,6 +258,14 @@ impl WindowState { subcompositor: &Arc, event_sink: &mut EventSink, ) -> LogicalSize { + // NOTE: when using fractional scaling or wl_compositor@v6 the scaling + // should be delivered before the first configure, thus apply it to + // properly scale the physical sizes provided by the users. + if let Some(initial_size) = self.initial_size.take() { + self.size = initial_size.to_logical(self.scale_factor()); + self.stateless_size = self.size; + } + if configure.decoration_mode == DecorationMode::Client && self.frame.is_none() && !self.csd_fails @@ -297,7 +310,7 @@ impl WindowState { event_sink.push_window_event(WindowEvent::Occluded(occluded), window_id); } - let new_size = if let Some(frame) = self.frame.as_mut() { + let (mut new_size, constrain) = if let Some(frame) = self.frame.as_mut() { // Configure the window states. frame.update_state(configure.state); @@ -305,22 +318,38 @@ impl WindowState { (Some(width), Some(height)) => { let (width, height) = frame.subtract_borders(width, height); ( - width.map(|w| w.get()).unwrap_or(1), - height.map(|h| h.get()).unwrap_or(1), + ( + width.map(|w| w.get()).unwrap_or(1), + height.map(|h| h.get()).unwrap_or(1), + ) + .into(), + false, ) - .into() } - (_, _) if stateless => self.stateless_size, - _ => self.size, + (_, _) if stateless => (self.stateless_size, true), + _ => (self.size, true), } } else { match configure.new_size { - (Some(width), Some(height)) => (width.get(), height.get()).into(), - _ if stateless => self.stateless_size, - _ => self.size, + (Some(width), Some(height)) => ((width.get(), height.get()).into(), false), + _ if stateless => (self.stateless_size, true), + _ => (self.size, true), } }; + // Apply configure bounds only when compositor let the user decide what size to pick. + if constrain { + let bounds = self.inner_size_bounds(&configure); + new_size.width = bounds + .0 + .map(|bound_w| new_size.width.min(bound_w.get())) + .unwrap_or(new_size.width); + new_size.height = bounds + .1 + .map(|bound_h| new_size.height.min(bound_h.get())) + .unwrap_or(new_size.height); + } + // XXX Set the configure before doing a resize. self.last_configure = Some(configure); @@ -330,6 +359,30 @@ impl WindowState { new_size } + /// Compute the bounds for the inner size of the surface. + fn inner_size_bounds( + &self, + configure: &WindowConfigure, + ) -> (Option, Option) { + let configure_bounds = match configure.suggested_bounds { + Some((width, height)) => (NonZeroU32::new(width), NonZeroU32::new(height)), + None => (None, None), + }; + + if let Some(frame) = self.frame.as_ref() { + let (width, height) = frame.subtract_borders( + configure_bounds.0.unwrap_or(NonZeroU32::new(1).unwrap()), + configure_bounds.1.unwrap_or(NonZeroU32::new(1).unwrap()), + ); + ( + configure_bounds.0.and(width), + configure_bounds.1.and(height), + ) + } else { + configure_bounds + } + } + #[inline] fn is_stateless(configure: &WindowConfigure) -> bool { !(configure.is_maximized() || configure.is_fullscreen() || configure.is_tiled()) @@ -568,8 +621,22 @@ impl WindowState { } } + /// Try to resize the window when the user can do so. + pub fn request_inner_size(&mut self, inner_size: Size) -> PhysicalSize { + if self + .last_configure + .as_ref() + .map(Self::is_stateless) + .unwrap_or(true) + { + self.resize(inner_size.to_logical(self.scale_factor())) + } + + self.inner_size().to_physical(self.scale_factor()) + } + /// Resize the window to the new inner size. - pub fn resize(&mut self, inner_size: LogicalSize) { + fn resize(&mut self, inner_size: LogicalSize) { self.size = inner_size; // Update the stateless size. diff --git a/src/platform_impl/linux/x11/monitor.rs b/src/platform_impl/linux/x11/monitor.rs index 7c708613c7..9269f49ebc 100644 --- a/src/platform_impl/linux/x11/monitor.rs +++ b/src/platform_impl/linux/x11/monitor.rs @@ -212,7 +212,7 @@ impl XConnection { return Ok(MonitorHandle::dummy()); } - let default = monitors.get(0).unwrap(); + let default = monitors.first().unwrap(); let window_rect = match window_rect { Some(rect) => rect, From 5a3be586f4b5d465243097e12f3757eccd3649b6 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Sat, 28 Oct 2023 02:22:45 +0400 Subject: [PATCH 2/8] On Windows, add support for Window::set_transparent --- CHANGELOG.md | 1 + src/platform_impl/windows/window.rs | 11 ++++++++++- src/window.rs | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 282a4f2d6e..20eaef64da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ Unreleased` header. - On Wayland, ignore resize requests when the window is fully tiled. - On Wayland, use `configure_bounds` to constrain `with_inner_size` when compositor wants users to pick size. - On Windows, fix deadlock when accessing the state during `Cursor{Enter,Leave}`. +- On Windows, add support for `Window::set_transparent`. - On macOS, fix deadlock when entering a nested event loop from an event handler. # 0.29.2 diff --git a/src/platform_impl/windows/window.rs b/src/platform_impl/windows/window.rs index 92e70f7604..3f891d5be8 100644 --- a/src/platform_impl/windows/window.rs +++ b/src/platform_impl/windows/window.rs @@ -126,7 +126,16 @@ impl Window { } } - pub fn set_transparent(&self, _transparent: bool) {} + pub fn set_transparent(&self, transparent: bool) { + let window = self.window.clone(); + let window_state = Arc::clone(&self.window_state); + self.thread_executor.execute_in_thread(move || { + let _ = &window; + WindowState::set_window_flags(window_state.lock().unwrap(), window.0, |f| { + f.set(WindowFlags::TRANSPARENT, transparent) + }); + }); + } pub fn set_blur(&self, _blur: bool) {} diff --git a/src/window.rs b/src/window.rs index 3352abbadd..3a00fd2bc1 100644 --- a/src/window.rs +++ b/src/window.rs @@ -904,7 +904,7 @@ impl Window { /// /// ## Platform-specific /// - /// - **Windows / Web / iOS / Android / Orbital:** Unsupported. + /// - **Web / iOS / Android / Orbital:** Unsupported. /// - **X11:** Can only be set while building the window, with [`WindowBuilder::with_transparent`]. #[inline] pub fn set_transparent(&self, transparent: bool) { From 92b7dcccc14492cb0fb9870b70eb4bd34866c39a Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Sat, 28 Oct 2023 14:22:10 +0400 Subject: [PATCH 3/8] On macOS, add support for `Window::set_blur` --- CHANGELOG.md | 1 + src/platform_impl/macos/appkit/window.rs | 3 +++ src/platform_impl/macos/ffi.rs | 9 +++++++++ src/platform_impl/macos/window.rs | 16 +++++++++++++++- src/window.rs | 2 +- 5 files changed, 29 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 20eaef64da..3ec858b1a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ Unreleased` header. - On Windows, fix deadlock when accessing the state during `Cursor{Enter,Leave}`. - On Windows, add support for `Window::set_transparent`. - On macOS, fix deadlock when entering a nested event loop from an event handler. +- On macOS, add support for `Window::set_blur`. # 0.29.2 diff --git a/src/platform_impl/macos/appkit/window.rs b/src/platform_impl/macos/appkit/window.rs index 74b2bf3b3e..5f5d8f179f 100644 --- a/src/platform_impl/macos/appkit/window.rs +++ b/src/platform_impl/macos/appkit/window.rs @@ -36,6 +36,9 @@ extern_methods!( #[method(frame)] pub(crate) fn frame(&self) -> NSRect; + #[method(windowNumber)] + pub(crate) fn windowNumber(&self) -> NSInteger; + #[method(backingScaleFactor)] pub(crate) fn backingScaleFactor(&self) -> CGFloat; diff --git a/src/platform_impl/macos/ffi.rs b/src/platform_impl/macos/ffi.rs index 05397facf0..5396d32584 100644 --- a/src/platform_impl/macos/ffi.rs +++ b/src/platform_impl/macos/ffi.rs @@ -11,6 +11,7 @@ use core_graphics::{ base::CGError, display::{CGDirectDisplayID, CGDisplayConfigRef}, }; +use objc2::{ffi::NSInteger, runtime::AnyObject}; pub type CGDisplayFadeInterval = f32; pub type CGDisplayReservationInterval = f32; @@ -113,6 +114,14 @@ extern "C" { pub fn CGDisplayModeCopyPixelEncoding(mode: CGDisplayModeRef) -> CFStringRef; pub fn CGDisplayModeRetain(mode: CGDisplayModeRef); pub fn CGDisplayModeRelease(mode: CGDisplayModeRef); + + // Wildly used private APIs; Apple uses them for their Terminal.app. + pub fn CGSMainConnectionID() -> *mut AnyObject; + pub fn CGSSetWindowBackgroundBlurRadius( + connection_id: *mut AnyObject, + window_id: NSInteger, + radius: i64, + ) -> i32; } mod core_video { diff --git a/src/platform_impl/macos/window.rs b/src/platform_impl/macos/window.rs index 0096a6bd06..7e7d6f383e 100644 --- a/src/platform_impl/macos/window.rs +++ b/src/platform_impl/macos/window.rs @@ -46,6 +46,8 @@ use super::appkit::{ NSView, NSWindow, NSWindowButton, NSWindowLevel, NSWindowSharingType, NSWindowStyleMask, NSWindowTabbingMode, NSWindowTitleVisibility, }; +use super::ffi::CGSMainConnectionID; +use super::ffi::CGSSetWindowBackgroundBlurRadius; pub(crate) struct Window { window: MainThreadBound>, @@ -494,6 +496,10 @@ impl WinitWindow { this.setBackgroundColor(&NSColor::clear()); } + if attrs.blur { + this.set_blur(attrs.blur); + } + if let Some(dim) = attrs.min_inner_size { this.set_min_inner_size(Some(dim)); } @@ -582,7 +588,15 @@ impl WinitWindow { self.setOpaque(!transparent) } - pub fn set_blur(&self, _blur: bool) {} + pub fn set_blur(&self, blur: bool) { + // NOTE: in general we want to specify the blur radius, but the choice of 80 + // should be a reasonable default. + let radius = if blur { 80 } else { 0 }; + let window_number = self.windowNumber(); + unsafe { + CGSSetWindowBackgroundBlurRadius(CGSMainConnectionID(), window_number, radius); + } + } pub fn set_visible(&self, visible: bool) { match visible { diff --git a/src/window.rs b/src/window.rs index 3a00fd2bc1..e3950c34d9 100644 --- a/src/window.rs +++ b/src/window.rs @@ -918,7 +918,7 @@ impl Window { /// /// ## Platform-specific /// - /// - **Android / iOS / macOS / X11 / Web / Windows:** Unsupported. + /// - **Android / iOS / X11 / Web / Windows:** Unsupported. /// - **Wayland:** Only works with org_kde_kwin_blur_manager protocol. #[inline] pub fn set_blur(&self, blur: bool) { From 075dfcea1943e36e98d7910619121559a6e8bbee Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Sat, 28 Oct 2023 14:23:20 +0400 Subject: [PATCH 4/8] Clarify `scale_factor` docs Wayland scales each window individually, thus make it clear. Also recommend against using the `MonitorHandle::scale_factor`. Fixes #3183. --- src/dpi.rs | 3 ++- src/monitor.rs | 6 +++++- src/window.rs | 9 ++++++--- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/dpi.rs b/src/dpi.rs index 6d1bc388e4..2f027b18be 100644 --- a/src/dpi.rs +++ b/src/dpi.rs @@ -82,7 +82,8 @@ //! If `WINIT_X11_SCALE_FACTOR` is set to `randr`, it'll ignore the `Xft.dpi` field and use the //! XRandR scaling method. Generally speaking, you should try to configure the standard system //! variables to do what you want before resorting to `WINIT_X11_SCALE_FACTOR`. -//! - **Wayland:** Scale factor is suggested by the the compositor. +//! - **Wayland:** Scale factor is suggested by the compositor for each window individually. The +//! monitor scale factor may differ from the window scale factor. //! - **iOS:** Scale factors are set by Apple to the value that best suits the device, and range //! from `1.0` to `3.0`. See [this article][apple_1] and [this article][apple_2] for more //! information. diff --git a/src/monitor.rs b/src/monitor.rs index 47d3280928..45c355e529 100644 --- a/src/monitor.rs +++ b/src/monitor.rs @@ -138,14 +138,18 @@ impl MonitorHandle { self.inner.refresh_rate_millihertz() } - /// Returns the scale factor that can be used to map logical pixels to physical pixels, and vice versa. + /// Returns the scale factor of the underlying monitor. To map logical pixels to physical + /// pixels and vice versa, use [`Window::scale_factor`]. /// /// See the [`dpi`](crate::dpi) module for more information. /// /// ## Platform-specific /// /// - **X11:** Can be overridden using the `WINIT_X11_SCALE_FACTOR` environment variable. + /// - **Wayland:** May differ from [`Window::scale_factor`]. /// - **Android:** Always returns 1.0. + /// + /// [`Window::scale_factor`]: crate::window::Window::scale_factor #[inline] pub fn scale_factor(&self) -> f64 { self.inner.scale_factor() diff --git a/src/window.rs b/src/window.rs index e3950c34d9..8251e92749 100644 --- a/src/window.rs +++ b/src/window.rs @@ -543,14 +543,17 @@ impl Window { self.window.maybe_wait_on_main(|w| WindowId(w.id())) } - /// Returns the scale factor that can be used to map logical pixels to physical pixels, and vice versa. - /// - /// See the [`dpi`](crate::dpi) module for more information. + /// Returns the scale factor that can be used to map logical pixels to physical pixels, and + /// vice versa. /// /// Note that this value can change depending on user action (for example if the window is /// moved to another screen); as such, tracking [`WindowEvent::ScaleFactorChanged`] events is /// the most robust way to track the DPI you need to use to draw. /// + /// This value may differ from [`MonitorHandle::scale_factor`]. + /// + /// See the [`dpi`](crate::dpi) module for more information. + /// /// ## Platform-specific /// /// - **X11:** This respects Xft.dpi, and can be overridden using the `WINIT_X11_SCALE_FACTOR` environment variable. From 3c9f9da19e8d4ac5d19828717e5370af7a2f6c12 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Sat, 28 Oct 2023 21:09:28 +0400 Subject: [PATCH 5/8] Bump version on master This commit does not represent a release and only synchronizes CHANGELOG from the latest release. --- CHANGELOG.md | 2 ++ Cargo.toml | 2 +- README.md | 6 +++--- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ec858b1a1..7ec3c32da0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ Unreleased` header. # Unreleased +# 0.29.3 + - On Wayland, apply correct scale to `PhysicalSize` passed in `WindowBuilder::with_inner_size` when possible. - On Wayland, fix `RedrawRequsted` being always sent without decorations and `sctk-adwaita` feature. - On Wayland, ignore resize requests when the window is fully tiled. diff --git a/Cargo.toml b/Cargo.toml index 8b2e021ef4..b54d37c06a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "winit" -version = "0.29.2" +version = "0.29.3" authors = ["The winit contributors", "Pierre Krieger "] description = "Cross-platform window creation library." edition = "2021" diff --git a/README.md b/README.md index 185d68af30..165ce8636f 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ ```toml [dependencies] -winit = "0.29.2" +winit = "0.29.3" ``` ## [Documentation](https://docs.rs/winit) @@ -116,7 +116,7 @@ clash. | winit | ndk-glue | | :---: | :--------------------------: | -| 0.29.2| `android-activity = "0.5"` | +| 0.29 | `android-activity = "0.5"` | | 0.28 | `android-activity = "0.4"` | | 0.27 | `ndk-glue = "0.7"` | | 0.26 | `ndk-glue = "0.5"` | @@ -157,7 +157,7 @@ For more details, refer to these `android-activity` [example applications](https If your application is currently based on `NativeActivity` via the `ndk-glue` crate and building with `cargo apk` then the minimal changes would be: 1. Remove `ndk-glue` from your `Cargo.toml` -2. Enable the `"android-native-activity"` feature for Winit: `winit = { version = "0.29.2", features = [ "android-native-activity" ] }` +2. Enable the `"android-native-activity"` feature for Winit: `winit = { version = "0.29.3", features = [ "android-native-activity" ] }` 3. Add an `android_main` entrypoint (as above), instead of using the '`[ndk_glue::main]` proc macro from `ndk-macros` (optionally add a dependency on `android_logger` and initialize logging as above). 4. Pass a clone of the `AndroidApp` that your application receives to Winit when building your event loop (as shown above). From 52af1b4a7741af00bc9bb15cbc1a453d63ec88de Mon Sep 17 00:00:00 2001 From: Jasper Bekkers Date: Tue, 31 Oct 2023 16:20:34 +0100 Subject: [PATCH 6/8] On Windows, fix MT safety when starting drag --- CHANGELOG.md | 2 ++ src/platform_impl/windows/window.rs | 52 ++++++++++++++++++----------- 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ec3c32da0..561e24cb17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ Unreleased` header. # Unreleased +- On Windows, fix so `drag_window` and `drag_resize_window` can be called from another thread. + # 0.29.3 - On Wayland, apply correct scale to `PhysicalSize` passed in `WindowBuilder::with_inner_size` when possible. diff --git a/src/platform_impl/windows/window.rs b/src/platform_impl/windows/window.rs index 3f891d5be8..7d5bc6d746 100644 --- a/src/platform_impl/windows/window.rs +++ b/src/platform_impl/windows/window.rs @@ -472,27 +472,41 @@ impl Window { } unsafe fn handle_os_dragging(&self, wparam: WPARAM) { - let points = { - let mut pos = unsafe { mem::zeroed() }; - unsafe { GetCursorPos(&mut pos) }; - pos - }; - let points = POINTS { - x: points.x as i16, - y: points.y as i16, - }; - unsafe { ReleaseCapture() }; + let window = self.window.clone(); + let window_state = self.window_state.clone(); - self.window_state_lock().dragging = true; + self.thread_executor.execute_in_thread(move || { + { + let mut guard = window_state.lock().unwrap(); + if !guard.dragging { + guard.dragging = true; + } else { + return; + } + } - unsafe { - PostMessageW( - self.hwnd(), - WM_NCLBUTTONDOWN, - wparam, - &points as *const _ as LPARAM, - ) - }; + let points = { + let mut pos = unsafe { mem::zeroed() }; + unsafe { GetCursorPos(&mut pos) }; + pos + }; + let points = POINTS { + x: points.x as i16, + y: points.y as i16, + }; + + // ReleaseCapture needs to execute on the main thread + unsafe { ReleaseCapture() }; + + unsafe { + PostMessageW( + window.0, + WM_NCLBUTTONDOWN, + wparam, + &points as *const _ as LPARAM, + ) + }; + }); } #[inline] From d333dd86643243e2e25945c4c988adf8d13e90e3 Mon Sep 17 00:00:00 2001 From: Linda_pp Date: Wed, 1 Nov 2023 00:21:36 +0900 Subject: [PATCH 7/8] Fix crash when minimizing example on Windows --- examples/util/fill.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/examples/util/fill.rs b/examples/util/fill.rs index a47ce95a04..6ff4ed69eb 100644 --- a/examples/util/fill.rs +++ b/examples/util/fill.rs @@ -53,6 +53,13 @@ pub(super) fn fill_window(window: &Window) { } GC.with(|gc| { + let size = window.inner_size(); + let (Some(width), Some(height)) = + (NonZeroU32::new(size.width), NonZeroU32::new(size.height)) + else { + return; + }; + // Either get the last context used or create a new one. let mut gc = gc.borrow_mut(); let surface = gc @@ -61,13 +68,9 @@ pub(super) fn fill_window(window: &Window) { // Fill a buffer with a solid color. const DARK_GRAY: u32 = 0xFF181818; - let size = window.inner_size(); surface - .resize( - NonZeroU32::new(size.width).expect("Width must be greater than zero"), - NonZeroU32::new(size.height).expect("Height must be greater than zero"), - ) + .resize(width, height) .expect("Failed to resize the softbuffer surface"); let mut buffer = surface From bcce5134e166dd618604f374eb06c95e9006487c Mon Sep 17 00:00:00 2001 From: DevJac Date: Wed, 1 Nov 2023 15:07:35 -0600 Subject: [PATCH 8/8] Fix typo in pre_present_notify docs Fix typo and other small grammar corrections. --- src/window.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/window.rs b/src/window.rs index 8251e92749..87531e8ad8 100644 --- a/src/window.rs +++ b/src/window.rs @@ -600,11 +600,11 @@ impl Window { self.window.maybe_queue_on_main(|w| w.request_redraw()) } - /// Notify the windowing system that you're before presenting to the window. + /// Notify the windowing system before presenting to the window. /// - /// You should call this event after you've done drawing operations, but before you submit + /// You should call this event after your drawing operations, but before you submit /// the buffer to the display or commit your drawings. Doing so will help winit to properly - /// schedule and do assumptions about its internal state. For example, it could properly + /// schedule and make assumptions about its internal state. For example, it could properly /// throttle [`WindowEvent::RedrawRequested`]. /// /// ## Example