Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sync upstream #3

Merged
merged 8 commits into from
Nov 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,18 @@ 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.
- 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 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

Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "winit"
version = "0.29.2"
version = "0.29.3"
authors = ["The winit contributors", "Pierre Krieger <[email protected]>"]
description = "Cross-platform window creation library."
edition = "2021"
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

```toml
[dependencies]
winit = "0.29.2"
winit = "0.29.3"
```

## [Documentation](https://docs.rs/winit)
Expand Down Expand Up @@ -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"` |
Expand Down Expand Up @@ -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).

Expand Down
13 changes: 8 additions & 5 deletions examples/util/fill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
3 changes: 2 additions & 1 deletion src/dpi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
6 changes: 5 additions & 1 deletion src/monitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
2 changes: 1 addition & 1 deletion src/platform_impl/linux/wayland/event_loop/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ impl<T: 'static> EventLoop<T> {
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());
});
}

Expand Down
16 changes: 6 additions & 10 deletions src/platform_impl/linux/wayland/window/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<u32> = attributes
let size: Size = attributes
.inner_size
.map(|size| size.to_logical::<u32>(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.
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -315,12 +314,9 @@ impl Window {
#[inline]
pub fn request_inner_size(&self, size: Size) -> Option<PhysicalSize<u32>> {
let mut window_state = self.window_state.lock().unwrap();
let scale_factor = window_state.scale_factor();
window_state.resize(size.to_logical::<u32>(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.
Expand Down
95 changes: 81 additions & 14 deletions src/platform_impl/linux/wayland/window/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -133,6 +133,10 @@ pub struct WindowState {
/// sends `None` for the new size in the configure.
stateless_size: LogicalSize<u32>,

/// Initial window size provided by the user. Removed on the first
/// configure.
initial_size: Option<Size>,

/// The state of the frame callback.
frame_callback_state: FrameCallbackState,

Expand All @@ -153,7 +157,7 @@ impl WindowState {
connection: Connection,
queue_handle: &QueueHandle<WinitState>,
winit_state: &WinitState,
size: LogicalSize<u32>,
initial_size: Size,
window: Window,
theme: Option<Theme>,
) -> Self {
Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -253,6 +258,14 @@ impl WindowState {
subcompositor: &Arc<SubcompositorState>,
event_sink: &mut EventSink,
) -> LogicalSize<u32> {
// 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
Expand Down Expand Up @@ -297,30 +310,46 @@ 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);

match configure.new_size {
(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);

Expand All @@ -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<NonZeroU32>, Option<NonZeroU32>) {
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())
Expand Down Expand Up @@ -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<u32> {
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<u32>) {
fn resize(&mut self, inner_size: LogicalSize<u32>) {
self.size = inner_size;

// Update the stateless size.
Expand Down
2 changes: 1 addition & 1 deletion src/platform_impl/linux/x11/monitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
3 changes: 3 additions & 0 deletions src/platform_impl/macos/appkit/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
9 changes: 9 additions & 0 deletions src/platform_impl/macos/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand Down
Loading
Loading