Compare commits

..

10 Commits

Author SHA1 Message Date
Kirill Chibisov
2e4338bb8d Release 0.27.2 version 2022-08-12 14:39:44 +04:00
Kirill Chibisov
ec2888b8b7 On Wayland, fix Window::request_redraw being delayed
On Waylnad when asking for redraw before `MainEventsCleared`
would result for redraw being send on the next event loop tick,
which is not expectable given that it must be delivered on the same
event loop tick.
2022-08-12 11:54:02 +04:00
Kirill Chibisov
fa83bace12 Remove redundant steps from CI
Tests are already building the entire crate, so no need for a
separate builds slowing down the CI.
2022-08-11 19:31:11 +04:00
Kirill Chibisov
ee7dc48e3b Fix missleading breaking change on Windows
The applications should not rely on not-implemented behavior and
should use the right functions for that.
2022-08-11 19:07:40 +04:00
Robert Bragg
11d4a301e4 Implement version 0.4 of the HasRawWindowHandle trait
This makes Winit 0.27 compatible with crates like Wgpu 0.13 that are
using the raw_window_handle v0.4 crate and aren't able to upgrade to 0.5
until they do a new release (since it requires a semver change).

The change is intended to be self-contained (instead of pushing
the details into all the platform_impl backends) since this is only
intended to be a temporary trait implementation for backwards
compatibility that will likely be removed before the next Winit release.

Fixes #2415.
2022-08-11 18:33:02 +04:00
Mads Marquart
ad41eaf151 Add CODEOWNERS file (#2420)
* Add CODEOWNERS file

This makes it very clear when you're stepping down from the post as a maintainer, and makes it clear for users who is expected to review their PR

* Fix grammar

* Make @kchibisov receive pings for the X11 platform

* Fix typo

Co-authored-by: Kirill Chibisov <contact@kchibisov.com>
2022-08-11 16:13:56 +02:00
ajtribick
9b71df9f97 On Windows, add opt-in function for device events (#2409) 2022-08-11 15:17:46 +02:00
Mads Marquart
b1c9e4a6fa Fix tracking of phase changes for mousewheel on trackpad (#2158) 2022-08-10 18:28:19 +02:00
Anton Bulakh
cdbaf4816a On X11, fix window hints not persisting
This commit fixes the issue with min, max, and resize increments
not persisting across the dpi changes.
2022-08-08 18:27:11 +04:00
Amr Bashir
6b7ceedc91 Windows: respect min/max sizes when creating the window (#2393) 2022-08-04 23:03:55 +02:00
19 changed files with 399 additions and 150 deletions

35
.github/CODEOWNERS vendored Normal file
View File

@@ -0,0 +1,35 @@
# Core maintainers:
# - @msiglreith
# - @kchibisov
# - @madsmtm
# - @maroider
# Android
/src/platform/android.rs @msiglreith
/src/platform_impl/android @msiglreith
# iOS
/src/platform/ios.rs @francesca64
/src/platform_impl/ios @francesca64
# Unix in general
/src/platform/unix.rs @kchibisov
/src/platform_impl/linux/mod.rs @kchibisov
# Wayland
/src/platform_impl/linux/wayland @kchibisov
# X11
/src/platform_impl/linux/x11 @kchibisov
# macOS
/src/platform/macos.rs @madsmtm
/src/platform_impl/macos @madsmtm
# Web (no maintainer)
/src/platform/web.rs
/src/platform_impl/web
# Windows
/src/platform/windows.rs @msiglreith
/src/platform_impl/windows @msiglreith

View File

@@ -86,10 +86,6 @@ jobs:
shell: bash
run: cargo $CMD doc --no-deps --target ${{ matrix.platform.target }} $OPTIONS --features $FEATURES --document-private-items
- name: Build
shell: bash
run: cargo $CMD build --verbose --target ${{ matrix.platform.target }} $OPTIONS --features $FEATURES
- name: Build tests
shell: bash
run: cargo $CMD test --no-run --verbose --target ${{ matrix.platform.target }} $OPTIONS --features $FEATURES
@@ -106,10 +102,6 @@ jobs:
if: (matrix.rust_version == '1.57.0') && !contains(matrix.platform.options, '--no-default-features')
run: cargo clippy --all-targets --target ${{ matrix.platform.target }} $OPTIONS --features $FEATURES -- -Dwarnings
- name: Build with serde enabled
shell: bash
run: cargo $CMD build --verbose --target ${{ matrix.platform.target }} $OPTIONS --features serde,$FEATURES
- name: Build tests with serde enabled
shell: bash
run: cargo $CMD test --no-run --verbose --target ${{ matrix.platform.target }} $OPTIONS --features serde,$FEATURES

View File

@@ -8,6 +8,15 @@ And please only add new entries to the top of this list, right below the `# Unre
# Unreleased
# 0.27.2 (2022-8-12)
- On macOS, fixed touch phase reporting when scrolling.
- On X11, fix min, max and resize increment hints not persisting for resizable windows (e.g. on DPI change).
- On Windows, respect min/max inner sizes when creating the window.
- For backwards compatibility, `Window` now (additionally) implements the old version (`0.4`) of the `HasRawWindowHandle` trait
- On Windows, added support for `EventLoopWindowTarget::set_device_event_filter`.
- On Wayland, fix user requested `WindowEvent::RedrawRequested` being delayed by a frame.
# 0.27.1 (2022-07-30)
- The minimum supported Rust version was lowered to `1.57.0` and now explicitly tested.

View File

@@ -44,10 +44,9 @@ Once your PR is deemed ready, the merging maintainer will take care of resolving
## Maintainers & Testers
The current [list of testers and contributors](https://github.com/rust-windowing/winit/wiki/Testers-and-Contributors)
can be found on the Wiki.
The current maintainers are listed in the [CODEOWNERS](.github/CODEOWNERS) file.
If you are interested in contributing or testing on a platform, please add yourself to that table!
If you are interested in being pinged when testing is needed for a certain platform, please add yourself to the [Testers and Contributors](https://github.com/rust-windowing/winit/wiki/Testers-and-Contributors) table!
## Making a new release

View File

@@ -1,6 +1,6 @@
[package]
name = "winit"
version = "0.27.1"
version = "0.27.2"
authors = ["The winit contributors", "Pierre Krieger <pierre.krieger1708@gmail.com>"]
description = "Cross-platform window creation library."
edition = "2021"
@@ -46,7 +46,8 @@ instant = { version = "0.1", features = ["wasm-bindgen"] }
once_cell = "1.12"
log = "0.4"
serde = { version = "1", optional = true, features = ["serde_derive"] }
raw-window-handle = "0.5.0"
raw_window_handle = { package = "raw-window-handle", version = "0.5" }
raw_window_handle_04 = { package = "raw-window-handle", version = "0.4" }
bitflags = "1"
mint = { version = "0.5.6", optional = true }

View File

@@ -15,9 +15,12 @@ future endeavors:
vastly more sustainable era of winit.
* [@goddessfreya]: For selflessly taking over maintainership of glutin, and her
stellar dedication to improving both winit and glutin.
* [@ArturKovacs]: For consistently maintaining the macOS backend, and his
immense involvement in designing and implementing the new keyboard API.
[@tomaka]: https://github.com/tomaka
[@vberger]: https://github.com/vberger
[@francesca64]: https://github.com/francesca64
[@Osspial]: https://github.com/Osspial
[@goddessfreya]: https://github.com/goddessfreya
[@ArturKovacs]: https://github.com/ArturKovacs

View File

@@ -6,7 +6,7 @@
```toml
[dependencies]
winit = "0.27.1"
winit = "0.27.2"
```
## [Documentation](https://docs.rs/winit)

View File

@@ -511,6 +511,29 @@ impl Size {
Size::Logical(size) => size.to_physical(scale_factor),
}
}
pub fn clamp<S: Into<Size>>(input: S, min: S, max: S, scale_factor: f64) -> Size {
let (input, min, max) = (
input.into().to_physical::<f64>(scale_factor),
min.into().to_physical::<f64>(scale_factor),
max.into().to_physical::<f64>(scale_factor),
);
let clamp = |input: f64, min: f64, max: f64| {
if input < min {
min
} else if input > max {
max
} else {
input
}
};
let width = clamp(input.width, min.width, max.width);
let height = clamp(input.height, min.height, max.height);
PhysicalSize::new(width, height).into()
}
}
impl<P: Pixel> From<PhysicalSize<P>> for Size {

View File

@@ -323,7 +323,7 @@ impl<T> EventLoopWindowTarget<T> {
///
/// ## Platform-specific
///
/// - **Wayland / Windows / macOS / iOS / Android / Web:** Unsupported.
/// - **Wayland / macOS / iOS / Android / Web:** Unsupported.
///
/// [`DeviceEvent`]: crate::event::DeviceEvent
pub fn set_device_event_filter(&self, _filter: DeviceEventFilter) {
@@ -332,7 +332,8 @@ impl<T> EventLoopWindowTarget<T> {
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd"
target_os = "openbsd",
target_os = "windows"
))]
self.p.set_device_event_filter(_filter);
}

View File

@@ -2,6 +2,7 @@ use std::cell::RefCell;
use std::collections::HashMap;
use std::error::Error;
use std::io::Result as IOResult;
use std::mem;
use std::process;
use std::rc::Rc;
use std::time::{Duration, Instant};
@@ -26,7 +27,7 @@ use crate::platform_impl::EventLoopWindowTarget as PlatformEventLoopWindowTarget
use super::env::{WindowingFeatures, WinitEnv};
use super::output::OutputManager;
use super::seat::SeatManager;
use super::window::shim::{self, WindowUpdate};
use super::window::shim::{self, WindowCompositorUpdate, WindowUserRequest};
use super::{DeviceId, WindowId};
mod proxy;
@@ -82,6 +83,9 @@ impl<T> EventLoopWindowTarget<T> {
}
pub struct EventLoop<T: 'static> {
/// Dispatcher of Wayland events.
pub wayland_dispatcher: WinitDispatcher,
/// Event loop.
event_loop: calloop::EventLoop<'static, WinitState>,
@@ -94,9 +98,6 @@ pub struct EventLoop<T: 'static> {
/// Sender of user events.
user_events_sender: calloop::channel::Sender<T>,
/// Dispatcher of Wayland events.
pub wayland_dispatcher: WinitDispatcher,
/// Window target.
window_target: RootEventLoopWindowTarget<T>,
@@ -164,17 +165,19 @@ impl<T: 'static> EventLoop<T> {
let (event_loop_awakener, event_loop_awakener_source) = calloop::ping::make_ping()?;
// Handler of window requests.
event_loop.handle().insert_source(
event_loop_awakener_source,
move |_, _, winit_state| {
shim::handle_window_requests(winit_state);
},
)?;
event_loop
.handle()
.insert_source(event_loop_awakener_source, move |_, _, state| {
// Drain events here as well to account for application doing batch event processing
// on RedrawEventsCleared.
shim::handle_window_requests(state);
})?;
let event_loop_handle = event_loop.handle();
let window_map = HashMap::new();
let event_sink = EventSink::new();
let window_updates = HashMap::new();
let window_user_requests = HashMap::new();
let window_compositor_updates = HashMap::new();
// Create event loop window target.
let event_loop_window_target = EventLoopWindowTarget {
@@ -183,7 +186,8 @@ impl<T: 'static> EventLoop<T> {
state: RefCell::new(WinitState {
window_map,
event_sink,
window_updates,
window_user_requests,
window_compositor_updates,
}),
event_loop_handle,
output_manager,
@@ -236,7 +240,8 @@ impl<T: 'static> EventLoop<T> {
// applications don't themselves have a formal suspend/resume lifecycle.
callback(Event::Resumed, &self.window_target, &mut control_flow);
let mut window_updates: Vec<(WindowId, WindowUpdate)> = Vec::new();
let mut window_compositor_updates: Vec<(WindowId, WindowCompositorUpdate)> = Vec::new();
let mut window_user_requests: Vec<(WindowId, WindowUserRequest)> = Vec::new();
let mut event_sink_back_buffer = Vec::new();
// NOTE We break on errors from dispatches, since if we've got protocol error
@@ -357,25 +362,26 @@ impl<T: 'static> EventLoop<T> {
);
}
// Process 'new' pending updates.
// Process 'new' pending updates from compositor.
self.with_state(|state| {
window_updates.clear();
window_updates.extend(
window_compositor_updates.clear();
window_compositor_updates.extend(
state
.window_updates
.window_compositor_updates
.iter_mut()
.map(|(wid, window_update)| (*wid, window_update.take())),
.map(|(wid, window_update)| (*wid, mem::take(window_update))),
);
});
for (window_id, window_update) in window_updates.iter_mut() {
if let Some(scale_factor) = window_update.scale_factor.map(|f| f as f64) {
for (window_id, window_compositor_update) in window_compositor_updates.iter_mut() {
if let Some(scale_factor) = window_compositor_update.scale_factor.map(|f| f as f64)
{
let mut physical_size = self.with_state(|state| {
let window_handle = state.window_map.get(window_id).unwrap();
let mut size = window_handle.size.lock().unwrap();
// Update the new logical size if it was changed.
let window_size = window_update.size.unwrap_or(*size);
let window_size = window_compositor_update.size.unwrap_or(*size);
*size = window_size;
window_size.to_physical(scale_factor)
@@ -397,26 +403,27 @@ impl<T: 'static> EventLoop<T> {
// We don't update size on a window handle since we'll do that later
// when handling size update.
let new_logical_size = physical_size.to_logical(scale_factor);
window_update.size = Some(new_logical_size);
window_compositor_update.size = Some(new_logical_size);
}
if let Some(size) = window_update.size.take() {
if let Some(size) = window_compositor_update.size.take() {
let physical_size = self.with_state(|state| {
let window_handle = state.window_map.get_mut(window_id).unwrap();
let mut window_size = window_handle.size.lock().unwrap();
// Always issue resize event on scale factor change.
let physical_size =
if window_update.scale_factor.is_none() && *window_size == size {
// The size hasn't changed, don't inform downstream about that.
None
} else {
*window_size = size;
let scale_factor =
sctk::get_surface_scale_factor(window_handle.window.surface());
let physical_size = size.to_physical(scale_factor as f64);
Some(physical_size)
};
let physical_size = if window_compositor_update.scale_factor.is_none()
&& *window_size == size
{
// The size hasn't changed, don't inform downstream about that.
None
} else {
*window_size = size;
let scale_factor =
sctk::get_surface_scale_factor(window_handle.window.surface());
let physical_size = size.to_physical(scale_factor as f64);
Some(physical_size)
};
// We still perform all of those resize related logic even if the size
// hasn't changed, since GNOME relies on `set_geometry` calls after
@@ -425,7 +432,11 @@ impl<T: 'static> EventLoop<T> {
window_handle.window.refresh();
// Mark that refresh isn't required, since we've done it right now.
window_update.refresh_frame = false;
state
.window_user_requests
.get_mut(window_id)
.unwrap()
.refresh_frame = false;
physical_size
});
@@ -443,7 +454,8 @@ impl<T: 'static> EventLoop<T> {
}
}
if window_update.close_window {
// If the close is requested, send it here.
if window_compositor_update.close_window {
sticky_exit_callback(
Event::WindowEvent {
window_id: crate::window::WindowId(*window_id),
@@ -480,21 +492,40 @@ impl<T: 'static> EventLoop<T> {
&mut callback,
);
// Apply user requests, so every event required resize and latter surface commit will
// be applied right before drawing. This will also ensure that every `RedrawRequested`
// event will be delivered in time.
self.with_state(|state| {
shim::handle_window_requests(state);
});
// Process 'new' pending updates from compositor.
self.with_state(|state| {
window_user_requests.clear();
window_user_requests.extend(
state
.window_user_requests
.iter_mut()
.map(|(wid, window_request)| (*wid, mem::take(window_request))),
);
});
// Handle RedrawRequested events.
for (window_id, window_update) in window_updates.iter() {
for (window_id, mut window_request) in window_user_requests.iter() {
// Handle refresh of the frame.
if window_update.refresh_frame {
if window_request.refresh_frame {
self.with_state(|state| {
let window_handle = state.window_map.get_mut(window_id).unwrap();
window_handle.window.refresh();
if !window_update.redraw_requested {
window_handle.window.surface().commit();
}
});
// In general refreshing the frame requires surface commit, those force user
// to redraw.
window_request.redraw_requested = true;
}
// Handle redraw request.
if window_update.redraw_requested {
if window_request.redraw_requested {
sticky_exit_callback(
Event::RedrawRequested(crate::window::WindowId(*window_id)),
&self.window_target,

View File

@@ -3,7 +3,9 @@
use std::collections::HashMap;
use super::EventSink;
use crate::platform_impl::wayland::window::shim::{WindowHandle, WindowUpdate};
use crate::platform_impl::wayland::window::shim::{
WindowCompositorUpdate, WindowHandle, WindowUserRequest,
};
use crate::platform_impl::wayland::WindowId;
/// Wrapper to carry winit's state.
@@ -12,10 +14,14 @@ pub struct WinitState {
/// event loop and forwarded downstream afterwards.
pub event_sink: EventSink,
/// Window updates comming from the user requests. Those are separatelly dispatched right after
/// `MainEventsCleared`.
pub window_user_requests: HashMap<WindowId, WindowUserRequest>,
/// Window updates, which are coming from SCTK or the compositor, which require
/// calling back to the winit's downstream. They are handled right in the event loop,
/// unlike the ones coming from buffers on the `WindowHandle`'s.
pub window_updates: HashMap<WindowId, WindowUpdate>,
pub window_compositor_updates: HashMap<WindowId, WindowCompositorUpdate>,
/// Window map containing all SCTK windows. Since those windows aren't allowed
/// to be sent to other threads, they live on the event loop's thread

View File

@@ -30,7 +30,7 @@ use super::{EventLoopWindowTarget, WindowId};
pub mod shim;
use shim::{WindowHandle, WindowRequest, WindowUpdate};
use shim::{WindowCompositorUpdate, WindowHandle, WindowRequest, WindowUserRequest};
#[cfg(feature = "sctk-adwaita")]
pub type WinitFrame = sctk_adwaita::AdwaitaFrame;
@@ -94,11 +94,20 @@ impl Window {
// Get the window that received the event.
let window_id = super::make_wid(&surface);
let mut window_update = winit_state.window_updates.get_mut(&window_id).unwrap();
let mut window_compositor_update = winit_state
.window_compositor_updates
.get_mut(&window_id)
.unwrap();
// Mark that we need a frame refresh on the DPI change.
winit_state
.window_user_requests
.get_mut(&window_id)
.unwrap()
.refresh_frame = true;
// Set pending scale factor.
window_update.scale_factor = Some(scale);
window_update.redraw_requested = true;
window_compositor_update.scale_factor = Some(scale);
surface.set_buffer_scale(scale);
})
@@ -128,11 +137,19 @@ impl Window {
use sctk::window::{Event, State};
let winit_state = dispatch_data.get::<WinitState>().unwrap();
let mut window_update = winit_state.window_updates.get_mut(&window_id).unwrap();
let mut window_compositor_update = winit_state
.window_compositor_updates
.get_mut(&window_id)
.unwrap();
let mut window_user_requests = winit_state
.window_user_requests
.get_mut(&window_id)
.unwrap();
match event {
Event::Refresh => {
window_update.refresh_frame = true;
window_user_requests.refresh_frame = true;
}
Event::Configure { new_size, states } => {
let is_maximized = states.contains(&State::Maximized);
@@ -140,14 +157,13 @@ impl Window {
let is_fullscreen = states.contains(&State::Fullscreen);
fullscreen_clone.store(is_fullscreen, Ordering::Relaxed);
window_update.refresh_frame = true;
window_update.redraw_requested = true;
window_user_requests.refresh_frame = true;
if let Some((w, h)) = new_size {
window_update.size = Some(LogicalSize::new(w, h));
window_compositor_update.size = Some(LogicalSize::new(w, h));
}
}
Event::Close => {
window_update.close_window = true;
window_compositor_update.close_window = true;
}
}
},
@@ -234,9 +250,9 @@ impl Window {
let size = Arc::new(Mutex::new(LogicalSize::new(width, height)));
// We should trigger redraw and commit the surface for the newly created window.
let mut window_update = WindowUpdate::new();
window_update.refresh_frame = true;
window_update.redraw_requested = true;
let mut window_user_request = WindowUserRequest::new();
window_user_request.refresh_frame = true;
window_user_request.redraw_requested = true;
let window_id = super::make_wid(&surface);
let window_requests = Arc::new(Mutex::new(Vec::with_capacity(64)));
@@ -262,9 +278,13 @@ impl Window {
.event_sink
.push_window_event(crate::event::WindowEvent::Focused(false), window_id);
// Add state for the window.
winit_state
.window_updates
.insert(window_id, WindowUpdate::new());
.window_user_requests
.insert(window_id, window_user_request);
winit_state
.window_compositor_updates
.insert(window_id, WindowCompositorUpdate::new());
let windowing_features = event_loop_window_target.windowing_features;

View File

@@ -98,56 +98,38 @@ pub enum WindowRequest {
Close,
}
/// Pending update to a window from SCTK window.
#[derive(Debug, Clone, Copy)]
pub struct WindowUpdate {
// The window update comming from the compositor.
#[derive(Default, Debug, Clone, Copy)]
pub struct WindowCompositorUpdate {
/// New window size.
pub size: Option<LogicalSize<u32>>,
/// New scale factor.
pub scale_factor: Option<i32>,
/// Close the window.
pub close_window: bool,
}
impl WindowCompositorUpdate {
pub fn new() -> Self {
Default::default()
}
}
/// Pending update to a window requested by the user.
#[derive(Default, Debug, Clone, Copy)]
pub struct WindowUserRequest {
/// Whether `redraw` was requested.
pub redraw_requested: bool,
/// Wether the frame should be refreshed.
pub refresh_frame: bool,
/// Close the window.
pub close_window: bool,
}
impl WindowUpdate {
impl WindowUserRequest {
pub fn new() -> Self {
Self {
size: None,
scale_factor: None,
redraw_requested: false,
refresh_frame: false,
close_window: false,
}
}
pub fn take(&mut self) -> Self {
let size = self.size.take();
let scale_factor = self.scale_factor.take();
let redraw_requested = self.redraw_requested;
self.redraw_requested = false;
let refresh_frame = self.refresh_frame;
self.refresh_frame = false;
let close_window = self.close_window;
self.close_window = false;
Self {
size,
scale_factor,
redraw_requested,
refresh_frame,
close_window,
}
Default::default()
}
}
@@ -422,7 +404,8 @@ impl WindowHandle {
#[inline]
pub fn handle_window_requests(winit_state: &mut WinitState) {
let window_map = &mut winit_state.window_map;
let window_updates = &mut winit_state.window_updates;
let window_user_requests = &mut winit_state.window_user_requests;
let window_compositor_updates = &mut winit_state.window_compositor_updates;
let mut windows_to_close: Vec<WindowId> = Vec::new();
// Process the rest of the events.
@@ -478,15 +461,15 @@ pub fn handle_window_requests(winit_state: &mut WinitState) {
window_handle.window.set_decorate(decorations);
// We should refresh the frame to apply decorations change.
let window_update = window_updates.get_mut(window_id).unwrap();
window_update.refresh_frame = true;
let window_request = window_user_requests.get_mut(window_id).unwrap();
window_request.refresh_frame = true;
}
#[cfg(feature = "sctk-adwaita")]
WindowRequest::CsdThemeVariant(theme) => {
window_handle.window.set_frame_config(theme.into());
let window_update = window_updates.get_mut(window_id).unwrap();
window_update.refresh_frame = true;
let window_requst = window_user_requests.get_mut(window_id).unwrap();
window_requst.refresh_frame = true;
}
#[cfg(not(feature = "sctk-adwaita"))]
WindowRequest::CsdThemeVariant(_) => {}
@@ -494,29 +477,29 @@ pub fn handle_window_requests(winit_state: &mut WinitState) {
window_handle.window.set_resizable(resizeable);
// We should refresh the frame to update button state.
let window_update = window_updates.get_mut(window_id).unwrap();
window_update.refresh_frame = true;
let window_request = window_user_requests.get_mut(window_id).unwrap();
window_request.refresh_frame = true;
}
WindowRequest::Title(title) => {
window_handle.window.set_title(title);
// We should refresh the frame to draw new title.
let window_update = window_updates.get_mut(window_id).unwrap();
window_update.refresh_frame = true;
let window_request = window_user_requests.get_mut(window_id).unwrap();
window_request.refresh_frame = true;
}
WindowRequest::MinSize(size) => {
let size = size.map(|size| (size.width, size.height));
window_handle.window.set_min_size(size);
let window_update = window_updates.get_mut(window_id).unwrap();
window_update.redraw_requested = true;
let window_request = window_user_requests.get_mut(window_id).unwrap();
window_request.refresh_frame = true;
}
WindowRequest::MaxSize(size) => {
let size = size.map(|size| (size.width, size.height));
window_handle.window.set_max_size(size);
let window_update = window_updates.get_mut(window_id).unwrap();
window_update.redraw_requested = true;
let window_request = window_user_requests.get_mut(window_id).unwrap();
window_request.refresh_frame = true;
}
WindowRequest::FrameSize(size) => {
if !window_handle.is_resizable.get() {
@@ -530,21 +513,21 @@ pub fn handle_window_requests(winit_state: &mut WinitState) {
window_handle.window.resize(size.width, size.height);
// We should refresh the frame after resize.
let window_update = window_updates.get_mut(window_id).unwrap();
window_update.refresh_frame = true;
let window_request = window_user_requests.get_mut(window_id).unwrap();
window_request.refresh_frame = true;
}
WindowRequest::PassthroughMouseInput(passthrough) => {
window_handle.passthrough_mouse_input(passthrough);
let window_update = window_updates.get_mut(window_id).unwrap();
window_update.refresh_frame = true;
let window_request = window_user_requests.get_mut(window_id).unwrap();
window_request.refresh_frame = true;
}
WindowRequest::Attention(request_type) => {
window_handle.set_user_attention(request_type);
}
WindowRequest::Redraw => {
let window_update = window_updates.get_mut(window_id).unwrap();
window_update.redraw_requested = true;
let window_request = window_user_requests.get_mut(window_id).unwrap();
window_request.redraw_requested = true;
}
WindowRequest::Close => {
// The window was requested to be closed.
@@ -561,7 +544,8 @@ pub fn handle_window_requests(winit_state: &mut WinitState) {
// Close the windows.
for window in windows_to_close {
let _ = window_map.remove(&window);
let _ = window_updates.remove(&window);
let _ = window_user_requests.remove(&window);
let _ = window_compositor_updates.remove(&window);
}
}

View File

@@ -371,15 +371,15 @@ impl UnownedWindow {
} else {
max_inner_size = Some(dimensions.into());
min_inner_size = Some(dimensions.into());
let mut shared_state = window.shared_state.get_mut();
shared_state.min_inner_size = window_attrs.min_inner_size;
shared_state.max_inner_size = window_attrs.max_inner_size;
shared_state.resize_increments = pl_attribs.resize_increments;
shared_state.base_size = pl_attribs.base_size;
}
}
let mut shared_state = window.shared_state.get_mut();
shared_state.min_inner_size = min_inner_size.map(Into::into);
shared_state.max_inner_size = max_inner_size.map(Into::into);
shared_state.resize_increments = pl_attribs.resize_increments;
shared_state.base_size = pl_attribs.base_size;
let mut normal_hints = util::NormalHints::new(xconn);
normal_hints.set_position(position.map(|PhysicalPosition { x, y }| (x, y)));
normal_hints.set_size(Some(dimensions));

View File

@@ -1148,12 +1148,27 @@ extern "C" fn scroll_wheel(this: &Object, _sel: Sel, event: id) {
MouseScrollDelta::LineDelta(x as f32, y as f32)
}
};
let phase = match event.phase() {
// The "momentum phase," if any, has higher priority than touch phase (the two should
// be mutually exclusive anyhow, which is why the API is rather incoherent). If no momentum
// phase is recorded (or rather, the started/ended cases of the momentum phase) then we
// report the touch phase.
let phase = match event.momentumPhase() {
NSEventPhase::NSEventPhaseMayBegin | NSEventPhase::NSEventPhaseBegan => {
TouchPhase::Started
}
NSEventPhase::NSEventPhaseEnded => TouchPhase::Ended,
_ => TouchPhase::Moved,
NSEventPhase::NSEventPhaseEnded | NSEventPhase::NSEventPhaseCancelled => {
TouchPhase::Ended
}
_ => match event.phase() {
NSEventPhase::NSEventPhaseMayBegin | NSEventPhase::NSEventPhaseBegan => {
TouchPhase::Started
}
NSEventPhase::NSEventPhaseEnded | NSEventPhase::NSEventPhaseCancelled => {
TouchPhase::Ended
}
_ => TouchPhase::Moved,
},
};
let device_event = Event::DeviceEvent {

View File

@@ -77,7 +77,9 @@ use windows_sys::Win32::{
use crate::{
dpi::{PhysicalPosition, PhysicalSize},
event::{DeviceEvent, Event, Force, Ime, KeyboardInput, Touch, TouchPhase, WindowEvent},
event_loop::{ControlFlow, EventLoopClosed, EventLoopWindowTarget as RootELW},
event_loop::{
ControlFlow, DeviceEventFilter, EventLoopClosed, EventLoopWindowTarget as RootELW,
},
monitor::MonitorHandle as RootMonitorHandle,
platform_impl::platform::{
dark_mode::try_theme,
@@ -207,7 +209,10 @@ impl<T: 'static> EventLoop<T> {
let thread_msg_sender =
insert_event_target_window_data::<T>(thread_msg_target, runner_shared.clone());
raw_input::register_all_mice_and_keyboards_for_raw_input(thread_msg_target);
raw_input::register_all_mice_and_keyboards_for_raw_input(
thread_msg_target,
Default::default(),
);
EventLoop {
thread_msg_sender,
@@ -322,6 +327,10 @@ impl<T> EventLoopWindowTarget<T> {
pub fn raw_display_handle(&self) -> RawDisplayHandle {
RawDisplayHandle::Windows(WindowsDisplayHandle::empty())
}
pub fn set_device_event_filter(&self, filter: DeviceEventFilter) {
raw_input::register_all_mice_and_keyboards_for_raw_input(self.thread_msg_target, filter);
}
}
/// Returns the id of the main thread.

View File

@@ -12,9 +12,9 @@ use windows_sys::Win32::{
Input::{
GetRawInputData, GetRawInputDeviceInfoW, GetRawInputDeviceList,
RegisterRawInputDevices, HRAWINPUT, RAWINPUT, RAWINPUTDEVICE, RAWINPUTDEVICELIST,
RAWINPUTHEADER, RIDEV_DEVNOTIFY, RIDEV_INPUTSINK, RIDI_DEVICEINFO, RIDI_DEVICENAME,
RID_DEVICE_INFO, RID_DEVICE_INFO_HID, RID_DEVICE_INFO_KEYBOARD, RID_DEVICE_INFO_MOUSE,
RID_INPUT, RIM_TYPEHID, RIM_TYPEKEYBOARD, RIM_TYPEMOUSE,
RAWINPUTHEADER, RIDEV_DEVNOTIFY, RIDEV_INPUTSINK, RIDEV_REMOVE, RIDI_DEVICEINFO,
RIDI_DEVICENAME, RID_DEVICE_INFO, RID_DEVICE_INFO_HID, RID_DEVICE_INFO_KEYBOARD,
RID_DEVICE_INFO_MOUSE, RID_INPUT, RIM_TYPEHID, RIM_TYPEKEYBOARD, RIM_TYPEMOUSE,
},
WindowsAndMessaging::{
RI_MOUSE_LEFT_BUTTON_DOWN, RI_MOUSE_LEFT_BUTTON_UP, RI_MOUSE_MIDDLE_BUTTON_DOWN,
@@ -23,7 +23,7 @@ use windows_sys::Win32::{
},
};
use crate::{event::ElementState, platform_impl::platform::util};
use crate::{event::ElementState, event_loop::DeviceEventFilter, platform_impl::platform::util};
#[allow(dead_code)]
pub fn get_raw_input_device_list() -> Option<Vec<RAWINPUTDEVICELIST>> {
@@ -138,10 +138,21 @@ pub fn register_raw_input_devices(devices: &[RAWINPUTDEVICE]) -> bool {
}
}
pub fn register_all_mice_and_keyboards_for_raw_input(window_handle: HWND) -> bool {
pub fn register_all_mice_and_keyboards_for_raw_input(
mut window_handle: HWND,
filter: DeviceEventFilter,
) -> bool {
// RIDEV_DEVNOTIFY: receive hotplug events
// RIDEV_INPUTSINK: receive events even if we're not in the foreground
let flags = RIDEV_DEVNOTIFY | RIDEV_INPUTSINK;
// RIDEV_REMOVE: don't receive device events (requires NULL hwndTarget)
let flags = match filter {
DeviceEventFilter::Always => {
window_handle = 0;
RIDEV_REMOVE
}
DeviceEventFilter::Unfocused => RIDEV_DEVNOTIFY,
DeviceEventFilter::Never => RIDEV_DEVNOTIFY | RIDEV_INPUTSINK,
};
let devices: [RAWINPUTDEVICE; 2] = [
RAWINPUTDEVICE {

View File

@@ -879,10 +879,17 @@ impl<'a, T: 'static> InitData<'a, T> {
win.set_fullscreen(attributes.fullscreen);
force_window_active(win.window.0);
} else {
let dimensions = attributes
let size = attributes
.inner_size
.unwrap_or_else(|| PhysicalSize::new(800, 600).into());
win.set_inner_size(dimensions);
let max_size = attributes
.max_inner_size
.unwrap_or_else(|| PhysicalSize::new(f64::MAX, f64::MAX).into());
let min_size = attributes
.min_inner_size
.unwrap_or_else(|| PhysicalSize::new(0, 0).into());
let clamped_size = Size::clamp(size, min_size, max_size, win.scale_factor());
win.set_inner_size(clamped_size);
if attributes.maximized {
// Need to set MAXIMIZED after setting `inner_size` as

View File

@@ -1066,6 +1066,109 @@ unsafe impl HasRawDisplayHandle for Window {
self.window.raw_display_handle()
}
}
unsafe impl raw_window_handle_04::HasRawWindowHandle for Window {
/// Returns a [`raw_window_handle_04::RawWindowHandle`] for the Window
///
/// This provides backwards compatibility for downstream crates that have not yet
/// upgraded to `raw_window_handle` version 0.5, such as Wgpu version 0.13.
///
/// ## Platform-specific
///
/// ### Android
///
/// Only available after receiving [`Event::Resumed`] and before [`Event::Suspended`]. *If you
/// try to get the handle outside of that period, this function will panic*!
///
/// Make sure to release or destroy any resources created from this `RawWindowHandle` (ie. Vulkan
/// or OpenGL surfaces) before returning from [`Event::Suspended`], at which point Android will
/// release the underlying window/surface: any subsequent interaction is undefined behavior.
///
/// [`Event::Resumed`]: crate::event::Event::Resumed
/// [`Event::Suspended`]: crate::event::Event::Suspended
fn raw_window_handle(&self) -> raw_window_handle_04::RawWindowHandle {
use raw_window_handle_04::{
AndroidNdkHandle, AppKitHandle, HaikuHandle, OrbitalHandle, UiKitHandle, WaylandHandle,
WebHandle, Win32Handle, WinRtHandle, XcbHandle, XlibHandle,
};
// XXX: Ideally this would be encapsulated either through a
// compatibility API from raw_window_handle_05 or else within the
// backends but since this is only to provide short-term backwards
// compatibility, we just handle the full mapping inline here.
//
// The intention is to remove this trait implementation before Winit
// 0.28, once crates have had time to upgrade to raw_window_handle 0.5
match (self.window.raw_window_handle(), self.window.raw_display_handle()) {
(RawWindowHandle::UiKit(window_handle), _) => {
let mut handle = UiKitHandle::empty();
handle.ui_view = window_handle.ui_view;
handle.ui_window = window_handle.ui_window;
handle.ui_view_controller = window_handle.ui_view_controller;
raw_window_handle_04::RawWindowHandle::UiKit(handle)
},
(RawWindowHandle::AppKit(window_handle), _) => {
let mut handle = AppKitHandle::empty();
handle.ns_window = window_handle.ns_window;
handle.ns_view = window_handle.ns_view;
raw_window_handle_04::RawWindowHandle::AppKit(handle)
},
(RawWindowHandle::Orbital(window_handle), _) => {
let mut handle = OrbitalHandle::empty();
handle.window = window_handle.window;
raw_window_handle_04::RawWindowHandle::Orbital(handle)
},
(RawWindowHandle::Xlib(window_handle), RawDisplayHandle::Xlib(display_handle)) => {
let mut handle = XlibHandle::empty();
handle.display = display_handle.display;
handle.window = window_handle.window;
handle.visual_id = window_handle.visual_id;
raw_window_handle_04::RawWindowHandle::Xlib(handle)
},
(RawWindowHandle::Xcb(window_handle), RawDisplayHandle::Xcb(display_handle)) => {
let mut handle = XcbHandle::empty();
handle.connection = display_handle.connection;
handle.window = window_handle.window;
handle.visual_id = window_handle.visual_id;
raw_window_handle_04::RawWindowHandle::Xcb(handle)
},
(RawWindowHandle::Wayland(window_handle), RawDisplayHandle::Wayland(display_handle)) => {
let mut handle = WaylandHandle::empty();
handle.display = display_handle.display;
handle.surface = window_handle.surface;
raw_window_handle_04::RawWindowHandle::Wayland(handle)
},
(RawWindowHandle::Win32(window_handle), _) => {
let mut handle = Win32Handle::empty();
handle.hwnd = window_handle.hwnd;
handle.hinstance = window_handle.hinstance;
raw_window_handle_04::RawWindowHandle::Win32(handle)
},
(RawWindowHandle::WinRt(window_handle), _) => {
let mut handle = WinRtHandle::empty();
handle.core_window = window_handle.core_window;
raw_window_handle_04::RawWindowHandle::WinRt(handle)
},
(RawWindowHandle::Web(window_handle), _) => {
let mut handle = WebHandle::empty();
handle.id = window_handle.id;
raw_window_handle_04::RawWindowHandle::Web(handle)
},
(RawWindowHandle::AndroidNdk(window_handle), _) => {
let mut handle = AndroidNdkHandle::empty();
handle.a_native_window = window_handle.a_native_window;
raw_window_handle_04::RawWindowHandle::AndroidNdk(handle)
},
(RawWindowHandle::Haiku(window_handle), _) => {
let mut handle = HaikuHandle::empty();
handle.b_window = window_handle.b_window;
handle.b_direct_window = window_handle.b_direct_window;
raw_window_handle_04::RawWindowHandle::Haiku(handle)
},
_ => panic!("No HasRawWindowHandle version 0.4 backwards compatibility for new Winit window type"),
}
}
}
/// The behavior of cursor grabbing.
///