Compare commits

..

6 Commits

Author SHA1 Message Date
Mads Marquart
ac0f918500 Add more specific error RequestIgnored 2024-02-10 10:26:28 +01:00
Mads Marquart
4112fccc12 Update meeting time (#3475) 2024-02-09 17:20:46 +01:00
Jeremy Soller
bd6ce32860 On Orbital, map keys to NamedKey when possible 2024-02-09 11:28:30 +04:00
Kirill Chibisov
8936fe1acd Fix nightly CI dead_code warnings 2024-02-08 13:28:26 +04:00
Jeremy Soller
fedb86ea5a On Orbital, implement KeyEventExtModifiersSupplement
This also fixes `logical_key` and `text` not reported in `KeyEvent`.
2024-02-08 12:55:11 +04:00
Kirill Chibisov
20687fef1c Fix compatibility with platforms without AtomicU64
Fixes #3456.
2024-02-08 00:58:43 +04:00
230 changed files with 2147 additions and 1955 deletions

View File

@@ -35,7 +35,7 @@ jobs:
- { name: 'Linux 64bit', target: x86_64-unknown-linux-gnu, os: ubuntu-latest, } - { name: 'Linux 64bit', target: x86_64-unknown-linux-gnu, os: ubuntu-latest, }
- { name: 'X11', target: x86_64-unknown-linux-gnu, os: ubuntu-latest, options: '--no-default-features --features=x11' } - { name: 'X11', target: x86_64-unknown-linux-gnu, os: ubuntu-latest, options: '--no-default-features --features=x11' }
- { name: 'Wayland', target: x86_64-unknown-linux-gnu, os: ubuntu-latest, options: '--no-default-features --features=wayland,wayland-dlopen' } - { name: 'Wayland', target: x86_64-unknown-linux-gnu, os: ubuntu-latest, options: '--no-default-features --features=wayland,wayland-dlopen' }
- { name: 'Android', target: aarch64-linux-android, os: ubuntu-latest, options: '--features=android-native-activity', cmd: 'apk --' } - { name: 'Android', target: aarch64-linux-android, os: ubuntu-latest, options: '--package=winit --features=android-native-activity', cmd: 'apk --' }
- { name: 'Redox OS', target: x86_64-unknown-redox, os: ubuntu-latest, } - { name: 'Redox OS', target: x86_64-unknown-redox, os: ubuntu-latest, }
- { name: 'macOS', target: x86_64-apple-darwin, os: macos-latest, } - { name: 'macOS', target: x86_64-apple-darwin, os: macos-latest, }
- { name: 'iOS x86_64', target: x86_64-apple-ios, os: macos-latest, } - { name: 'iOS x86_64', target: x86_64-apple-ios, os: macos-latest, }
@@ -125,13 +125,13 @@ jobs:
RUSTDOCFLAGS: '--deny=warnings ${{ matrix.platform.rustflags }}' RUSTDOCFLAGS: '--deny=warnings ${{ matrix.platform.rustflags }}'
- name: Build crate - name: Build crate
run: cargo $CMD build -p winit $OPTIONS run: cargo $CMD build $OPTIONS
- name: Build tests - name: Build tests
if: > if: >
!contains(matrix.platform.target, 'redox') && !contains(matrix.platform.target, 'redox') &&
matrix.toolchain != '1.70.0' matrix.toolchain != '1.70.0'
run: cargo $CMD test -p winit --no-run $OPTIONS run: cargo $CMD test --no-run $OPTIONS
- name: Run tests - name: Run tests
if: > if: >
@@ -150,7 +150,7 @@ jobs:
if: > if: >
!contains(matrix.platform.target, 'redox') && !contains(matrix.platform.target, 'redox') &&
matrix.toolchain != '1.70.0' matrix.toolchain != '1.70.0'
run: cargo $CMD test --no-run $OPTIONS -p winit --features serde run: cargo $CMD test --no-run $OPTIONS --features serde
- name: Run tests with serde enabled - name: Run tests with serde enabled
if: > if: >

View File

@@ -11,6 +11,8 @@ Unreleased` header.
# Unreleased # Unreleased
- **Breaking:** Use `RequestIgnored` as the error type in `InnerSizeWriter::request_inner_size`.
- Fix compatibility with 32-bit platforms without 64-bit atomics.
- On X11, fix swapped instance and general class names. - On X11, fix swapped instance and general class names.
- **Breaking:** Removed unnecessary generic parameter `T` from `EventLoopWindowTarget`. - **Breaking:** Removed unnecessary generic parameter `T` from `EventLoopWindowTarget`.
- On Windows, macOS, X11, Wayland and Web, implement setting images as cursors. See the `custom_cursors.rs` example. - On Windows, macOS, X11, Wayland and Web, implement setting images as cursors. See the `custom_cursors.rs` example.
@@ -49,14 +51,9 @@ Unreleased` header.
- On Wayland, fix `Window::set_{min,max}_inner_size` not always applied. - On Wayland, fix `Window::set_{min,max}_inner_size` not always applied.
- On Windows, fix inconsistent resizing behavior with multi-monitor setups when repositioning outside the event loop. - On Windows, fix inconsistent resizing behavior with multi-monitor setups when repositioning outside the event loop.
- On Wayland, fix `WAYLAND_SOCKET` not used when detecting platform. - On Wayland, fix `WAYLAND_SOCKET` not used when detecting platform.
- **Breaking:** Move some types to the `winit-core` crate. Most types are - On Orbital, fix `logical_key` and `text` not reported in `KeyEvent`.
re-exported verbatim; however: - On Orbital, implement `KeyEventExtModifierSupplement`.
- `Event`, `WindowEvent` and `KeyEvent` now take a generic that `winit` - On Orbital, map keys to `NamedKey` when possible.
implements.
- `ActivationToken` and `InnerSizeWriter` expose new methods to make them
useful.
- `InnerSizeWriter::request_inner_size` returns an `InnerSizeIgnored` error
instead of an `ExternalError`.
# 0.29.10 # 0.29.10

View File

@@ -1,16 +1,265 @@
[package]
name = "winit"
version = "0.29.10"
authors = ["The winit contributors", "Pierre Krieger <pierre.krieger1708@gmail.com>"]
description = "Cross-platform window creation library."
edition = "2021"
keywords = ["windowing"]
license = "Apache-2.0"
readme = "README.md"
repository = "https://github.com/rust-windowing/winit"
documentation = "https://docs.rs/winit"
categories = ["gui"]
rust-version = "1.70.0"
[package.metadata.docs.rs]
features = [
"rwh_04",
"rwh_05",
"rwh_06",
"serde",
"mint",
# Enabled to get docs to compile
"android-native-activity",
]
default-target = "x86_64-unknown-linux-gnu"
# These are all tested in CI
targets = [
# Windows
"i686-pc-windows-msvc",
"x86_64-pc-windows-msvc",
# macOS
"x86_64-apple-darwin",
# Unix (X11 & Wayland)
"i686-unknown-linux-gnu",
"x86_64-unknown-linux-gnu",
# iOS
"x86_64-apple-ios",
# Android
"aarch64-linux-android",
# Web
"wasm32-unknown-unknown",
]
rustdoc-args = ["--cfg", "docsrs"]
[features]
default = ["rwh_06", "x11", "wayland", "wayland-dlopen", "wayland-csd-adwaita"]
x11 = ["x11-dl", "bytemuck", "percent-encoding", "xkbcommon-dl/x11", "x11rb"]
wayland = ["wayland-client", "wayland-backend", "wayland-protocols", "wayland-protocols-plasma", "sctk", "ahash", "memmap2"]
wayland-dlopen = ["wayland-backend/dlopen"]
wayland-csd-adwaita = ["sctk-adwaita", "sctk-adwaita/ab_glyph"]
wayland-csd-adwaita-crossfont = ["sctk-adwaita", "sctk-adwaita/crossfont"]
wayland-csd-adwaita-notitle = ["sctk-adwaita"]
android-native-activity = ["android-activity/native-activity"]
android-game-activity = ["android-activity/game-activity"]
serde = ["dep:serde", "cursor-icon/serde", "smol_str/serde"]
rwh_04 = ["dep:rwh_04", "ndk/rwh_04"]
rwh_05 = ["dep:rwh_05", "ndk/rwh_05"]
rwh_06 = ["dep:rwh_06", "ndk/rwh_06"]
[build-dependencies]
cfg_aliases = "0.2.0"
[dependencies]
bitflags = "2"
cursor-icon = "1.1.0"
log = "0.4"
mint = { version = "0.5.6", optional = true }
once_cell = "1.12"
rwh_04 = { package = "raw-window-handle", version = "0.4", optional = true }
rwh_05 = { package = "raw-window-handle", version = "0.5.2", features = ["std"], optional = true }
rwh_06 = { package = "raw-window-handle", version = "0.6", features = ["std"], optional = true }
serde = { version = "1", optional = true, features = ["serde_derive"] }
smol_str = "0.2.0"
[dev-dependencies]
image = { version = "0.24.0", default-features = false, features = ["png"] }
simple_logger = { version = "4.2.0", default_features = false }
winit = { path = ".", features = ["rwh_05"] }
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dev-dependencies]
softbuffer = { version = "0.3.0", default-features = false, features = ["x11", "x11-dlopen", "wayland", "wayland-dlopen"] }
[target.'cfg(target_os = "android")'.dependencies]
android-activity = "0.5.0"
ndk = { version = "0.8.0", default-features = false }
ndk-sys = "0.5.0"
[target.'cfg(any(target_os = "ios", target_os = "macos"))'.dependencies]
core-foundation = "0.9.3"
objc2 = "0.5.0"
[target.'cfg(target_os = "macos")'.dependencies]
core-graphics = "0.23.1"
[target.'cfg(target_os = "macos")'.dependencies.icrate]
version = "0.1.0"
features = [
"dispatch",
"Foundation",
"Foundation_NSArray",
"Foundation_NSAttributedString",
"Foundation_NSMutableAttributedString",
"Foundation_NSData",
"Foundation_NSDictionary",
"Foundation_NSString",
"Foundation_NSProcessInfo",
"Foundation_NSThread",
"Foundation_NSNumber",
"AppKit",
"AppKit_NSAppearance",
"AppKit_NSApplication",
"AppKit_NSBitmapImageRep",
"AppKit_NSButton",
"AppKit_NSColor",
"AppKit_NSControl",
"AppKit_NSCursor",
"AppKit_NSEvent",
"AppKit_NSGraphicsContext",
"AppKit_NSImage",
"AppKit_NSImageRep",
"AppKit_NSMenu",
"AppKit_NSMenuItem",
"AppKit_NSPasteboard",
"AppKit_NSResponder",
"AppKit_NSScreen",
"AppKit_NSTextInputContext",
"AppKit_NSView",
"AppKit_NSWindow",
"AppKit_NSWindowTabGroup",
]
[target.'cfg(target_os = "ios")'.dependencies.icrate]
version = "0.1.0"
features = [
"dispatch",
"Foundation",
"Foundation_NSArray",
"Foundation_NSString",
"Foundation_NSProcessInfo",
"Foundation_NSThread",
"Foundation_NSSet",
]
[target.'cfg(target_os = "windows")'.dependencies]
unicode-segmentation = "1.7.1"
[target.'cfg(target_os = "windows")'.dependencies.windows-sys]
version = "0.48"
features = [
"Win32_Devices_HumanInterfaceDevice",
"Win32_Foundation",
"Win32_Globalization",
"Win32_Graphics_Dwm",
"Win32_Graphics_Gdi",
"Win32_Media",
"Win32_System_Com_StructuredStorage",
"Win32_System_Com",
"Win32_System_LibraryLoader",
"Win32_System_Ole",
"Win32_System_SystemInformation",
"Win32_System_SystemServices",
"Win32_System_Threading",
"Win32_System_WindowsProgramming",
"Win32_UI_Accessibility",
"Win32_UI_Controls",
"Win32_UI_HiDpi",
"Win32_UI_Input_Ime",
"Win32_UI_Input_KeyboardAndMouse",
"Win32_UI_Input_Pointer",
"Win32_UI_Input_Touch",
"Win32_UI_Shell",
"Win32_UI_TextServices",
"Win32_UI_WindowsAndMessaging",
]
[target.'cfg(all(unix, not(any(target_os = "redox", target_family = "wasm", target_os = "android", target_os = "ios", target_os = "macos"))))'.dependencies]
ahash = { version = "0.8.7", features = ["no-rng"], optional = true }
bytemuck = { version = "1.13.1", default-features = false, optional = true }
calloop = "0.12.3"
libc = "0.2.64"
memmap2 = { version = "0.9.0", optional = true }
percent-encoding = { version = "2.0", optional = true }
rustix = { version = "0.38.4", default-features = false, features = ["std", "system", "thread", "process"] }
sctk = { package = "smithay-client-toolkit", version = "0.18.0", default-features = false, features = ["calloop"], optional = true }
sctk-adwaita = { version = "0.8.0", default_features = false, optional = true }
wayland-backend = { version = "0.3.0", default_features = false, features = ["client_system"], optional = true }
wayland-client = { version = "0.31.1", optional = true }
wayland-protocols = { version = "0.31.0", features = [ "staging"], optional = true }
wayland-protocols-plasma = { version = "0.2.0", features = [ "client" ], optional = true }
x11-dl = { version = "2.18.5", optional = true }
x11rb = { version = "0.13.0", default-features = false, features = ["allow-unsafe-code", "dl-libxcb", "randr", "resource_manager", "xinput", "xkb"], optional = true }
xkbcommon-dl = "0.4.0"
[target.'cfg(target_os = "redox")'.dependencies]
orbclient = { version = "0.3.47", default-features = false }
redox_syscall = "0.4.1"
[target.'cfg(target_family = "wasm")'.dependencies.web_sys]
package = "web-sys"
version = "0.3.64"
features = [
'AbortController',
'AbortSignal',
'Blob',
'console',
'CssStyleDeclaration',
'Document',
'DomException',
'DomRect',
'DomRectReadOnly',
'Element',
'Event',
'EventTarget',
'FocusEvent',
'HtmlCanvasElement',
'HtmlElement',
'HtmlImageElement',
'ImageBitmap',
'ImageBitmapOptions',
'ImageBitmapRenderingContext',
'ImageData',
'IntersectionObserver',
'IntersectionObserverEntry',
'KeyboardEvent',
'MediaQueryList',
'MessageChannel',
'MessagePort',
'Node',
'PageTransitionEvent',
'PointerEvent',
'PremultiplyAlpha',
'ResizeObserver',
'ResizeObserverBoxOptions',
'ResizeObserverEntry',
'ResizeObserverOptions',
'ResizeObserverSize',
'VisibilityState',
'Window',
'WheelEvent',
'Url',
]
[target.'cfg(target_family = "wasm")'.dependencies]
js-sys = "0.3.64"
pin-project = "1"
wasm-bindgen = "0.2"
wasm-bindgen-futures = "0.4"
web-time = "1"
[target.'cfg(all(target_family = "wasm", target_feature = "atomics"))'.dependencies]
atomic-waker = "1"
concurrent-queue = { version = "2", default-features = false }
[target.'cfg(target_family = "wasm")'.dev-dependencies]
console_log = "1"
web-sys = { version = "0.3.22", features = ['CanvasRenderingContext2d'] }
[workspace] [workspace]
members = [ members = [
"run-wasm", "run-wasm",
"winit",
"winit-core"
] ]
resolver = "2"
[workspace.dependencies] [[example]]
bitflags = "2" doc-scrape-examples = true
cfg_aliases = "0.2.0" name = "window"
cursor-icon = "1.1.0"
serde = { version = "1", features = ["serde_derive"] }
smol_str = "0.2.0"
web-time = "1"
winit-core = { path = "./winit-core", default-features = false, features = ["std"] }

View File

@@ -21,7 +21,7 @@ For features _outside_ the scope of winit, see [Are we GUI Yet?](https://arewegu
Join us in our [![Matrix](https://img.shields.io/badge/Matrix-%23rust--windowing%3Amatrix.org-blueviolet.svg)](https://matrix.to/#/#rust-windowing:matrix.org) room. If you don't get an answer there, try [![Libera.Chat](https://img.shields.io/badge/libera.chat-%23winit-red.svg)](https://web.libera.chat/#winit). Join us in our [![Matrix](https://img.shields.io/badge/Matrix-%23rust--windowing%3Amatrix.org-blueviolet.svg)](https://matrix.to/#/#rust-windowing:matrix.org) room. If you don't get an answer there, try [![Libera.Chat](https://img.shields.io/badge/libera.chat-%23winit-red.svg)](https://web.libera.chat/#winit).
The maintainers have a meeting every friday at UTC 14. The meeting notes can be found [here](https://hackmd.io/@winit-meetings). The maintainers have a meeting every friday at UTC 15. The meeting notes can be found [here](https://hackmd.io/@winit-meetings).
## Usage ## Usage

View File

@@ -35,9 +35,7 @@ skip = [
{ name = "bitflags" }, # the ecosystem is in the process of migrating. { name = "bitflags" }, # the ecosystem is in the process of migrating.
{ name = "libloading" }, # x11rb uses a different version until the next update { name = "libloading" }, # x11rb uses a different version until the next update
] ]
skip-tree = [ skip-tree = []
{ name = "run-wasm", version = "0.1.0" }
]
[licenses] [licenses]

View File

Before

Width:  |  Height:  |  Size: 159 B

After

Width:  |  Height:  |  Size: 159 B

View File

Before

Width:  |  Height:  |  Size: 129 B

After

Width:  |  Height:  |  Size: 129 B

View File

Before

Width:  |  Height:  |  Size: 229 B

After

Width:  |  Height:  |  Size: 229 B

View File

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@@ -2,7 +2,8 @@
name = "run-wasm" name = "run-wasm"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
publish = false
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
cargo-run-wasm = "0.2.0" cargo-run-wasm = "0.2.0"

View File

@@ -97,7 +97,7 @@
//! [points]: https://en.wikipedia.org/wiki/Point_(typography) //! [points]: https://en.wikipedia.org/wiki/Point_(typography)
//! [picas]: https://en.wikipedia.org/wiki/Pica_(typography) //! [picas]: https://en.wikipedia.org/wiki/Pica_(typography)
//! [`ScaleFactorChanged`]: crate::event::WindowEvent::ScaleFactorChanged //! [`ScaleFactorChanged`]: crate::event::WindowEvent::ScaleFactorChanged
//! [`window.scale_factor()`]: https://docs.rs/winit/latest/winit/window/struct.Window.html#method.scale_factor //! [`window.scale_factor()`]: crate::window::Window::scale_factor
//! [windows_1]: https://docs.microsoft.com/en-us/windows/win32/hidpi/high-dpi-desktop-application-development-on-windows //! [windows_1]: https://docs.microsoft.com/en-us/windows/win32/hidpi/high-dpi-desktop-application-development-on-windows
//! [apple_1]: https://developer.apple.com/library/archive/documentation/DeviceInformation/Reference/iOSDeviceCompatibility/Displays/Displays.html //! [apple_1]: https://developer.apple.com/library/archive/documentation/DeviceInformation/Reference/iOSDeviceCompatibility/Displays/Displays.html
//! [apple_2]: https://developer.apple.com/design/human-interface-guidelines/macos/icons-and-images/image-size-and-resolution/ //! [apple_2]: https://developer.apple.com/design/human-interface-guidelines/macos/icons-and-images/image-size-and-resolution/

View File

@@ -1,8 +1,6 @@
use crate::platform_impl;
use std::{error, fmt}; use std::{error, fmt};
#[doc(inline)] use crate::platform_impl;
pub use winit_core::error::NotSupportedError;
// TODO: Rename // TODO: Rename
/// An error that may be generated when requesting Winit state /// An error that may be generated when requesting Winit state
@@ -16,10 +14,10 @@ pub enum ExternalError {
Os(OsError), Os(OsError),
} }
impl From<winit_core::event::InnerSizeIgnored> for ExternalError { /// The error type for when the requested operation is not supported by the backend.
fn from(_: winit_core::event::InnerSizeIgnored) -> Self { #[derive(Clone)]
Self::Ignored pub struct NotSupportedError {
} _marker: (),
} }
/// The error type for when the OS cannot perform the requested operation. /// The error type for when the OS cannot perform the requested operation.
@@ -49,6 +47,14 @@ impl From<OsError> for EventLoopError {
} }
} }
impl NotSupportedError {
#[inline]
#[allow(dead_code)]
pub(crate) fn new() -> NotSupportedError {
NotSupportedError { _marker: () }
}
}
impl OsError { impl OsError {
#[allow(dead_code)] #[allow(dead_code)]
pub(crate) fn new(line: u32, file: &'static str, error: platform_impl::OsError) -> OsError { pub(crate) fn new(line: u32, file: &'static str, error: platform_impl::OsError) -> OsError {
@@ -82,6 +88,18 @@ impl fmt::Display for ExternalError {
} }
} }
impl fmt::Debug for NotSupportedError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
f.debug_struct("NotSupportedError").finish()
}
}
impl fmt::Display for NotSupportedError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
f.pad("the requested operation is not supported by Winit")
}
}
impl fmt::Display for EventLoopError { impl fmt::Display for EventLoopError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
match self { match self {
@@ -95,6 +113,7 @@ impl fmt::Display for EventLoopError {
impl error::Error for OsError {} impl error::Error for OsError {}
impl error::Error for ExternalError {} impl error::Error for ExternalError {}
impl error::Error for NotSupportedError {}
impl error::Error for EventLoopError {} impl error::Error for EventLoopError {}
#[cfg(test)] #[cfg(test)]
@@ -106,6 +125,11 @@ mod tests {
// Eat attributes for testing // Eat attributes for testing
#[test] #[test]
fn ensure_fmt_does_not_panic() { fn ensure_fmt_does_not_panic() {
let _ = format!(
"{:?}, {}",
NotSupportedError::new(),
NotSupportedError::new().clone()
);
let _ = format!( let _ = format!(
"{:?}, {}", "{:?}, {}",
ExternalError::NotSupported(NotSupportedError::new()), ExternalError::NotSupported(NotSupportedError::new()),

View File

@@ -1,64 +1,65 @@
//! Incoming notifications from the GUI system. //! The [`Event`] enum and assorted supporting types.
//!
use crate::dpi::{PhysicalPosition, PhysicalSize}; //! These are sent to the closure given to [`EventLoop::run(...)`], where they get
use crate::event_loop::AsyncRequestSerial; //! processed and used to modify the program state. For more details, see the root-level documentation.
use crate::keyboard::{self, ModifiersKeyState, ModifiersKeys, ModifiersState}; //!
use crate::window::{ActivationToken, Theme, WindowId}; //! Some of these events represent different "parts" of a traditional event-handling loop. You could
//! approximate the basic ordering loop of [`EventLoop::run(...)`] like this:
//!
//! ```rust,ignore
//! let mut start_cause = StartCause::Init;
//!
//! while !elwt.exiting() {
//! event_handler(NewEvents(start_cause), elwt);
//!
//! for e in (window events, user events, device events) {
//! event_handler(e, elwt);
//! }
//!
//! for w in (redraw windows) {
//! event_handler(RedrawRequested(w), elwt);
//! }
//!
//! event_handler(AboutToWait, elwt);
//! start_cause = wait_if_necessary();
//! }
//!
//! event_handler(LoopExiting, elwt);
//! ```
//!
//! This leaves out timing details like [`ControlFlow::WaitUntil`] but hopefully
//! describes what happens in what order.
//!
//! [`EventLoop::run(...)`]: crate::event_loop::EventLoop::run
//! [`ControlFlow::WaitUntil`]: crate::event_loop::ControlFlow::WaitUntil
use std::error::Error;
use std::fmt; use std::fmt;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::{Mutex, Weak}; use std::sync::{Mutex, Weak};
#[cfg(not(web_platform))] #[cfg(not(web_platform))]
use std::time::Instant; use std::time::Instant;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use smol_str::SmolStr;
#[cfg(web_platform)] #[cfg(web_platform)]
use web_time::Instant; use web_time::Instant;
#[cfg(feature = "serde")] #[cfg(doc)]
pub use serde::{Deserialize, Serialize}; use crate::window::Window;
use crate::{
use smol_str::SmolStr; dpi::{PhysicalPosition, PhysicalSize},
event_loop::AsyncRequestSerial,
/// Identifier of an input device. keyboard::{self, ModifiersKeyState, ModifiersKeys, ModifiersState},
/// platform_impl,
/// Whenever you receive an event arising from a particular input device, this event contains a `DeviceId` which window::{ActivationToken, Theme, WindowId},
/// identifies its origin. Note that devices may be virtual (representing an on-screen cursor and keyboard focus) or };
/// physical. Virtual devices typically aggregate inputs from multiple physical devices.
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct DeviceId(u64);
impl DeviceId {
/// Returns a dummy id, useful for unit testing.
///
/// # Safety
///
/// The only guarantee made about the return value of this function is that
/// it will always be equal to itself and to future values returned by this function.
/// No other guarantees are made. This may be equal to a real `DeviceId`.
///
/// **Passing this into a winit function will result in undefined behavior.**
pub const unsafe fn dummy() -> Self {
DeviceId(0)
}
}
impl From<u64> for DeviceId {
fn from(value: u64) -> Self {
Self(value)
}
}
impl From<DeviceId> for u64 {
fn from(value: DeviceId) -> Self {
value.0
}
}
/// Describes a generic event. /// Describes a generic event.
/// ///
/// See the module-level docs for more information on the event loop manages each event. /// See the module-level docs for more information on the event loop manages each event.
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum Event<T: 'static, KeyExtra> { pub enum Event<T: 'static> {
/// Emitted when new events arrive from the OS to be processed. /// Emitted when new events arrive from the OS to be processed.
/// ///
/// This event type is useful as a place to put code that should be done before you start /// This event type is useful as a place to put code that should be done before you start
@@ -70,7 +71,7 @@ pub enum Event<T: 'static, KeyExtra> {
/// Emitted when the OS sends an event to a winit window. /// Emitted when the OS sends an event to a winit window.
WindowEvent { WindowEvent {
window_id: WindowId, window_id: WindowId,
event: WindowEvent<KeyExtra>, event: WindowEvent,
}, },
/// Emitted when the OS sends an event to a device. /// Emitted when the OS sends an event to a device.
@@ -79,7 +80,7 @@ pub enum Event<T: 'static, KeyExtra> {
event: DeviceEvent, event: DeviceEvent,
}, },
/// Emitted when an event is sent from [`EventLoopProxy::send_event`](https://docs.rs/winit/latest/winit/event_loop/struct.EventLoopProxy.html#method.send_event) /// Emitted when an event is sent from [`EventLoopProxy::send_event`](crate::event_loop::EventLoopProxy::send_event)
UserEvent(T), UserEvent(T),
/// Emitted when the application has been suspended. /// Emitted when the application has been suspended.
@@ -255,9 +256,9 @@ pub enum Event<T: 'static, KeyExtra> {
MemoryWarning, MemoryWarning,
} }
impl<T, Extra> Event<T, Extra> { impl<T> Event<T> {
#[allow(clippy::result_large_err)] #[allow(clippy::result_large_err)]
pub fn map_nonuser_event<U>(self) -> Result<Event<U, Extra>, Event<T, Extra>> { pub fn map_nonuser_event<U>(self) -> Result<Event<U>, Event<T>> {
use self::Event::*; use self::Event::*;
match self { match self {
UserEvent(_) => Err(self), UserEvent(_) => Err(self),
@@ -304,10 +305,8 @@ pub enum StartCause {
} }
/// Describes an event from a [`Window`]. /// Describes an event from a [`Window`].
///
/// [`Window`]: https://docs.rs/winit/latest/winit/window/struct.Window.html
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum WindowEvent<KeyExtra> { pub enum WindowEvent {
/// The activation token was delivered back and now could be used. /// The activation token was delivered back and now could be used.
/// ///
#[cfg_attr( #[cfg_attr(
@@ -369,7 +368,7 @@ pub enum WindowEvent<KeyExtra> {
/// events which are not marked as `is_synthetic`. /// events which are not marked as `is_synthetic`.
KeyboardInput { KeyboardInput {
device_id: DeviceId, device_id: DeviceId,
event: KeyEvent<KeyExtra>, event: KeyEvent,
/// If `true`, the event was generated synthetically by winit /// If `true`, the event was generated synthetically by winit
/// in one of the following circumstances: /// in one of the following circumstances:
@@ -393,8 +392,6 @@ pub enum WindowEvent<KeyExtra> {
/// ## Platform-specific /// ## Platform-specific
/// ///
/// - **iOS / Android / Web / Orbital:** Unsupported. /// - **iOS / Android / Web / Orbital:** Unsupported.
///
/// [`Window::set_ime_allowed`]: https://docs.rs/winit/latest/winit/window/struct.Window.html#method.set_ime_allowed
Ime(Ime), Ime(Ime),
/// The cursor has moved on the window. /// The cursor has moved on the window.
@@ -600,11 +597,33 @@ pub enum WindowEvent<KeyExtra> {
/// ///
/// Winit will aggregate duplicate redraw requests into a single event, to /// Winit will aggregate duplicate redraw requests into a single event, to
/// help avoid duplicating rendering work. /// help avoid duplicating rendering work.
///
/// [`Window::request_redraw`]: https://docs.rs/winit/latest/winit/window/struct.Window.html#method.request_redraw
RedrawRequested, RedrawRequested,
} }
/// Identifier of an input device.
///
/// Whenever you receive an event arising from a particular input device, this event contains a `DeviceId` which
/// identifies its origin. Note that devices may be virtual (representing an on-screen cursor and keyboard focus) or
/// physical. Virtual devices typically aggregate inputs from multiple physical devices.
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct DeviceId(pub(crate) platform_impl::DeviceId);
impl DeviceId {
/// Returns a dummy id, useful for unit testing.
///
/// # Safety
///
/// The only guarantee made about the return value of this function is that
/// it will always be equal to itself and to future values returned by this function.
/// No other guarantees are made. This may be equal to a real `DeviceId`.
///
/// **Passing this into a winit function will result in undefined behavior.**
pub const unsafe fn dummy() -> Self {
#[allow(unused_unsafe)]
DeviceId(unsafe { platform_impl::DeviceId::dummy() })
}
}
/// Represents raw hardware events that are not associated with any particular window. /// Represents raw hardware events that are not associated with any particular window.
/// ///
/// Useful for interactions that diverge significantly from a conventional 2D GUI, such as 3D camera or first-person /// Useful for interactions that diverge significantly from a conventional 2D GUI, such as 3D camera or first-person
@@ -665,7 +684,7 @@ pub struct RawKeyEvent {
/// Describes a keyboard input targeting a window. /// Describes a keyboard input targeting a window.
#[derive(Debug, Clone, Eq, PartialEq, Hash)] #[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct KeyEvent<Extra> { pub struct KeyEvent {
/// Represents the position of a key independent of the currently active layout. /// Represents the position of a key independent of the currently active layout.
/// ///
/// It also uniquely identifies the physical key (i.e. it's mostly synonymous with a scancode). /// It also uniquely identifies the physical key (i.e. it's mostly synonymous with a scancode).
@@ -715,7 +734,7 @@ pub struct KeyEvent<Extra> {
/// - **Web:** Dead keys might be reported as the real key instead /// - **Web:** Dead keys might be reported as the real key instead
/// of `Dead` depending on the browser/OS. /// of `Dead` depending on the browser/OS.
/// ///
/// [`key_without_modifiers`]: https://docs.rs/winit/latest/winit/platform/modifier_supplement/trait.KeyEventExtModifierSupplement.html#tymethod.key_without_modifiers /// [`key_without_modifiers`]: crate::platform::modifier_supplement::KeyEventExtModifierSupplement::key_without_modifiers
pub logical_key: keyboard::Key, pub logical_key: keyboard::Key,
/// Contains the text produced by this keypress. /// Contains the text produced by this keypress.
@@ -772,7 +791,7 @@ pub struct KeyEvent<Extra> {
/// modifiers applied. /// modifiers applied.
/// ///
/// On Android, iOS, Redox and Web, this type is a no-op. /// On Android, iOS, Redox and Web, this type is a no-op.
pub extra: Extra, pub(crate) platform_specific: platform_impl::KeyEventExtra,
} }
/// Describes keyboard modifiers event. /// Describes keyboard modifiers event.
@@ -787,15 +806,6 @@ pub struct Modifiers {
} }
impl Modifiers { impl Modifiers {
/// Only `winit` should instantiate this!
#[doc(hidden)]
pub fn new(state: ModifiersState, pressed_mods: ModifiersKeys) -> Self {
Self {
state,
pressed_mods,
}
}
/// The state of the modifiers. /// The state of the modifiers.
pub fn state(&self) -> ModifiersState { pub fn state(&self) -> ModifiersState {
self.state self.state
@@ -895,8 +905,6 @@ impl From<ModifiersState> for Modifiers {
/// Ime::Preedit("", None) // Synthetic event generated by winit to clear preedit. /// Ime::Preedit("", None) // Synthetic event generated by winit to clear preedit.
/// Ime::Commit("啊不") /// Ime::Commit("啊不")
/// ``` /// ```
///
/// [`Window::set_ime_cursor_area`]: https://docs.rs/winit/latest/winit/window/struct.Window.html#method.set_ime_cursor_area
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Ime { pub enum Ime {
@@ -905,8 +913,6 @@ pub enum Ime {
/// After getting this event you could receive [`Preedit`](Self::Preedit) and /// After getting this event you could receive [`Preedit`](Self::Preedit) and
/// [`Commit`](Self::Commit) events. You should also start performing IME related requests /// [`Commit`](Self::Commit) events. You should also start performing IME related requests
/// like [`Window::set_ime_cursor_area`]. /// like [`Window::set_ime_cursor_area`].
///
/// [`Window::set_ime_cursor_area`]: https://docs.rs/winit/latest/winit/window/struct.Window.html#method.set_ime_cursor_area
Enabled, Enabled,
/// Notifies when a new composing text should be set at the cursor position. /// Notifies when a new composing text should be set at the cursor position.
@@ -929,8 +935,6 @@ pub enum Ime {
/// [`Commit`](Self::Commit) events until the next [`Enabled`](Self::Enabled) event. You should /// [`Commit`](Self::Commit) events until the next [`Enabled`](Self::Enabled) event. You should
/// also stop issuing IME related requests like [`Window::set_ime_cursor_area`] and clear pending /// also stop issuing IME related requests like [`Window::set_ime_cursor_area`] and clear pending
/// preedit text. /// preedit text.
///
/// [`Window::set_ime_cursor_area`]: https://docs.rs/winit/latest/winit/window/struct.Window.html#method.set_ime_cursor_area
Disabled, Disabled,
} }
@@ -1119,27 +1123,29 @@ pub struct InnerSizeWriter {
impl InnerSizeWriter { impl InnerSizeWriter {
#[cfg(not(orbital_platform))] #[cfg(not(orbital_platform))]
pub fn new(new_inner_size: Weak<Mutex<PhysicalSize<u32>>>) -> Self { pub(crate) fn new(new_inner_size: Weak<Mutex<PhysicalSize<u32>>>) -> Self {
Self { new_inner_size } Self { new_inner_size }
} }
/// Try to request inner size which will be set synchroniously on the window. /// Try to request a new inner size which will be set synchronously on the
/// window.
///
///
/// # Errors
///
/// This method returns an error when the request was ignored because it
/// was done asynchronously, outside the event loop callback.
pub fn request_inner_size( pub fn request_inner_size(
&mut self, &mut self,
new_inner_size: PhysicalSize<u32>, new_inner_size: PhysicalSize<u32>,
) -> Result<(), InnerSizeIgnored> { ) -> Result<(), RequestIgnored> {
if let Some(inner) = self.new_inner_size.upgrade() { if let Some(inner) = self.new_inner_size.upgrade() {
*inner.lock().unwrap() = new_inner_size; *inner.lock().unwrap() = new_inner_size;
Ok(()) Ok(())
} else { } else {
Err(InnerSizeIgnored { _private: () }) Err(RequestIgnored { _priv: () })
} }
} }
/// Get the underlying size.
pub fn get(&self) -> PhysicalSize<u32> {
*self.new_inner_size.upgrade().unwrap().lock().unwrap()
}
} }
impl PartialEq for InnerSizeWriter { impl PartialEq for InnerSizeWriter {
@@ -1148,24 +1154,21 @@ impl PartialEq for InnerSizeWriter {
} }
} }
/// Could not write the inner size. /// The request to change the inner size synchronously was ignored.
pub struct InnerSizeIgnored { ///
_private: (), /// See [`InnerSizeWriter::request_inner_size`] for details.
#[derive(Debug, Clone)] // Explicitly not other traits, in case we want to extend it in the future
pub struct RequestIgnored {
_priv: (),
} }
impl fmt::Debug for InnerSizeIgnored { impl fmt::Display for RequestIgnored {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
f.debug_struct("InnerSizeIgnored").finish_non_exhaustive() f.write_str("the request to change the inner size was ignored")
} }
} }
impl fmt::Display for InnerSizeIgnored { impl Error for RequestIgnored {}
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("tried to write inner size after")
}
}
impl std::error::Error for InnerSizeIgnored {}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
@@ -1292,7 +1295,7 @@ mod tests {
#[allow(clippy::redundant_clone)] #[allow(clippy::redundant_clone)]
#[test] #[test]
fn test_event_clone() { fn test_event_clone() {
foreach_event!(|event: event::Event<(), ()>| { foreach_event!(|event: event::Event<()>| {
let event2 = event.clone(); let event2 = event.clone();
assert_eq!(event, event2); assert_eq!(event, event2);
}) })
@@ -1300,7 +1303,7 @@ mod tests {
#[test] #[test]
fn test_map_nonuser_event() { fn test_map_nonuser_event() {
foreach_event!(|event: event::Event<(), ()>| { foreach_event!(|event: event::Event<()>| {
let is_user = matches!(event, event::Event::UserEvent(())); let is_user = matches!(event, event::Event::UserEvent(()));
let event2 = event.map_nonuser_event::<()>(); let event2 = event.map_nonuser_event::<()>();
if is_user { if is_user {
@@ -1334,7 +1337,7 @@ mod tests {
#[allow(clippy::clone_on_copy)] #[allow(clippy::clone_on_copy)]
#[test] #[test]
fn ensure_attrs_do_not_panic() { fn ensure_attrs_do_not_panic() {
foreach_event!(|event: event::Event<(), ()>| { foreach_event!(|event: event::Event<()>| {
let _ = format!("{:?}", event); let _ = format!("{:?}", event);
}); });
let _ = event::StartCause::Init.clone(); let _ = event::StartCause::Init.clone();

View File

@@ -11,15 +11,17 @@ use std::marker::PhantomData;
use std::ops::Deref; use std::ops::Deref;
#[cfg(any(x11_platform, wayland_platform))] #[cfg(any(x11_platform, wayland_platform))]
use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd}; use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd};
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::{error, fmt}; use std::{error, fmt};
#[cfg(not(web_platform))]
use std::time::{Duration, Instant};
#[cfg(web_platform)]
use web_time::{Duration, Instant};
use crate::error::EventLoopError; use crate::error::EventLoopError;
use crate::{event::Event, monitor::MonitorHandle, platform_impl}; use crate::{event::Event, monitor::MonitorHandle, platform_impl};
#[doc(inline)]
pub use winit_core::event_loop::{AsyncRequestSerial, ControlFlow};
/// Provides a way to retrieve events from the system and from the windows that were registered to /// Provides a way to retrieve events from the system and from the windows that were registered to
/// the events loop. /// the events loop.
/// ///
@@ -139,6 +141,50 @@ impl fmt::Debug for EventLoopWindowTarget {
} }
} }
/// Set through [`EventLoopWindowTarget::set_control_flow()`].
///
/// Indicates the desired behavior of the event loop after [`Event::AboutToWait`] is emitted.
///
/// Defaults to [`Wait`].
///
/// [`Wait`]: Self::Wait
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
pub enum ControlFlow {
/// When the current loop iteration finishes, immediately begin a new iteration regardless of
/// whether or not new events are available to process.
Poll,
/// When the current loop iteration finishes, suspend the thread until another event arrives.
#[default]
Wait,
/// When the current loop iteration finishes, suspend the thread until either another event
/// arrives or the given time is reached.
///
/// Useful for implementing efficient timers. Applications which want to render at the display's
/// native refresh rate should instead use [`Poll`] and the VSync functionality of a graphics API
/// to reduce odds of missed frames.
///
/// [`Poll`]: Self::Poll
WaitUntil(Instant),
}
impl ControlFlow {
/// Creates a [`ControlFlow`] that waits until a timeout has expired.
///
/// In most cases, this is set to [`WaitUntil`]. However, if the timeout overflows, it is
/// instead set to [`Wait`].
///
/// [`WaitUntil`]: Self::WaitUntil
/// [`Wait`]: Self::Wait
pub fn wait_duration(timeout: Duration) -> Self {
match Instant::now().checked_add(timeout) {
Some(instant) => Self::WaitUntil(instant),
None => Self::Wait,
}
}
}
impl EventLoop<()> { impl EventLoop<()> {
/// Create the event loop. /// Create the event loop.
/// ///
@@ -460,3 +506,29 @@ pub enum DeviceEvents {
/// Never capture device events. /// Never capture device events.
Never, Never,
} }
/// A unique identifier of the winit's async request.
///
/// This could be used to identify the async request once it's done
/// and a specific action must be taken.
///
/// One of the handling scenarious could be to maintain a working list
/// containing [`AsyncRequestSerial`] and some closure associated with it.
/// Then once event is arriving the working list is being traversed and a job
/// executed and removed from the list.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct AsyncRequestSerial {
serial: usize,
}
impl AsyncRequestSerial {
// TODO(kchibisov): Remove `cfg` when the clipboard will be added.
#[allow(dead_code)]
pub(crate) fn get() -> Self {
static CURRENT_SERIAL: AtomicUsize = AtomicUsize::new(0);
// NOTE: We rely on wrap around here, while the user may just request
// in the loop usize::MAX times that's issue is considered on them.
let serial = CURRENT_SERIAL.fetch_add(1, Ordering::Relaxed);
Self { serial }
}
}

View File

@@ -1454,29 +1454,6 @@ pub enum NamedKey {
F35, F35,
} }
// NOTE: the exact modifier key is not used to represent modifiers state in the
// first place due to a fact that modifiers state could be changed without any
// key being pressed and on some platforms like Wayland/X11 which key resulted
// in modifiers change is hidden, also, not that it really matters.
//
// The reason this API is even exposed is mostly to provide a way for users
// to treat modifiers differently based on their position, which is required
// on macOS due to their AltGr/Option situation.
bitflags! {
#[doc(hidden)]
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ModifiersKeys: u8 {
const LSHIFT = 0b0000_0001;
const RSHIFT = 0b0000_0010;
const LCONTROL = 0b0000_0100;
const RCONTROL = 0b0000_1000;
const LALT = 0b0001_0000;
const RALT = 0b0010_0000;
const LSUPER = 0b0100_0000;
const RSUPER = 0b1000_0000;
}
}
/// Key represents the meaning of a keypress. /// Key represents the meaning of a keypress.
/// ///
/// This is a superset of the UI Events Specification's [`KeyboardEvent.key`] with /// This is a superset of the UI Events Specification's [`KeyboardEvent.key`] with
@@ -1588,7 +1565,7 @@ impl NamedKey {
/// # Examples /// # Examples
/// ///
/// ``` /// ```
/// use winit_core::keyboard::NamedKey; /// use winit::keyboard::NamedKey;
/// ///
/// assert_eq!(NamedKey::Enter.to_text(), Some("\r")); /// assert_eq!(NamedKey::Enter.to_text(), Some("\r"));
/// assert_eq!(NamedKey::F20.to_text(), None); /// assert_eq!(NamedKey::F20.to_text(), None);
@@ -1611,7 +1588,7 @@ impl Key {
/// # Examples /// # Examples
/// ///
/// ``` /// ```
/// use winit_core::keyboard::{NamedKey, Key}; /// use winit::keyboard::{NamedKey, Key};
/// ///
/// assert_eq!(Key::Character("a".into()).to_text(), Some("a")); /// assert_eq!(Key::Character("a".into()).to_text(), Some("a"));
/// assert_eq!(Key::Named(NamedKey::Enter).to_text(), Some("\r")); /// assert_eq!(Key::Named(NamedKey::Enter).to_text(), Some("\r"));
@@ -1750,6 +1727,28 @@ pub enum ModifiersKeyState {
Unknown, Unknown,
} }
// NOTE: the exact modifier key is not used to represent modifiers state in the
// first place due to a fact that modifiers state could be changed without any
// key being pressed and on some platforms like Wayland/X11 which key resulted
// in modifiers change is hidden, also, not that it really matters.
//
// The reason this API is even exposed is mostly to provide a way for users
// to treat modifiers differently based on their position, which is required
// on macOS due to their AltGr/Option situation.
bitflags! {
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(crate) struct ModifiersKeys: u8 {
const LSHIFT = 0b0000_0001;
const RSHIFT = 0b0000_0010;
const LCONTROL = 0b0000_0100;
const RCONTROL = 0b0000_1000;
const LALT = 0b0001_0000;
const RALT = 0b0010_0000;
const LSUPER = 0b0100_0000;
const RSUPER = 0b1000_0000;
}
}
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
mod modifiers_serde { mod modifiers_serde {
use super::ModifiersState; use super::ModifiersState;

View File

@@ -164,15 +164,14 @@
#[cfg(feature = "rwh_06")] #[cfg(feature = "rwh_06")]
pub use rwh_06 as raw_window_handle; pub use rwh_06 as raw_window_handle;
#[doc(inline)] pub mod dpi;
pub use winit_core::{dpi, keyboard};
#[macro_use] #[macro_use]
pub mod error; pub mod error;
mod cursor; mod cursor;
pub mod event; pub mod event;
pub mod event_loop; pub mod event_loop;
mod icon; mod icon;
pub mod keyboard;
pub mod monitor; pub mod monitor;
mod platform_impl; mod platform_impl;
pub mod window; pub mod window;

View File

@@ -46,6 +46,7 @@ pub mod pump_events;
macos_platform, macos_platform,
x11_platform, x11_platform,
wayland_platform, wayland_platform,
orbital_platform,
docsrs docsrs
))] ))]
pub mod modifier_supplement; pub mod modifier_supplement;

View File

@@ -25,8 +25,7 @@ pub trait KeyEventExtModifierSupplement {
impl KeyEventExtModifierSupplement for KeyEvent { impl KeyEventExtModifierSupplement for KeyEvent {
#[inline] #[inline]
fn text_with_all_modifiers(&self) -> Option<&str> { fn text_with_all_modifiers(&self) -> Option<&str> {
self.extra self.platform_specific
.extra
.text_with_all_modifiers .text_with_all_modifiers
.as_ref() .as_ref()
.map(|s| s.as_str()) .map(|s| s.as_str())
@@ -34,6 +33,6 @@ impl KeyEventExtModifierSupplement for KeyEvent {
#[inline] #[inline]
fn key_without_modifiers(&self) -> Key { fn key_without_modifiers(&self) -> Key {
self.extra.extra.key_without_modifiers.clone() self.platform_specific.key_without_modifiers.clone()
} }
} }

View File

@@ -64,7 +64,7 @@ impl EventLoopExtStartupNotify for EventLoopWindowTarget {
crate::platform_impl::EventLoopWindowTarget::X(_) => env::var(X11_VAR), crate::platform_impl::EventLoopWindowTarget::X(_) => env::var(X11_VAR),
} }
.ok() .ok()
.map(ActivationToken::new) .map(ActivationToken::_new)
} }
} }
@@ -94,6 +94,6 @@ pub fn reset_activation_token_env() {
/// ///
/// This could be used before running daemon processes. /// This could be used before running daemon processes.
pub fn set_activation_token_env(token: ActivationToken) { pub fn set_activation_token_env(token: ActivationToken) {
env::set_var(X11_VAR, token.token()); env::set_var(X11_VAR, &token._token);
env::set_var(WAYLAND_VAR, token.token()); env::set_var(WAYLAND_VAR, token._token);
} }

View File

@@ -504,7 +504,7 @@ pub trait DeviceIdExtWindows {
impl DeviceIdExtWindows for DeviceId { impl DeviceIdExtWindows for DeviceId {
#[inline] #[inline]
fn persistent_identifier(&self) -> Option<String> { fn persistent_identifier(&self) -> Option<String> {
crate::platform_impl::persistent_identifier(*self) self.0.persistent_identifier()
} }
} }

View File

@@ -27,8 +27,7 @@ use crate::{
event_loop::{self, ControlFlow, DeviceEvents, EventLoopWindowTarget as RootELW}, event_loop::{self, ControlFlow, DeviceEvents, EventLoopWindowTarget as RootELW},
platform::pump_events::PumpStatus, platform::pump_events::PumpStatus,
window::{ window::{
self, CursorGrabMode, ImePurpose, ResizeDirection, Theme, WindowButtons, WindowId, self, CursorGrabMode, ImePurpose, ResizeDirection, Theme, WindowButtons, WindowLevel,
WindowLevel,
}, },
}; };
use crate::{error::EventLoopError, platform_impl::Fullscreen}; use crate::{error::EventLoopError, platform_impl::Fullscreen};
@@ -36,7 +35,6 @@ use crate::{error::EventLoopError, platform_impl::Fullscreen};
mod keycodes; mod keycodes;
static HAS_FOCUS: Lazy<RwLock<bool>> = Lazy::new(|| RwLock::new(true)); static HAS_FOCUS: Lazy<RwLock<bool>> = Lazy::new(|| RwLock::new(true));
const WINDOW_ID: u64 = 0;
/// Returns the minimum `Option<Duration>`, taking into account that `None` /// Returns the minimum `Option<Duration>`, taking into account that `None`
/// equates to an infinite timeout, not a zero timeout (so can't just use /// equates to an infinite timeout, not a zero timeout (so can't just use
@@ -236,7 +234,7 @@ impl<T: 'static> EventLoop<T> {
*HAS_FOCUS.write().unwrap() = true; *HAS_FOCUS.write().unwrap() = true;
callback( callback(
event::Event::WindowEvent { event::Event::WindowEvent {
window_id: WindowId::from(WINDOW_ID), window_id: window::WindowId(WindowId),
event: event::WindowEvent::Focused(true), event: event::WindowEvent::Focused(true),
}, },
self.window_target(), self.window_target(),
@@ -246,7 +244,7 @@ impl<T: 'static> EventLoop<T> {
*HAS_FOCUS.write().unwrap() = false; *HAS_FOCUS.write().unwrap() = false;
callback( callback(
event::Event::WindowEvent { event::Event::WindowEvent {
window_id: WindowId::from(WINDOW_ID), window_id: window::WindowId(WindowId),
event: event::WindowEvent::Focused(false), event: event::WindowEvent::Focused(false),
}, },
self.window_target(), self.window_target(),
@@ -261,7 +259,7 @@ impl<T: 'static> EventLoop<T> {
MonitorHandle::new(self.android_app.clone()).size(), MonitorHandle::new(self.android_app.clone()).size(),
)); ));
let event = event::Event::WindowEvent { let event = event::Event::WindowEvent {
window_id: WindowId::from(WINDOW_ID), window_id: window::WindowId(WindowId),
event: event::WindowEvent::ScaleFactorChanged { event: event::WindowEvent::ScaleFactorChanged {
inner_size_writer: InnerSizeWriter::new(Arc::downgrade( inner_size_writer: InnerSizeWriter::new(Arc::downgrade(
&new_inner_size, &new_inner_size,
@@ -349,7 +347,7 @@ impl<T: 'static> EventLoop<T> {
PhysicalSize::new(0, 0) PhysicalSize::new(0, 0)
}; };
let event = event::Event::WindowEvent { let event = event::Event::WindowEvent {
window_id: WindowId::from(WINDOW_ID), window_id: window::WindowId(WindowId),
event: event::WindowEvent::Resized(size), event: event::WindowEvent::Resized(size),
}; };
callback(event, self.window_target()); callback(event, self.window_target());
@@ -359,7 +357,7 @@ impl<T: 'static> EventLoop<T> {
if pending_redraw { if pending_redraw {
pending_redraw = false; pending_redraw = false;
let event = event::Event::WindowEvent { let event = event::Event::WindowEvent {
window_id: WindowId::from(WINDOW_ID), window_id: window::WindowId(WindowId),
event: event::WindowEvent::RedrawRequested, event: event::WindowEvent::RedrawRequested,
}; };
callback(event, self.window_target()); callback(event, self.window_target());
@@ -384,8 +382,8 @@ impl<T: 'static> EventLoop<T> {
let mut input_status = InputStatus::Handled; let mut input_status = InputStatus::Handled;
match event { match event {
InputEvent::MotionEvent(motion_event) => { InputEvent::MotionEvent(motion_event) => {
let window_id = WindowId::from(WINDOW_ID); let window_id = window::WindowId(WindowId);
let device_id = event::DeviceId::from(motion_event.device_id() as u64); let device_id = event::DeviceId(DeviceId(motion_event.device_id()));
let phase = match motion_event.action() { let phase = match motion_event.action() {
MotionAction::Down | MotionAction::PointerDown => { MotionAction::Down | MotionAction::PointerDown => {
@@ -455,9 +453,9 @@ impl<T: 'static> EventLoop<T> {
); );
let event = event::Event::WindowEvent { let event = event::Event::WindowEvent {
window_id: WindowId::from(WINDOW_ID), window_id: window::WindowId(WindowId),
event: event::WindowEvent::KeyboardInput { event: event::WindowEvent::KeyboardInput {
device_id: event::DeviceId::from(key.device_id() as u64), device_id: event::DeviceId(DeviceId(key.device_id())),
event: event::KeyEvent { event: event::KeyEvent {
state, state,
physical_key: keycodes::to_physical_key(keycode), physical_key: keycodes::to_physical_key(keycode),
@@ -465,9 +463,7 @@ impl<T: 'static> EventLoop<T> {
location: keycodes::to_location(keycode), location: keycodes::to_location(keycode),
repeat: key.repeat_count() > 0, repeat: key.repeat_count() > 0,
text: None, text: None,
extra: event::KeyExtra { platform_specific: KeyEventExtra {},
extra: KeyEventExtra {},
},
}, },
is_synthetic: false, is_synthetic: false,
}, },
@@ -746,6 +742,36 @@ impl OwnedDisplayHandle {
} }
} }
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub(crate) struct WindowId;
impl WindowId {
pub const fn dummy() -> Self {
WindowId
}
}
impl From<WindowId> for u64 {
fn from(_: WindowId) -> Self {
0
}
}
impl From<u64> for WindowId {
fn from(_: u64) -> Self {
Self
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct DeviceId(i32);
impl DeviceId {
pub const fn dummy() -> Self {
DeviceId(0)
}
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct PlatformSpecificWindowBuilderAttributes; pub struct PlatformSpecificWindowBuilderAttributes;
@@ -776,7 +802,7 @@ impl Window {
} }
pub fn id(&self) -> WindowId { pub fn id(&self) -> WindowId {
WindowId::from(WINDOW_ID) WindowId
} }
pub fn primary_monitor(&self) -> Option<MonitorHandle> { pub fn primary_monitor(&self) -> Option<MonitorHandle> {

View File

@@ -30,6 +30,7 @@ use crate::{
dpi::PhysicalSize, dpi::PhysicalSize,
event::{Event, InnerSizeWriter, StartCause, WindowEvent}, event::{Event, InnerSizeWriter, StartCause, WindowEvent},
event_loop::{ControlFlow, EventLoopWindowTarget as RootEventLoopWindowTarget}, event_loop::{ControlFlow, EventLoopWindowTarget as RootEventLoopWindowTarget},
window::WindowId as RootWindowId,
}; };
macro_rules! bug { macro_rules! bug {
@@ -92,15 +93,17 @@ enum UserCallbackTransitionResult<'a> {
}, },
} }
fn is_redraw(event: &Event<HandlePendingUserEvents>) -> bool { impl Event<HandlePendingUserEvents> {
fn is_redraw(&self) -> bool {
matches!( matches!(
event, self,
Event::WindowEvent { Event::WindowEvent {
event: WindowEvent::RedrawRequested, event: WindowEvent::RedrawRequested,
.. ..
} }
) )
} }
}
// this is the state machine for the app lifecycle // this is the state machine for the app lifecycle
#[derive(Debug)] #[derive(Debug)]
@@ -619,9 +622,9 @@ pub(crate) fn handle_nonuser_events<I: IntoIterator<Item = EventWrapper>>(
for wrapper in events { for wrapper in events {
match wrapper { match wrapper {
EventWrapper::StaticEvent(event) => { EventWrapper::StaticEvent(event) => {
if !processing_redraws && is_redraw(&event) { if !processing_redraws && event.is_redraw() {
log::info!("processing `RedrawRequested` during the main event loop"); log::info!("processing `RedrawRequested` during the main event loop");
} else if processing_redraws && !is_redraw(&event) { } else if processing_redraws && !event.is_redraw() {
log::warn!( log::warn!(
"processing non `RedrawRequested` event after the main event loop: {:#?}", "processing non `RedrawRequested` event after the main event loop: {:#?}",
event event
@@ -673,9 +676,9 @@ pub(crate) fn handle_nonuser_events<I: IntoIterator<Item = EventWrapper>>(
for wrapper in queued_events { for wrapper in queued_events {
match wrapper { match wrapper {
EventWrapper::StaticEvent(event) => { EventWrapper::StaticEvent(event) => {
if !processing_redraws && is_redraw(&event) { if !processing_redraws && event.is_redraw() {
log::info!("processing `RedrawRequested` during the main event loop"); log::info!("processing `RedrawRequested` during the main event loop");
} else if processing_redraws && !is_redraw(&event) { } else if processing_redraws && !event.is_redraw() {
log::warn!( log::warn!(
"processing non-`RedrawRequested` event after the main event loop: {:#?}", "processing non-`RedrawRequested` event after the main event loop: {:#?}",
event event
@@ -765,7 +768,7 @@ pub fn handle_main_events_cleared(mtm: MainThreadMarker) {
.into_iter() .into_iter()
.map(|window| { .map(|window| {
EventWrapper::StaticEvent(Event::WindowEvent { EventWrapper::StaticEvent(Event::WindowEvent {
window_id: window.id(), window_id: RootWindowId(window.id()),
event: WindowEvent::RedrawRequested, event: WindowEvent::RedrawRequested,
}) })
}) })
@@ -796,7 +799,7 @@ fn handle_hidpi_proxy(handler: &mut EventLoopHandler, event: ScaleFactorChanged)
} = event; } = event;
let new_inner_size = Arc::new(Mutex::new(suggested_size)); let new_inner_size = Arc::new(Mutex::new(suggested_size));
let event = Event::WindowEvent { let event = Event::WindowEvent {
window_id: window.id(), window_id: RootWindowId(window.id()),
event: WindowEvent::ScaleFactorChanged { event: WindowEvent::ScaleFactorChanged {
scale_factor, scale_factor,
inner_size_writer: InnerSizeWriter::new(Arc::downgrade(&new_inner_size)), inner_size_writer: InnerSizeWriter::new(Arc::downgrade(&new_inner_size)),

View File

@@ -68,7 +68,7 @@ mod window;
use std::fmt; use std::fmt;
use crate::event::DeviceId; use crate::event::DeviceId as RootDeviceId;
pub(crate) use self::{ pub(crate) use self::{
event_loop::{ event_loop::{
@@ -76,14 +76,27 @@ pub(crate) use self::{
PlatformSpecificEventLoopAttributes, PlatformSpecificEventLoopAttributes,
}, },
monitor::{MonitorHandle, VideoModeHandle}, monitor::{MonitorHandle, VideoModeHandle},
window::{PlatformSpecificWindowBuilderAttributes, Window}, window::{PlatformSpecificWindowBuilderAttributes, Window, WindowId},
}; };
pub(crate) use crate::cursor::NoCustomCursor as PlatformCustomCursor; pub(crate) use crate::cursor::NoCustomCursor as PlatformCustomCursor;
pub(crate) use crate::cursor::NoCustomCursor as PlatformCustomCursorBuilder; pub(crate) use crate::cursor::NoCustomCursor as PlatformCustomCursorBuilder;
pub(crate) use crate::icon::NoIcon as PlatformIcon; pub(crate) use crate::icon::NoIcon as PlatformIcon;
pub(crate) use crate::platform_impl::Fullscreen; pub(crate) use crate::platform_impl::Fullscreen;
pub(crate) const DEVICE_ID: DeviceId = unsafe { DeviceId::dummy() }; /// There is no way to detect which device that performed a certain event in
/// UIKit (i.e. you can't differentiate between different external keyboards,
/// or wether it was the main touchscreen, assistive technologies, or some
/// other pointer device that caused a touch event).
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct DeviceId;
impl DeviceId {
pub const unsafe fn dummy() -> Self {
DeviceId
}
}
pub(crate) const DEVICE_ID: RootDeviceId = RootDeviceId(DeviceId);
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct KeyEventExtra {} pub struct KeyEventExtra {}

View File

@@ -15,6 +15,7 @@ use super::uikit::{
UIStatusBarStyle, UITapGestureRecognizer, UITouch, UITouchPhase, UITouchType, UIStatusBarStyle, UITapGestureRecognizer, UITouch, UITouchPhase, UITouchType,
UITraitCollection, UIView, UIViewController, UIWindow, UITraitCollection, UIView, UIViewController, UIWindow,
}; };
use super::window::WindowId;
use crate::{ use crate::{
dpi::PhysicalPosition, dpi::PhysicalPosition,
event::{Event, Force, Touch, TouchPhase, WindowEvent}, event::{Event, Force, Touch, TouchPhase, WindowEvent},
@@ -23,7 +24,7 @@ use crate::{
ffi::{UIRectEdge, UIUserInterfaceIdiom}, ffi::{UIRectEdge, UIUserInterfaceIdiom},
Fullscreen, DEVICE_ID, Fullscreen, DEVICE_ID,
}, },
window::{WindowAttributes, WindowId}, window::{WindowAttributes, WindowId as RootWindowId},
}; };
pub struct WinitViewState { pub struct WinitViewState {
@@ -54,7 +55,7 @@ declare_class!(
app_state::handle_nonuser_event( app_state::handle_nonuser_event(
mtm, mtm,
EventWrapper::StaticEvent(Event::WindowEvent { EventWrapper::StaticEvent(Event::WindowEvent {
window_id: window.id(), window_id: RootWindowId(window.id()),
event: WindowEvent::RedrawRequested, event: WindowEvent::RedrawRequested,
}), }),
); );
@@ -89,7 +90,7 @@ declare_class!(
app_state::handle_nonuser_event( app_state::handle_nonuser_event(
mtm, mtm,
EventWrapper::StaticEvent(Event::WindowEvent { EventWrapper::StaticEvent(Event::WindowEvent {
window_id: window.id(), window_id: RootWindowId(window.id()),
event: WindowEvent::Resized(size), event: WindowEvent::Resized(size),
}), }),
); );
@@ -128,7 +129,7 @@ declare_class!(
width: screen_frame.size.width as f64, width: screen_frame.size.width as f64,
height: screen_frame.size.height as f64, height: screen_frame.size.height as f64,
}; };
let window_id = window.id(); let window_id = RootWindowId(window.id());
app_state::handle_nonuser_events( app_state::handle_nonuser_events(
mtm, mtm,
std::iter::once(EventWrapper::ScaleFactorChanged( std::iter::once(EventWrapper::ScaleFactorChanged(
@@ -182,7 +183,7 @@ declare_class!(
}; };
let gesture_event = EventWrapper::StaticEvent(Event::WindowEvent { let gesture_event = EventWrapper::StaticEvent(Event::WindowEvent {
window_id: window.id(), window_id: RootWindowId(window.id()),
event: WindowEvent::PinchGesture { event: WindowEvent::PinchGesture {
device_id: DEVICE_ID, device_id: DEVICE_ID,
delta: recognizer.velocity() as _, delta: recognizer.velocity() as _,
@@ -200,7 +201,7 @@ declare_class!(
if recognizer.state() == UIGestureRecognizerState::Ended { if recognizer.state() == UIGestureRecognizerState::Ended {
let gesture_event = EventWrapper::StaticEvent(Event::WindowEvent { let gesture_event = EventWrapper::StaticEvent(Event::WindowEvent {
window_id: window.id(), window_id: RootWindowId(window.id()),
event: WindowEvent::DoubleTapGesture { event: WindowEvent::DoubleTapGesture {
device_id: DEVICE_ID, device_id: DEVICE_ID,
}, },
@@ -228,7 +229,7 @@ declare_class!(
// Flip the velocity to match macOS. // Flip the velocity to match macOS.
let delta = -recognizer.velocity() as _; let delta = -recognizer.velocity() as _;
let gesture_event = EventWrapper::StaticEvent(Event::WindowEvent { let gesture_event = EventWrapper::StaticEvent(Event::WindowEvent {
window_id: window.id(), window_id: RootWindowId(window.id()),
event: WindowEvent::RotationGesture { event: WindowEvent::RotationGesture {
device_id: DEVICE_ID, device_id: DEVICE_ID,
delta, delta,
@@ -379,7 +380,7 @@ impl WinitView {
) )
}; };
touch_events.push(EventWrapper::StaticEvent(Event::WindowEvent { touch_events.push(EventWrapper::StaticEvent(Event::WindowEvent {
window_id: window.id(), window_id: RootWindowId(window.id()),
event: WindowEvent::Touch(Touch { event: WindowEvent::Touch(Touch {
device_id: DEVICE_ID, device_id: DEVICE_ID,
id: touch_id, id: touch_id,
@@ -582,7 +583,7 @@ declare_class!(
app_state::handle_nonuser_event( app_state::handle_nonuser_event(
mtm, mtm,
EventWrapper::StaticEvent(Event::WindowEvent { EventWrapper::StaticEvent(Event::WindowEvent {
window_id: self.id(), window_id: RootWindowId(self.id()),
event: WindowEvent::Focused(true), event: WindowEvent::Focused(true),
}), }),
); );
@@ -595,7 +596,7 @@ declare_class!(
app_state::handle_nonuser_event( app_state::handle_nonuser_event(
mtm, mtm,
EventWrapper::StaticEvent(Event::WindowEvent { EventWrapper::StaticEvent(Event::WindowEvent {
window_id: self.id(), window_id: RootWindowId(self.id()),
event: WindowEvent::Focused(false), event: WindowEvent::Focused(false),
}), }),
); );
@@ -690,7 +691,7 @@ declare_class!(
&*ptr &*ptr
}; };
events.push(EventWrapper::StaticEvent(Event::WindowEvent { events.push(EventWrapper::StaticEvent(Event::WindowEvent {
window_id: window.id(), window_id: RootWindowId(window.id()),
event: WindowEvent::Destroyed, event: WindowEvent::Destroyed,
})); }));
} }
@@ -720,7 +721,7 @@ impl WinitApplicationDelegate {
&*ptr &*ptr
}; };
events.push(EventWrapper::StaticEvent(Event::WindowEvent { events.push(EventWrapper::StaticEvent(Event::WindowEvent {
window_id: window.id(), window_id: RootWindowId(window.id()),
event: WindowEvent::Occluded(occluded), event: WindowEvent::Occluded(occluded),
})); }));
} }

View File

@@ -5,6 +5,7 @@ use std::collections::VecDeque;
use icrate::Foundation::{CGFloat, CGPoint, CGRect, CGSize, MainThreadBound, MainThreadMarker}; use icrate::Foundation::{CGFloat, CGPoint, CGRect, CGSize, MainThreadBound, MainThreadMarker};
use log::{debug, warn}; use log::{debug, warn};
use objc2::rc::Id; use objc2::rc::Id;
use objc2::runtime::AnyObject;
use objc2::{class, msg_send}; use objc2::{class, msg_send};
use super::app_state::EventWrapper; use super::app_state::EventWrapper;
@@ -22,7 +23,7 @@ use crate::{
}, },
window::{ window::{
CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType, WindowAttributes, CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType, WindowAttributes,
WindowButtons, WindowId, WindowLevel, WindowButtons, WindowId as RootWindowId, WindowLevel,
}, },
}; };
@@ -464,7 +465,7 @@ impl Window {
width: screen_frame.size.width as f64, width: screen_frame.size.width as f64,
height: screen_frame.size.height as f64, height: screen_frame.size.height as f64,
}; };
let window_id = window.id(); let window_id = RootWindowId(window.id());
app_state::handle_nonuser_events( app_state::handle_nonuser_events(
mtm, mtm,
std::iter::once(EventWrapper::ScaleFactorChanged( std::iter::once(EventWrapper::ScaleFactorChanged(
@@ -638,6 +639,44 @@ impl Inner {
} }
} }
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct WindowId {
window: *mut WinitUIWindow,
}
impl WindowId {
pub const unsafe fn dummy() -> Self {
WindowId {
window: std::ptr::null_mut(),
}
}
}
impl From<WindowId> for u64 {
fn from(window_id: WindowId) -> Self {
window_id.window as u64
}
}
impl From<u64> for WindowId {
fn from(raw_id: u64) -> Self {
Self {
window: raw_id as _,
}
}
}
unsafe impl Send for WindowId {}
unsafe impl Sync for WindowId {}
impl From<&AnyObject> for WindowId {
fn from(window: &AnyObject) -> WindowId {
WindowId {
window: window as *const _ as _,
}
}
}
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]
pub struct PlatformSpecificWindowBuilderAttributes { pub struct PlatformSpecificWindowBuilderAttributes {
pub scale_factor: Option<f64>, pub scale_factor: Option<f64>,

View File

@@ -409,9 +409,7 @@ impl KbdState {
location, location,
state, state,
repeat, repeat,
extra: crate::event::KeyExtra { platform_specific,
extra: platform_specific,
},
} }
} }

Some files were not shown because too many files have changed in this diff Show More