mirror of
https://github.com/rust-windowing/winit.git
synced 2026-06-26 22:53:15 -04:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2e4338bb8d | ||
|
|
ec2888b8b7 | ||
|
|
fa83bace12 | ||
|
|
ee7dc48e3b | ||
|
|
11d4a301e4 | ||
|
|
ad41eaf151 | ||
|
|
9b71df9f97 | ||
|
|
b1c9e4a6fa | ||
|
|
cdbaf4816a | ||
|
|
6b7ceedc91 | ||
|
|
c53a574bff | ||
|
|
95246d81c1 | ||
|
|
bf537009d9 |
35
.github/CODEOWNERS
vendored
Normal file
35
.github/CODEOWNERS
vendored
Normal 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
|
||||
12
.github/workflows/ci.yml
vendored
12
.github/workflows/ci.yml
vendored
@@ -22,7 +22,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
rust_version: [stable, nightly]
|
||||
rust_version: [1.57.0, stable, nightly]
|
||||
platform:
|
||||
# Note: Make sure that we test all the `docs.rs` targets defined in Cargo.toml!
|
||||
- { target: x86_64-pc-windows-msvc, os: windows-latest, }
|
||||
@@ -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
|
||||
@@ -103,13 +99,9 @@ jobs:
|
||||
|
||||
- name: Lint with clippy
|
||||
shell: bash
|
||||
if: (matrix.rust_version != 'nightly') && !contains(matrix.platform.options, '--no-default-features')
|
||||
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
|
||||
|
||||
14
CHANGELOG.md
14
CHANGELOG.md
@@ -8,6 +8,20 @@ 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.
|
||||
- On X11, fix crash on start due to inability to create an IME context without any preedit.
|
||||
|
||||
# 0.27.0 (2022-07-26)
|
||||
|
||||
- On Windows, fix hiding a maximized window.
|
||||
|
||||
@@ -20,6 +20,7 @@ your description of the issue as detailed as possible:
|
||||
|
||||
When making a code contribution to winit, before opening your pull request, please make sure that:
|
||||
|
||||
- your patch builds with Winit's minimal supported rust version - Rust 1.57.0.
|
||||
- you tested your modifications on all the platforms impacted, or if not possible detail which platforms
|
||||
were not tested, and what should be tested, so that a maintainer or another contributor can test them
|
||||
- you updated any relevant documentation in winit
|
||||
@@ -43,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
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "winit"
|
||||
version = "0.27.0"
|
||||
version = "0.27.2"
|
||||
authors = ["The winit contributors", "Pierre Krieger <pierre.krieger1708@gmail.com>"]
|
||||
description = "Cross-platform window creation library."
|
||||
edition = "2021"
|
||||
@@ -10,6 +10,7 @@ readme = "README.md"
|
||||
repository = "https://github.com/rust-windowing/winit"
|
||||
documentation = "https://docs.rs/winit"
|
||||
categories = ["gui"]
|
||||
rust-version = "1.57.0"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = ["serde"]
|
||||
@@ -45,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 }
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
winit = "0.27.0"
|
||||
winit = "0.27.2"
|
||||
```
|
||||
|
||||
## [Documentation](https://docs.rs/winit)
|
||||
|
||||
@@ -59,12 +59,12 @@ fn main() {
|
||||
}
|
||||
VirtualKeyCode::F => {
|
||||
let fullscreen = Some(Fullscreen::Exclusive(mode.clone()));
|
||||
println!("Setting mode: {fullscreen:?}");
|
||||
println!("Setting mode: {:?}", fullscreen);
|
||||
window.set_fullscreen(fullscreen);
|
||||
}
|
||||
VirtualKeyCode::B => {
|
||||
let fullscreen = Some(Fullscreen::Borderless(Some(monitor.clone())));
|
||||
println!("Setting mode: {fullscreen:?}");
|
||||
println!("Setting mode: {:?}", fullscreen);
|
||||
window.set_fullscreen(fullscreen);
|
||||
}
|
||||
VirtualKeyCode::S => {
|
||||
|
||||
23
src/dpi.rs
23
src/dpi.rs
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -299,10 +299,11 @@ impl WindowExtUnix for Window {
|
||||
#[inline]
|
||||
#[cfg(feature = "wayland")]
|
||||
fn wayland_set_csd_theme(&self, theme: Theme) {
|
||||
#[allow(clippy::single_match)]
|
||||
match self.window {
|
||||
LinuxWindow::Wayland(ref w) => w.set_csd_theme(theme),
|
||||
#[cfg(feature = "x11")]
|
||||
_ => {}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -793,7 +793,7 @@ pub unsafe fn handle_main_events_cleared() {
|
||||
return;
|
||||
}
|
||||
match this.state_mut() {
|
||||
&mut AppStateImpl::ProcessingEvents { .. } => {}
|
||||
AppStateImpl::ProcessingEvents { .. } => {}
|
||||
_ => bug!("`ProcessingRedraws` happened unexpectedly"),
|
||||
};
|
||||
drop(this);
|
||||
|
||||
@@ -587,7 +587,8 @@ impl Window {
|
||||
|
||||
/// Hooks for X11 errors.
|
||||
#[cfg(feature = "x11")]
|
||||
pub(crate) static mut XLIB_ERROR_HOOKS: Mutex<Vec<XlibErrorHook>> = Mutex::new(Vec::new());
|
||||
pub(crate) static mut XLIB_ERROR_HOOKS: Lazy<Mutex<Vec<XlibErrorHook>>> =
|
||||
Lazy::new(|| Mutex::new(Vec::new()));
|
||||
|
||||
#[cfg(feature = "x11")]
|
||||
unsafe extern "C" fn x_error_callback(
|
||||
@@ -633,7 +634,7 @@ unsafe extern "C" fn x_error_callback(
|
||||
|
||||
pub enum EventLoop<T: 'static> {
|
||||
#[cfg(feature = "wayland")]
|
||||
Wayland(wayland::EventLoop<T>),
|
||||
Wayland(Box<wayland::EventLoop<T>>),
|
||||
#[cfg(feature = "x11")]
|
||||
X(x11::EventLoop<T>),
|
||||
}
|
||||
@@ -723,7 +724,7 @@ impl<T: 'static> EventLoop<T> {
|
||||
|
||||
#[cfg(feature = "wayland")]
|
||||
fn new_wayland_any_thread() -> Result<EventLoop<T>, Box<dyn Error>> {
|
||||
wayland::EventLoop::new().map(EventLoop::Wayland)
|
||||
wayland::EventLoop::new().map(|evlp| EventLoop::Wayland(Box::new(evlp)))
|
||||
}
|
||||
|
||||
#[cfg(feature = "x11")]
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
use std::mem::transmute;
|
||||
use std::ffi::CStr;
|
||||
use std::os::raw::c_short;
|
||||
use std::ptr;
|
||||
use std::sync::Arc;
|
||||
use std::{mem, ptr};
|
||||
|
||||
use x11_dl::xlib::{XIMCallback, XIMPreeditCaretCallbackStruct, XIMPreeditDrawCallbackStruct};
|
||||
|
||||
use crate::platform_impl::platform::x11::ime::{ImeEvent, ImeEventSender};
|
||||
|
||||
use super::{ffi, util, XConnection, XError};
|
||||
use crate::platform_impl::platform::x11::ime::{ImeEvent, ImeEventSender};
|
||||
use std::ffi::CStr;
|
||||
use x11_dl::xlib::{XIMCallback, XIMPreeditCaretCallbackStruct, XIMPreeditDrawCallbackStruct};
|
||||
|
||||
/// IME creation error.
|
||||
#[derive(Debug)]
|
||||
@@ -163,7 +164,7 @@ struct PreeditCallbacks {
|
||||
impl PreeditCallbacks {
|
||||
pub fn new(client_data: ffi::XPointer) -> PreeditCallbacks {
|
||||
let start_callback = create_xim_callback(client_data, unsafe {
|
||||
transmute(preedit_start_callback as usize)
|
||||
mem::transmute(preedit_start_callback as usize)
|
||||
});
|
||||
let done_callback = create_xim_callback(client_data, preedit_done_callback);
|
||||
let caret_callback = create_xim_callback(client_data, preedit_caret_callback);
|
||||
|
||||
@@ -120,7 +120,33 @@ impl Ime {
|
||||
// Create empty entry in map, so that when IME is rebuilt, this window has a context.
|
||||
None
|
||||
} else {
|
||||
let event = if with_preedit {
|
||||
let context = unsafe {
|
||||
ImeContext::new(
|
||||
&self.inner.xconn,
|
||||
self.inner.im,
|
||||
window,
|
||||
None,
|
||||
with_preedit,
|
||||
self.inner.event_sender.clone(),
|
||||
)
|
||||
.or_else(|_| {
|
||||
debug!(
|
||||
"failed to create an IME context {} preedit support",
|
||||
if with_preedit { "with" } else { "without" }
|
||||
);
|
||||
ImeContext::new(
|
||||
&self.inner.xconn,
|
||||
self.inner.im,
|
||||
window,
|
||||
None,
|
||||
!with_preedit,
|
||||
self.inner.event_sender.clone(),
|
||||
)
|
||||
})
|
||||
}?;
|
||||
|
||||
// Check the state on the context, since it could fail to enable or disable preedit.
|
||||
let event = if context.is_allowed {
|
||||
ImeEvent::Enabled
|
||||
} else {
|
||||
// There's no IME without preedit.
|
||||
@@ -132,16 +158,7 @@ impl Ime {
|
||||
.send((window, event))
|
||||
.expect("Failed to send enabled event");
|
||||
|
||||
Some(unsafe {
|
||||
ImeContext::new(
|
||||
&self.inner.xconn,
|
||||
self.inner.im,
|
||||
window,
|
||||
None,
|
||||
with_preedit,
|
||||
self.inner.event_sender.clone(),
|
||||
)
|
||||
}?)
|
||||
Some(context)
|
||||
};
|
||||
self.inner.contexts.insert(window, context);
|
||||
Ok(!self.is_destroyed())
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
103
src/window.rs
103
src/window.rs
@@ -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.
|
||||
///
|
||||
|
||||
Reference in New Issue
Block a user