mirror of
https://github.com/rust-windowing/winit.git
synced 2026-06-26 22:53:15 -04:00
Compare commits
2 Commits
madsmtm/dp
...
madsmtm/do
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f1754bf14f | ||
|
|
69783445f1 |
@@ -91,8 +91,8 @@ image = { version = "0.25.0", default-features = false, features = ["png"] }
|
||||
tracing = { version = "0.1.40", default-features = false, features = ["log"] }
|
||||
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
|
||||
|
||||
[target.'cfg(not(target_os = "android"))'.dev-dependencies]
|
||||
softbuffer = { version = "0.4.6", default-features = false, features = [
|
||||
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dev-dependencies]
|
||||
softbuffer = { version = "0.4.0", default-features = false, features = [
|
||||
"x11",
|
||||
"x11-dlopen",
|
||||
"wayland",
|
||||
@@ -270,7 +270,7 @@ xkbcommon-dl = "0.4.2"
|
||||
# Orbital
|
||||
[target.'cfg(target_os = "redox")'.dependencies]
|
||||
orbclient = { version = "0.3.47", default-features = false }
|
||||
redox_syscall = "0.5.7"
|
||||
redox_syscall = "0.4.1"
|
||||
|
||||
# Web
|
||||
[target.'cfg(target_family = "wasm")'.dependencies]
|
||||
|
||||
@@ -11,8 +11,6 @@ Unreleased` header.
|
||||
|
||||
## Unreleased
|
||||
|
||||
- Add `Rect`, `PhysicalRect` and `LogicalRect`.
|
||||
|
||||
## 0.1.1
|
||||
|
||||
- Derive `Debug`, `Copy`, `Clone`, `PartialEq`, `Serialize`, `Deserialize` traits for `PixelUnit`.
|
||||
|
||||
114
dpi/src/lib.rs
114
dpi/src/lib.rs
@@ -759,120 +759,6 @@ impl<P: Pixel> From<LogicalPosition<P>> for Position {
|
||||
}
|
||||
}
|
||||
|
||||
/// A rectangle represented in logical pixels.
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Default, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub struct LogicalRect<P> {
|
||||
pub origin: LogicalPosition<P>,
|
||||
pub size: LogicalSize<P>,
|
||||
}
|
||||
|
||||
impl<P> LogicalRect<P> {
|
||||
#[inline]
|
||||
pub const fn new(origin: LogicalPosition<P>, size: LogicalSize<P>) -> Self {
|
||||
Self { origin, size }
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: Pixel> LogicalRect<P> {
|
||||
#[inline]
|
||||
pub fn from_physical<T: Into<PhysicalRect<X>>, X: Pixel>(
|
||||
physical: T,
|
||||
scale_factor: f64,
|
||||
) -> Self {
|
||||
physical.into().to_logical(scale_factor)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_physical<X: Pixel>(&self, scale_factor: f64) -> PhysicalRect<X> {
|
||||
let origin = self.origin.to_physical(scale_factor);
|
||||
let size = self.size.to_physical(scale_factor);
|
||||
PhysicalRect::new(origin, size)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn cast<X: Pixel>(&self) -> LogicalRect<X> {
|
||||
LogicalRect { origin: self.origin.cast(), size: self.size.cast() }
|
||||
}
|
||||
}
|
||||
|
||||
/// A rectangle represented in physical pixels.
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Default, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub struct PhysicalRect<P> {
|
||||
pub origin: PhysicalPosition<P>,
|
||||
pub size: PhysicalSize<P>,
|
||||
}
|
||||
|
||||
impl<P> PhysicalRect<P> {
|
||||
#[inline]
|
||||
pub const fn new(origin: PhysicalPosition<P>, size: PhysicalSize<P>) -> Self {
|
||||
Self { origin, size }
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: Pixel> PhysicalRect<P> {
|
||||
#[inline]
|
||||
pub fn from_logical<T: Into<LogicalRect<X>>, X: Pixel>(logical: T, scale_factor: f64) -> Self {
|
||||
logical.into().to_physical(scale_factor)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_logical<X: Pixel>(&self, scale_factor: f64) -> LogicalRect<X> {
|
||||
assert!(validate_scale_factor(scale_factor));
|
||||
let origin = self.origin.to_logical(scale_factor);
|
||||
let size = self.size.to_logical(scale_factor);
|
||||
LogicalRect::new(origin, size)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn cast<X: Pixel>(&self) -> PhysicalRect<X> {
|
||||
PhysicalRect { origin: self.origin.cast(), size: self.size.cast() }
|
||||
}
|
||||
}
|
||||
|
||||
/// A rectangle that's either physical or logical.
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub enum Rect {
|
||||
Physical(PhysicalRect<i32>),
|
||||
Logical(LogicalRect<f64>),
|
||||
}
|
||||
|
||||
impl Rect {
|
||||
pub fn new<R: Into<Self>>(rect: R) -> Self {
|
||||
rect.into()
|
||||
}
|
||||
|
||||
pub fn to_logical<P: Pixel>(&self, scale_factor: f64) -> LogicalRect<P> {
|
||||
match *self {
|
||||
Self::Physical(rect) => rect.to_logical(scale_factor),
|
||||
Self::Logical(rect) => rect.cast(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_physical<P: Pixel>(&self, scale_factor: f64) -> PhysicalRect<P> {
|
||||
match *self {
|
||||
Self::Physical(rect) => rect.cast(),
|
||||
Self::Logical(rect) => rect.to_physical(scale_factor),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: Pixel> From<PhysicalRect<P>> for Rect {
|
||||
#[inline]
|
||||
fn from(rect: PhysicalRect<P>) -> Self {
|
||||
Self::Physical(rect.cast())
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: Pixel> From<LogicalRect<P>> for Rect {
|
||||
#[inline]
|
||||
fn from(rect: LogicalRect<P>) -> Self {
|
||||
Self::Logical(rect.cast())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::collections::HashSet;
|
||||
|
||||
@@ -44,7 +44,7 @@ fn main() -> Result<(), impl std::error::Error> {
|
||||
self.windows.clear();
|
||||
event_loop.exit();
|
||||
},
|
||||
WindowEvent::PointerEntered { device_id: _, .. } => {
|
||||
WindowEvent::CursorEntered { device_id: _ } => {
|
||||
// On x11, println when the cursor entered in a window even if the child window
|
||||
// is created by some key inputs.
|
||||
// the child windows are always placed at (0, 0) with size (200, 200) in the
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
use std::collections::HashMap;
|
||||
use std::error::Error;
|
||||
use std::fmt::Debug;
|
||||
#[cfg(not(android_platform))]
|
||||
#[cfg(not(any(android_platform, ios_platform)))]
|
||||
use std::num::NonZeroU32;
|
||||
use std::sync::mpsc::{self, Receiver, Sender};
|
||||
use std::sync::Arc;
|
||||
@@ -11,9 +11,9 @@ use std::{fmt, mem};
|
||||
|
||||
use ::tracing::{error, info};
|
||||
use cursor_icon::CursorIcon;
|
||||
#[cfg(not(android_platform))]
|
||||
#[cfg(not(any(android_platform, ios_platform)))]
|
||||
use rwh_06::{DisplayHandle, HasDisplayHandle};
|
||||
#[cfg(not(android_platform))]
|
||||
#[cfg(not(any(android_platform, ios_platform)))]
|
||||
use softbuffer::{Context, Surface};
|
||||
use winit::application::ApplicationHandler;
|
||||
use winit::dpi::{LogicalSize, PhysicalPosition, PhysicalSize};
|
||||
@@ -22,9 +22,7 @@ use winit::event::{DeviceEvent, DeviceId, Ime, MouseButton, MouseScrollDelta, Wi
|
||||
use winit::event_loop::{ActiveEventLoop, EventLoop};
|
||||
use winit::keyboard::{Key, ModifiersState};
|
||||
#[cfg(macos_platform)]
|
||||
use winit::platform::macos::{
|
||||
ApplicationHandlerExtMacOS, OptionAsAlt, WindowAttributesExtMacOS, WindowExtMacOS,
|
||||
};
|
||||
use winit::platform::macos::{OptionAsAlt, WindowAttributesExtMacOS, WindowExtMacOS};
|
||||
#[cfg(any(x11_platform, wayland_platform))]
|
||||
use winit::platform::startup_notify::{
|
||||
self, EventLoopExtStartupNotify, WindowAttributesExtStartupNotify, WindowExtStartupNotify,
|
||||
@@ -85,14 +83,14 @@ struct Application {
|
||||
/// Drawing context.
|
||||
///
|
||||
/// With OpenGL it could be EGLDisplay.
|
||||
#[cfg(not(android_platform))]
|
||||
#[cfg(not(any(android_platform, ios_platform)))]
|
||||
context: Option<Context<DisplayHandle<'static>>>,
|
||||
}
|
||||
|
||||
impl Application {
|
||||
fn new(event_loop: &EventLoop, receiver: Receiver<Action>, sender: Sender<Action>) -> Self {
|
||||
// SAFETY: we drop the context right before the event loop is stopped, thus making it safe.
|
||||
#[cfg(not(android_platform))]
|
||||
#[cfg(not(any(android_platform, ios_platform)))]
|
||||
let context = Some(
|
||||
Context::new(unsafe {
|
||||
std::mem::transmute::<DisplayHandle<'_>, DisplayHandle<'static>>(
|
||||
@@ -121,7 +119,7 @@ impl Application {
|
||||
Self {
|
||||
receiver,
|
||||
sender,
|
||||
#[cfg(not(android_platform))]
|
||||
#[cfg(not(any(android_platform, ios_platform)))]
|
||||
context,
|
||||
custom_cursors,
|
||||
icon,
|
||||
@@ -448,23 +446,20 @@ impl ApplicationHandler for Application {
|
||||
}
|
||||
}
|
||||
},
|
||||
WindowEvent::PointerButton { button, state, .. } => {
|
||||
info!("Pointer button {button:?} {state:?}");
|
||||
WindowEvent::MouseInput { button, state, .. } => {
|
||||
let mods = window.modifiers;
|
||||
if let Some(action) = state
|
||||
.is_pressed()
|
||||
.then(|| Self::process_mouse_binding(button.mouse_button(), &mods))
|
||||
.flatten()
|
||||
if let Some(action) =
|
||||
state.is_pressed().then(|| Self::process_mouse_binding(button, &mods)).flatten()
|
||||
{
|
||||
self.handle_action_with_window(event_loop, window_id, action);
|
||||
}
|
||||
},
|
||||
WindowEvent::PointerLeft { .. } => {
|
||||
info!("Pointer left Window={window_id:?}");
|
||||
WindowEvent::CursorLeft { .. } => {
|
||||
info!("Cursor left Window={window_id:?}");
|
||||
window.cursor_left();
|
||||
},
|
||||
WindowEvent::PointerMoved { position, .. } => {
|
||||
info!("Moved pointer to {position:?}");
|
||||
WindowEvent::CursorMoved { position, .. } => {
|
||||
info!("Moved cursor to {position:?}");
|
||||
window.cursor_moved(position);
|
||||
},
|
||||
WindowEvent::ActivationTokenDone { token: _token, .. } => {
|
||||
@@ -515,10 +510,11 @@ impl ApplicationHandler for Application {
|
||||
WindowEvent::TouchpadPressure { .. }
|
||||
| WindowEvent::HoveredFileCancelled
|
||||
| WindowEvent::KeyboardInput { .. }
|
||||
| WindowEvent::PointerEntered { .. }
|
||||
| WindowEvent::CursorEntered { .. }
|
||||
| WindowEvent::DroppedFile(_)
|
||||
| WindowEvent::HoveredFile(_)
|
||||
| WindowEvent::Destroyed
|
||||
| WindowEvent::Touch(_)
|
||||
| WindowEvent::Moved(_) => (),
|
||||
}
|
||||
}
|
||||
@@ -526,7 +522,7 @@ impl ApplicationHandler for Application {
|
||||
fn device_event(
|
||||
&mut self,
|
||||
_event_loop: &dyn ActiveEventLoop,
|
||||
device_id: Option<DeviceId>,
|
||||
device_id: DeviceId,
|
||||
event: DeviceEvent,
|
||||
) {
|
||||
info!("Device {device_id:?} event: {event:?}");
|
||||
@@ -549,28 +545,11 @@ impl ApplicationHandler for Application {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(android_platform))]
|
||||
#[cfg(not(any(android_platform, ios_platform)))]
|
||||
fn exiting(&mut self, _event_loop: &dyn ActiveEventLoop) {
|
||||
// We must drop the context here.
|
||||
self.context = None;
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
fn macos_handler(&mut self) -> Option<&mut dyn ApplicationHandlerExtMacOS> {
|
||||
Some(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
impl ApplicationHandlerExtMacOS for Application {
|
||||
fn standard_key_binding(
|
||||
&mut self,
|
||||
_event_loop: &dyn ActiveEventLoop,
|
||||
window_id: WindowId,
|
||||
action: &str,
|
||||
) {
|
||||
info!(?window_id, ?action, "macOS standard key binding");
|
||||
}
|
||||
}
|
||||
|
||||
/// State of the window.
|
||||
@@ -580,7 +559,7 @@ struct WindowState {
|
||||
/// Render surface.
|
||||
///
|
||||
/// NOTE: This surface must be dropped before the `Window`.
|
||||
#[cfg(not(android_platform))]
|
||||
#[cfg(not(any(android_platform, ios_platform)))]
|
||||
surface: Surface<DisplayHandle<'static>, Arc<dyn Window>>,
|
||||
/// The actual winit Window.
|
||||
window: Arc<dyn Window>,
|
||||
@@ -616,7 +595,7 @@ impl WindowState {
|
||||
|
||||
// SAFETY: the surface is dropped before the `window` which provided it with handle, thus
|
||||
// it doesn't outlive it.
|
||||
#[cfg(not(android_platform))]
|
||||
#[cfg(not(any(android_platform, ios_platform)))]
|
||||
let surface = Surface::new(app.context.as_ref().unwrap(), Arc::clone(&window))?;
|
||||
|
||||
let theme = window.theme().unwrap_or(Theme::Dark);
|
||||
@@ -635,7 +614,7 @@ impl WindowState {
|
||||
custom_idx: app.custom_cursors.as_ref().map(Vec::len).unwrap_or(1) - 1,
|
||||
cursor_grab: CursorGrabMode::None,
|
||||
named_idx,
|
||||
#[cfg(not(android_platform))]
|
||||
#[cfg(not(any(android_platform, ios_platform)))]
|
||||
surface,
|
||||
window,
|
||||
theme,
|
||||
@@ -817,7 +796,7 @@ impl WindowState {
|
||||
/// Resize the surface to the new size.
|
||||
fn resize(&mut self, size: PhysicalSize<u32>) {
|
||||
info!("Surface resized to {size:?}");
|
||||
#[cfg(not(android_platform))]
|
||||
#[cfg(not(any(android_platform, ios_platform)))]
|
||||
{
|
||||
let (width, height) = match (NonZeroU32::new(size.width), NonZeroU32::new(size.height))
|
||||
{
|
||||
@@ -910,7 +889,7 @@ impl WindowState {
|
||||
}
|
||||
|
||||
/// Draw the window contents.
|
||||
#[cfg(not(android_platform))]
|
||||
#[cfg(not(any(android_platform, ios_platform)))]
|
||||
fn draw(&mut self) -> Result<(), Box<dyn Error>> {
|
||||
if self.occluded {
|
||||
info!("Skipping drawing occluded window={:?}", self.window.id());
|
||||
@@ -932,7 +911,7 @@ impl WindowState {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(android_platform)]
|
||||
#[cfg(any(android_platform, ios_platform))]
|
||||
fn draw(&mut self) -> Result<(), Box<dyn Error>> {
|
||||
info!("Drawing but without rendering...");
|
||||
Ok(())
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
use crate::event::{DeviceEvent, DeviceId, StartCause, WindowEvent};
|
||||
use crate::event_loop::ActiveEventLoop;
|
||||
#[cfg(any(docsrs, macos_platform))]
|
||||
use crate::platform::macos::ApplicationHandlerExtMacOS;
|
||||
use crate::window::WindowId;
|
||||
|
||||
/// The handler of the application events.
|
||||
@@ -43,21 +41,11 @@ pub trait ApplicationHandler {
|
||||
/// [`pageshow`]: https://developer.mozilla.org/en-US/docs/Web/API/Window/pageshow_event
|
||||
/// [`bfcache`]: https://web.dev/bfcache/
|
||||
///
|
||||
/// ### Android
|
||||
///
|
||||
/// On Android, the [`resumed()`] method is called when the `Activity` is (again, if after a
|
||||
/// prior [`suspended()`]) being displayed to the user. This is a good place to begin drawing
|
||||
/// visual elements, running animations, etc. It is driven by Android's [`onStart()`] method.
|
||||
///
|
||||
/// [`onStart()`]: https://developer.android.com/reference/android/app/Activity#onStart()
|
||||
///
|
||||
/// ### Others
|
||||
///
|
||||
/// **macOS / Orbital / Wayland / Windows / X11:** Unsupported.
|
||||
/// **Android / macOS / Orbital / Wayland / Windows / X11:** Unsupported.
|
||||
///
|
||||
/// [`resumed()`]: Self::resumed()
|
||||
/// [`suspended()`]: Self::suspended()
|
||||
/// [`exiting()`]: Self::exiting()
|
||||
/// [`resumed()`]: Self::resumed
|
||||
fn resumed(&mut self, event_loop: &dyn ActiveEventLoop) {
|
||||
let _ = event_loop;
|
||||
}
|
||||
@@ -83,24 +71,26 @@ pub trait ApplicationHandler {
|
||||
///
|
||||
/// ### Android
|
||||
///
|
||||
/// On Android, the [`can_create_surfaces()`] method is called when a new [`NativeWindow`]
|
||||
/// (native [`Surface`]) is created which backs the application window. This is expected to
|
||||
/// closely correlate with the [`onStart`] lifecycle event which typically results in a surface
|
||||
/// to be created after the app becomes visible.
|
||||
/// On Android, the [`can_create_surfaces()`] method is called when a new [`SurfaceView`] has
|
||||
/// been created. This is expected to closely correlate with the [`onResume`] lifecycle
|
||||
/// event but there may technically be a discrepancy.
|
||||
///
|
||||
/// Applications that need to run on Android must wait until they have received a surface before
|
||||
/// [`onResume`]: https://developer.android.com/reference/android/app/Activity#onResume()
|
||||
///
|
||||
/// Applications that need to run on Android must wait until they have been "resumed" before
|
||||
/// they will be able to create a render surface (such as an `EGLSurface`, [`VkSurfaceKHR`]
|
||||
/// or [`wgpu::Surface`]) which depend on having a [`NativeWindow`]. Applications must handle
|
||||
/// [`destroy_surfaces()`], where their render surfaces are invalid and should be dropped.
|
||||
/// or [`wgpu::Surface`]) which depend on having a [`SurfaceView`]. Applications must also
|
||||
/// assume that if they are [suspended], then their render surfaces are invalid and should
|
||||
/// be dropped.
|
||||
///
|
||||
/// [`NativeWindow`]: https://developer.android.com/ndk/reference/group/a-native-window
|
||||
/// [`Surface`]: https://developer.android.com/reference/android/view/Surface
|
||||
/// [`onStart`]: https://developer.android.com/reference/android/app/Activity#onStart()
|
||||
/// [suspended]: Self::destroy_surfaces
|
||||
/// [`SurfaceView`]: https://developer.android.com/reference/android/view/SurfaceView
|
||||
/// [Activity lifecycle]: https://developer.android.com/guide/components/activities/activity-lifecycle
|
||||
/// [`VkSurfaceKHR`]: https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VkSurfaceKHR.html
|
||||
/// [`wgpu::Surface`]: https://docs.rs/wgpu/latest/wgpu/struct.Surface.html
|
||||
///
|
||||
/// [`can_create_surfaces()`]: Self::can_create_surfaces()
|
||||
/// [`destroy_surfaces()`]: Self::destroy_surfaces()
|
||||
/// [`can_create_surfaces()`]: Self::can_create_surfaces
|
||||
/// [`destroy_surfaces()`]: Self::destroy_surfaces
|
||||
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop);
|
||||
|
||||
/// Called after a wake up is requested using [`EventLoopProxy::wake_up()`].
|
||||
@@ -206,7 +196,7 @@ pub trait ApplicationHandler {
|
||||
fn device_event(
|
||||
&mut self,
|
||||
event_loop: &dyn ActiveEventLoop,
|
||||
device_id: Option<DeviceId>,
|
||||
device_id: DeviceId,
|
||||
event: DeviceEvent,
|
||||
) {
|
||||
let _ = (event_loop, device_id, event);
|
||||
@@ -245,30 +235,18 @@ pub trait ApplicationHandler {
|
||||
/// ### Web
|
||||
///
|
||||
/// On Web, the [`suspended()`] method is called in response to a [`pagehide`] event if the
|
||||
/// page is being stored in the [`bfcache`] (back/forward cache) - an in-memory cache that
|
||||
/// page is being restored from the [`bfcache`] (back/forward cache) - an in-memory cache that
|
||||
/// stores a complete snapshot of a page (including the JavaScript heap) as the user is
|
||||
/// navigating away.
|
||||
///
|
||||
/// [`pagehide`]: https://developer.mozilla.org/en-US/docs/Web/API/Window/pagehide_event
|
||||
/// [`bfcache`]: https://web.dev/bfcache/
|
||||
///
|
||||
/// ### Android
|
||||
///
|
||||
/// On Android, the [`suspended()`] method is called when the `Activity` is no longer visible
|
||||
/// to the user. This is a good place to stop refreshing UI, running animations and other visual
|
||||
/// things. It is driven by Android's [`onStop()`] method.
|
||||
///
|
||||
/// After this event the application either receives [`resumed()`] again, or [`exiting()`].
|
||||
///
|
||||
/// [`onStop()`]: https://developer.android.com/reference/android/app/Activity#onStop()
|
||||
///
|
||||
/// ### Others
|
||||
///
|
||||
/// **macOS / Orbital / Wayland / Windows / X11:** Unsupported.
|
||||
/// **Android / macOS / Orbital / Wayland / Windows / X11:** Unsupported.
|
||||
///
|
||||
/// [`resumed()`]: Self::resumed()
|
||||
/// [`suspended()`]: Self::suspended()
|
||||
/// [`exiting()`]: Self::exiting()
|
||||
/// [`suspended()`]: Self::suspended
|
||||
fn suspended(&mut self, event_loop: &dyn ActiveEventLoop) {
|
||||
let _ = event_loop;
|
||||
}
|
||||
@@ -281,22 +259,24 @@ pub trait ApplicationHandler {
|
||||
///
|
||||
/// ### Android
|
||||
///
|
||||
/// On Android, the [`destroy_surfaces()`] method is called when the application's
|
||||
/// [`NativeWindow`] (native [`Surface`]) is destroyed. This is expected to closely correlate
|
||||
/// with the [`onStop`] lifecycle event which typically results in the surface to be destroyed
|
||||
/// after the app becomes invisible.
|
||||
/// On Android, the [`destroy_surfaces()`] method is called when the application's associated
|
||||
/// [`SurfaceView`] is destroyed. This is expected to closely correlate with the [`onPause`]
|
||||
/// lifecycle event but there may technically be a discrepancy.
|
||||
///
|
||||
/// Applications that need to run on Android should assume their [`NativeWindow`] has been
|
||||
/// [`onPause`]: https://developer.android.com/reference/android/app/Activity#onPause()
|
||||
///
|
||||
/// Applications that need to run on Android should assume their [`SurfaceView`] has been
|
||||
/// destroyed, which indirectly invalidates any existing render surfaces that may have been
|
||||
/// created outside of Winit (such as an `EGLSurface`, [`VkSurfaceKHR`] or [`wgpu::Surface`]).
|
||||
///
|
||||
/// When receiving [`destroy_surfaces()`] Android applications should drop all render surfaces
|
||||
/// before the event callback completes, which may be re-created when the application next
|
||||
/// receives [`can_create_surfaces()`].
|
||||
/// After being [suspended] on Android applications must drop all render surfaces before
|
||||
/// the event callback completes, which may be re-created when the application is next
|
||||
/// [resumed].
|
||||
///
|
||||
/// [`NativeWindow`]: https://developer.android.com/ndk/reference/group/a-native-window
|
||||
/// [`Surface`]: https://developer.android.com/reference/android/view/Surface
|
||||
/// [`onStop`]: https://developer.android.com/reference/android/app/Activity#onStop()
|
||||
/// [suspended]: Self::destroy_surfaces
|
||||
/// [resumed]: Self::can_create_surfaces
|
||||
/// [`SurfaceView`]: https://developer.android.com/reference/android/view/SurfaceView
|
||||
/// [Activity lifecycle]: https://developer.android.com/guide/components/activities/activity-lifecycle
|
||||
/// [`VkSurfaceKHR`]: https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VkSurfaceKHR.html
|
||||
/// [`wgpu::Surface`]: https://docs.rs/wgpu/latest/wgpu/struct.Surface.html
|
||||
///
|
||||
@@ -304,8 +284,8 @@ pub trait ApplicationHandler {
|
||||
///
|
||||
/// - **iOS / macOS / Orbital / Wayland / Web / Windows / X11:** Unsupported.
|
||||
///
|
||||
/// [`can_create_surfaces()`]: Self::can_create_surfaces()
|
||||
/// [`destroy_surfaces()`]: Self::destroy_surfaces()
|
||||
/// [`can_create_surfaces()`]: Self::can_create_surfaces
|
||||
/// [`destroy_surfaces()`]: Self::destroy_surfaces
|
||||
fn destroy_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
|
||||
let _ = event_loop;
|
||||
}
|
||||
@@ -345,15 +325,6 @@ pub trait ApplicationHandler {
|
||||
fn memory_warning(&mut self, event_loop: &dyn ActiveEventLoop) {
|
||||
let _ = event_loop;
|
||||
}
|
||||
|
||||
/// The macOS-specific handler.
|
||||
///
|
||||
/// The return value from this should not change at runtime.
|
||||
#[cfg(any(docsrs, macos_platform))]
|
||||
#[inline(always)]
|
||||
fn macos_handler(&mut self) -> Option<&mut dyn ApplicationHandlerExtMacOS> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[deny(clippy::missing_trait_methods)]
|
||||
@@ -392,7 +363,7 @@ impl<A: ?Sized + ApplicationHandler> ApplicationHandler for &mut A {
|
||||
fn device_event(
|
||||
&mut self,
|
||||
event_loop: &dyn ActiveEventLoop,
|
||||
device_id: Option<DeviceId>,
|
||||
device_id: DeviceId,
|
||||
event: DeviceEvent,
|
||||
) {
|
||||
(**self).device_event(event_loop, device_id, event);
|
||||
@@ -422,12 +393,6 @@ impl<A: ?Sized + ApplicationHandler> ApplicationHandler for &mut A {
|
||||
fn memory_warning(&mut self, event_loop: &dyn ActiveEventLoop) {
|
||||
(**self).memory_warning(event_loop);
|
||||
}
|
||||
|
||||
#[cfg(any(docsrs, macos_platform))]
|
||||
#[inline]
|
||||
fn macos_handler(&mut self) -> Option<&mut dyn ApplicationHandlerExtMacOS> {
|
||||
(**self).macos_handler()
|
||||
}
|
||||
}
|
||||
|
||||
#[deny(clippy::missing_trait_methods)]
|
||||
@@ -466,7 +431,7 @@ impl<A: ?Sized + ApplicationHandler> ApplicationHandler for Box<A> {
|
||||
fn device_event(
|
||||
&mut self,
|
||||
event_loop: &dyn ActiveEventLoop,
|
||||
device_id: Option<DeviceId>,
|
||||
device_id: DeviceId,
|
||||
event: DeviceEvent,
|
||||
) {
|
||||
(**self).device_event(event_loop, device_id, event);
|
||||
@@ -496,10 +461,4 @@ impl<A: ?Sized + ApplicationHandler> ApplicationHandler for Box<A> {
|
||||
fn memory_warning(&mut self, event_loop: &dyn ActiveEventLoop) {
|
||||
(**self).memory_warning(event_loop);
|
||||
}
|
||||
|
||||
#[cfg(any(docsrs, macos_platform))]
|
||||
#[inline]
|
||||
fn macos_handler(&mut self) -> Option<&mut dyn ApplicationHandlerExtMacOS> {
|
||||
(**self).macos_handler()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,18 +56,15 @@ changelog entry.
|
||||
|
||||
Keep in mind that handles do not auto-upgrade after permissions are granted and have to be
|
||||
re-created to make full use of this feature.
|
||||
- Add `Touch::finger_id` with a new type `FingerId`.
|
||||
- On Web and Windows, add `FingerIdExt*::is_primary()`, exposing a way to determine
|
||||
the primary finger in a multi-touch interaction.
|
||||
- Implement `Clone`, `Copy`, `Debug`, `Deserialize`, `Eq`, `Hash`, `Ord`, `PartialEq`, `PartialOrd`
|
||||
and `Serialize` on many types.
|
||||
- Add `MonitorHandle::current_video_mode()`.
|
||||
- Add basic iOS IME support. The soft keyboard can now be shown using `Window::set_ime_allowed`.
|
||||
- Add `ApplicationHandlerExtMacOS` trait, and a `macos_handler` method to `ApplicationHandler` which returns a `dyn ApplicationHandlerExtMacOS` which allows for macOS specific extensions to winit.
|
||||
- Add a `standard_key_binding` method to the `ApplicationHandlerExtMacOS` trait. This allows handling of standard keybindings such as "go to end of line" on macOS.
|
||||
- On macOS, add `WindowExtMacOS::set_borderless_game` and `WindowAttributesExtMacOS::with_borderless_game`
|
||||
to fully disable the menu bar and dock in Borderless Fullscreen as commonly done in games.
|
||||
- Add `WindowId::into_raw()` and `from_raw()`.
|
||||
- Add `PointerKind`, `PointerSource`, `ButtonSource`, `FingerId` and `position` to all pointer
|
||||
events as part of the pointer event overhaul.
|
||||
- Add `DeviceId::into_raw()` and `from_raw()`.
|
||||
|
||||
### Changed
|
||||
|
||||
@@ -86,14 +83,14 @@ changelog entry.
|
||||
- Changed `EventLoopProxy::send_event` to `EventLoopProxy::wake_up`, it now
|
||||
only wakes up the loop.
|
||||
- On X11, implement smooth resizing through the sync extension API.
|
||||
- `ApplicationHandler::can_create|destroy_surfaces()` was split off from
|
||||
- `ApplicationHandler::create|destroy_surfaces()` was split off from
|
||||
`ApplicationHandler::resumed/suspended()`.
|
||||
|
||||
`ApplicationHandler::can_create_surfaces()` should, for portability reasons
|
||||
to Android, be the only place to create render surfaces.
|
||||
|
||||
`ApplicationHandler::resumed/suspended()` are now only emitted by iOS, Web
|
||||
and Android, and now signify actually resuming/suspending the application.
|
||||
`ApplicationHandler::resumed/suspended()` are now only emitted by iOS and Web
|
||||
and now signify actually resuming/suspending the application.
|
||||
- Rename `platform::web::*ExtWebSys` to `*ExtWeb`.
|
||||
- Change signature of `EventLoop::run_app`, `EventLoopExtPumpEvents::pump_app_events` and
|
||||
`EventLoopExtRunOnDemand::run_app_on_demand` to accept a `impl ApplicationHandler` directly,
|
||||
@@ -127,31 +124,6 @@ changelog entry.
|
||||
- `Window::set_max_inner_size` to `set_max_surface_size`.
|
||||
|
||||
To migrate, you can probably just replace all instances of `inner_size` with `surface_size` in your codebase.
|
||||
- Every event carrying a `DeviceId` now uses `Option<DeviceId>` instead. A `None` value signifies that the
|
||||
device can't be uniquely identified.
|
||||
- Pointer `WindowEvent`s were overhauled. The new events can handle any type of pointer, serving as
|
||||
a single pointer input source. Now your application can handle any pointer type without having to
|
||||
explicitly handle e.g. `Touch`:
|
||||
- Rename `CursorMoved` to `PointerMoved`.
|
||||
- Rename `CursorEntered` to `PointerEntered`.
|
||||
- Rename `CursorLeft` to `PointerLeft`.
|
||||
- Rename `MouseInput` to `PointerButton`.
|
||||
- Add `position` to every `PointerEvent`.
|
||||
- `PointerMoved` is **not sent** after `PointerEntered` anymore.
|
||||
- Remove `Touch`, which is folded into the `Pointer*` events.
|
||||
- New `PointerKind` added to `PointerEntered` and `PointerLeft`, signifying which pointer type is
|
||||
the source of this event.
|
||||
- New `PointerSource` added to `PointerMoved`, similar to `PointerKind` but holding additional
|
||||
data.
|
||||
- New `ButtonSource` added to `PointerButton`, similar to `PointerKind` but holding pointer type
|
||||
specific buttons. Use `ButtonSource::mouse_button()` to easily normalize any pointer button
|
||||
type to a generic mouse button.
|
||||
- New `FingerId` added to `PointerKind::Touch` and `PointerSource::Touch` able to uniquely
|
||||
identify a finger in a multi-touch interaction. Replaces the old `Touch::id`.
|
||||
- On Web and Windows, add `FingerIdExt*::is_primary()`, exposing a way to determine
|
||||
the primary finger in a multi-touch interaction.
|
||||
- In the same spirit rename `DeviceEvent::MouseMotion` to `PointerMotion`.
|
||||
- Remove `Force::Calibrated::altitude_angle`.
|
||||
|
||||
### Removed
|
||||
|
||||
@@ -174,21 +146,11 @@ changelog entry.
|
||||
v0.5 support. v0.6 remains in place and is enabled by default.
|
||||
- Remove `DeviceEvent::Added` and `DeviceEvent::Removed`.
|
||||
- Remove `DeviceEvent::Motion` and `WindowEvent::AxisMotion`.
|
||||
- Remove `Touch::id` in favor of `Touch::finger_id`.
|
||||
- Remove `MonitorHandle::size()` and `refresh_rate_millihertz()` in favor of
|
||||
`MonitorHandle::current_video_mode()`.
|
||||
- On Android, remove all `MonitorHandle` support instead of emitting false data.
|
||||
- Remove `impl From<u64> for WindowId` and `impl From<WindowId> for u64`. Replaced with
|
||||
`WindowId::into_raw()` and `from_raw()`.
|
||||
- Remove `dummy()` from `WindowId` and `DeviceId`.
|
||||
- Remove `WindowEvent::Touch` and `Touch` in favor of the new `PointerKind`, `PointerSource` and
|
||||
`ButtonSource` as part of the new pointer event overhaul.
|
||||
- Remove `Force::altitude_angle`.
|
||||
|
||||
### Fixed
|
||||
|
||||
- On Orbital, `MonitorHandle::name()` now returns `None` instead of a dummy name.
|
||||
- On macOS, fix `WindowEvent::Moved` sometimes being triggered unnecessarily on resize.
|
||||
- On macOS, package manifest definitions of `LSUIElement` will no longer be overridden with the
|
||||
default activation policy, unless explicitly provided during initialization.
|
||||
- On macOS, fix crash when calling `drag_window()` without a left click present.
|
||||
- On X11, key events forward to IME anyway, even when it's disabled.
|
||||
|
||||
488
src/event.rs
488
src/event.rs
@@ -63,51 +63,51 @@ use crate::window::{ActivationToken, Theme, WindowId};
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub(crate) enum Event {
|
||||
/// See [`ApplicationHandler::new_events()`] for details.
|
||||
/// See [`ApplicationHandler::new_events`] for details.
|
||||
///
|
||||
/// [`ApplicationHandler::new_events()`]: crate::application::ApplicationHandler::new_events()
|
||||
/// [`ApplicationHandler::new_events`]: crate::application::ApplicationHandler::new_events
|
||||
NewEvents(StartCause),
|
||||
|
||||
/// See [`ApplicationHandler::window_event()`] for details.
|
||||
/// See [`ApplicationHandler::window_event`] for details.
|
||||
///
|
||||
/// [`ApplicationHandler::window_event()`]: crate::application::ApplicationHandler::window_event()
|
||||
/// [`ApplicationHandler::window_event`]: crate::application::ApplicationHandler::window_event
|
||||
#[allow(clippy::enum_variant_names)]
|
||||
WindowEvent { window_id: WindowId, event: WindowEvent },
|
||||
|
||||
/// See [`ApplicationHandler::device_event()`] for details.
|
||||
/// See [`ApplicationHandler::device_event`] for details.
|
||||
///
|
||||
/// [`ApplicationHandler::device_event()`]: crate::application::ApplicationHandler::device_event()
|
||||
/// [`ApplicationHandler::device_event`]: crate::application::ApplicationHandler::device_event
|
||||
#[allow(clippy::enum_variant_names)]
|
||||
DeviceEvent { device_id: Option<DeviceId>, event: DeviceEvent },
|
||||
DeviceEvent { device_id: DeviceId, event: DeviceEvent },
|
||||
|
||||
/// See [`ApplicationHandler::suspended()`] for details.
|
||||
/// See [`ApplicationHandler::suspended`] for details.
|
||||
///
|
||||
/// [`ApplicationHandler::suspended()`]: crate::application::ApplicationHandler::suspended()
|
||||
/// [`ApplicationHandler::suspended`]: crate::application::ApplicationHandler::suspended
|
||||
Suspended,
|
||||
|
||||
/// See [`ApplicationHandler::can_create_surfaces()`] for details.
|
||||
/// See [`ApplicationHandler::can_create_surfaces`] for details.
|
||||
///
|
||||
/// [`ApplicationHandler::can_create_surfaces()`]: crate::application::ApplicationHandler::can_create_surfaces()
|
||||
/// [`ApplicationHandler::can_create_surfaces`]: crate::application::ApplicationHandler::can_create_surfaces
|
||||
CreateSurfaces,
|
||||
|
||||
/// See [`ApplicationHandler::resumed()`] for details.
|
||||
/// See [`ApplicationHandler::resumed`] for details.
|
||||
///
|
||||
/// [`ApplicationHandler::resumed()`]: crate::application::ApplicationHandler::resumed()
|
||||
/// [`ApplicationHandler::resumed`]: crate::application::ApplicationHandler::resumed
|
||||
Resumed,
|
||||
|
||||
/// See [`ApplicationHandler::about_to_wait()`] for details.
|
||||
/// See [`ApplicationHandler::about_to_wait`] for details.
|
||||
///
|
||||
/// [`ApplicationHandler::about_to_wait()`]: crate::application::ApplicationHandler::about_to_wait()
|
||||
/// [`ApplicationHandler::about_to_wait`]: crate::application::ApplicationHandler::about_to_wait
|
||||
AboutToWait,
|
||||
|
||||
/// See [`ApplicationHandler::exiting()`] for details.
|
||||
/// See [`ApplicationHandler::exiting`] for details.
|
||||
///
|
||||
/// [`ApplicationHandler::exiting()`]: crate::application::ApplicationHandler::exiting()
|
||||
/// [`ApplicationHandler::exiting`]: crate::application::ApplicationHandler::exiting
|
||||
LoopExiting,
|
||||
|
||||
/// See [`ApplicationHandler::memory_warning()`] for details.
|
||||
/// See [`ApplicationHandler::memory_warning`] for details.
|
||||
///
|
||||
/// [`ApplicationHandler::memory_warning()`]: crate::application::ApplicationHandler::memory_warning()
|
||||
/// [`ApplicationHandler::memory_warning`]: crate::application::ApplicationHandler::memory_warning
|
||||
MemoryWarning,
|
||||
|
||||
/// User requested a wake up.
|
||||
@@ -199,7 +199,7 @@ pub enum WindowEvent {
|
||||
/// numpad keys act as if NumLock wasn't active. When this is used, the OS sends fake key
|
||||
/// events which are not marked as `is_synthetic`.
|
||||
KeyboardInput {
|
||||
device_id: Option<DeviceId>,
|
||||
device_id: DeviceId,
|
||||
event: KeyEvent,
|
||||
|
||||
/// If `true`, the event was generated synthetically by winit
|
||||
@@ -226,89 +226,52 @@ pub enum WindowEvent {
|
||||
/// - **iOS / Android / Web / Orbital:** Unsupported.
|
||||
Ime(Ime),
|
||||
|
||||
/// The pointer has moved on the window.
|
||||
PointerMoved {
|
||||
device_id: Option<DeviceId>,
|
||||
/// The cursor has moved on the window.
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// - **Web:** Doesn't take into account CSS [`border`], [`padding`], or [`transform`].
|
||||
///
|
||||
/// [`border`]: https://developer.mozilla.org/en-US/docs/Web/CSS/border
|
||||
/// [`padding`]: https://developer.mozilla.org/en-US/docs/Web/CSS/padding
|
||||
/// [`transform`]: https://developer.mozilla.org/en-US/docs/Web/CSS/transform
|
||||
CursorMoved {
|
||||
device_id: DeviceId,
|
||||
|
||||
/// (x,y) coordinates in pixels relative to the top-left corner of the window. Because the
|
||||
/// range of this data is limited by the display area and it may have been
|
||||
/// transformed by the OS to implement effects such as pointer acceleration, it
|
||||
/// should not be used to implement non-pointer-like interactions such as 3D camera
|
||||
/// control. For that, consider [`DeviceEvent::PointerMotion`].
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// **Web:** Doesn't take into account CSS [`border`], [`padding`], or [`transform`].
|
||||
///
|
||||
/// [`border`]: https://developer.mozilla.org/en-US/docs/Web/CSS/border
|
||||
/// [`padding`]: https://developer.mozilla.org/en-US/docs/Web/CSS/padding
|
||||
/// [`transform`]: https://developer.mozilla.org/en-US/docs/Web/CSS/transform
|
||||
/// (x,y) coords in pixels relative to the top-left corner of the window. Because the range
|
||||
/// of this data is limited by the display area and it may have been transformed by
|
||||
/// the OS to implement effects such as cursor acceleration, it should not be used
|
||||
/// to implement non-cursor-like interactions such as 3D camera control.
|
||||
position: PhysicalPosition<f64>,
|
||||
|
||||
source: PointerSource,
|
||||
},
|
||||
|
||||
/// The pointer has entered the window.
|
||||
PointerEntered {
|
||||
device_id: Option<DeviceId>,
|
||||
/// The cursor has entered the window.
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// - **Web:** Doesn't take into account CSS [`border`], [`padding`], or [`transform`].
|
||||
///
|
||||
/// [`border`]: https://developer.mozilla.org/en-US/docs/Web/CSS/border
|
||||
/// [`padding`]: https://developer.mozilla.org/en-US/docs/Web/CSS/padding
|
||||
/// [`transform`]: https://developer.mozilla.org/en-US/docs/Web/CSS/transform
|
||||
CursorEntered { device_id: DeviceId },
|
||||
|
||||
/// The position of the pointer when it entered the window.
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// - **Orbital: Always emits `(0., 0.)`.
|
||||
/// - **Web:** Doesn't take into account CSS [`border`], [`padding`], or [`transform`].
|
||||
///
|
||||
/// [`border`]: https://developer.mozilla.org/en-US/docs/Web/CSS/border
|
||||
/// [`padding`]: https://developer.mozilla.org/en-US/docs/Web/CSS/padding
|
||||
/// [`transform`]: https://developer.mozilla.org/en-US/docs/Web/CSS/transform
|
||||
position: PhysicalPosition<f64>,
|
||||
|
||||
kind: PointerKind,
|
||||
},
|
||||
|
||||
/// The pointer has left the window.
|
||||
PointerLeft {
|
||||
device_id: Option<DeviceId>,
|
||||
|
||||
/// The position of the pointer when it left the window. The position reported can be
|
||||
/// outside the bounds of the window.
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// - **Orbital/Windows:** Always emits [`None`].
|
||||
/// - **Web:** Doesn't take into account CSS [`border`], [`padding`], or [`transform`].
|
||||
///
|
||||
/// [`border`]: https://developer.mozilla.org/en-US/docs/Web/CSS/border
|
||||
/// [`padding`]: https://developer.mozilla.org/en-US/docs/Web/CSS/padding
|
||||
/// [`transform`]: https://developer.mozilla.org/en-US/docs/Web/CSS/transform
|
||||
position: Option<PhysicalPosition<f64>>,
|
||||
|
||||
kind: PointerKind,
|
||||
},
|
||||
/// The cursor has left the window.
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// - **Web:** Doesn't take into account CSS [`border`], [`padding`], or [`transform`].
|
||||
///
|
||||
/// [`border`]: https://developer.mozilla.org/en-US/docs/Web/CSS/border
|
||||
/// [`padding`]: https://developer.mozilla.org/en-US/docs/Web/CSS/padding
|
||||
/// [`transform`]: https://developer.mozilla.org/en-US/docs/Web/CSS/transform
|
||||
CursorLeft { device_id: DeviceId },
|
||||
|
||||
/// A mouse wheel movement or touchpad scroll occurred.
|
||||
MouseWheel { device_id: Option<DeviceId>, delta: MouseScrollDelta, phase: TouchPhase },
|
||||
MouseWheel { device_id: DeviceId, delta: MouseScrollDelta, phase: TouchPhase },
|
||||
|
||||
/// An mouse button press has been received.
|
||||
PointerButton {
|
||||
device_id: Option<DeviceId>,
|
||||
state: ElementState,
|
||||
|
||||
/// The position of the pointer when the button was pressed.
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// - **Orbital: Always emits `(0., 0.)`.
|
||||
/// - **Web:** Doesn't take into account CSS [`border`], [`padding`], or [`transform`].
|
||||
///
|
||||
/// [`border`]: https://developer.mozilla.org/en-US/docs/Web/CSS/border
|
||||
/// [`padding`]: https://developer.mozilla.org/en-US/docs/Web/CSS/padding
|
||||
/// [`transform`]: https://developer.mozilla.org/en-US/docs/Web/CSS/transform
|
||||
position: PhysicalPosition<f64>,
|
||||
|
||||
button: ButtonSource,
|
||||
},
|
||||
MouseInput { device_id: DeviceId, state: ElementState, button: MouseButton },
|
||||
|
||||
/// Two-finger pinch gesture, often used for magnification.
|
||||
///
|
||||
@@ -317,7 +280,7 @@ pub enum WindowEvent {
|
||||
/// - Only available on **macOS** and **iOS**.
|
||||
/// - On iOS, not recognized by default. It must be enabled when needed.
|
||||
PinchGesture {
|
||||
device_id: Option<DeviceId>,
|
||||
device_id: DeviceId,
|
||||
/// Positive values indicate magnification (zooming in) and negative
|
||||
/// values indicate shrinking (zooming out).
|
||||
///
|
||||
@@ -333,7 +296,7 @@ pub enum WindowEvent {
|
||||
/// - Only available on **iOS**.
|
||||
/// - On iOS, not recognized by default. It must be enabled when needed.
|
||||
PanGesture {
|
||||
device_id: Option<DeviceId>,
|
||||
device_id: DeviceId,
|
||||
/// Change in pixels of pan gesture from last update.
|
||||
delta: PhysicalPosition<f32>,
|
||||
phase: TouchPhase,
|
||||
@@ -357,7 +320,7 @@ pub enum WindowEvent {
|
||||
///
|
||||
/// - Only available on **macOS 10.8** and later, and **iOS**.
|
||||
/// - On iOS, not recognized by default. It must be enabled when needed.
|
||||
DoubleTapGesture { device_id: Option<DeviceId> },
|
||||
DoubleTapGesture { device_id: DeviceId },
|
||||
|
||||
/// Two-finger rotation gesture.
|
||||
///
|
||||
@@ -369,7 +332,7 @@ pub enum WindowEvent {
|
||||
/// - Only available on **macOS** and **iOS**.
|
||||
/// - On iOS, not recognized by default. It must be enabled when needed.
|
||||
RotationGesture {
|
||||
device_id: Option<DeviceId>,
|
||||
device_id: DeviceId,
|
||||
/// change in rotation in degrees
|
||||
delta: f32,
|
||||
phase: TouchPhase,
|
||||
@@ -380,7 +343,19 @@ pub enum WindowEvent {
|
||||
/// At the moment, only supported on Apple forcetouch-capable macbooks.
|
||||
/// The parameters are: pressure level (value between 0 and 1 representing how hard the
|
||||
/// touchpad is being pressed) and stage (integer representing the click level).
|
||||
TouchpadPressure { device_id: Option<DeviceId>, pressure: f32, stage: i64 },
|
||||
TouchpadPressure { device_id: DeviceId, pressure: f32, stage: i64 },
|
||||
|
||||
/// Touch event has been received
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// - **Web:** Doesn't take into account CSS [`border`], [`padding`], or [`transform`].
|
||||
/// - **macOS:** Unsupported.
|
||||
///
|
||||
/// [`border`]: https://developer.mozilla.org/en-US/docs/Web/CSS/border
|
||||
/// [`padding`]: https://developer.mozilla.org/en-US/docs/Web/CSS/padding
|
||||
/// [`transform`]: https://developer.mozilla.org/en-US/docs/Web/CSS/transform
|
||||
Touch(Touch),
|
||||
|
||||
/// The window's scale factor has changed.
|
||||
///
|
||||
@@ -455,129 +430,6 @@ pub enum WindowEvent {
|
||||
RedrawRequested,
|
||||
}
|
||||
|
||||
/// Represents the kind type of a pointer event.
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// **Wayland/X11:** [`Unknown`](Self::Unknown) device types are converted to known variants by the
|
||||
/// system.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum PointerKind {
|
||||
Mouse,
|
||||
/// See [`PointerSource::Touch`] for more details.
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// **macOS:** Unsupported.
|
||||
Touch(FingerId),
|
||||
Unknown,
|
||||
}
|
||||
|
||||
/// Represents the pointer type and its data for a pointer event.
|
||||
///
|
||||
/// **Wayland/X11:** [`Unknown`](Self::Unknown) device types are converted to known variants by the
|
||||
/// system.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum PointerSource {
|
||||
Mouse,
|
||||
/// Represents a touch event.
|
||||
///
|
||||
/// Every time the user touches the screen, a [`WindowEvent::PointerEntered`] and a
|
||||
/// [`WindowEvent::PointerButton`] with [`ElementState::Pressed`] event with an unique
|
||||
/// identifier for the finger is emitted. When a finger is lifted, a
|
||||
/// [`WindowEvent::PointerButton`] with [`ElementState::Released`] and a
|
||||
/// [`WindowEvent::PointerLeft`] event is generated with the same [`FingerId`].
|
||||
///
|
||||
/// After a [`WindowEvent::PointerEntered`] event has been emitted, there may be zero or more
|
||||
/// [`WindowEvent::PointerMoved`] events when the finger is moved or the touch pressure
|
||||
/// changes.
|
||||
///
|
||||
/// A [`WindowEvent::PointerLeft`] without a [`WindowEvent::PointerButton`] with
|
||||
/// [`ElementState::Released`] event is emitted when the system has canceled tracking this
|
||||
/// touch, such as when the window loses focus, or on mobile devices if the user moves the
|
||||
/// device against their face.
|
||||
///
|
||||
/// The [`FingerId`] may be reused by the system after a [`WindowEvent::PointerLeft`] event.
|
||||
/// The user should assume that a new [`WindowEvent::PointerEntered`] event received with the
|
||||
/// same ID has nothing to do with the old finger and is a new finger.
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// **macOS:** Unsupported.
|
||||
Touch {
|
||||
finger_id: FingerId,
|
||||
|
||||
/// Describes how hard the screen was pressed. May be [`None`] if the hardware does not
|
||||
/// support pressure sensitivity.
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// - **MacOS / Orbital / Wayland / X11:** Always emits [`None`].
|
||||
/// - **Android:** Will never be [`None`]. If the device doesn't support pressure
|
||||
/// sensitivity, force will either be 0.0 or 1.0. Also see the
|
||||
/// [android documentation](https://developer.android.com/reference/android/view/MotionEvent#AXIS_PRESSURE).#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
/// - **Web:** Will never be [`None`]. If the device doesn't support pressure sensitivity,
|
||||
/// force will be 0.5 when a button is pressed or 0.0 otherwise.
|
||||
force: Option<Force>,
|
||||
},
|
||||
Unknown,
|
||||
}
|
||||
|
||||
impl From<PointerSource> for PointerKind {
|
||||
fn from(source: PointerSource) -> Self {
|
||||
match source {
|
||||
PointerSource::Mouse => Self::Mouse,
|
||||
PointerSource::Touch { finger_id, .. } => Self::Touch(finger_id),
|
||||
PointerSource::Unknown => Self::Unknown,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents the pointer type of a [`WindowEvent::PointerButton`].
|
||||
///
|
||||
/// **Wayland/X11:** [`Unknown`](Self::Unknown) device types are converted to known variants by the
|
||||
/// system.
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum ButtonSource {
|
||||
Mouse(MouseButton),
|
||||
/// See [`PointerSource::Touch`] for more details.
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// **macOS:** Unsupported.
|
||||
Touch {
|
||||
finger_id: FingerId,
|
||||
force: Option<Force>,
|
||||
},
|
||||
Unknown(u16),
|
||||
}
|
||||
|
||||
impl ButtonSource {
|
||||
/// Convert any [`ButtonSource`] to an equivalent [`MouseButton`]. If a pointer type has no
|
||||
/// special handling in an application, this method can be used to handle it like any generic
|
||||
/// mouse input.
|
||||
pub fn mouse_button(self) -> MouseButton {
|
||||
match self {
|
||||
ButtonSource::Mouse(mouse) => mouse,
|
||||
ButtonSource::Touch { .. } => MouseButton::Left,
|
||||
ButtonSource::Unknown(button) => match button {
|
||||
0 => MouseButton::Left,
|
||||
1 => MouseButton::Middle,
|
||||
2 => MouseButton::Right,
|
||||
3 => MouseButton::Back,
|
||||
4 => MouseButton::Forward,
|
||||
_ => MouseButton::Other(button),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<MouseButton> for ButtonSource {
|
||||
fn from(mouse: MouseButton) -> Self {
|
||||
Self::Mouse(mouse)
|
||||
}
|
||||
}
|
||||
|
||||
/// Identifier of an input device.
|
||||
///
|
||||
/// Whenever you receive an event arising from a particular input device, this event contains a
|
||||
@@ -585,23 +437,24 @@ impl From<MouseButton> for ButtonSource {
|
||||
/// 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(i64);
|
||||
pub struct DeviceId(pub(crate) platform_impl::DeviceId);
|
||||
|
||||
impl Default for DeviceId {
|
||||
fn default() -> Self {
|
||||
Self::dummy()
|
||||
}
|
||||
}
|
||||
|
||||
impl DeviceId {
|
||||
/// Convert the [`DeviceId`] into the underlying integer.
|
||||
/// Returns a dummy id, useful for unit testing.
|
||||
///
|
||||
/// This is useful if you need to pass the ID across an FFI boundary, or store it in an atomic.
|
||||
#[allow(dead_code)]
|
||||
pub(crate) const fn into_raw(self) -> i64 {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Construct a [`DeviceId`] from the underlying integer.
|
||||
/// # Notes
|
||||
///
|
||||
/// This should only be called with integers returned from [`DeviceId::into_raw`].
|
||||
#[allow(dead_code)]
|
||||
pub(crate) const fn from_raw(id: i64) -> Self {
|
||||
Self(id)
|
||||
/// 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`.
|
||||
pub const fn dummy() -> Self {
|
||||
DeviceId(platform_impl::DeviceId::dummy())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -613,8 +466,14 @@ impl DeviceId {
|
||||
pub struct FingerId(pub(crate) platform_impl::FingerId);
|
||||
|
||||
impl FingerId {
|
||||
#[cfg(test)]
|
||||
pub(crate) const fn dummy() -> Self {
|
||||
/// Returns a dummy id, useful for unit testing.
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
/// 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 `FingerId`.
|
||||
pub const fn dummy() -> Self {
|
||||
FingerId(platform_impl::FingerId::dummy())
|
||||
}
|
||||
}
|
||||
@@ -624,7 +483,7 @@ impl FingerId {
|
||||
/// Useful for interactions that diverge significantly from a conventional 2D GUI, such as 3D camera
|
||||
/// or first-person game controls. Many physical actions, such as mouse movement, can produce both
|
||||
/// device and window events. Because window events typically arise from virtual devices
|
||||
/// (corresponding to GUI pointers and keyboard focus) the device IDs may not match.
|
||||
/// (corresponding to GUI cursors and keyboard focus) the device IDs may not match.
|
||||
///
|
||||
/// Note that these events are delivered regardless of input focus.
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
@@ -632,7 +491,7 @@ pub enum DeviceEvent {
|
||||
/// Change in physical position of a pointing device.
|
||||
///
|
||||
/// This represents raw, unfiltered physical motion. Not to be confused with
|
||||
/// [`WindowEvent::PointerMoved`].
|
||||
/// [`WindowEvent::CursorMoved`].
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
@@ -649,7 +508,7 @@ pub enum DeviceEvent {
|
||||
///
|
||||
#[rustfmt::skip]
|
||||
/// [`CursorGrabMode::Locked`]: crate::window::CursorGrabMode::Locked
|
||||
PointerMotion {
|
||||
MouseMotion {
|
||||
/// (x, y) change in position in unspecified units.
|
||||
///
|
||||
/// Different devices may use different units.
|
||||
@@ -978,6 +837,50 @@ pub enum TouchPhase {
|
||||
Cancelled,
|
||||
}
|
||||
|
||||
/// Represents a touch event
|
||||
///
|
||||
/// Every time the user touches the screen, a new [`TouchPhase::Started`] event with an unique
|
||||
/// identifier for the finger is generated. When the finger is lifted, an [`TouchPhase::Ended`]
|
||||
/// event is generated with the same finger id.
|
||||
///
|
||||
/// After a `Started` event has been emitted, there may be zero or more `Move`
|
||||
/// events when the finger is moved or the touch pressure changes.
|
||||
///
|
||||
/// The finger id may be reused by the system after an `Ended` event. The user
|
||||
/// should assume that a new `Started` event received with the same id has nothing
|
||||
/// to do with the old finger and is a new finger.
|
||||
///
|
||||
/// A [`TouchPhase::Cancelled`] event is emitted when the system has canceled tracking this
|
||||
/// touch, such as when the window loses focus, or on iOS if the user moves the
|
||||
/// device against their face.
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// - **Web:** Doesn't take into account CSS [`border`], [`padding`], or [`transform`].
|
||||
/// - **macOS:** Unsupported.
|
||||
///
|
||||
/// [`border`]: https://developer.mozilla.org/en-US/docs/Web/CSS/border
|
||||
/// [`padding`]: https://developer.mozilla.org/en-US/docs/Web/CSS/padding
|
||||
/// [`transform`]: https://developer.mozilla.org/en-US/docs/Web/CSS/transform
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct Touch {
|
||||
pub device_id: DeviceId,
|
||||
pub phase: TouchPhase,
|
||||
pub location: PhysicalPosition<f64>,
|
||||
/// Describes how hard the screen was pressed. May be `None` if the platform
|
||||
/// does not support pressure sensitivity.
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// - Only available on **iOS** 9.0+, **Windows** 8+, **Web**, and **Android**.
|
||||
/// - **Android**: This will never be [None]. If the device doesn't support pressure
|
||||
/// sensitivity, force will either be 0.0 or 1.0. Also see the
|
||||
/// [android documentation](https://developer.android.com/reference/android/view/MotionEvent#AXIS_PRESSURE).
|
||||
pub force: Option<Force>,
|
||||
/// Unique identifier of a finger.
|
||||
pub finger_id: FingerId,
|
||||
}
|
||||
|
||||
/// Describes the force of a touch event
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
@@ -998,6 +901,12 @@ pub enum Force {
|
||||
/// The value of this field is sufficiently high to provide a wide
|
||||
/// dynamic range for values of the `force` field.
|
||||
max_possible_force: f64,
|
||||
/// The altitude (in radians) of the stylus.
|
||||
///
|
||||
/// A value of 0 radians indicates that the stylus is parallel to the
|
||||
/// surface. The value of this property is Pi/2 when the stylus is
|
||||
/// perpendicular to the surface.
|
||||
altitude_angle: Option<f64>,
|
||||
},
|
||||
/// If the platform reports the force as normalized, we have no way of
|
||||
/// knowing how much pressure 1.0 corresponds to – we know it's the maximum
|
||||
@@ -1014,7 +923,13 @@ impl Force {
|
||||
/// consistent across devices.
|
||||
pub fn normalized(&self) -> f64 {
|
||||
match self {
|
||||
Force::Calibrated { force, max_possible_force } => force / max_possible_force,
|
||||
Force::Calibrated { force, max_possible_force, altitude_angle } => {
|
||||
let force = match altitude_angle {
|
||||
Some(altitude_angle) => force / altitude_angle.sin(),
|
||||
None => *force,
|
||||
};
|
||||
force / max_possible_force
|
||||
},
|
||||
Force::Normalized(force) => *force,
|
||||
}
|
||||
}
|
||||
@@ -1130,6 +1045,7 @@ mod tests {
|
||||
($closure:expr) => {{
|
||||
#[allow(unused_mut)]
|
||||
let mut x = $closure;
|
||||
let did = event::DeviceId::dummy();
|
||||
let fid = event::FingerId::dummy();
|
||||
|
||||
#[allow(deprecated)]
|
||||
@@ -1137,11 +1053,10 @@ mod tests {
|
||||
use crate::event::Event::*;
|
||||
use crate::event::Ime::Enabled;
|
||||
use crate::event::WindowEvent::*;
|
||||
use crate::event::{PointerKind, PointerSource};
|
||||
use crate::window::WindowId;
|
||||
|
||||
// Mainline events.
|
||||
let wid = WindowId::from_raw(0);
|
||||
let wid = WindowId::dummy();
|
||||
x(NewEvents(event::StartCause::Init));
|
||||
x(AboutToWait);
|
||||
x(LoopExiting);
|
||||
@@ -1160,59 +1075,44 @@ mod tests {
|
||||
with_window_event(HoveredFile("x.txt".into()));
|
||||
with_window_event(HoveredFileCancelled);
|
||||
with_window_event(Ime(Enabled));
|
||||
with_window_event(PointerMoved {
|
||||
device_id: None,
|
||||
position: (0, 0).into(),
|
||||
source: PointerSource::Mouse,
|
||||
});
|
||||
with_window_event(CursorMoved { device_id: did, position: (0, 0).into() });
|
||||
with_window_event(ModifiersChanged(event::Modifiers::default()));
|
||||
with_window_event(PointerEntered {
|
||||
device_id: None,
|
||||
position: (0, 0).into(),
|
||||
kind: PointerKind::Mouse,
|
||||
});
|
||||
with_window_event(PointerLeft {
|
||||
device_id: None,
|
||||
position: Some((0, 0).into()),
|
||||
kind: PointerKind::Mouse,
|
||||
});
|
||||
with_window_event(CursorEntered { device_id: did });
|
||||
with_window_event(CursorLeft { device_id: did });
|
||||
with_window_event(MouseWheel {
|
||||
device_id: None,
|
||||
device_id: did,
|
||||
delta: event::MouseScrollDelta::LineDelta(0.0, 0.0),
|
||||
phase: event::TouchPhase::Started,
|
||||
});
|
||||
with_window_event(PointerButton {
|
||||
device_id: None,
|
||||
with_window_event(MouseInput {
|
||||
device_id: did,
|
||||
state: event::ElementState::Pressed,
|
||||
position: (0, 0).into(),
|
||||
button: event::MouseButton::Other(0).into(),
|
||||
});
|
||||
with_window_event(PointerButton {
|
||||
device_id: None,
|
||||
state: event::ElementState::Released,
|
||||
position: (0, 0).into(),
|
||||
button: event::ButtonSource::Touch {
|
||||
finger_id: fid,
|
||||
force: Some(event::Force::Normalized(0.0)),
|
||||
},
|
||||
button: event::MouseButton::Other(0),
|
||||
});
|
||||
with_window_event(PinchGesture {
|
||||
device_id: None,
|
||||
device_id: did,
|
||||
delta: 0.0,
|
||||
phase: event::TouchPhase::Started,
|
||||
});
|
||||
with_window_event(DoubleTapGesture { device_id: None });
|
||||
with_window_event(DoubleTapGesture { device_id: did });
|
||||
with_window_event(RotationGesture {
|
||||
device_id: None,
|
||||
device_id: did,
|
||||
delta: 0.0,
|
||||
phase: event::TouchPhase::Started,
|
||||
});
|
||||
with_window_event(PanGesture {
|
||||
device_id: None,
|
||||
device_id: did,
|
||||
delta: PhysicalPosition::<f32>::new(0.0, 0.0),
|
||||
phase: event::TouchPhase::Started,
|
||||
});
|
||||
with_window_event(TouchpadPressure { device_id: None, pressure: 0.0, stage: 0 });
|
||||
with_window_event(TouchpadPressure { device_id: did, pressure: 0.0, stage: 0 });
|
||||
with_window_event(Touch(event::Touch {
|
||||
device_id: did,
|
||||
phase: event::TouchPhase::Started,
|
||||
location: (0.0, 0.0).into(),
|
||||
finger_id: fid,
|
||||
force: Some(event::Force::Normalized(0.0)),
|
||||
}));
|
||||
with_window_event(ThemeChanged(crate::window::Theme::Light));
|
||||
with_window_event(Occluded(true));
|
||||
}
|
||||
@@ -1222,9 +1122,9 @@ mod tests {
|
||||
use event::DeviceEvent::*;
|
||||
|
||||
let with_device_event =
|
||||
|dev_ev| x(event::Event::DeviceEvent { device_id: None, event: dev_ev });
|
||||
|dev_ev| x(event::Event::DeviceEvent { device_id: did, event: dev_ev });
|
||||
|
||||
with_device_event(PointerMotion { delta: (0.0, 0.0).into() });
|
||||
with_device_event(MouseMotion { delta: (0.0, 0.0).into() });
|
||||
with_device_event(MouseWheel {
|
||||
delta: event::MouseScrollDelta::LineDelta(0.0, 0.0),
|
||||
});
|
||||
@@ -1247,10 +1147,15 @@ mod tests {
|
||||
let force = event::Force::Normalized(0.0);
|
||||
assert_eq!(force.normalized(), 0.0);
|
||||
|
||||
let force2 = event::Force::Calibrated { force: 5.0, max_possible_force: 2.5 };
|
||||
let force2 =
|
||||
event::Force::Calibrated { force: 5.0, max_possible_force: 2.5, altitude_angle: None };
|
||||
assert_eq!(force2.normalized(), 2.0);
|
||||
|
||||
let force3 = event::Force::Calibrated { force: 5.0, max_possible_force: 2.5 };
|
||||
let force3 = event::Force::Calibrated {
|
||||
force: 5.0,
|
||||
max_possible_force: 2.5,
|
||||
altitude_angle: Some(std::f64::consts::PI / 2.0),
|
||||
};
|
||||
assert_eq!(force3.normalized(), 2.0);
|
||||
}
|
||||
|
||||
@@ -1262,18 +1167,29 @@ mod tests {
|
||||
});
|
||||
let _ = event::StartCause::Init.clone();
|
||||
|
||||
let did = crate::event::DeviceId::dummy().clone();
|
||||
let fid = crate::event::FingerId::dummy().clone();
|
||||
HashSet::new().insert(fid);
|
||||
let mut set = [fid, fid, fid];
|
||||
HashSet::new().insert(did);
|
||||
let mut set = [did, did, did];
|
||||
set.sort_unstable();
|
||||
let mut set2 = BTreeSet::new();
|
||||
set2.insert(fid);
|
||||
set2.insert(fid);
|
||||
set2.insert(did);
|
||||
set2.insert(did);
|
||||
|
||||
HashSet::new().insert(event::TouchPhase::Started.clone());
|
||||
HashSet::new().insert(event::MouseButton::Left.clone());
|
||||
HashSet::new().insert(event::Ime::Enabled);
|
||||
|
||||
let _ = event::Force::Calibrated { force: 0.0, max_possible_force: 0.0 }.clone();
|
||||
let _ = event::Touch {
|
||||
device_id: did,
|
||||
phase: event::TouchPhase::Started,
|
||||
location: (0.0, 0.0).into(),
|
||||
finger_id: fid,
|
||||
force: Some(event::Force::Normalized(0.0)),
|
||||
}
|
||||
.clone();
|
||||
let _ =
|
||||
event::Force::Calibrated { force: 0.0, max_possible_force: 0.0, altitude_angle: None }
|
||||
.clone();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ impl EventLoopBuilder {
|
||||
/// Attempting to create the event loop off the main thread will panic. This
|
||||
/// restriction isn't strictly necessary on all platforms, but is imposed to
|
||||
/// eliminate any nasty surprises when porting to platforms that require it.
|
||||
/// `EventLoopBuilderExt::with_any_thread` functions are exposed in the relevant
|
||||
/// `EventLoopBuilderExt::any_thread` functions are exposed in the relevant
|
||||
/// [`platform`] module if the target platform supports creating an event
|
||||
/// loop on any thread.
|
||||
///
|
||||
@@ -148,11 +148,12 @@ pub enum ControlFlow {
|
||||
/// 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.
|
||||
/// Useful for implementing efficient timers, but should not be relied on for real-time needs
|
||||
/// like rendering (VSync) or audio. Applications which want to render at the display's native
|
||||
/// refresh rate should instead issue a [`Window::request_redraw`] at the end of
|
||||
/// [`WindowEvent::RedrawRequested`].
|
||||
///
|
||||
/// [`Poll`]: Self::Poll
|
||||
/// [`WindowEvent::RedrawRequested`]: crate::event::WindowEvent::RedrawRequested
|
||||
WaitUntil(Instant),
|
||||
}
|
||||
|
||||
@@ -420,7 +421,7 @@ impl rwh_06::HasDisplayHandle for dyn ActiveEventLoop + '_ {
|
||||
|
||||
/// A proxy for the underlying display handle.
|
||||
///
|
||||
/// The purpose of this type is to provide a cheaply cloneable handle to the underlying
|
||||
/// The purpose of this type is to provide a cheaply clonable handle to the underlying
|
||||
/// display handle. This is often used by graphics APIs to connect to the underlying APIs.
|
||||
/// It is difficult to keep a handle to the [`EventLoop`] type or the [`ActiveEventLoop`]
|
||||
/// type. In contrast, this type involves no lifetimes and can be persisted for as long as
|
||||
|
||||
56
src/lib.rs
56
src/lib.rs
@@ -147,62 +147,6 @@
|
||||
//! See the [`platform`] module for documentation on platform-specific cargo
|
||||
//! features.
|
||||
//!
|
||||
//! # Platform/Architecture Support
|
||||
//!
|
||||
//! Platform support on `winit` has two tiers: Tier 1 and Tier 2.
|
||||
//!
|
||||
//! - Tier 1 is **guaranteed to work**. Targets in this tier are actively tested both in CI and by
|
||||
//! maintainers.
|
||||
//! - Tier 2 is **guaranteed to build**. Code compilation is tested in CI, but deeper testing is not
|
||||
//! done.
|
||||
//!
|
||||
//! Please open an issue if you would like to add a Tier 2 target, or if you would
|
||||
//! like a Tier 2 target moved to Tier 1.
|
||||
//!
|
||||
//! ## Tier 1 Targets
|
||||
//!
|
||||
//! |Target Name |Target Triple |APIs |
|
||||
//! |-------------------------------|------------------------------------|---------------|
|
||||
//! |32-Bit x86 Windows with MSVC |`i686-pc-windows-msvc` |Win32 |
|
||||
//! |64-Bit x86 Windows with MSVC |`x86_64-pc-windows-msvc` |Win32 |
|
||||
//! |32-Bit x86 Windows with glibc |`i686-pc-windows-gnu` |Win32 |
|
||||
//! |64-Bit x86 Windows with glibc |`x86_64-pc-windows-gnu` |Win32 |
|
||||
//! |32-Bit x86 Linux with glibc |`i686-unknown-linux-gnu` |X11, Wayland |
|
||||
//! |64-Bit x86 Linux with glibc |`x86_64-unknown-linux-gnu` |X11, Wayland |
|
||||
//! |64-Bit ARM Android |`aarch64-linux-android` |Android |
|
||||
//! |64-Bit x86 Redox OS |`x86_64-unknown-redox` |Orbital |
|
||||
//! |32-Bit x86 Redox OS |`i686-unknown-redox` |Orbital |
|
||||
//! |64-Bit ARM Redox OS |`aarch64-unknown-redox` |Orbital |
|
||||
//! |64-bit x64 macOS |`x86_64-apple-darwin` |AppKit |
|
||||
//! |64-bit ARM macOS |`aarch64-apple-darwin` |AppKit |
|
||||
//! |32-bit Wasm Web browser |`wasm32-unknown-unknown` |`wasm-bindgen` |
|
||||
//!
|
||||
//! ## Tier 2 Targets
|
||||
//!
|
||||
//! |Target Name |Target Triple |APIs |
|
||||
//! |------------------------------------|------------------------------------|---------------|
|
||||
//! |64-Bit ARM Windows with MSVC |`aarch64-pc-windows-msvc` |Win32 |
|
||||
//! |32-Bit x86 Windows 7 with MSVC |`i686-win7-windows-msvc` |Win32 |
|
||||
//! |64-Bit x86 Windows 7 with MSVC |`x86_64-win7-windows-msvc` |Win32 |
|
||||
//! |64-bit x86 Linux with Musl |`x86_64-unknown-linux-musl` |X11, Wayland |
|
||||
//! |64-bit x86 Linux with 32-bit glibc |`x86_64-unknown-linux-gnux32` |X11, Wayland |
|
||||
//! |64-bit x86 Android |`x86_64-linux-android` |Android |
|
||||
//! |64-bit x64 iOS |`x86_64-apple-ios` |UIKit |
|
||||
//! |64-bit ARM iOS |`aarch64-apple-ios` |UIKit |
|
||||
//! |64-bit ARM Mac Catalyst |`aarch64-apple-ios-macabi` |UIKit |
|
||||
//! |32-bit x86 Android |`i686-linux-android` |Android |
|
||||
//! |64-bit x86 FreeBSD |`x86_64-unknown-freebsd` |X11, Wayland |
|
||||
//! |64-bit x86 NetBSD |`x86_64-unknown-netbsd` |X11 |
|
||||
//! |32-bit x86 Linux with Musl |`i686-unknown-linux-musl` |X11, Wayland |
|
||||
//! |64-bit RISC-V Linux with glibc |`riscv64gc-unknown-linux-gnu` |X11, Wayland |
|
||||
//! |64-bit ARM Linux with glibc |`aarch64-unknown-linux-gnu` |X11, Wayland |
|
||||
//! |64-bit ARM Linux with Musl |`aarch64-unknown-linux-musl` |X11, Wayland |
|
||||
//! |64-bit PowerPC Linux with glibc |`powerpc64le-unknown-linux-gnu` |X11, Wayland |
|
||||
//! |32-Bit ARM Linux with glibc |`armv5te-unknown-linux-gnueabi` |X11, Wayland |
|
||||
//! |64-Bit Linux on IBM Supercomputers |`s390x-unknown-linux-gnu` |X11, Wayland |
|
||||
//! |32-bit ARM Android |`arm-linux-androideabi` |Android |
|
||||
//! |64-bit SPARC Linux with glibc |`sparc64-unknown-linux-gnu` |X11, Wayland |
|
||||
//!
|
||||
//! [`EventLoop`]: event_loop::EventLoop
|
||||
//! [`EventLoop::new()`]: event_loop::EventLoop::new
|
||||
//! [`EventLoop::run_app()`]: event_loop::EventLoop::run_app
|
||||
|
||||
@@ -75,10 +75,9 @@ use std::os::raw::c_void;
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::application::ApplicationHandler;
|
||||
use crate::event_loop::{ActiveEventLoop, EventLoopBuilder};
|
||||
use crate::monitor::MonitorHandle;
|
||||
use crate::window::{Window, WindowAttributes, WindowId};
|
||||
use crate::window::{Window, WindowAttributes};
|
||||
|
||||
/// Additional methods on [`Window`] that are specific to MacOS.
|
||||
pub trait WindowExtMacOS {
|
||||
@@ -385,12 +384,9 @@ impl WindowAttributesExtMacOS for WindowAttributes {
|
||||
}
|
||||
|
||||
pub trait EventLoopBuilderExtMacOS {
|
||||
/// Sets the activation policy for the application. If used, this will override
|
||||
/// any relevant settings provided in the package manifest.
|
||||
/// For instance, `with_activation_policy(ActivationPolicy::Regular)` will prevent
|
||||
/// the application from running as an "agent", even if LSUIElement is set to true.
|
||||
/// Sets the activation policy for the application.
|
||||
///
|
||||
/// If unused, the Winit will honor the package manifest.
|
||||
/// It is set to [`ActivationPolicy::Regular`] by default.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
@@ -442,7 +438,7 @@ pub trait EventLoopBuilderExtMacOS {
|
||||
impl EventLoopBuilderExtMacOS for EventLoopBuilder {
|
||||
#[inline]
|
||||
fn with_activation_policy(&mut self, activation_policy: ActivationPolicy) -> &mut Self {
|
||||
self.platform_specific.activation_policy = Some(activation_policy);
|
||||
self.platform_specific.activation_policy = activation_policy;
|
||||
self
|
||||
}
|
||||
|
||||
@@ -549,52 +545,3 @@ pub enum OptionAsAlt {
|
||||
#[default]
|
||||
None,
|
||||
}
|
||||
|
||||
/// Additional events on [`ApplicationHandler`] that are specific to macOS.
|
||||
///
|
||||
/// This can be registered with [`ApplicationHandler::macos_handler`].
|
||||
pub trait ApplicationHandlerExtMacOS: ApplicationHandler {
|
||||
/// The system interpreted a keypress as a standard key binding command.
|
||||
///
|
||||
/// Examples include inserting tabs and newlines, or moving the insertion point, see
|
||||
/// [`NSStandardKeyBindingResponding`] for the full list of key bindings. They are often text
|
||||
/// editing related.
|
||||
///
|
||||
/// This corresponds to the [`doCommandBySelector:`] method on `NSTextInputClient`.
|
||||
///
|
||||
/// The `action` parameter contains the string representation of the selector. Examples include
|
||||
/// `"insertBacktab:"`, `"indent:"` and `"noop:"`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```ignore
|
||||
/// impl ApplicationHandlerExtMacOS for App {
|
||||
/// fn standard_key_binding(
|
||||
/// &mut self,
|
||||
/// event_loop: &dyn ActiveEventLoop,
|
||||
/// window_id: WindowId,
|
||||
/// action: &str,
|
||||
/// ) {
|
||||
/// match action {
|
||||
/// "moveBackward:" => self.cursor.position -= 1,
|
||||
/// "moveForward:" => self.cursor.position += 1,
|
||||
/// _ => {} // Ignore other actions
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// [`NSStandardKeyBindingResponding`]: https://developer.apple.com/documentation/appkit/nsstandardkeybindingresponding?language=objc
|
||||
/// [`doCommandBySelector:`]: https://developer.apple.com/documentation/appkit/nstextinputclient/1438256-docommandbyselector?language=objc
|
||||
#[doc(alias = "doCommandBySelector:")]
|
||||
fn standard_key_binding(
|
||||
&mut self,
|
||||
event_loop: &dyn ActiveEventLoop,
|
||||
window_id: WindowId,
|
||||
action: &str,
|
||||
) {
|
||||
let _ = event_loop;
|
||||
let _ = window_id;
|
||||
let _ = action;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,16 +29,17 @@
|
||||
//! The following APIs can't take them into account and will therefore provide inaccurate results:
|
||||
//! - [`WindowEvent::SurfaceResized`] and [`Window::(set_)surface_size()`]
|
||||
//! - [`WindowEvent::Occluded`]
|
||||
//! - [`WindowEvent::PointerMoved`], [`WindowEvent::PointerEntered`] and
|
||||
//! [`WindowEvent::PointerLeft`].
|
||||
//! - [`WindowEvent::CursorMoved`], [`WindowEvent::CursorEntered`], [`WindowEvent::CursorLeft`], and
|
||||
//! [`WindowEvent::Touch`].
|
||||
//! - [`Window::set_outer_position()`]
|
||||
//!
|
||||
//! [`WindowEvent::SurfaceResized`]: crate::event::WindowEvent::SurfaceResized
|
||||
//! [`Window::(set_)surface_size()`]: crate::window::Window::surface_size
|
||||
//! [`WindowEvent::Occluded`]: crate::event::WindowEvent::Occluded
|
||||
//! [`WindowEvent::PointerMoved`]: crate::event::WindowEvent::PointerMoved
|
||||
//! [`WindowEvent::PointerEntered`]: crate::event::WindowEvent::PointerEntered
|
||||
//! [`WindowEvent::PointerLeft`]: crate::event::WindowEvent::PointerLeft
|
||||
//! [`WindowEvent::CursorMoved`]: crate::event::WindowEvent::CursorMoved
|
||||
//! [`WindowEvent::CursorEntered`]: crate::event::WindowEvent::CursorEntered
|
||||
//! [`WindowEvent::CursorLeft`]: crate::event::WindowEvent::CursorLeft
|
||||
//! [`WindowEvent::Touch`]: crate::event::WindowEvent::Touch
|
||||
//! [`Window::set_outer_position()`]: crate::window::Window::set_outer_position
|
||||
|
||||
use std::cell::Ref;
|
||||
|
||||
@@ -9,8 +9,6 @@ use std::path::Path;
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
#[cfg(windows_platform)]
|
||||
use windows_sys::Win32::Foundation::HANDLE;
|
||||
|
||||
use crate::dpi::PhysicalSize;
|
||||
use crate::event::{DeviceId, FingerId};
|
||||
@@ -658,15 +656,10 @@ pub trait DeviceIdExtWindows {
|
||||
fn persistent_identifier(&self) -> Option<String>;
|
||||
}
|
||||
|
||||
#[cfg(windows_platform)]
|
||||
impl DeviceIdExtWindows for DeviceId {
|
||||
#[inline]
|
||||
fn persistent_identifier(&self) -> Option<String> {
|
||||
let raw_id = self.into_raw();
|
||||
if raw_id != 0 {
|
||||
crate::platform_impl::raw_input::get_raw_input_device_name(raw_id as HANDLE)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
self.0.persistent_identifier()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -80,7 +80,9 @@ pub type XWindow = u32;
|
||||
#[inline]
|
||||
pub fn register_xlib_error_hook(hook: XlibErrorHook) {
|
||||
// Append new hook.
|
||||
crate::platform_impl::XLIB_ERROR_HOOKS.lock().unwrap().push(hook);
|
||||
unsafe {
|
||||
crate::platform_impl::XLIB_ERROR_HOOKS.lock().unwrap().push(hook);
|
||||
}
|
||||
}
|
||||
|
||||
/// Additional methods on [`ActiveEventLoop`] that are specific to X11.
|
||||
|
||||
@@ -15,7 +15,7 @@ use crate::application::ApplicationHandler;
|
||||
use crate::cursor::Cursor;
|
||||
use crate::dpi::{PhysicalPosition, PhysicalSize, Position, Size};
|
||||
use crate::error::{EventLoopError, NotSupportedError, RequestError};
|
||||
use crate::event::{self, DeviceId, Force, StartCause, SurfaceSizeWriter};
|
||||
use crate::event::{self, Force, StartCause, SurfaceSizeWriter};
|
||||
use crate::event_loop::{
|
||||
ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents,
|
||||
EventLoopProxy as RootEventLoopProxy, OwnedDisplayHandle as RootOwnedDisplayHandle,
|
||||
@@ -24,8 +24,7 @@ use crate::monitor::MonitorHandle as RootMonitorHandle;
|
||||
use crate::platform::pump_events::PumpStatus;
|
||||
use crate::window::{
|
||||
self, CursorGrabMode, CustomCursor, CustomCursorSource, Fullscreen, ImePurpose,
|
||||
ResizeDirection, Theme, Window as CoreWindow, WindowAttributes, WindowButtons, WindowId,
|
||||
WindowLevel,
|
||||
ResizeDirection, Theme, Window as CoreWindow, WindowAttributes, WindowButtons, WindowLevel,
|
||||
};
|
||||
|
||||
mod keycodes;
|
||||
@@ -123,9 +122,6 @@ impl Default for PlatformSpecificEventLoopAttributes {
|
||||
}
|
||||
}
|
||||
|
||||
// Android currently only supports one window
|
||||
const GLOBAL_WINDOW: WindowId = WindowId::from_raw(0);
|
||||
|
||||
impl EventLoop {
|
||||
pub(crate) fn new(
|
||||
attributes: &PlatformSpecificEventLoopAttributes,
|
||||
@@ -191,19 +187,22 @@ impl EventLoop {
|
||||
},
|
||||
MainEvent::GainedFocus => {
|
||||
HAS_FOCUS.store(true, Ordering::Relaxed);
|
||||
let window_id = window::WindowId(WindowId);
|
||||
let event = event::WindowEvent::Focused(true);
|
||||
app.window_event(&self.window_target, GLOBAL_WINDOW, event);
|
||||
app.window_event(&self.window_target, window_id, event);
|
||||
},
|
||||
MainEvent::LostFocus => {
|
||||
HAS_FOCUS.store(false, Ordering::Relaxed);
|
||||
let window_id = window::WindowId(WindowId);
|
||||
let event = event::WindowEvent::Focused(false);
|
||||
app.window_event(&self.window_target, GLOBAL_WINDOW, event);
|
||||
app.window_event(&self.window_target, window_id, event);
|
||||
},
|
||||
MainEvent::ConfigChanged { .. } => {
|
||||
let old_scale_factor = scale_factor(&self.android_app);
|
||||
let scale_factor = scale_factor(&self.android_app);
|
||||
if (scale_factor - old_scale_factor).abs() < f64::EPSILON {
|
||||
let new_surface_size = Arc::new(Mutex::new(screen_size(&self.android_app)));
|
||||
let window_id = window::WindowId(WindowId);
|
||||
let event = event::WindowEvent::ScaleFactorChanged {
|
||||
surface_size_writer: SurfaceSizeWriter::new(Arc::downgrade(
|
||||
&new_surface_size,
|
||||
@@ -211,18 +210,18 @@ impl EventLoop {
|
||||
scale_factor,
|
||||
};
|
||||
|
||||
app.window_event(&self.window_target, GLOBAL_WINDOW, event);
|
||||
app.window_event(&self.window_target, window_id, event);
|
||||
}
|
||||
},
|
||||
MainEvent::LowMemory => {
|
||||
app.memory_warning(&self.window_target);
|
||||
},
|
||||
MainEvent::Start => {
|
||||
app.resumed(self.window_target());
|
||||
// XXX: how to forward this state to applications?
|
||||
warn!("TODO: forward onStart notification to application");
|
||||
},
|
||||
MainEvent::Resume { .. } => {
|
||||
debug!("App Resumed - is running");
|
||||
// TODO: This is incorrect - will be solved in https://github.com/rust-windowing/winit/pull/3897
|
||||
self.running = true;
|
||||
},
|
||||
MainEvent::SaveState { .. } => {
|
||||
@@ -232,11 +231,11 @@ impl EventLoop {
|
||||
},
|
||||
MainEvent::Pause => {
|
||||
debug!("App Paused - stopped running");
|
||||
// TODO: This is incorrect - will be solved in https://github.com/rust-windowing/winit/pull/3897
|
||||
self.running = false;
|
||||
},
|
||||
MainEvent::Stop => {
|
||||
app.suspended(self.window_target());
|
||||
// XXX: how to forward this state to applications?
|
||||
warn!("TODO: forward onStop notification to application");
|
||||
},
|
||||
MainEvent::Destroy => {
|
||||
// XXX: maybe exit mainloop to drop things before being
|
||||
@@ -287,15 +286,17 @@ impl EventLoop {
|
||||
} else {
|
||||
PhysicalSize::new(0, 0)
|
||||
};
|
||||
let window_id = window::WindowId(WindowId);
|
||||
let event = event::WindowEvent::SurfaceResized(size);
|
||||
app.window_event(&self.window_target, GLOBAL_WINDOW, event);
|
||||
app.window_event(&self.window_target, window_id, event);
|
||||
}
|
||||
|
||||
pending_redraw |= self.redraw_flag.get_and_reset();
|
||||
if pending_redraw {
|
||||
pending_redraw = false;
|
||||
let window_id = window::WindowId(WindowId);
|
||||
let event = event::WindowEvent::RedrawRequested;
|
||||
app.window_event(&self.window_target, GLOBAL_WINDOW, event);
|
||||
app.window_event(&self.window_target, window_id, event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -314,116 +315,50 @@ impl EventLoop {
|
||||
let mut input_status = InputStatus::Handled;
|
||||
match event {
|
||||
InputEvent::MotionEvent(motion_event) => {
|
||||
let device_id = Some(DeviceId::from_raw(motion_event.device_id() as i64));
|
||||
let action = motion_event.action();
|
||||
let window_id = window::WindowId(WindowId);
|
||||
let device_id = event::DeviceId(DeviceId(motion_event.device_id()));
|
||||
|
||||
let pointers: Option<
|
||||
Box<dyn Iterator<Item = android_activity::input::Pointer<'_>>>,
|
||||
> = match action {
|
||||
MotionAction::Down
|
||||
| MotionAction::PointerDown
|
||||
| MotionAction::Up
|
||||
| MotionAction::PointerUp => Some(Box::new(std::iter::once(
|
||||
motion_event.pointer_at_index(motion_event.pointer_index()),
|
||||
))),
|
||||
MotionAction::Move | MotionAction::Cancel => {
|
||||
Some(Box::new(motion_event.pointers()))
|
||||
let phase = match motion_event.action() {
|
||||
MotionAction::Down | MotionAction::PointerDown => {
|
||||
Some(event::TouchPhase::Started)
|
||||
},
|
||||
MotionAction::Up | MotionAction::PointerUp => Some(event::TouchPhase::Ended),
|
||||
MotionAction::Move => Some(event::TouchPhase::Moved),
|
||||
MotionAction::Cancel => Some(event::TouchPhase::Cancelled),
|
||||
_ => {
|
||||
None // TODO mouse events
|
||||
},
|
||||
// TODO mouse events
|
||||
_ => None,
|
||||
};
|
||||
if let Some(phase) = phase {
|
||||
let pointers: Box<dyn Iterator<Item = android_activity::input::Pointer<'_>>> =
|
||||
match phase {
|
||||
event::TouchPhase::Started | event::TouchPhase::Ended => {
|
||||
Box::new(std::iter::once(
|
||||
motion_event.pointer_at_index(motion_event.pointer_index()),
|
||||
))
|
||||
},
|
||||
event::TouchPhase::Moved | event::TouchPhase::Cancelled => {
|
||||
Box::new(motion_event.pointers())
|
||||
},
|
||||
};
|
||||
|
||||
if let Some(pointers) = pointers {
|
||||
for pointer in pointers {
|
||||
let tool_type = pointer.tool_type();
|
||||
let position =
|
||||
let location =
|
||||
PhysicalPosition { x: pointer.x() as _, y: pointer.y() as _ };
|
||||
trace!(
|
||||
"Input event {device_id:?}, {action:?}, loc={position:?}, \
|
||||
pointer={pointer:?}, tool_type={tool_type:?}"
|
||||
"Input event {device_id:?}, {phase:?}, loc={location:?}, \
|
||||
pointer={pointer:?}"
|
||||
);
|
||||
let finger_id = event::FingerId(FingerId(pointer.pointer_id()));
|
||||
let force = Some(Force::Normalized(pointer.pressure() as f64));
|
||||
|
||||
match action {
|
||||
MotionAction::Down | MotionAction::PointerDown => {
|
||||
let event = event::WindowEvent::PointerEntered {
|
||||
device_id,
|
||||
position,
|
||||
kind: match tool_type {
|
||||
android_activity::input::ToolType::Finger => {
|
||||
event::PointerKind::Touch(finger_id)
|
||||
},
|
||||
// TODO mouse events
|
||||
android_activity::input::ToolType::Mouse => continue,
|
||||
_ => event::PointerKind::Unknown,
|
||||
},
|
||||
};
|
||||
app.window_event(&self.window_target, GLOBAL_WINDOW, event);
|
||||
let event = event::WindowEvent::PointerButton {
|
||||
device_id,
|
||||
state: event::ElementState::Pressed,
|
||||
position,
|
||||
button: match tool_type {
|
||||
android_activity::input::ToolType::Finger => {
|
||||
event::ButtonSource::Touch { finger_id, force }
|
||||
},
|
||||
// TODO mouse events
|
||||
android_activity::input::ToolType::Mouse => continue,
|
||||
_ => event::ButtonSource::Unknown(0),
|
||||
},
|
||||
};
|
||||
app.window_event(&self.window_target, GLOBAL_WINDOW, event);
|
||||
},
|
||||
MotionAction::Move => {
|
||||
let event = event::WindowEvent::PointerMoved {
|
||||
device_id,
|
||||
position,
|
||||
source: match tool_type {
|
||||
android_activity::input::ToolType::Finger => {
|
||||
event::PointerSource::Touch { finger_id, force }
|
||||
},
|
||||
// TODO mouse events
|
||||
android_activity::input::ToolType::Mouse => continue,
|
||||
_ => event::PointerSource::Unknown,
|
||||
},
|
||||
};
|
||||
app.window_event(&self.window_target, GLOBAL_WINDOW, event);
|
||||
},
|
||||
MotionAction::Up | MotionAction::PointerUp | MotionAction::Cancel => {
|
||||
if let MotionAction::Up | MotionAction::PointerUp = action {
|
||||
let event = event::WindowEvent::PointerButton {
|
||||
device_id,
|
||||
state: event::ElementState::Released,
|
||||
position,
|
||||
button: match tool_type {
|
||||
android_activity::input::ToolType::Finger => {
|
||||
event::ButtonSource::Touch { finger_id, force }
|
||||
},
|
||||
// TODO mouse events
|
||||
android_activity::input::ToolType::Mouse => continue,
|
||||
_ => event::ButtonSource::Unknown(0),
|
||||
},
|
||||
};
|
||||
app.window_event(&self.window_target, GLOBAL_WINDOW, event);
|
||||
}
|
||||
let event = event::WindowEvent::Touch(event::Touch {
|
||||
device_id,
|
||||
phase,
|
||||
location,
|
||||
finger_id: event::FingerId(FingerId(pointer.pointer_id())),
|
||||
force: Some(Force::Normalized(pointer.pressure() as f64)),
|
||||
});
|
||||
|
||||
let event = event::WindowEvent::PointerLeft {
|
||||
device_id,
|
||||
position: Some(position),
|
||||
kind: match tool_type {
|
||||
android_activity::input::ToolType::Finger => {
|
||||
event::PointerKind::Touch(finger_id)
|
||||
},
|
||||
// TODO mouse events
|
||||
android_activity::input::ToolType::Mouse => continue,
|
||||
_ => event::PointerKind::Unknown,
|
||||
},
|
||||
};
|
||||
app.window_event(&self.window_target, GLOBAL_WINDOW, event);
|
||||
},
|
||||
_ => unreachable!(),
|
||||
}
|
||||
app.window_event(&self.window_target, window_id, event);
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -451,8 +386,9 @@ impl EventLoop {
|
||||
&mut self.combining_accent,
|
||||
);
|
||||
|
||||
let window_id = window::WindowId(WindowId);
|
||||
let event = event::WindowEvent::KeyboardInput {
|
||||
device_id: Some(DeviceId::from_raw(key.device_id() as i64)),
|
||||
device_id: event::DeviceId(DeviceId(key.device_id())),
|
||||
event: event::KeyEvent {
|
||||
state,
|
||||
physical_key: keycodes::to_physical_key(keycode),
|
||||
@@ -465,7 +401,7 @@ impl EventLoop {
|
||||
is_synthetic: false,
|
||||
};
|
||||
|
||||
app.window_event(&self.window_target, GLOBAL_WINDOW, event);
|
||||
app.window_event(&self.window_target, window_id, event);
|
||||
},
|
||||
}
|
||||
},
|
||||
@@ -728,11 +664,40 @@ 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, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||
pub struct FingerId(i32);
|
||||
|
||||
impl FingerId {
|
||||
#[cfg(test)]
|
||||
pub const fn dummy() -> Self {
|
||||
FingerId(0)
|
||||
}
|
||||
@@ -805,8 +770,8 @@ impl rwh_06::HasWindowHandle for Window {
|
||||
}
|
||||
|
||||
impl CoreWindow for Window {
|
||||
fn id(&self) -> WindowId {
|
||||
GLOBAL_WINDOW
|
||||
fn id(&self) -> window::WindowId {
|
||||
window::WindowId(WindowId)
|
||||
}
|
||||
|
||||
fn primary_monitor(&self) -> Option<RootMonitorHandle> {
|
||||
|
||||
@@ -7,6 +7,7 @@ use objc2_app_kit::{NSApplication, NSEvent, NSEventModifierFlags, NSEventType, N
|
||||
use objc2_foundation::{MainThreadMarker, NSObject};
|
||||
|
||||
use super::app_state::AppState;
|
||||
use super::DEVICE_ID;
|
||||
use crate::event::{DeviceEvent, ElementState};
|
||||
|
||||
declare_class!(
|
||||
@@ -60,7 +61,7 @@ fn maybe_dispatch_device_event(app_state: &Rc<AppState>, event: &NSEvent) {
|
||||
|
||||
if delta_x != 0.0 || delta_y != 0.0 {
|
||||
app_state.maybe_queue_with_handler(move |app, event_loop| {
|
||||
app.device_event(event_loop, None, DeviceEvent::PointerMotion {
|
||||
app.device_event(event_loop, DEVICE_ID, DeviceEvent::MouseMotion {
|
||||
delta: (delta_x, delta_y),
|
||||
});
|
||||
});
|
||||
@@ -69,7 +70,7 @@ fn maybe_dispatch_device_event(app_state: &Rc<AppState>, event: &NSEvent) {
|
||||
NSEventType::LeftMouseDown | NSEventType::RightMouseDown | NSEventType::OtherMouseDown => {
|
||||
let button = unsafe { event.buttonNumber() } as u32;
|
||||
app_state.maybe_queue_with_handler(move |app, event_loop| {
|
||||
app.device_event(event_loop, None, DeviceEvent::Button {
|
||||
app.device_event(event_loop, DEVICE_ID, DeviceEvent::Button {
|
||||
button,
|
||||
state: ElementState::Pressed,
|
||||
});
|
||||
@@ -78,7 +79,7 @@ fn maybe_dispatch_device_event(app_state: &Rc<AppState>, event: &NSEvent) {
|
||||
NSEventType::LeftMouseUp | NSEventType::RightMouseUp | NSEventType::OtherMouseUp => {
|
||||
let button = unsafe { event.buttonNumber() } as u32;
|
||||
app_state.maybe_queue_with_handler(move |app, event_loop| {
|
||||
app.device_event(event_loop, None, DeviceEvent::Button {
|
||||
app.device_event(event_loop, DEVICE_ID, DeviceEvent::Button {
|
||||
button,
|
||||
state: ElementState::Released,
|
||||
});
|
||||
|
||||
@@ -10,17 +10,17 @@ use objc2_foundation::{MainThreadMarker, NSNotification};
|
||||
|
||||
use super::super::event_handler::EventHandler;
|
||||
use super::event_loop::{stop_app_immediately, ActiveEventLoop, PanicInfo};
|
||||
use super::menu;
|
||||
use super::observer::{EventLoopWaker, RunLoop};
|
||||
use super::{menu, WindowId};
|
||||
use crate::application::ApplicationHandler;
|
||||
use crate::event::{StartCause, WindowEvent};
|
||||
use crate::event_loop::ControlFlow;
|
||||
use crate::window::WindowId;
|
||||
use crate::window::WindowId as RootWindowId;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(super) struct AppState {
|
||||
mtm: MainThreadMarker,
|
||||
activation_policy: Option<NSApplicationActivationPolicy>,
|
||||
activation_policy: NSApplicationActivationPolicy,
|
||||
default_menu: bool,
|
||||
activate_ignoring_other_apps: bool,
|
||||
run_loop: RunLoop,
|
||||
@@ -65,7 +65,7 @@ static GLOBAL: StaticMainThreadBound<OnceCell<Rc<AppState>>> =
|
||||
impl AppState {
|
||||
pub(super) fn setup_global(
|
||||
mtm: MainThreadMarker,
|
||||
activation_policy: Option<NSApplicationActivationPolicy>,
|
||||
activation_policy: NSApplicationActivationPolicy,
|
||||
default_menu: bool,
|
||||
activate_ignoring_other_apps: bool,
|
||||
) -> Rc<Self> {
|
||||
@@ -113,11 +113,7 @@ impl AppState {
|
||||
// We need to delay setting the activation policy and activating the app
|
||||
// until `applicationDidFinishLaunching` has been called. Otherwise the
|
||||
// menu bar is initially unresponsive on macOS 10.15.
|
||||
// If no activation policy is explicitly provided, do not set it at all
|
||||
// to allow the package manifest to define behavior via LSUIElement.
|
||||
if self.activation_policy.is_some() {
|
||||
app.setActivationPolicy(self.activation_policy.unwrap());
|
||||
}
|
||||
app.setActivationPolicy(self.activation_policy);
|
||||
|
||||
#[allow(deprecated)]
|
||||
app.activateIgnoringOtherApps(self.activate_ignoring_other_apps);
|
||||
@@ -245,7 +241,7 @@ impl AppState {
|
||||
// -> Don't go back into the event handler when our callstack originates from there
|
||||
if !self.event_handler.in_use() {
|
||||
self.with_handler(|app, event_loop| {
|
||||
app.window_event(event_loop, window_id, WindowEvent::RedrawRequested);
|
||||
app.window_event(event_loop, RootWindowId(window_id), WindowEvent::RedrawRequested);
|
||||
});
|
||||
|
||||
// `pump_events` will request to stop immediately _after_ dispatching RedrawRequested
|
||||
@@ -357,7 +353,7 @@ impl AppState {
|
||||
let redraw = mem::take(&mut *self.pending_redraw.borrow_mut());
|
||||
for window_id in redraw {
|
||||
self.with_handler(|app, event_loop| {
|
||||
app.window_event(event_loop, window_id, WindowEvent::RedrawRequested);
|
||||
app.window_event(event_loop, RootWindowId(window_id), WindowEvent::RedrawRequested);
|
||||
});
|
||||
}
|
||||
self.with_handler(|app, event_loop| {
|
||||
|
||||
@@ -190,14 +190,18 @@ pub struct EventLoop {
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub(crate) struct PlatformSpecificEventLoopAttributes {
|
||||
pub(crate) activation_policy: Option<ActivationPolicy>,
|
||||
pub(crate) activation_policy: ActivationPolicy,
|
||||
pub(crate) default_menu: bool,
|
||||
pub(crate) activate_ignoring_other_apps: bool,
|
||||
}
|
||||
|
||||
impl Default for PlatformSpecificEventLoopAttributes {
|
||||
fn default() -> Self {
|
||||
Self { activation_policy: None, default_menu: true, activate_ignoring_other_apps: true }
|
||||
Self {
|
||||
activation_policy: Default::default(), // Regular
|
||||
default_menu: true,
|
||||
activate_ignoring_other_apps: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,10 +223,9 @@ impl EventLoop {
|
||||
}
|
||||
|
||||
let activation_policy = match attributes.activation_policy {
|
||||
None => None,
|
||||
Some(ActivationPolicy::Regular) => Some(NSApplicationActivationPolicy::Regular),
|
||||
Some(ActivationPolicy::Accessory) => Some(NSApplicationActivationPolicy::Accessory),
|
||||
Some(ActivationPolicy::Prohibited) => Some(NSApplicationActivationPolicy::Prohibited),
|
||||
ActivationPolicy::Regular => NSApplicationActivationPolicy::Regular,
|
||||
ActivationPolicy::Accessory => NSApplicationActivationPolicy::Accessory,
|
||||
ActivationPolicy::Prohibited => NSApplicationActivationPolicy::Prohibited,
|
||||
};
|
||||
|
||||
let app_state = AppState::setup_global(
|
||||
|
||||
@@ -21,17 +21,29 @@ pub(crate) use self::event_loop::{
|
||||
PlatformSpecificEventLoopAttributes,
|
||||
};
|
||||
pub(crate) use self::monitor::{MonitorHandle, VideoModeHandle};
|
||||
pub(crate) use self::window::Window;
|
||||
pub(crate) use self::window::{Window, WindowId};
|
||||
pub(crate) use self::window_delegate::PlatformSpecificWindowAttributes;
|
||||
pub(crate) use crate::cursor::OnlyCursorImageSource as PlatformCustomCursorSource;
|
||||
use crate::event::DeviceId as RootDeviceId;
|
||||
pub(crate) use crate::icon::NoIcon as PlatformIcon;
|
||||
pub(crate) use crate::platform_impl::Fullscreen;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct DeviceId;
|
||||
|
||||
impl DeviceId {
|
||||
pub const fn dummy() -> Self {
|
||||
DeviceId
|
||||
}
|
||||
}
|
||||
|
||||
// Constant device ID; to be removed when if backend is updated to report real device IDs.
|
||||
pub(crate) const DEVICE_ID: RootDeviceId = RootDeviceId(DeviceId);
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct FingerId;
|
||||
|
||||
impl FingerId {
|
||||
#[cfg(test)]
|
||||
pub const fn dummy() -> Self {
|
||||
FingerId
|
||||
}
|
||||
|
||||
@@ -24,13 +24,15 @@ use super::event::{
|
||||
scancode_to_physicalkey,
|
||||
};
|
||||
use super::window::WinitWindow;
|
||||
use super::DEVICE_ID;
|
||||
use crate::dpi::{LogicalPosition, LogicalSize};
|
||||
use crate::event::{
|
||||
DeviceEvent, ElementState, Ime, Modifiers, MouseButton, MouseScrollDelta, PointerKind,
|
||||
PointerSource, TouchPhase, WindowEvent,
|
||||
DeviceEvent, ElementState, Ime, Modifiers, MouseButton, MouseScrollDelta, TouchPhase,
|
||||
WindowEvent,
|
||||
};
|
||||
use crate::keyboard::{Key, KeyCode, KeyLocation, ModifiersState, NamedKey};
|
||||
use crate::platform::macos::OptionAsAlt;
|
||||
use crate::window::WindowId as RootWindowId;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct CursorState {
|
||||
@@ -412,9 +414,8 @@ declare_class!(
|
||||
// Basically, we're sent this message whenever a keyboard event that doesn't generate a "human
|
||||
// readable" character happens, i.e. newlines, tabs, and Ctrl+C.
|
||||
#[method(doCommandBySelector:)]
|
||||
fn do_command_by_selector(&self, command: Sel) {
|
||||
fn do_command_by_selector(&self, _command: Sel) {
|
||||
trace_scope!("doCommandBySelector:");
|
||||
|
||||
// We shouldn't forward any character from just committed text, since we'll end up sending
|
||||
// it twice with some IMEs like Korean one. We'll also always send `Enter` in that case,
|
||||
// which is not desired given it was used to confirm IME input.
|
||||
@@ -429,18 +430,6 @@ declare_class!(
|
||||
// Leave preedit so that we also report the key-up for this key.
|
||||
self.ivars().ime_state.set(ImeState::Ground);
|
||||
}
|
||||
|
||||
// Send command action to user if they requested it.
|
||||
let window_id = self.window().id();
|
||||
self.ivars().app_state.maybe_queue_with_handler(move |app, event_loop| {
|
||||
if let Some(handler) = app.macos_handler() {
|
||||
handler.standard_key_binding(event_loop, window_id, command.name());
|
||||
}
|
||||
});
|
||||
|
||||
// The documentation for `-[NSTextInputClient doCommandBySelector:]` clearly states that
|
||||
// we should not be forwarding this event up the responder chain, so no calling `super`
|
||||
// here either.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -497,7 +486,7 @@ declare_class!(
|
||||
if !had_ime_input || self.ivars().forward_key_to_app.get() {
|
||||
let key_event = create_key_event(&event, true, unsafe { event.isARepeat() }, None);
|
||||
self.queue_event(WindowEvent::KeyboardInput {
|
||||
device_id: None,
|
||||
device_id: DEVICE_ID,
|
||||
event: key_event,
|
||||
is_synthetic: false,
|
||||
});
|
||||
@@ -517,7 +506,7 @@ declare_class!(
|
||||
ImeState::Ground | ImeState::Disabled
|
||||
) {
|
||||
self.queue_event(WindowEvent::KeyboardInput {
|
||||
device_id: None,
|
||||
device_id: DEVICE_ID,
|
||||
event: create_key_event(&event, false, false, None),
|
||||
is_synthetic: false,
|
||||
});
|
||||
@@ -568,7 +557,7 @@ declare_class!(
|
||||
let event = create_key_event(&event, true, unsafe { event.isARepeat() }, None);
|
||||
|
||||
self.queue_event(WindowEvent::KeyboardInput {
|
||||
device_id: None,
|
||||
device_id: DEVICE_ID,
|
||||
event,
|
||||
is_synthetic: false,
|
||||
});
|
||||
@@ -650,28 +639,19 @@ declare_class!(
|
||||
}
|
||||
|
||||
#[method(mouseEntered:)]
|
||||
fn mouse_entered(&self, event: &NSEvent) {
|
||||
fn mouse_entered(&self, _event: &NSEvent) {
|
||||
trace_scope!("mouseEntered:");
|
||||
|
||||
let position = self.mouse_view_point(event).to_physical(self.scale_factor());
|
||||
|
||||
self.queue_event(WindowEvent::PointerEntered {
|
||||
device_id: None,
|
||||
position,
|
||||
kind: PointerKind::Mouse,
|
||||
self.queue_event(WindowEvent::CursorEntered {
|
||||
device_id: DEVICE_ID,
|
||||
});
|
||||
}
|
||||
|
||||
#[method(mouseExited:)]
|
||||
fn mouse_exited(&self, event: &NSEvent) {
|
||||
fn mouse_exited(&self, _event: &NSEvent) {
|
||||
trace_scope!("mouseExited:");
|
||||
|
||||
let position = self.mouse_view_point(event).to_physical(self.scale_factor());
|
||||
|
||||
self.queue_event(WindowEvent::PointerLeft {
|
||||
device_id: None,
|
||||
position: Some(position),
|
||||
kind: PointerKind::Mouse,
|
||||
self.queue_event(WindowEvent::CursorLeft {
|
||||
device_id: DEVICE_ID,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -709,10 +689,10 @@ declare_class!(
|
||||
self.update_modifiers(event, false);
|
||||
|
||||
self.ivars().app_state.maybe_queue_with_handler(move |app, event_loop|
|
||||
app.device_event(event_loop, None, DeviceEvent::MouseWheel { delta })
|
||||
app.device_event(event_loop, DEVICE_ID, DeviceEvent::MouseWheel { delta })
|
||||
);
|
||||
self.queue_event(WindowEvent::MouseWheel {
|
||||
device_id: None,
|
||||
device_id: DEVICE_ID,
|
||||
delta,
|
||||
phase,
|
||||
});
|
||||
@@ -734,7 +714,7 @@ declare_class!(
|
||||
};
|
||||
|
||||
self.queue_event(WindowEvent::PinchGesture {
|
||||
device_id: None,
|
||||
device_id: DEVICE_ID,
|
||||
delta: unsafe { event.magnification() },
|
||||
phase,
|
||||
});
|
||||
@@ -747,7 +727,7 @@ declare_class!(
|
||||
self.mouse_motion(event);
|
||||
|
||||
self.queue_event(WindowEvent::DoubleTapGesture {
|
||||
device_id: None,
|
||||
device_id: DEVICE_ID,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -767,7 +747,7 @@ declare_class!(
|
||||
};
|
||||
|
||||
self.queue_event(WindowEvent::RotationGesture {
|
||||
device_id: None,
|
||||
device_id: DEVICE_ID,
|
||||
delta: unsafe { event.rotation() },
|
||||
phase,
|
||||
});
|
||||
@@ -778,7 +758,7 @@ declare_class!(
|
||||
trace_scope!("pressureChangeWithEvent:");
|
||||
|
||||
self.queue_event(WindowEvent::TouchpadPressure {
|
||||
device_id: None,
|
||||
device_id: DEVICE_ID,
|
||||
pressure: unsafe { event.pressure() },
|
||||
stage: unsafe { event.stage() } as i64,
|
||||
});
|
||||
@@ -854,7 +834,7 @@ impl WinitView {
|
||||
}
|
||||
|
||||
fn queue_event(&self, event: WindowEvent) {
|
||||
let window_id = self.window().id();
|
||||
let window_id = RootWindowId(self.window().id());
|
||||
self.ivars().app_state.maybe_queue_with_handler(move |app, event_loop| {
|
||||
app.window_event(event_loop, window_id, event);
|
||||
});
|
||||
@@ -992,7 +972,7 @@ impl WinitView {
|
||||
event.location = KeyLocation::Left;
|
||||
event.physical_key = get_left_modifier_code(&event.logical_key).into();
|
||||
events.push_back(WindowEvent::KeyboardInput {
|
||||
device_id: None,
|
||||
device_id: DEVICE_ID,
|
||||
event,
|
||||
is_synthetic: false,
|
||||
});
|
||||
@@ -1001,7 +981,7 @@ impl WinitView {
|
||||
event.location = KeyLocation::Right;
|
||||
event.physical_key = get_right_modifier_code(&event.logical_key).into();
|
||||
events.push_back(WindowEvent::KeyboardInput {
|
||||
device_id: None,
|
||||
device_id: DEVICE_ID,
|
||||
event,
|
||||
is_synthetic: false,
|
||||
});
|
||||
@@ -1032,7 +1012,7 @@ impl WinitView {
|
||||
}
|
||||
|
||||
events.push_back(WindowEvent::KeyboardInput {
|
||||
device_id: None,
|
||||
device_id: DEVICE_ID,
|
||||
event,
|
||||
is_synthetic: false,
|
||||
});
|
||||
@@ -1054,21 +1034,20 @@ impl WinitView {
|
||||
}
|
||||
|
||||
fn mouse_click(&self, event: &NSEvent, button_state: ElementState) {
|
||||
let position = self.mouse_view_point(event).to_physical(self.scale_factor());
|
||||
let button = mouse_button(event);
|
||||
|
||||
self.update_modifiers(event, false);
|
||||
|
||||
self.queue_event(WindowEvent::PointerButton {
|
||||
device_id: None,
|
||||
self.queue_event(WindowEvent::MouseInput {
|
||||
device_id: DEVICE_ID,
|
||||
state: button_state,
|
||||
position,
|
||||
button: button.into(),
|
||||
button,
|
||||
});
|
||||
}
|
||||
|
||||
fn mouse_motion(&self, event: &NSEvent) {
|
||||
let view_point = self.mouse_view_point(event);
|
||||
let window_point = unsafe { event.locationInWindow() };
|
||||
let view_point = self.convertPoint_fromView(window_point, None);
|
||||
let frame = self.frame();
|
||||
|
||||
if view_point.x.is_sign_negative()
|
||||
@@ -1083,21 +1062,15 @@ impl WinitView {
|
||||
}
|
||||
}
|
||||
|
||||
let view_point = LogicalPosition::new(view_point.x, view_point.y);
|
||||
|
||||
self.update_modifiers(event, false);
|
||||
|
||||
self.queue_event(WindowEvent::PointerMoved {
|
||||
device_id: None,
|
||||
self.queue_event(WindowEvent::CursorMoved {
|
||||
device_id: DEVICE_ID,
|
||||
position: view_point.to_physical(self.scale_factor()),
|
||||
source: PointerSource::Mouse,
|
||||
});
|
||||
}
|
||||
|
||||
fn mouse_view_point(&self, event: &NSEvent) -> LogicalPosition<f64> {
|
||||
let window_point = unsafe { event.locationInWindow() };
|
||||
let view_point = self.convertPoint_fromView(window_point, None);
|
||||
|
||||
LogicalPosition::new(view_point.x, view_point.y)
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the mouse button from the NSEvent.
|
||||
|
||||
@@ -12,7 +12,7 @@ use crate::error::RequestError;
|
||||
use crate::monitor::MonitorHandle as CoreMonitorHandle;
|
||||
use crate::window::{
|
||||
Cursor, Fullscreen, Icon, ImePurpose, Theme, UserAttentionType, Window as CoreWindow,
|
||||
WindowAttributes, WindowButtons, WindowId, WindowLevel,
|
||||
WindowAttributes, WindowButtons, WindowLevel,
|
||||
};
|
||||
|
||||
pub(crate) struct Window {
|
||||
@@ -92,7 +92,7 @@ impl rwh_06::HasWindowHandle for Window {
|
||||
|
||||
impl CoreWindow for Window {
|
||||
fn id(&self) -> crate::window::WindowId {
|
||||
self.maybe_wait_on_main(|delegate| delegate.id())
|
||||
self.maybe_wait_on_main(|delegate| crate::window::WindowId(delegate.id()))
|
||||
}
|
||||
|
||||
fn scale_factor(&self) -> f64 {
|
||||
@@ -284,7 +284,8 @@ impl CoreWindow for Window {
|
||||
}
|
||||
|
||||
fn drag_window(&self) -> Result<(), RequestError> {
|
||||
self.maybe_wait_on_main(|delegate| delegate.drag_window())
|
||||
self.maybe_wait_on_main(|delegate| delegate.drag_window());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn drag_resize_window(
|
||||
@@ -334,6 +335,27 @@ impl CoreWindow for Window {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct WindowId(pub usize);
|
||||
|
||||
impl WindowId {
|
||||
pub const fn dummy() -> Self {
|
||||
Self(0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<WindowId> for u64 {
|
||||
fn from(window_id: WindowId) -> Self {
|
||||
window_id.0 as u64
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u64> for WindowId {
|
||||
fn from(raw_id: u64) -> Self {
|
||||
Self(raw_id as usize)
|
||||
}
|
||||
}
|
||||
|
||||
declare_class!(
|
||||
#[derive(Debug)]
|
||||
pub struct WinitWindow;
|
||||
@@ -364,6 +386,6 @@ declare_class!(
|
||||
|
||||
impl WinitWindow {
|
||||
pub(super) fn id(&self) -> WindowId {
|
||||
WindowId::from_raw(self as *const Self as usize)
|
||||
WindowId(self as *const Self as usize)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,14 +33,14 @@ use super::monitor::{self, flip_window_screen_coordinates, get_display_id};
|
||||
use super::observer::RunLoop;
|
||||
use super::view::WinitView;
|
||||
use super::window::WinitWindow;
|
||||
use super::{ffi, Fullscreen, MonitorHandle};
|
||||
use super::{ffi, Fullscreen, MonitorHandle, WindowId};
|
||||
use crate::dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Position, Size};
|
||||
use crate::error::{NotSupportedError, RequestError};
|
||||
use crate::event::{SurfaceSizeWriter, WindowEvent};
|
||||
use crate::platform::macos::{OptionAsAlt, WindowExtMacOS};
|
||||
use crate::window::{
|
||||
Cursor, CursorGrabMode, Icon, ImePurpose, ResizeDirection, Theme, UserAttentionType,
|
||||
WindowAttributes, WindowButtons, WindowId, WindowLevel,
|
||||
WindowAttributes, WindowButtons, WindowId as RootWindowId, WindowLevel,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
@@ -88,8 +88,8 @@ pub(crate) struct State {
|
||||
|
||||
// During `windowDidResize`, we use this to only send Moved if the position changed.
|
||||
//
|
||||
// This is expressed in desktop coordinates, and flipped to match Winit's coordinate system.
|
||||
previous_position: Cell<NSPoint>,
|
||||
// This is expressed in native screen coordinates.
|
||||
previous_position: Cell<Option<NSPoint>>,
|
||||
|
||||
// Used to prevent redundant events.
|
||||
previous_scale_factor: Cell<f64>,
|
||||
@@ -218,10 +218,10 @@ declare_class!(
|
||||
trace_scope!("windowDidResignKey:");
|
||||
// It happens rather often, e.g. when the user is Cmd+Tabbing, that the
|
||||
// NSWindowDelegate will receive a didResignKey event despite no event
|
||||
// being received when the modifiers are released. This is because
|
||||
// being received when the modifiers are released. This is because
|
||||
// flagsChanged events are received by the NSView instead of the
|
||||
// NSWindowDelegate, and as a result a tracked modifiers state can quite
|
||||
// easily fall out of synchrony with reality. This requires us to emit
|
||||
// easily fall out of synchrony with reality. This requires us to emit
|
||||
// a synthetic ModifiersChanged event when we lose focus.
|
||||
self.view().reset_modifiers();
|
||||
|
||||
@@ -722,7 +722,7 @@ impl WindowDelegate {
|
||||
let delegate = mtm.alloc().set_ivars(State {
|
||||
app_state: Rc::clone(app_state),
|
||||
window: window.retain(),
|
||||
previous_position: Cell::new(flip_window_screen_coordinates(window.frame())),
|
||||
previous_position: Cell::new(None),
|
||||
previous_scale_factor: Cell::new(scale_factor),
|
||||
surface_resize_increments: Cell::new(surface_resize_increments),
|
||||
decorations: Cell::new(attrs.decorations),
|
||||
@@ -819,7 +819,7 @@ impl WindowDelegate {
|
||||
}
|
||||
|
||||
pub(crate) fn queue_event(&self, event: WindowEvent) {
|
||||
let window_id = self.window().id();
|
||||
let window_id = RootWindowId(self.window().id());
|
||||
self.ivars().app_state.maybe_queue_with_handler(move |app, event_loop| {
|
||||
app.window_event(event_loop, window_id, event);
|
||||
});
|
||||
@@ -849,12 +849,13 @@ impl WindowDelegate {
|
||||
}
|
||||
|
||||
fn emit_move_event(&self) {
|
||||
let position = flip_window_screen_coordinates(self.window().frame());
|
||||
if self.ivars().previous_position.get() == position {
|
||||
let frame = self.window().frame();
|
||||
if self.ivars().previous_position.get() == Some(frame.origin) {
|
||||
return;
|
||||
}
|
||||
self.ivars().previous_position.set(position);
|
||||
self.ivars().previous_position.set(Some(frame.origin));
|
||||
|
||||
let position = flip_window_screen_coordinates(frame);
|
||||
let position =
|
||||
LogicalPosition::new(position.x, position.y).to_physical(self.scale_factor());
|
||||
self.queue_event(WindowEvent::Moved(position));
|
||||
@@ -1171,12 +1172,10 @@ impl WindowDelegate {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn drag_window(&self) -> Result<(), RequestError> {
|
||||
pub fn drag_window(&self) {
|
||||
let mtm = MainThreadMarker::from(self);
|
||||
let event =
|
||||
NSApplication::sharedApplication(mtm).currentEvent().ok_or(RequestError::Ignored)?;
|
||||
let event = NSApplication::sharedApplication(mtm).currentEvent().unwrap();
|
||||
self.window().performWindowDragWithEvent(&event);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
||||
@@ -29,6 +29,7 @@ use crate::application::ApplicationHandler;
|
||||
use crate::dpi::PhysicalSize;
|
||||
use crate::event::{Event, StartCause, SurfaceSizeWriter, WindowEvent};
|
||||
use crate::event_loop::ControlFlow;
|
||||
use crate::window::WindowId as RootWindowId;
|
||||
|
||||
macro_rules! bug {
|
||||
($($msg:tt)*) => {
|
||||
@@ -149,8 +150,6 @@ impl AppState {
|
||||
// must be mut because plain `static` requires `Sync`
|
||||
static mut APP_STATE: RefCell<Option<AppState>> = RefCell::new(None);
|
||||
|
||||
#[allow(unknown_lints)] // New lint below
|
||||
#[allow(static_mut_refs)] // TODO: Use `MainThreadBound` instead.
|
||||
let mut guard = unsafe { APP_STATE.borrow_mut() };
|
||||
if guard.is_none() {
|
||||
#[inline(never)]
|
||||
@@ -598,7 +597,7 @@ pub(crate) fn send_occluded_event_for_all_windows(application: &UIApplication, o
|
||||
&*ptr
|
||||
};
|
||||
events.push(EventWrapper::StaticEvent(Event::WindowEvent {
|
||||
window_id: window.id(),
|
||||
window_id: RootWindowId(window.id()),
|
||||
event: WindowEvent::Occluded(occluded),
|
||||
}));
|
||||
}
|
||||
@@ -625,7 +624,7 @@ pub fn handle_main_events_cleared(mtm: MainThreadMarker) {
|
||||
.into_iter()
|
||||
.map(|window| {
|
||||
EventWrapper::StaticEvent(Event::WindowEvent {
|
||||
window_id: window.id(),
|
||||
window_id: RootWindowId(window.id()),
|
||||
event: WindowEvent::RedrawRequested,
|
||||
})
|
||||
})
|
||||
@@ -654,7 +653,7 @@ pub(crate) fn terminated(application: &UIApplication) {
|
||||
&*ptr
|
||||
};
|
||||
events.push(EventWrapper::StaticEvent(Event::WindowEvent {
|
||||
window_id: window.id(),
|
||||
window_id: RootWindowId(window.id()),
|
||||
event: WindowEvent::Destroyed,
|
||||
}));
|
||||
}
|
||||
@@ -672,7 +671,7 @@ fn handle_hidpi_proxy(mtm: MainThreadMarker, event: ScaleFactorChanged) {
|
||||
let ScaleFactorChanged { suggested_size, scale_factor, window } = event;
|
||||
let new_surface_size = Arc::new(Mutex::new(suggested_size));
|
||||
let event = Event::WindowEvent {
|
||||
window_id: window.id(),
|
||||
window_id: RootWindowId(window.id()),
|
||||
event: WindowEvent::ScaleFactorChanged {
|
||||
scale_factor,
|
||||
surface_size_writer: SurfaceSizeWriter::new(Arc::downgrade(&new_surface_size)),
|
||||
|
||||
@@ -14,18 +14,33 @@ pub(crate) use self::event_loop::{
|
||||
PlatformSpecificEventLoopAttributes,
|
||||
};
|
||||
pub(crate) use self::monitor::{MonitorHandle, VideoModeHandle};
|
||||
pub(crate) use self::window::{PlatformSpecificWindowAttributes, Window};
|
||||
pub(crate) use self::window::{PlatformSpecificWindowAttributes, Window, WindowId};
|
||||
pub(crate) use crate::cursor::{
|
||||
NoCustomCursor as PlatformCustomCursor, NoCustomCursor as PlatformCustomCursorSource,
|
||||
};
|
||||
use crate::event::DeviceId as RootDeviceId;
|
||||
pub(crate) use crate::icon::NoIcon as PlatformIcon;
|
||||
pub(crate) use crate::platform_impl::Fullscreen;
|
||||
|
||||
/// 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 whether 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 fn dummy() -> Self {
|
||||
DeviceId
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) const DEVICE_ID: RootDeviceId = RootDeviceId(DeviceId);
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct FingerId(usize);
|
||||
|
||||
impl FingerId {
|
||||
#[cfg(test)]
|
||||
pub const fn dummy() -> Self {
|
||||
FingerId(0)
|
||||
}
|
||||
|
||||
@@ -14,15 +14,14 @@ use objc2_ui_kit::{
|
||||
|
||||
use super::app_state::{self, EventWrapper};
|
||||
use super::window::WinitUIWindow;
|
||||
use super::FingerId;
|
||||
use super::{FingerId, DEVICE_ID};
|
||||
use crate::dpi::PhysicalPosition;
|
||||
use crate::event::{
|
||||
ButtonSource, ElementState, Event, FingerId as RootFingerId, Force, KeyEvent, PointerKind,
|
||||
PointerSource, TouchPhase, WindowEvent,
|
||||
ElementState, Event, FingerId as RootFingerId, Force, KeyEvent, Touch, TouchPhase, WindowEvent,
|
||||
};
|
||||
use crate::keyboard::{Key, KeyCode, KeyLocation, NamedKey, NativeKeyCode, PhysicalKey};
|
||||
use crate::platform_impl::KeyEventExtra;
|
||||
use crate::window::WindowAttributes;
|
||||
use crate::window::{WindowAttributes, WindowId as RootWindowId};
|
||||
|
||||
pub struct WinitViewState {
|
||||
pinch_gesture_recognizer: RefCell<Option<Retained<UIPinchGestureRecognizer>>>,
|
||||
@@ -58,7 +57,7 @@ declare_class!(
|
||||
app_state::handle_nonuser_event(
|
||||
mtm,
|
||||
EventWrapper::StaticEvent(Event::WindowEvent {
|
||||
window_id: window.id(),
|
||||
window_id: RootWindowId(window.id()),
|
||||
event: WindowEvent::RedrawRequested,
|
||||
}),
|
||||
);
|
||||
@@ -93,7 +92,7 @@ declare_class!(
|
||||
app_state::handle_nonuser_event(
|
||||
mtm,
|
||||
EventWrapper::StaticEvent(Event::WindowEvent {
|
||||
window_id: window.id(),
|
||||
window_id: RootWindowId(window.id()),
|
||||
event: WindowEvent::SurfaceResized(size),
|
||||
}),
|
||||
);
|
||||
@@ -132,7 +131,7 @@ declare_class!(
|
||||
width: screen_frame.size.width 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(
|
||||
mtm,
|
||||
std::iter::once(EventWrapper::ScaleFactorChanged(
|
||||
@@ -197,9 +196,9 @@ declare_class!(
|
||||
};
|
||||
|
||||
let gesture_event = EventWrapper::StaticEvent(Event::WindowEvent {
|
||||
window_id: window.id(),
|
||||
window_id: RootWindowId(window.id()),
|
||||
event: WindowEvent::PinchGesture {
|
||||
device_id: None,
|
||||
device_id: DEVICE_ID,
|
||||
delta: delta as f64,
|
||||
phase,
|
||||
},
|
||||
@@ -215,9 +214,9 @@ declare_class!(
|
||||
|
||||
if recognizer.state() == UIGestureRecognizerState::Ended {
|
||||
let gesture_event = EventWrapper::StaticEvent(Event::WindowEvent {
|
||||
window_id: window.id(),
|
||||
window_id: RootWindowId(window.id()),
|
||||
event: WindowEvent::DoubleTapGesture {
|
||||
device_id: None,
|
||||
device_id: DEVICE_ID,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -257,9 +256,9 @@ declare_class!(
|
||||
|
||||
// Make delta negative to match macos, convert to degrees
|
||||
let gesture_event = EventWrapper::StaticEvent(Event::WindowEvent {
|
||||
window_id: window.id(),
|
||||
window_id: RootWindowId(window.id()),
|
||||
event: WindowEvent::RotationGesture {
|
||||
device_id: None,
|
||||
device_id: DEVICE_ID,
|
||||
delta: -delta.to_degrees() as _,
|
||||
phase,
|
||||
},
|
||||
@@ -308,9 +307,9 @@ declare_class!(
|
||||
|
||||
|
||||
let gesture_event = EventWrapper::StaticEvent(Event::WindowEvent {
|
||||
window_id: window.id(),
|
||||
window_id: RootWindowId(window.id()),
|
||||
event: WindowEvent::PanGesture {
|
||||
device_id: None,
|
||||
device_id: DEVICE_ID,
|
||||
delta: PhysicalPosition::new(dx as _, dy as _),
|
||||
phase,
|
||||
},
|
||||
@@ -484,18 +483,25 @@ impl WinitView {
|
||||
for touch in touches {
|
||||
let logical_location = touch.locationInView(None);
|
||||
let touch_type = touch.r#type();
|
||||
let force = if let UITouchType::Pencil = touch_type {
|
||||
None
|
||||
} else if os_supports_force {
|
||||
let force = if os_supports_force {
|
||||
let trait_collection = self.traitCollection();
|
||||
let touch_capability = trait_collection.forceTouchCapability();
|
||||
// Both the OS _and_ the device need to be checked for force touch support.
|
||||
if touch_capability == UIForceTouchCapability::Available {
|
||||
if touch_capability == UIForceTouchCapability::Available
|
||||
|| touch_type == UITouchType::Pencil
|
||||
{
|
||||
let force = touch.force();
|
||||
let max_possible_force = touch.maximumPossibleForce();
|
||||
let altitude_angle: Option<f64> = if touch_type == UITouchType::Pencil {
|
||||
let angle = touch.altitudeAngle();
|
||||
Some(angle as _)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Some(Force::Calibrated {
|
||||
force: force as _,
|
||||
max_possible_force: max_possible_force as _,
|
||||
altitude_angle,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
@@ -505,91 +511,32 @@ impl WinitView {
|
||||
};
|
||||
let touch_id = touch as *const UITouch as usize;
|
||||
let phase = touch.phase();
|
||||
let position = {
|
||||
let phase = match phase {
|
||||
UITouchPhase::Began => TouchPhase::Started,
|
||||
UITouchPhase::Moved => TouchPhase::Moved,
|
||||
// 2 is UITouchPhase::Stationary and is not expected here
|
||||
UITouchPhase::Ended => TouchPhase::Ended,
|
||||
UITouchPhase::Cancelled => TouchPhase::Cancelled,
|
||||
_ => panic!("unexpected touch phase: {phase:?}"),
|
||||
};
|
||||
|
||||
let physical_location = {
|
||||
let scale_factor = self.contentScaleFactor();
|
||||
PhysicalPosition::from_logical::<(f64, f64), f64>(
|
||||
(logical_location.x as _, logical_location.y as _),
|
||||
scale_factor as f64,
|
||||
)
|
||||
};
|
||||
let window_id = window.id();
|
||||
let finger_id = RootFingerId(FingerId(touch_id));
|
||||
|
||||
match phase {
|
||||
UITouchPhase::Began => {
|
||||
touch_events.push(EventWrapper::StaticEvent(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerEntered {
|
||||
device_id: None,
|
||||
position,
|
||||
kind: if let UITouchType::Pencil = touch_type {
|
||||
PointerKind::Unknown
|
||||
} else {
|
||||
PointerKind::Touch(finger_id)
|
||||
},
|
||||
},
|
||||
}));
|
||||
touch_events.push(EventWrapper::StaticEvent(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerButton {
|
||||
device_id: None,
|
||||
state: ElementState::Pressed,
|
||||
position,
|
||||
button: if let UITouchType::Pencil = touch_type {
|
||||
ButtonSource::Unknown(0)
|
||||
} else {
|
||||
ButtonSource::Touch { finger_id, force }
|
||||
},
|
||||
},
|
||||
}));
|
||||
},
|
||||
UITouchPhase::Moved => {
|
||||
touch_events.push(EventWrapper::StaticEvent(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerMoved {
|
||||
device_id: None,
|
||||
position,
|
||||
source: if let UITouchType::Pencil = touch_type {
|
||||
PointerSource::Unknown
|
||||
} else {
|
||||
PointerSource::Touch { finger_id, force }
|
||||
},
|
||||
},
|
||||
}));
|
||||
},
|
||||
// 2 is UITouchPhase::Stationary and is not expected here
|
||||
UITouchPhase::Ended | UITouchPhase::Cancelled => {
|
||||
if let UITouchPhase::Ended = phase {
|
||||
touch_events.push(EventWrapper::StaticEvent(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerButton {
|
||||
device_id: None,
|
||||
state: ElementState::Released,
|
||||
position,
|
||||
button: if let UITouchType::Pencil = touch_type {
|
||||
ButtonSource::Unknown(0)
|
||||
} else {
|
||||
ButtonSource::Touch { finger_id, force }
|
||||
},
|
||||
},
|
||||
}));
|
||||
}
|
||||
|
||||
touch_events.push(EventWrapper::StaticEvent(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerLeft {
|
||||
device_id: None,
|
||||
position: Some(position),
|
||||
kind: if let UITouchType::Pencil = touch_type {
|
||||
PointerKind::Unknown
|
||||
} else {
|
||||
PointerKind::Touch(finger_id)
|
||||
},
|
||||
},
|
||||
}));
|
||||
},
|
||||
_ => panic!("unexpected touch phase: {phase:?}"),
|
||||
}
|
||||
touch_events.push(EventWrapper::StaticEvent(Event::WindowEvent {
|
||||
window_id: RootWindowId(window.id()),
|
||||
event: WindowEvent::Touch(Touch {
|
||||
device_id: DEVICE_ID,
|
||||
finger_id: RootFingerId(FingerId(touch_id)),
|
||||
location: physical_location,
|
||||
force,
|
||||
phase,
|
||||
}),
|
||||
}));
|
||||
}
|
||||
let mtm = MainThreadMarker::new().unwrap();
|
||||
app_state::handle_nonuser_events(mtm, touch_events);
|
||||
@@ -597,7 +544,7 @@ impl WinitView {
|
||||
|
||||
fn handle_insert_text(&self, text: &NSString) {
|
||||
let window = self.window().unwrap();
|
||||
let window_id = window.id();
|
||||
let window_id = RootWindowId(window.id());
|
||||
let mtm = MainThreadMarker::new().unwrap();
|
||||
// send individual events for each character
|
||||
app_state::handle_nonuser_events(
|
||||
@@ -625,7 +572,7 @@ impl WinitView {
|
||||
platform_specific: KeyEventExtra {},
|
||||
},
|
||||
is_synthetic: false,
|
||||
device_id: None,
|
||||
device_id: DEVICE_ID,
|
||||
},
|
||||
})
|
||||
})
|
||||
@@ -635,7 +582,7 @@ impl WinitView {
|
||||
|
||||
fn handle_delete_backward(&self) {
|
||||
let window = self.window().unwrap();
|
||||
let window_id = window.id();
|
||||
let window_id = RootWindowId(window.id());
|
||||
let mtm = MainThreadMarker::new().unwrap();
|
||||
app_state::handle_nonuser_events(
|
||||
mtm,
|
||||
@@ -643,7 +590,7 @@ impl WinitView {
|
||||
EventWrapper::StaticEvent(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::KeyboardInput {
|
||||
device_id: None,
|
||||
device_id: DEVICE_ID,
|
||||
event: KeyEvent {
|
||||
state,
|
||||
logical_key: Key::Named(NamedKey::Backspace),
|
||||
|
||||
@@ -3,9 +3,10 @@
|
||||
use std::collections::VecDeque;
|
||||
|
||||
use objc2::rc::Retained;
|
||||
use objc2::runtime::{AnyObject, NSObject};
|
||||
use objc2::{class, declare_class, msg_send, msg_send_id, mutability, ClassType, DeclaredClass};
|
||||
use objc2_foundation::{
|
||||
CGFloat, CGPoint, CGRect, CGSize, MainThreadBound, MainThreadMarker, NSObject, NSObjectProtocol,
|
||||
CGFloat, CGPoint, CGRect, CGSize, MainThreadBound, MainThreadMarker, NSObjectProtocol,
|
||||
};
|
||||
use objc2_ui_kit::{
|
||||
UIApplication, UICoordinateSpace, UIResponder, UIScreen, UIScreenOverscanCompensation,
|
||||
@@ -26,7 +27,7 @@ use crate::monitor::MonitorHandle as CoreMonitorHandle;
|
||||
use crate::platform::ios::{ScreenEdge, StatusBarStyle, ValidOrientations};
|
||||
use crate::window::{
|
||||
CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType, Window as CoreWindow,
|
||||
WindowAttributes, WindowButtons, WindowId, WindowLevel,
|
||||
WindowAttributes, WindowButtons, WindowId as CoreWindowId, WindowLevel,
|
||||
};
|
||||
|
||||
declare_class!(
|
||||
@@ -49,7 +50,7 @@ declare_class!(
|
||||
app_state::handle_nonuser_event(
|
||||
mtm,
|
||||
EventWrapper::StaticEvent(Event::WindowEvent {
|
||||
window_id: self.id(),
|
||||
window_id: CoreWindowId(self.id()),
|
||||
event: WindowEvent::Focused(true),
|
||||
}),
|
||||
);
|
||||
@@ -62,7 +63,7 @@ declare_class!(
|
||||
app_state::handle_nonuser_event(
|
||||
mtm,
|
||||
EventWrapper::StaticEvent(Event::WindowEvent {
|
||||
window_id: self.id(),
|
||||
window_id: CoreWindowId(self.id()),
|
||||
event: WindowEvent::Focused(false),
|
||||
}),
|
||||
);
|
||||
@@ -105,7 +106,7 @@ impl WinitUIWindow {
|
||||
}
|
||||
|
||||
pub(crate) fn id(&self) -> WindowId {
|
||||
WindowId::from_raw(self as *const Self as usize)
|
||||
(self as *const Self as usize as u64).into()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -522,6 +523,7 @@ impl Window {
|
||||
width: screen_frame.size.width as f64,
|
||||
height: screen_frame.size.height as f64,
|
||||
};
|
||||
let window_id = CoreWindowId(window.id());
|
||||
app_state::handle_nonuser_events(
|
||||
mtm,
|
||||
std::iter::once(EventWrapper::ScaleFactorChanged(app_state::ScaleFactorChanged {
|
||||
@@ -531,7 +533,7 @@ impl Window {
|
||||
}))
|
||||
.chain(std::iter::once(EventWrapper::StaticEvent(
|
||||
Event::WindowEvent {
|
||||
window_id: window.id(),
|
||||
window_id,
|
||||
event: WindowEvent::SurfaceResized(size.to_physical(scale_factor)),
|
||||
},
|
||||
))),
|
||||
@@ -585,7 +587,7 @@ impl rwh_06::HasWindowHandle for Window {
|
||||
|
||||
impl CoreWindow for Window {
|
||||
fn id(&self) -> crate::window::WindowId {
|
||||
self.maybe_wait_on_main(|delegate| delegate.id())
|
||||
self.maybe_wait_on_main(|delegate| crate::window::WindowId(delegate.id()))
|
||||
}
|
||||
|
||||
fn scale_factor(&self) -> f64 {
|
||||
@@ -939,6 +941,38 @@ impl Inner {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct WindowId {
|
||||
window: *mut WinitUIWindow,
|
||||
}
|
||||
|
||||
impl WindowId {
|
||||
pub const 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, PartialEq)]
|
||||
pub struct PlatformSpecificWindowAttributes {
|
||||
pub scale_factor: Option<f64>,
|
||||
|
||||
@@ -638,7 +638,7 @@ pub fn keysym_to_key(keysym: u32) -> Key {
|
||||
// keysyms::ISO_Release_Margin_Left => NamedKey::IsoReleaseMarginLeft,
|
||||
// keysyms::ISO_Release_Margin_Right => NamedKey::IsoReleaseMarginRight,
|
||||
// keysyms::ISO_Release_Both_Margins => NamedKey::IsoReleaseBothMargins,
|
||||
// keysyms::ISO_Fast_Cursor_Left => NamedKey::IsoFastPointerLeft,
|
||||
// keysyms::ISO_Fast_Cursor_Left => NamedKey::IsoFastCursorLeft,
|
||||
// keysyms::ISO_Fast_Cursor_Right => NamedKey::IsoFastCursorRight,
|
||||
// keysyms::ISO_Fast_Cursor_Up => NamedKey::IsoFastCursorUp,
|
||||
// keysyms::ISO_Fast_Cursor_Down => NamedKey::IsoFastCursorDown,
|
||||
|
||||
@@ -107,6 +107,44 @@ impl Default for PlatformSpecificWindowAttributes {
|
||||
pub(crate) static X11_BACKEND: Lazy<Mutex<Result<Arc<XConnection>, XNotSupported>>> =
|
||||
Lazy::new(|| Mutex::new(XConnection::new(Some(x_error_callback)).map(Arc::new)));
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct WindowId(u64);
|
||||
|
||||
impl From<WindowId> for u64 {
|
||||
fn from(window_id: WindowId) -> Self {
|
||||
window_id.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u64> for WindowId {
|
||||
fn from(raw_id: u64) -> Self {
|
||||
Self(raw_id)
|
||||
}
|
||||
}
|
||||
|
||||
impl WindowId {
|
||||
pub const fn dummy() -> Self {
|
||||
Self(0)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub enum DeviceId {
|
||||
#[cfg(x11_platform)]
|
||||
X(x11::DeviceId),
|
||||
#[cfg(wayland_platform)]
|
||||
Wayland(wayland::DeviceId),
|
||||
}
|
||||
|
||||
impl DeviceId {
|
||||
pub const fn dummy() -> Self {
|
||||
#[cfg(wayland_platform)]
|
||||
return DeviceId::Wayland(wayland::DeviceId::dummy());
|
||||
#[cfg(all(not(wayland_platform), x11_platform))]
|
||||
return DeviceId::X(x11::DeviceId::dummy());
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub enum FingerId {
|
||||
#[cfg(x11_platform)]
|
||||
@@ -116,7 +154,6 @@ pub enum FingerId {
|
||||
}
|
||||
|
||||
impl FingerId {
|
||||
#[cfg(test)]
|
||||
pub const fn dummy() -> Self {
|
||||
#[cfg(wayland_platform)]
|
||||
return FingerId::Wayland(wayland::FingerId::dummy());
|
||||
@@ -239,7 +276,7 @@ pub(crate) enum PlatformCustomCursor {
|
||||
|
||||
/// Hooks for X11 errors.
|
||||
#[cfg(x11_platform)]
|
||||
pub(crate) static XLIB_ERROR_HOOKS: Mutex<Vec<XlibErrorHook>> = Mutex::new(Vec::new());
|
||||
pub(crate) static mut XLIB_ERROR_HOOKS: Mutex<Vec<XlibErrorHook>> = Mutex::new(Vec::new());
|
||||
|
||||
#[cfg(x11_platform)]
|
||||
unsafe extern "C" fn x_error_callback(
|
||||
@@ -250,7 +287,7 @@ unsafe extern "C" fn x_error_callback(
|
||||
if let Ok(ref xconn) = *xconn_lock {
|
||||
// Call all the hooks.
|
||||
let mut error_handled = false;
|
||||
for hook in XLIB_ERROR_HOOKS.lock().unwrap().iter() {
|
||||
for hook in unsafe { XLIB_ERROR_HOOKS.lock() }.unwrap().iter() {
|
||||
error_handled |= hook(display as *mut _, event as *mut _);
|
||||
}
|
||||
|
||||
@@ -312,8 +349,8 @@ impl EventLoop {
|
||||
"Initializing the event loop outside of the main thread is a significant \
|
||||
cross-platform compatibility hazard. If you absolutely need to create an \
|
||||
EventLoop on a different thread, you can use the \
|
||||
`EventLoopBuilderExtX11::with_any_thread` or \
|
||||
`EventLoopBuilderExtWayland::with_any_thread` functions."
|
||||
`EventLoopBuilderExtX11::any_thread` or `EventLoopBuilderExtWayland::any_thread` \
|
||||
functions."
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ use sink::EventSink;
|
||||
|
||||
use super::state::{WindowCompositorUpdate, WinitState};
|
||||
use super::window::state::FrameCallbackState;
|
||||
use super::{logical_to_physical_rounded, WindowId};
|
||||
use super::{logical_to_physical_rounded, DeviceId, WindowId};
|
||||
|
||||
type WaylandDispatcher = calloop::Dispatcher<'static, WaylandSource<WinitState>, WinitState>;
|
||||
|
||||
@@ -312,12 +312,13 @@ impl EventLoop {
|
||||
let old_physical_size = physical_size;
|
||||
|
||||
let new_surface_size = Arc::new(Mutex::new(physical_size));
|
||||
let root_window_id = crate::window::WindowId(window_id);
|
||||
let event = WindowEvent::ScaleFactorChanged {
|
||||
scale_factor,
|
||||
surface_size_writer: SurfaceSizeWriter::new(Arc::downgrade(&new_surface_size)),
|
||||
};
|
||||
|
||||
app.window_event(&self.active_event_loop, window_id, event);
|
||||
app.window_event(&self.active_event_loop, root_window_id, event);
|
||||
|
||||
let physical_size = *new_surface_size.lock().unwrap();
|
||||
drop(new_surface_size);
|
||||
@@ -360,11 +361,13 @@ impl EventLoop {
|
||||
size
|
||||
});
|
||||
|
||||
let window_id = crate::window::WindowId(window_id);
|
||||
let event = WindowEvent::SurfaceResized(physical_size);
|
||||
app.window_event(&self.active_event_loop, window_id, event);
|
||||
}
|
||||
|
||||
if compositor_update.close_window {
|
||||
let window_id = crate::window::WindowId(window_id);
|
||||
app.window_event(&self.active_event_loop, window_id, WindowEvent::CloseRequested);
|
||||
}
|
||||
}
|
||||
@@ -434,7 +437,8 @@ impl EventLoop {
|
||||
});
|
||||
|
||||
if let Some(event) = event {
|
||||
app.window_event(&self.active_event_loop, *window_id, event);
|
||||
let window_id = crate::window::WindowId(*window_id);
|
||||
app.window_event(&self.active_event_loop, window_id, event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
|
||||
use std::vec::Drain;
|
||||
|
||||
use crate::event::{DeviceEvent, Event, WindowEvent};
|
||||
use crate::window::WindowId;
|
||||
use super::{DeviceId, WindowId};
|
||||
use crate::event::{DeviceEvent, DeviceId as RootDeviceId, Event, WindowEvent};
|
||||
use crate::platform_impl::platform::DeviceId as PlatformDeviceId;
|
||||
use crate::window::WindowId as RootWindowId;
|
||||
|
||||
/// An event loop's sink to deliver events from the Wayland event callbacks
|
||||
/// to the winit's user.
|
||||
@@ -25,14 +27,17 @@ impl EventSink {
|
||||
|
||||
/// Add new device event to a queue.
|
||||
#[inline]
|
||||
pub fn push_device_event(&mut self, event: DeviceEvent) {
|
||||
self.window_events.push(Event::DeviceEvent { event, device_id: None });
|
||||
pub fn push_device_event(&mut self, event: DeviceEvent, device_id: DeviceId) {
|
||||
self.window_events.push(Event::DeviceEvent {
|
||||
event,
|
||||
device_id: RootDeviceId(PlatformDeviceId::Wayland(device_id)),
|
||||
});
|
||||
}
|
||||
|
||||
/// Add new window event to a queue.
|
||||
#[inline]
|
||||
pub fn push_window_event(&mut self, event: WindowEvent, window_id: WindowId) {
|
||||
self.window_events.push(Event::WindowEvent { event, window_id });
|
||||
self.window_events.push(Event::WindowEvent { event, window_id: RootWindowId(window_id) });
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
||||
@@ -8,7 +8,7 @@ pub use window::Window;
|
||||
|
||||
pub(super) use crate::cursor::OnlyCursorImage as CustomCursor;
|
||||
use crate::dpi::{LogicalSize, PhysicalSize};
|
||||
use crate::window::WindowId;
|
||||
pub use crate::platform_impl::platform::WindowId;
|
||||
|
||||
mod event_loop;
|
||||
mod output;
|
||||
@@ -17,11 +17,20 @@ mod state;
|
||||
mod types;
|
||||
mod window;
|
||||
|
||||
/// Dummy device id, since Wayland doesn't have device events.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct DeviceId;
|
||||
|
||||
impl DeviceId {
|
||||
pub const fn dummy() -> Self {
|
||||
DeviceId
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct FingerId(i32);
|
||||
|
||||
impl FingerId {
|
||||
#[cfg(test)]
|
||||
pub const fn dummy() -> Self {
|
||||
FingerId(0)
|
||||
}
|
||||
@@ -30,7 +39,7 @@ impl FingerId {
|
||||
/// Get the WindowId out of the surface.
|
||||
#[inline]
|
||||
fn make_wid(surface: &WlSurface) -> WindowId {
|
||||
WindowId::from_raw(surface.id().as_ptr() as usize)
|
||||
WindowId(surface.id().as_ptr() as u64)
|
||||
}
|
||||
|
||||
/// The default routine does floor, but we need round on Wayland.
|
||||
|
||||
@@ -17,7 +17,7 @@ use crate::keyboard::ModifiersState;
|
||||
use crate::platform_impl::common::xkb::Context;
|
||||
use crate::platform_impl::wayland::event_loop::sink::EventSink;
|
||||
use crate::platform_impl::wayland::state::WinitState;
|
||||
use crate::platform_impl::wayland::{self, WindowId};
|
||||
use crate::platform_impl::wayland::{self, DeviceId, WindowId};
|
||||
|
||||
impl Dispatch<WlKeyboard, KeyboardData, WinitState> for WinitState {
|
||||
fn event(
|
||||
@@ -369,9 +369,10 @@ fn key_input(
|
||||
None => return,
|
||||
};
|
||||
|
||||
let device_id = crate::event::DeviceId(crate::platform_impl::DeviceId::Wayland(DeviceId));
|
||||
if let Some(mut key_context) = keyboard_state.xkb_context.key_context() {
|
||||
let event = key_context.process_key_event(keycode, state, repeat);
|
||||
let event = WindowEvent::KeyboardInput { device_id: None, event, is_synthetic: false };
|
||||
let event = WindowEvent::KeyboardInput { device_id, event, is_synthetic: false };
|
||||
event_sink.push_window_event(event, window_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,10 +27,10 @@ use sctk::seat::pointer::{
|
||||
use sctk::seat::SeatState;
|
||||
|
||||
use crate::dpi::{LogicalPosition, PhysicalPosition};
|
||||
use crate::event::{ElementState, MouseButton, MouseScrollDelta, PointerSource, PointerKind, TouchPhase, WindowEvent};
|
||||
use crate::event::{ElementState, MouseButton, MouseScrollDelta, TouchPhase, WindowEvent};
|
||||
|
||||
use crate::platform_impl::wayland::state::WinitState;
|
||||
use crate::platform_impl::wayland::{self, WindowId};
|
||||
use crate::platform_impl::wayland::{self, DeviceId, WindowId};
|
||||
|
||||
pub mod relative_pointer;
|
||||
|
||||
@@ -59,6 +59,8 @@ impl PointerHandler for WinitState {
|
||||
},
|
||||
};
|
||||
|
||||
let device_id = crate::event::DeviceId(crate::platform_impl::DeviceId::Wayland(DeviceId));
|
||||
|
||||
for event in events {
|
||||
let surface = &event.surface;
|
||||
|
||||
@@ -122,19 +124,18 @@ impl PointerHandler for WinitState {
|
||||
},
|
||||
// Regular events on the main surface.
|
||||
PointerEventKind::Enter { .. } => {
|
||||
self.events_sink.push_window_event(
|
||||
WindowEvent::PointerEntered {
|
||||
device_id: None,
|
||||
position,
|
||||
kind: PointerKind::Mouse,
|
||||
},
|
||||
window_id,
|
||||
);
|
||||
self.events_sink
|
||||
.push_window_event(WindowEvent::CursorEntered { device_id }, window_id);
|
||||
|
||||
window.pointer_entered(Arc::downgrade(themed_pointer));
|
||||
|
||||
// Set the currently focused surface.
|
||||
pointer.winit_data().inner.lock().unwrap().surface = Some(window_id);
|
||||
|
||||
self.events_sink.push_window_event(
|
||||
WindowEvent::CursorMoved { device_id, position },
|
||||
window_id,
|
||||
);
|
||||
},
|
||||
PointerEventKind::Leave { .. } => {
|
||||
window.pointer_left(Arc::downgrade(themed_pointer));
|
||||
@@ -142,22 +143,12 @@ impl PointerHandler for WinitState {
|
||||
// Remove the active surface.
|
||||
pointer.winit_data().inner.lock().unwrap().surface = None;
|
||||
|
||||
self.events_sink.push_window_event(
|
||||
WindowEvent::PointerLeft {
|
||||
device_id: None,
|
||||
position: Some(position),
|
||||
kind: PointerKind::Mouse,
|
||||
},
|
||||
window_id,
|
||||
);
|
||||
self.events_sink
|
||||
.push_window_event(WindowEvent::CursorLeft { device_id }, window_id);
|
||||
},
|
||||
PointerEventKind::Motion { .. } => {
|
||||
self.events_sink.push_window_event(
|
||||
WindowEvent::PointerMoved {
|
||||
device_id: None,
|
||||
position,
|
||||
source: PointerSource::Mouse,
|
||||
},
|
||||
WindowEvent::CursorMoved { device_id, position },
|
||||
window_id,
|
||||
);
|
||||
},
|
||||
@@ -173,12 +164,7 @@ impl PointerHandler for WinitState {
|
||||
ElementState::Released
|
||||
};
|
||||
self.events_sink.push_window_event(
|
||||
WindowEvent::PointerButton {
|
||||
device_id: None,
|
||||
state,
|
||||
position,
|
||||
button: button.into(),
|
||||
},
|
||||
WindowEvent::MouseInput { device_id, state, button },
|
||||
window_id,
|
||||
);
|
||||
},
|
||||
@@ -223,7 +209,7 @@ impl PointerHandler for WinitState {
|
||||
};
|
||||
|
||||
self.events_sink.push_window_event(
|
||||
WindowEvent::MouseWheel { device_id: None, delta, phase },
|
||||
WindowEvent::MouseWheel { device_id, delta, phase },
|
||||
window_id,
|
||||
)
|
||||
},
|
||||
|
||||
@@ -66,9 +66,10 @@ impl Dispatch<ZwpRelativePointerV1, GlobalData, WinitState> for RelativePointerS
|
||||
},
|
||||
_ => return,
|
||||
};
|
||||
state
|
||||
.events_sink
|
||||
.push_device_event(DeviceEvent::PointerMotion { delta: (dx_unaccel, dy_unaccel) });
|
||||
state.events_sink.push_device_event(
|
||||
DeviceEvent::MouseMotion { delta: (dx_unaccel, dy_unaccel) },
|
||||
super::DeviceId,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,9 +8,9 @@ use sctk::seat::touch::{TouchData, TouchHandler};
|
||||
use tracing::warn;
|
||||
|
||||
use crate::dpi::LogicalPosition;
|
||||
use crate::event::{ButtonSource, ElementState, PointerKind, PointerSource, WindowEvent};
|
||||
use crate::event::{Touch, TouchPhase, WindowEvent};
|
||||
use crate::platform_impl::wayland::state::WinitState;
|
||||
use crate::platform_impl::wayland::{self, FingerId};
|
||||
use crate::platform_impl::wayland::{self, DeviceId, FingerId};
|
||||
|
||||
impl TouchHandler for WinitState {
|
||||
fn down(
|
||||
@@ -42,25 +42,18 @@ impl TouchHandler for WinitState {
|
||||
let location = LogicalPosition::<f64>::from(position);
|
||||
seat_state.touch_map.insert(id, TouchPoint { surface, location });
|
||||
|
||||
let position = location.to_physical(scale_factor);
|
||||
let finger_id =
|
||||
crate::event::FingerId(crate::platform_impl::FingerId::Wayland(FingerId(id)));
|
||||
|
||||
self.events_sink.push_window_event(
|
||||
WindowEvent::PointerEntered {
|
||||
device_id: None,
|
||||
position,
|
||||
kind: PointerKind::Touch(finger_id),
|
||||
},
|
||||
window_id,
|
||||
);
|
||||
self.events_sink.push_window_event(
|
||||
WindowEvent::PointerButton {
|
||||
device_id: None,
|
||||
state: ElementState::Pressed,
|
||||
position,
|
||||
button: ButtonSource::Touch { finger_id, force: None },
|
||||
},
|
||||
WindowEvent::Touch(Touch {
|
||||
device_id: crate::event::DeviceId(crate::platform_impl::DeviceId::Wayland(
|
||||
DeviceId,
|
||||
)),
|
||||
phase: TouchPhase::Started,
|
||||
location: location.to_physical(scale_factor),
|
||||
force: None,
|
||||
finger_id: crate::event::FingerId(crate::platform_impl::FingerId::Wayland(
|
||||
FingerId(id),
|
||||
)),
|
||||
}),
|
||||
window_id,
|
||||
);
|
||||
}
|
||||
@@ -94,25 +87,18 @@ impl TouchHandler for WinitState {
|
||||
None => return,
|
||||
};
|
||||
|
||||
let position = touch_point.location.to_physical(scale_factor);
|
||||
let finger_id =
|
||||
crate::event::FingerId(crate::platform_impl::FingerId::Wayland(FingerId(id)));
|
||||
|
||||
self.events_sink.push_window_event(
|
||||
WindowEvent::PointerButton {
|
||||
device_id: None,
|
||||
state: ElementState::Released,
|
||||
position,
|
||||
button: ButtonSource::Touch { finger_id, force: None },
|
||||
},
|
||||
window_id,
|
||||
);
|
||||
self.events_sink.push_window_event(
|
||||
WindowEvent::PointerLeft {
|
||||
device_id: None,
|
||||
position: Some(position),
|
||||
kind: PointerKind::Touch(finger_id),
|
||||
},
|
||||
WindowEvent::Touch(Touch {
|
||||
device_id: crate::event::DeviceId(crate::platform_impl::DeviceId::Wayland(
|
||||
DeviceId,
|
||||
)),
|
||||
phase: TouchPhase::Ended,
|
||||
location: touch_point.location.to_physical(scale_factor),
|
||||
force: None,
|
||||
finger_id: crate::event::FingerId(crate::platform_impl::FingerId::Wayland(
|
||||
FingerId(id),
|
||||
)),
|
||||
}),
|
||||
window_id,
|
||||
);
|
||||
}
|
||||
@@ -149,16 +135,17 @@ impl TouchHandler for WinitState {
|
||||
touch_point.location = LogicalPosition::<f64>::from(position);
|
||||
|
||||
self.events_sink.push_window_event(
|
||||
WindowEvent::PointerMoved {
|
||||
device_id: None,
|
||||
position: touch_point.location.to_physical(scale_factor),
|
||||
source: PointerSource::Touch {
|
||||
finger_id: crate::event::FingerId(crate::platform_impl::FingerId::Wayland(
|
||||
FingerId(id),
|
||||
)),
|
||||
force: None,
|
||||
},
|
||||
},
|
||||
WindowEvent::Touch(Touch {
|
||||
device_id: crate::event::DeviceId(crate::platform_impl::DeviceId::Wayland(
|
||||
DeviceId,
|
||||
)),
|
||||
phase: TouchPhase::Moved,
|
||||
location: touch_point.location.to_physical(scale_factor),
|
||||
force: None,
|
||||
finger_id: crate::event::FingerId(crate::platform_impl::FingerId::Wayland(
|
||||
FingerId(id),
|
||||
)),
|
||||
}),
|
||||
window_id,
|
||||
);
|
||||
}
|
||||
@@ -179,16 +166,20 @@ impl TouchHandler for WinitState {
|
||||
None => return,
|
||||
};
|
||||
|
||||
let position = touch_point.location.to_physical(scale_factor);
|
||||
let location = touch_point.location.to_physical(scale_factor);
|
||||
|
||||
self.events_sink.push_window_event(
|
||||
WindowEvent::PointerLeft {
|
||||
device_id: None,
|
||||
position: Some(position),
|
||||
kind: PointerKind::Touch(crate::event::FingerId(
|
||||
crate::platform_impl::FingerId::Wayland(FingerId(id)),
|
||||
WindowEvent::Touch(Touch {
|
||||
device_id: crate::event::DeviceId(crate::platform_impl::DeviceId::Wayland(
|
||||
DeviceId,
|
||||
)),
|
||||
},
|
||||
phase: TouchPhase::Cancelled,
|
||||
location,
|
||||
force: None,
|
||||
finger_id: crate::event::FingerId(crate::platform_impl::FingerId::Wayland(
|
||||
FingerId(id),
|
||||
)),
|
||||
}),
|
||||
window_id,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,8 @@ use sctk::reexports::protocols::xdg::activation::v1::client::xdg_activation_v1::
|
||||
|
||||
use crate::event_loop::AsyncRequestSerial;
|
||||
use crate::platform_impl::wayland::state::WinitState;
|
||||
use crate::window::{ActivationToken, WindowId};
|
||||
use crate::platform_impl::WindowId;
|
||||
use crate::window::ActivationToken;
|
||||
|
||||
pub struct XdgActivationState {
|
||||
xdg_activation: XdgActivationV1,
|
||||
|
||||
@@ -16,7 +16,7 @@ use super::event_loop::sink::EventSink;
|
||||
use super::output::MonitorHandle;
|
||||
use super::state::WinitState;
|
||||
use super::types::xdg_activation::XdgActivationTokenData;
|
||||
use super::ActiveEventLoop;
|
||||
use super::{ActiveEventLoop, WindowId};
|
||||
use crate::dpi::{LogicalSize, PhysicalPosition, PhysicalSize, Position, Size};
|
||||
use crate::error::{NotSupportedError, RequestError};
|
||||
use crate::event::{Ime, WindowEvent};
|
||||
@@ -25,8 +25,8 @@ use crate::monitor::MonitorHandle as CoreMonitorHandle;
|
||||
use crate::platform_impl::{Fullscreen, MonitorHandle as PlatformMonitorHandle};
|
||||
use crate::window::{
|
||||
Cursor, CursorGrabMode, Fullscreen as CoreFullscreen, ImePurpose, ResizeDirection, Theme,
|
||||
UserAttentionType, Window as CoreWindow, WindowAttributes, WindowButtons, WindowId,
|
||||
WindowLevel,
|
||||
UserAttentionType, Window as CoreWindow, WindowAttributes, WindowButtons,
|
||||
WindowId as CoreWindowId, WindowLevel,
|
||||
};
|
||||
|
||||
pub(crate) mod state;
|
||||
@@ -273,8 +273,8 @@ impl rwh_06::HasDisplayHandle for Window {
|
||||
}
|
||||
|
||||
impl CoreWindow for Window {
|
||||
fn id(&self) -> WindowId {
|
||||
self.window_id
|
||||
fn id(&self) -> CoreWindowId {
|
||||
CoreWindowId(self.window_id)
|
||||
}
|
||||
|
||||
fn request_redraw(&self) {
|
||||
|
||||
@@ -38,8 +38,8 @@ use crate::platform_impl::wayland::seat::{
|
||||
use crate::platform_impl::wayland::state::{WindowCompositorUpdate, WinitState};
|
||||
use crate::platform_impl::wayland::types::cursor::{CustomCursor, SelectedCursor};
|
||||
use crate::platform_impl::wayland::types::kwin_blur::KWinBlurManager;
|
||||
use crate::platform_impl::PlatformCustomCursor;
|
||||
use crate::window::{CursorGrabMode, CursorIcon, ImePurpose, ResizeDirection, Theme, WindowId};
|
||||
use crate::platform_impl::{PlatformCustomCursor, WindowId};
|
||||
use crate::window::{CursorGrabMode, CursorIcon, ImePurpose, ResizeDirection, Theme};
|
||||
|
||||
#[cfg(feature = "sctk-adwaita")]
|
||||
pub type WinitFrame = sctk_adwaita::AdwaitaFrame<WinitState>;
|
||||
|
||||
@@ -22,8 +22,8 @@ use xkbcommon_dl::xkb_mod_mask_t;
|
||||
|
||||
use crate::dpi::{PhysicalPosition, PhysicalSize};
|
||||
use crate::event::{
|
||||
ButtonSource, DeviceEvent, DeviceId, ElementState, Event, Ime, MouseButton, MouseScrollDelta,
|
||||
PointerKind, PointerSource, RawKeyEvent, SurfaceSizeWriter, TouchPhase, WindowEvent,
|
||||
DeviceEvent, ElementState, Event, Ime, MouseButton, MouseScrollDelta, RawKeyEvent,
|
||||
SurfaceSizeWriter, Touch, TouchPhase, WindowEvent,
|
||||
};
|
||||
use crate::keyboard::ModifiersState;
|
||||
use crate::platform_impl::common::xkb::{self, XkbState};
|
||||
@@ -33,8 +33,8 @@ use crate::platform_impl::platform::x11::ActiveEventLoop;
|
||||
use crate::platform_impl::x11::atoms::*;
|
||||
use crate::platform_impl::x11::util::cookie::GenericEventCookie;
|
||||
use crate::platform_impl::x11::{
|
||||
mkdid, mkfid, mkwid, util, CookieResultExt, Device, DeviceInfo, Dnd, DndState, ImeReceiver,
|
||||
ScrollOrientation, UnownedWindow, WindowId,
|
||||
mkdid, mkfid, mkwid, util, CookieResultExt, Device, DeviceId, DeviceInfo, Dnd, DndState,
|
||||
ImeReceiver, ScrollOrientation, UnownedWindow, WindowId,
|
||||
};
|
||||
|
||||
/// The maximum amount of X modifiers to replay.
|
||||
@@ -142,18 +142,8 @@ impl EventProcessor {
|
||||
{
|
||||
let event_type = xev.get_type();
|
||||
|
||||
// If we have IME disabled, don't try to `filter_event`, since only IME can consume them
|
||||
// and forward back. This is not desired for e.g. games since some IMEs may delay the input
|
||||
// and game can toggle IME back when e.g. typing into some field where latency won't really
|
||||
// matter.
|
||||
if event_type == xlib::KeyPress || event_type == xlib::KeyRelease {
|
||||
let ime = self.target.ime.as_ref();
|
||||
let window = self.active_window.map(|window| window as XWindow);
|
||||
let forward_to_ime = ime
|
||||
.and_then(|ime| window.map(|window| ime.borrow().is_ime_allowed(window)))
|
||||
.unwrap_or(false);
|
||||
|
||||
if forward_to_ime && self.filter_event(xev) {
|
||||
if self.filter_event(xev) {
|
||||
if event_type == xlib::KeyPress || event_type == xlib::KeyRelease {
|
||||
let xev: &XKeyEvent = xev.as_ref();
|
||||
if self.xmodmap.is_modifier(xev.keycode as u8) {
|
||||
// Don't grow the buffer past the `MAX_MOD_REPLAY_LEN`. This could happen
|
||||
@@ -166,8 +156,7 @@ impl EventProcessor {
|
||||
self.xfiltered_modifiers.push_front(xev.serial);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.filter_event(xev);
|
||||
return;
|
||||
}
|
||||
|
||||
match event_type {
|
||||
@@ -249,8 +238,15 @@ impl EventProcessor {
|
||||
self.xinput2_unfocused(xev, &mut callback);
|
||||
},
|
||||
xinput2::XI_TouchBegin | xinput2::XI_TouchUpdate | xinput2::XI_TouchEnd => {
|
||||
let phase = match evtype {
|
||||
xinput2::XI_TouchBegin => TouchPhase::Started,
|
||||
xinput2::XI_TouchUpdate => TouchPhase::Moved,
|
||||
xinput2::XI_TouchEnd => TouchPhase::Ended,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let xev: &XIDeviceEvent = unsafe { xev.as_event() };
|
||||
self.xinput2_touch(xev, evtype, &mut callback);
|
||||
self.xinput2_touch(xev, phase, &mut callback);
|
||||
},
|
||||
xinput2::XI_RawButtonPress | xinput2::XI_RawButtonRelease => {
|
||||
let state = match evtype {
|
||||
@@ -330,7 +326,7 @@ impl EventProcessor {
|
||||
let mut devices = self.devices.borrow_mut();
|
||||
if let Some(info) = DeviceInfo::get(&self.target.xconn, device as _) {
|
||||
for info in info.iter() {
|
||||
devices.insert(mkdid(info.deviceid as xinput::DeviceId), Device::new(info));
|
||||
devices.insert(DeviceId(info.deviceid as _), Device::new(info));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -340,7 +336,7 @@ impl EventProcessor {
|
||||
F: Fn(&Arc<UnownedWindow>) -> Ret,
|
||||
{
|
||||
let mut deleted = false;
|
||||
let window_id = WindowId::from_raw(window_id as _);
|
||||
let window_id = WindowId(window_id as _);
|
||||
let result = self
|
||||
.target
|
||||
.windows
|
||||
@@ -809,7 +805,7 @@ impl EventProcessor {
|
||||
|
||||
// In the event that the window's been destroyed without being dropped first, we
|
||||
// cleanup again here.
|
||||
self.target.windows.borrow_mut().remove(&WindowId::from_raw(window as _));
|
||||
self.target.windows.borrow_mut().remove(&WindowId(window as _));
|
||||
|
||||
// Since all XIM stuff needs to happen from the same thread, we destroy the input
|
||||
// context here instead of when dropping the window.
|
||||
@@ -882,6 +878,7 @@ impl EventProcessor {
|
||||
};
|
||||
|
||||
let window_id = mkwid(window);
|
||||
let device_id = mkdid(util::VIRTUAL_CORE_KEYBOARD);
|
||||
|
||||
let keycode = xev.keycode as _;
|
||||
|
||||
@@ -945,11 +942,7 @@ impl EventProcessor {
|
||||
let event = key_processor.process_key_event(keycode, state, repeat);
|
||||
let event = Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::KeyboardInput {
|
||||
device_id: None,
|
||||
event,
|
||||
is_synthetic: false,
|
||||
},
|
||||
event: WindowEvent::KeyboardInput { device_id, event, is_synthetic: false },
|
||||
};
|
||||
callback(&self.target, event);
|
||||
}
|
||||
@@ -1019,7 +1012,7 @@ impl EventProcessor {
|
||||
F: FnMut(&ActiveEventLoop, Event),
|
||||
{
|
||||
let window_id = mkwid(event.event as xproto::Window);
|
||||
let device_id = Some(mkdid(event.deviceid as xinput::DeviceId));
|
||||
let device_id = mkdid(event.deviceid as xinput::DeviceId);
|
||||
|
||||
// Set the timestamp.
|
||||
self.target.xconn.set_timestamp(event.time as xproto::Timestamp);
|
||||
@@ -1029,27 +1022,16 @@ impl EventProcessor {
|
||||
return;
|
||||
}
|
||||
|
||||
let position = PhysicalPosition::new(event.event_x, event.event_y);
|
||||
|
||||
let event = match event.detail as u32 {
|
||||
xlib::Button1 => WindowEvent::PointerButton {
|
||||
device_id,
|
||||
state,
|
||||
position,
|
||||
button: MouseButton::Left.into(),
|
||||
xlib::Button1 => {
|
||||
WindowEvent::MouseInput { device_id, state, button: MouseButton::Left }
|
||||
},
|
||||
xlib::Button2 => WindowEvent::PointerButton {
|
||||
device_id,
|
||||
state,
|
||||
position,
|
||||
button: MouseButton::Middle.into(),
|
||||
xlib::Button2 => {
|
||||
WindowEvent::MouseInput { device_id, state, button: MouseButton::Middle }
|
||||
},
|
||||
|
||||
xlib::Button3 => WindowEvent::PointerButton {
|
||||
device_id,
|
||||
state,
|
||||
position,
|
||||
button: MouseButton::Right.into(),
|
||||
xlib::Button3 => {
|
||||
WindowEvent::MouseInput { device_id, state, button: MouseButton::Right }
|
||||
},
|
||||
|
||||
// Suppress emulated scroll wheel clicks, since we handle the real motion events for
|
||||
@@ -1067,25 +1049,10 @@ impl EventProcessor {
|
||||
},
|
||||
phase: TouchPhase::Moved,
|
||||
},
|
||||
8 => WindowEvent::PointerButton {
|
||||
device_id,
|
||||
state,
|
||||
position,
|
||||
button: MouseButton::Back.into(),
|
||||
},
|
||||
8 => WindowEvent::MouseInput { device_id, state, button: MouseButton::Back },
|
||||
|
||||
9 => WindowEvent::PointerButton {
|
||||
device_id,
|
||||
state,
|
||||
position,
|
||||
button: MouseButton::Forward.into(),
|
||||
},
|
||||
x => WindowEvent::PointerButton {
|
||||
device_id,
|
||||
state,
|
||||
position,
|
||||
button: MouseButton::Other(x as u16).into(),
|
||||
},
|
||||
9 => WindowEvent::MouseInput { device_id, state, button: MouseButton::Forward },
|
||||
x => WindowEvent::MouseInput { device_id, state, button: MouseButton::Other(x as u16) },
|
||||
};
|
||||
|
||||
let event = Event::WindowEvent { window_id, event };
|
||||
@@ -1099,7 +1066,7 @@ impl EventProcessor {
|
||||
// Set the timestamp.
|
||||
self.target.xconn.set_timestamp(event.time as xproto::Timestamp);
|
||||
|
||||
let device_id = Some(mkdid(event.deviceid as xinput::DeviceId));
|
||||
let device_id = mkdid(event.deviceid as xinput::DeviceId);
|
||||
let window = event.event as xproto::Window;
|
||||
let window_id = mkwid(window);
|
||||
let new_cursor_pos = (event.event_x, event.event_y);
|
||||
@@ -1114,11 +1081,7 @@ impl EventProcessor {
|
||||
|
||||
let event = Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerMoved {
|
||||
device_id,
|
||||
position,
|
||||
source: PointerSource::Mouse,
|
||||
},
|
||||
event: WindowEvent::CursorMoved { device_id, position },
|
||||
};
|
||||
callback(&self.target, event);
|
||||
} else if cursor_moved.is_none() {
|
||||
@@ -1130,7 +1093,7 @@ impl EventProcessor {
|
||||
slice::from_raw_parts(event.valuators.mask, event.valuators.mask_len as usize)
|
||||
};
|
||||
let mut devices = self.devices.borrow_mut();
|
||||
let physical_device = match devices.get_mut(&mkdid(event.sourceid as xinput::DeviceId)) {
|
||||
let physical_device = match devices.get_mut(&DeviceId(event.sourceid as xinput::DeviceId)) {
|
||||
Some(device) => device,
|
||||
None => return,
|
||||
};
|
||||
@@ -1189,7 +1152,7 @@ impl EventProcessor {
|
||||
if device_info.deviceid == event.sourceid
|
||||
|| device_info.attachment == event.sourceid
|
||||
{
|
||||
let device_id = mkdid(device_info.deviceid as xinput::DeviceId);
|
||||
let device_id = DeviceId(device_info.deviceid as _);
|
||||
if let Some(device) = devices.get_mut(&device_id) {
|
||||
device.reset_scroll_position(device_info);
|
||||
}
|
||||
@@ -1198,16 +1161,15 @@ impl EventProcessor {
|
||||
}
|
||||
|
||||
if self.window_exists(window) {
|
||||
let device_id = Some(device_id);
|
||||
let position = PhysicalPosition::new(event.event_x, event.event_y);
|
||||
|
||||
let event =
|
||||
Event::WindowEvent { window_id, event: WindowEvent::CursorEntered { device_id } };
|
||||
callback(&self.target, event);
|
||||
|
||||
let event = Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerEntered {
|
||||
device_id,
|
||||
position,
|
||||
kind: PointerKind::Mouse,
|
||||
},
|
||||
event: WindowEvent::CursorMoved { device_id, position },
|
||||
};
|
||||
callback(&self.target, event);
|
||||
}
|
||||
@@ -1227,10 +1189,8 @@ impl EventProcessor {
|
||||
if self.window_exists(window) {
|
||||
let event = Event::WindowEvent {
|
||||
window_id: mkwid(window),
|
||||
event: WindowEvent::PointerLeft {
|
||||
device_id: Some(mkdid(event.deviceid as xinput::DeviceId)),
|
||||
position: Some(PhysicalPosition::new(event.event_x, event.event_y)),
|
||||
kind: PointerKind::Mouse,
|
||||
event: WindowEvent::CursorLeft {
|
||||
device_id: mkdid(event.deviceid as xinput::DeviceId),
|
||||
},
|
||||
};
|
||||
callback(&self.target, event);
|
||||
@@ -1281,15 +1241,16 @@ impl EventProcessor {
|
||||
|
||||
// The deviceid for this event is for a keyboard instead of a pointer,
|
||||
// so we have to do a little extra work.
|
||||
let device_id = self
|
||||
let pointer_id = self
|
||||
.devices
|
||||
.borrow()
|
||||
.get(&mkdid(xev.deviceid as xinput::DeviceId))
|
||||
.map(|device| mkdid(device.attachment as xinput::DeviceId));
|
||||
.get(&DeviceId(xev.deviceid as xinput::DeviceId))
|
||||
.map(|device| device.attachment)
|
||||
.unwrap_or(2);
|
||||
|
||||
let event = Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerMoved { device_id, position, source: PointerSource::Mouse },
|
||||
event: WindowEvent::CursorMoved { device_id: mkdid(pointer_id as _), position },
|
||||
};
|
||||
callback(&self.target, event);
|
||||
}
|
||||
@@ -1345,7 +1306,7 @@ impl EventProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
fn xinput2_touch<F>(&mut self, xev: &XIDeviceEvent, phase: i32, mut callback: F)
|
||||
fn xinput2_touch<F>(&mut self, xev: &XIDeviceEvent, phase: TouchPhase, mut callback: F)
|
||||
where
|
||||
F: FnMut(&ActiveEventLoop, Event),
|
||||
{
|
||||
@@ -1356,81 +1317,32 @@ impl EventProcessor {
|
||||
if self.window_exists(window) {
|
||||
let window_id = mkwid(window);
|
||||
let id = xev.detail as u32;
|
||||
let position = PhysicalPosition::new(xev.event_x, xev.event_y);
|
||||
let location = PhysicalPosition::new(xev.event_x, xev.event_y);
|
||||
|
||||
// Mouse cursor position changes when touch events are received.
|
||||
// Only the first concurrently active touch ID moves the mouse cursor.
|
||||
if is_first_touch(&mut self.first_touch, &mut self.num_touch, id, phase) {
|
||||
let event = Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerMoved {
|
||||
device_id: None,
|
||||
position: position.cast(),
|
||||
source: PointerSource::Mouse,
|
||||
event: WindowEvent::CursorMoved {
|
||||
device_id: mkdid(util::VIRTUAL_CORE_POINTER),
|
||||
position: location.cast(),
|
||||
},
|
||||
};
|
||||
callback(&self.target, event);
|
||||
}
|
||||
|
||||
let device_id = Some(mkdid(xev.deviceid as xinput::DeviceId));
|
||||
let finger_id = mkfid(id);
|
||||
|
||||
match phase {
|
||||
xinput2::XI_TouchBegin => {
|
||||
let event = Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerEntered {
|
||||
device_id,
|
||||
position,
|
||||
kind: PointerKind::Touch(finger_id),
|
||||
},
|
||||
};
|
||||
callback(&self.target, event);
|
||||
let event = Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerButton {
|
||||
device_id,
|
||||
state: ElementState::Pressed,
|
||||
position,
|
||||
button: ButtonSource::Touch { finger_id, force: None },
|
||||
},
|
||||
};
|
||||
callback(&self.target, event);
|
||||
},
|
||||
xinput2::XI_TouchUpdate => {
|
||||
let event = Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerMoved {
|
||||
device_id,
|
||||
position,
|
||||
source: PointerSource::Touch { finger_id, force: None },
|
||||
},
|
||||
};
|
||||
callback(&self.target, event);
|
||||
},
|
||||
xinput2::XI_TouchEnd => {
|
||||
let event = Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerButton {
|
||||
device_id,
|
||||
state: ElementState::Released,
|
||||
position,
|
||||
button: ButtonSource::Touch { finger_id, force: None },
|
||||
},
|
||||
};
|
||||
callback(&self.target, event);
|
||||
let event = Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerLeft {
|
||||
device_id,
|
||||
position: Some(position),
|
||||
kind: PointerKind::Touch(finger_id),
|
||||
},
|
||||
};
|
||||
callback(&self.target, event);
|
||||
},
|
||||
_ => unreachable!(),
|
||||
}
|
||||
let event = Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::Touch(Touch {
|
||||
device_id: mkdid(xev.deviceid as xinput::DeviceId),
|
||||
phase,
|
||||
location,
|
||||
force: None, // TODO
|
||||
finger_id: mkfid(id),
|
||||
}),
|
||||
};
|
||||
callback(&self.target, event)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1443,7 +1355,7 @@ impl EventProcessor {
|
||||
|
||||
if xev.flags & xinput2::XIPointerEmulated == 0 {
|
||||
let event = Event::DeviceEvent {
|
||||
device_id: Some(mkdid(xev.deviceid as xinput::DeviceId)),
|
||||
device_id: mkdid(xev.deviceid as xinput::DeviceId),
|
||||
event: DeviceEvent::Button { state, button: xev.detail as u32 },
|
||||
};
|
||||
callback(&self.target, event);
|
||||
@@ -1457,7 +1369,7 @@ impl EventProcessor {
|
||||
// Set the timestamp.
|
||||
self.target.xconn.set_timestamp(xev.time as xproto::Timestamp);
|
||||
|
||||
let did = Some(mkdid(xev.deviceid as xinput::DeviceId));
|
||||
let did = mkdid(xev.deviceid as xinput::DeviceId);
|
||||
|
||||
let mask =
|
||||
unsafe { slice::from_raw_parts(xev.valuators.mask, xev.valuators.mask_len as usize) };
|
||||
@@ -1486,7 +1398,7 @@ impl EventProcessor {
|
||||
if let Some(mouse_delta) = mouse_delta.consume() {
|
||||
let event = Event::DeviceEvent {
|
||||
device_id: did,
|
||||
event: DeviceEvent::PointerMotion { delta: mouse_delta },
|
||||
event: DeviceEvent::MouseMotion { delta: mouse_delta },
|
||||
};
|
||||
callback(&self.target, event);
|
||||
}
|
||||
@@ -1509,7 +1421,7 @@ impl EventProcessor {
|
||||
// Set the timestamp.
|
||||
self.target.xconn.set_timestamp(xev.time as xproto::Timestamp);
|
||||
|
||||
let device_id = Some(mkdid(xev.sourceid as xinput::DeviceId));
|
||||
let device_id = mkdid(xev.sourceid as xinput::DeviceId);
|
||||
let keycode = xev.detail as u32;
|
||||
if keycode < KEYCODE_OFFSET as u32 {
|
||||
return;
|
||||
@@ -1531,7 +1443,7 @@ impl EventProcessor {
|
||||
self.init_device(info.deviceid as xinput::DeviceId);
|
||||
} else if 0 != info.flags & (xinput2::XISlaveRemoved | xinput2::XIMasterRemoved) {
|
||||
let mut devices = self.devices.borrow_mut();
|
||||
devices.remove(&mkdid(info.deviceid as xinput::DeviceId));
|
||||
devices.remove(&DeviceId(info.deviceid as xinput::DeviceId));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1783,6 +1695,8 @@ impl EventProcessor {
|
||||
) where
|
||||
F: FnMut(&ActiveEventLoop, Event),
|
||||
{
|
||||
let device_id = mkdid(util::VIRTUAL_CORE_KEYBOARD);
|
||||
|
||||
// Update modifiers state and emit key events based on which keys are currently pressed.
|
||||
let xcb = target.xconn.xcb_connection().get_raw_xcb_connection();
|
||||
|
||||
@@ -1805,7 +1719,7 @@ impl EventProcessor {
|
||||
let event = key_processor.process_key_event(keycode as u32, state, false);
|
||||
let event = Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::KeyboardInput { device_id: None, event, is_synthetic: true },
|
||||
event: WindowEvent::KeyboardInput { device_id, event, is_synthetic: true },
|
||||
};
|
||||
callback(target, event);
|
||||
}
|
||||
@@ -1850,15 +1764,15 @@ impl EventProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
fn is_first_touch(first: &mut Option<u32>, num: &mut u32, id: u32, phase: i32) -> bool {
|
||||
fn is_first_touch(first: &mut Option<u32>, num: &mut u32, id: u32, phase: TouchPhase) -> bool {
|
||||
match phase {
|
||||
xinput2::XI_TouchBegin => {
|
||||
TouchPhase::Started => {
|
||||
if *num == 0 {
|
||||
*first = Some(id);
|
||||
}
|
||||
*num += 1;
|
||||
},
|
||||
xinput2::XI_TouchEnd => {
|
||||
TouchPhase::Cancelled | TouchPhase::Ended => {
|
||||
if *first == Some(id) {
|
||||
*first = None;
|
||||
}
|
||||
|
||||
@@ -225,16 +225,6 @@ impl Ime {
|
||||
// Create new context supporting IME input.
|
||||
let _ = self.create_context(window, allowed);
|
||||
}
|
||||
|
||||
pub fn is_ime_allowed(&self, window: ffi::Window) -> bool {
|
||||
if self.is_destroyed() {
|
||||
false
|
||||
} else if let Some(Some(context)) = self.inner.contexts.get(&window) {
|
||||
context.is_allowed()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Ime {
|
||||
|
||||
@@ -24,19 +24,19 @@ use x11rb::xcb_ffi::ReplyOrIdError;
|
||||
|
||||
use crate::application::ApplicationHandler;
|
||||
use crate::error::{EventLoopError, RequestError};
|
||||
use crate::event::{DeviceId, Event, StartCause, WindowEvent};
|
||||
use crate::event::{Event, StartCause, WindowEvent};
|
||||
use crate::event_loop::{
|
||||
ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents,
|
||||
OwnedDisplayHandle as RootOwnedDisplayHandle,
|
||||
};
|
||||
use crate::platform::pump_events::PumpStatus;
|
||||
use crate::platform_impl::common::xkb::Context;
|
||||
use crate::platform_impl::platform::min_timeout;
|
||||
use crate::platform_impl::platform::{min_timeout, WindowId};
|
||||
use crate::platform_impl::x11::window::Window;
|
||||
use crate::platform_impl::{OwnedDisplayHandle, PlatformCustomCursor};
|
||||
use crate::window::{
|
||||
CustomCursor as RootCustomCursor, CustomCursorSource, Theme, Window as CoreWindow,
|
||||
WindowAttributes, WindowId,
|
||||
WindowAttributes,
|
||||
};
|
||||
|
||||
mod activation;
|
||||
@@ -521,14 +521,13 @@ impl EventLoop {
|
||||
|
||||
// Empty activation tokens.
|
||||
while let Ok((window_id, serial)) = self.activation_receiver.try_recv() {
|
||||
let token = self
|
||||
.event_processor
|
||||
.with_window(window_id.into_raw() as xproto::Window, |window| {
|
||||
window.generate_activation_token()
|
||||
});
|
||||
let token = self.event_processor.with_window(window_id.0 as xproto::Window, |window| {
|
||||
window.generate_activation_token()
|
||||
});
|
||||
|
||||
match token {
|
||||
Some(Ok(token)) => {
|
||||
let window_id = crate::window::WindowId(window_id);
|
||||
let event = WindowEvent::ActivationTokenDone {
|
||||
serial,
|
||||
token: crate::window::ActivationToken::_new(token),
|
||||
@@ -556,6 +555,7 @@ impl EventLoop {
|
||||
}
|
||||
|
||||
for window_id in windows {
|
||||
let window_id = crate::window::WindowId(window_id);
|
||||
app.window_event(
|
||||
&self.event_processor.target,
|
||||
window_id,
|
||||
@@ -574,9 +574,12 @@ impl EventLoop {
|
||||
while unsafe { self.event_processor.poll_one_event(xev.as_mut_ptr()) } {
|
||||
let mut xev = unsafe { xev.assume_init() };
|
||||
self.event_processor.process_event(&mut xev, |window_target, event: Event| {
|
||||
if let Event::WindowEvent { window_id, event: WindowEvent::RedrawRequested } = event
|
||||
if let Event::WindowEvent {
|
||||
window_id: crate::window::WindowId(wid),
|
||||
event: WindowEvent::RedrawRequested,
|
||||
} = event
|
||||
{
|
||||
window_target.redraw_sender.send(window_id);
|
||||
window_target.redraw_sender.send(wid);
|
||||
} else {
|
||||
match event {
|
||||
Event::WindowEvent { window_id, event } => {
|
||||
@@ -805,11 +808,20 @@ impl<'a> Deref for DeviceInfo<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct DeviceId(xinput::DeviceId);
|
||||
|
||||
impl DeviceId {
|
||||
#[allow(unused)]
|
||||
pub const fn dummy() -> Self {
|
||||
DeviceId(0)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct FingerId(u32);
|
||||
|
||||
impl FingerId {
|
||||
#[cfg(test)]
|
||||
#[allow(unused)]
|
||||
pub const fn dummy() -> Self {
|
||||
FingerId(0)
|
||||
@@ -988,10 +1000,10 @@ impl<'a, E: fmt::Debug> CookieResultExt for Result<VoidCookie<'a>, E> {
|
||||
}
|
||||
|
||||
fn mkwid(w: xproto::Window) -> crate::window::WindowId {
|
||||
crate::window::WindowId::from_raw(w as _)
|
||||
crate::window::WindowId(crate::platform_impl::platform::WindowId(w as _))
|
||||
}
|
||||
fn mkdid(w: xinput::DeviceId) -> DeviceId {
|
||||
DeviceId::from_raw(w as i64)
|
||||
fn mkdid(w: xinput::DeviceId) -> crate::event::DeviceId {
|
||||
crate::event::DeviceId(crate::platform_impl::DeviceId::X(DeviceId(w)))
|
||||
}
|
||||
|
||||
fn mkfid(w: u32) -> crate::event::FingerId {
|
||||
|
||||
@@ -6,6 +6,7 @@ use x11rb::protocol::xkb;
|
||||
use super::*;
|
||||
|
||||
pub const VIRTUAL_CORE_POINTER: u16 = 2;
|
||||
pub const VIRTUAL_CORE_KEYBOARD: u16 = 3;
|
||||
|
||||
// A base buffer size of 1kB uses a negligible amount of RAM while preventing us from having to
|
||||
// re-allocate (and make another round-trip) in the *vast* majority of cases.
|
||||
|
||||
@@ -18,7 +18,7 @@ use x11rb::protocol::{randr, xinput};
|
||||
|
||||
use super::util::{self, SelectedCursor};
|
||||
use super::{
|
||||
ffi, ActiveEventLoop, CookieResultExt, ImeRequest, ImeSender, VoidCookie, XConnection,
|
||||
ffi, ActiveEventLoop, CookieResultExt, ImeRequest, ImeSender, VoidCookie, WindowId, XConnection,
|
||||
};
|
||||
use crate::cursor::{Cursor, CustomCursor as RootCustomCursor};
|
||||
use crate::dpi::{PhysicalPosition, PhysicalSize, Position, Size};
|
||||
@@ -36,7 +36,7 @@ use crate::platform_impl::{
|
||||
};
|
||||
use crate::window::{
|
||||
CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType, Window as CoreWindow,
|
||||
WindowAttributes, WindowButtons, WindowId, WindowLevel,
|
||||
WindowAttributes, WindowButtons, WindowLevel,
|
||||
};
|
||||
|
||||
pub(crate) struct Window(Arc<UnownedWindow>);
|
||||
@@ -62,8 +62,8 @@ impl Window {
|
||||
}
|
||||
|
||||
impl CoreWindow for Window {
|
||||
fn id(&self) -> WindowId {
|
||||
self.0.id()
|
||||
fn id(&self) -> crate::window::WindowId {
|
||||
crate::window::WindowId(self.0.id())
|
||||
}
|
||||
|
||||
fn scale_factor(&self) -> f64 {
|
||||
@@ -331,9 +331,7 @@ impl Drop for Window {
|
||||
window.set_fullscreen(None);
|
||||
}
|
||||
|
||||
if let Ok(c) =
|
||||
xconn.xcb_connection().destroy_window(window.id().into_raw() as xproto::Window)
|
||||
{
|
||||
if let Ok(c) = xconn.xcb_connection().destroy_window(window.id().0 as xproto::Window) {
|
||||
c.ignore_error();
|
||||
}
|
||||
}
|
||||
@@ -1222,10 +1220,11 @@ impl UnownedWindow {
|
||||
&self.shared_state_lock(),
|
||||
);
|
||||
|
||||
let window_id = crate::window::WindowId(self.id());
|
||||
let old_surface_size = PhysicalSize::new(width, height);
|
||||
let surface_size = Arc::new(Mutex::new(PhysicalSize::new(new_width, new_height)));
|
||||
callback(Event::WindowEvent {
|
||||
window_id: self.id(),
|
||||
window_id,
|
||||
event: WindowEvent::ScaleFactorChanged {
|
||||
scale_factor: new_monitor.scale_factor,
|
||||
surface_size_writer: SurfaceSizeWriter::new(Arc::downgrade(&surface_size)),
|
||||
@@ -2135,7 +2134,7 @@ impl UnownedWindow {
|
||||
|
||||
#[inline]
|
||||
pub fn id(&self) -> WindowId {
|
||||
WindowId::from_raw(self.xwindow as _)
|
||||
WindowId(self.xwindow as _)
|
||||
}
|
||||
|
||||
pub(super) fn sync_counter_id(&self) -> Option<NonZeroU32> {
|
||||
@@ -2144,7 +2143,7 @@ impl UnownedWindow {
|
||||
|
||||
#[inline]
|
||||
pub fn request_redraw(&self) {
|
||||
self.redraw_sender.send(WindowId::from_raw(self.xwindow as _));
|
||||
self.redraw_sender.send(WindowId(self.xwindow as _));
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
||||
@@ -12,8 +12,8 @@ use orbclient::{
|
||||
use smol_str::SmolStr;
|
||||
|
||||
use super::{
|
||||
KeyEventExtra, MonitorHandle, PlatformSpecificEventLoopAttributes, RedoxSocket, TimeSocket,
|
||||
WindowProperties,
|
||||
DeviceId, KeyEventExtra, MonitorHandle, PlatformSpecificEventLoopAttributes, RedoxSocket,
|
||||
TimeSocket, WindowId, WindowProperties,
|
||||
};
|
||||
use crate::application::ApplicationHandler;
|
||||
use crate::error::{EventLoopError, NotSupportedError, RequestError};
|
||||
@@ -25,7 +25,8 @@ use crate::keyboard::{
|
||||
};
|
||||
use crate::platform_impl::Window;
|
||||
use crate::window::{
|
||||
CustomCursor as RootCustomCursor, CustomCursorSource, Theme, Window as CoreWindow, WindowId,
|
||||
CustomCursor as RootCustomCursor, CustomCursorSource, Theme, Window as CoreWindow,
|
||||
WindowId as RootWindowId,
|
||||
};
|
||||
|
||||
fn convert_scancode(scancode: u8) -> (PhysicalKey, Option<NamedKey>) {
|
||||
@@ -361,8 +362,9 @@ impl EventLoop {
|
||||
key_without_modifiers = logical_key.clone();
|
||||
}
|
||||
|
||||
let window_id = RootWindowId(window_id);
|
||||
let event = event::WindowEvent::KeyboardInput {
|
||||
device_id: None,
|
||||
device_id: event::DeviceId(DeviceId),
|
||||
event: event::KeyEvent {
|
||||
logical_key,
|
||||
physical_key,
|
||||
@@ -392,61 +394,81 @@ impl EventLoop {
|
||||
EventOption::TextInput(TextInputEvent { character }) => {
|
||||
app.window_event(
|
||||
window_target,
|
||||
window_id,
|
||||
RootWindowId(window_id),
|
||||
event::WindowEvent::Ime(Ime::Preedit("".into(), None)),
|
||||
);
|
||||
app.window_event(
|
||||
window_target,
|
||||
window_id,
|
||||
RootWindowId(window_id),
|
||||
event::WindowEvent::Ime(Ime::Commit(character.into())),
|
||||
);
|
||||
},
|
||||
EventOption::Mouse(MouseEvent { x, y }) => {
|
||||
app.window_event(window_target, window_id, event::WindowEvent::PointerMoved {
|
||||
device_id: None,
|
||||
position: (x, y).into(),
|
||||
source: event::PointerSource::Mouse,
|
||||
});
|
||||
app.window_event(
|
||||
window_target,
|
||||
RootWindowId(window_id),
|
||||
event::WindowEvent::CursorMoved {
|
||||
device_id: event::DeviceId(DeviceId),
|
||||
position: (x, y).into(),
|
||||
},
|
||||
);
|
||||
},
|
||||
EventOption::MouseRelative(MouseRelativeEvent { dx, dy }) => {
|
||||
app.device_event(window_target, None, event::DeviceEvent::PointerMotion {
|
||||
delta: (dx as f64, dy as f64),
|
||||
});
|
||||
app.device_event(
|
||||
window_target,
|
||||
event::DeviceId(DeviceId),
|
||||
event::DeviceEvent::MouseMotion { delta: (dx as f64, dy as f64) },
|
||||
);
|
||||
},
|
||||
EventOption::Button(ButtonEvent { left, middle, right }) => {
|
||||
while let Some((button, state)) = event_state.mouse(left, middle, right) {
|
||||
app.window_event(window_target, window_id, event::WindowEvent::PointerButton {
|
||||
device_id: None,
|
||||
state,
|
||||
position: dpi::PhysicalPosition::default(),
|
||||
button: button.into(),
|
||||
});
|
||||
app.window_event(
|
||||
window_target,
|
||||
RootWindowId(window_id),
|
||||
event::WindowEvent::MouseInput {
|
||||
device_id: event::DeviceId(DeviceId),
|
||||
state,
|
||||
button,
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
EventOption::Scroll(ScrollEvent { x, y }) => {
|
||||
app.window_event(window_target, window_id, event::WindowEvent::MouseWheel {
|
||||
device_id: None,
|
||||
delta: event::MouseScrollDelta::LineDelta(x as f32, y as f32),
|
||||
phase: event::TouchPhase::Moved,
|
||||
});
|
||||
app.window_event(
|
||||
window_target,
|
||||
RootWindowId(window_id),
|
||||
event::WindowEvent::MouseWheel {
|
||||
device_id: event::DeviceId(DeviceId),
|
||||
delta: event::MouseScrollDelta::LineDelta(x as f32, y as f32),
|
||||
phase: event::TouchPhase::Moved,
|
||||
},
|
||||
);
|
||||
},
|
||||
EventOption::Quit(QuitEvent {}) => {
|
||||
app.window_event(window_target, window_id, event::WindowEvent::CloseRequested);
|
||||
app.window_event(
|
||||
window_target,
|
||||
RootWindowId(window_id),
|
||||
event::WindowEvent::CloseRequested,
|
||||
);
|
||||
},
|
||||
EventOption::Focus(FocusEvent { focused }) => {
|
||||
app.window_event(window_target, window_id, event::WindowEvent::Focused(focused));
|
||||
app.window_event(
|
||||
window_target,
|
||||
RootWindowId(window_id),
|
||||
event::WindowEvent::Focused(focused),
|
||||
);
|
||||
},
|
||||
EventOption::Move(MoveEvent { x, y }) => {
|
||||
app.window_event(
|
||||
window_target,
|
||||
window_id,
|
||||
RootWindowId(window_id),
|
||||
event::WindowEvent::Moved((x, y).into()),
|
||||
);
|
||||
},
|
||||
EventOption::Resize(ResizeEvent { width, height }) => {
|
||||
app.window_event(
|
||||
window_target,
|
||||
window_id,
|
||||
RootWindowId(window_id),
|
||||
event::WindowEvent::SurfaceResized((width, height).into()),
|
||||
);
|
||||
|
||||
@@ -456,20 +478,12 @@ impl EventLoop {
|
||||
// TODO: Screen, Clipboard, Drop
|
||||
EventOption::Hover(HoverEvent { entered }) => {
|
||||
let event = if entered {
|
||||
event::WindowEvent::PointerEntered {
|
||||
device_id: None,
|
||||
position: dpi::PhysicalPosition::default(),
|
||||
kind: event::PointerKind::Mouse,
|
||||
}
|
||||
event::WindowEvent::CursorEntered { device_id: event::DeviceId(DeviceId) }
|
||||
} else {
|
||||
event::WindowEvent::PointerLeft {
|
||||
device_id: None,
|
||||
position: None,
|
||||
kind: event::PointerKind::Mouse,
|
||||
}
|
||||
event::WindowEvent::CursorLeft { device_id: event::DeviceId(DeviceId) }
|
||||
};
|
||||
|
||||
app.window_event(window_target, window_id, event);
|
||||
app.window_event(window_target, RootWindowId(window_id), event);
|
||||
},
|
||||
other => {
|
||||
tracing::warn!("unhandled event: {:?}", other);
|
||||
@@ -491,7 +505,7 @@ impl EventLoop {
|
||||
let mut creates = self.window_target.creates.lock().unwrap();
|
||||
creates.pop_front()
|
||||
} {
|
||||
let window_id = WindowId::from_raw(window.fd);
|
||||
let window_id = WindowId { fd: window.fd as u64 };
|
||||
|
||||
let mut buf: [u8; 4096] = [0; 4096];
|
||||
let path = window.fpath(&mut buf).expect("failed to read properties");
|
||||
@@ -499,6 +513,8 @@ impl EventLoop {
|
||||
|
||||
self.windows.push((window, EventState::default()));
|
||||
|
||||
let window_id = RootWindowId(window_id);
|
||||
|
||||
// Send resize event on create to indicate first size.
|
||||
let event = event::WindowEvent::SurfaceResized((properties.w, properties.h).into());
|
||||
app.window_event(&self.window_target, window_id, event);
|
||||
@@ -513,16 +529,16 @@ impl EventLoop {
|
||||
let mut destroys = self.window_target.destroys.lock().unwrap();
|
||||
destroys.pop_front()
|
||||
} {
|
||||
app.window_event(&self.window_target, destroy_id, event::WindowEvent::Destroyed);
|
||||
self.windows
|
||||
.retain(|(window, _event_state)| WindowId::from_raw(window.fd) != destroy_id);
|
||||
let window_id = RootWindowId(destroy_id);
|
||||
app.window_event(&self.window_target, window_id, event::WindowEvent::Destroyed);
|
||||
self.windows.retain(|(window, _event_state)| window.fd as u64 != destroy_id.fd);
|
||||
}
|
||||
|
||||
// Handle window events.
|
||||
let mut i = 0;
|
||||
// While loop is used here because the same window may be processed more than once.
|
||||
while let Some((window, event_state)) = self.windows.get_mut(i) {
|
||||
let window_id = WindowId::from_raw(window.fd);
|
||||
let window_id = WindowId { fd: window.fd as u64 };
|
||||
|
||||
let mut event_buf = [0u8; 16 * mem::size_of::<orbclient::Event>()];
|
||||
let count =
|
||||
@@ -580,7 +596,7 @@ impl EventLoop {
|
||||
} {
|
||||
app.window_event(
|
||||
&self.window_target,
|
||||
window_id,
|
||||
RootWindowId(window_id),
|
||||
event::WindowEvent::RedrawRequested,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -99,11 +99,42 @@ impl TimeSocket {
|
||||
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub(crate) struct PlatformSpecificEventLoopAttributes {}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||
pub struct WindowId {
|
||||
fd: u64,
|
||||
}
|
||||
|
||||
impl WindowId {
|
||||
pub const fn dummy() -> Self {
|
||||
WindowId { fd: u64::MAX }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<WindowId> for u64 {
|
||||
fn from(id: WindowId) -> Self {
|
||||
id.fd
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u64> for WindowId {
|
||||
fn from(fd: u64) -> Self {
|
||||
Self { fd }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||
pub struct DeviceId;
|
||||
|
||||
impl DeviceId {
|
||||
pub const fn dummy() -> Self {
|
||||
DeviceId
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||
pub struct FingerId;
|
||||
|
||||
impl FingerId {
|
||||
#[cfg(test)]
|
||||
pub const fn dummy() -> Self {
|
||||
FingerId
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
use std::collections::VecDeque;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use super::{ActiveEventLoop, MonitorHandle, RedoxSocket, TimeSocket, WindowProperties};
|
||||
use super::{ActiveEventLoop, MonitorHandle, RedoxSocket, TimeSocket, WindowId, WindowProperties};
|
||||
use crate::cursor::Cursor;
|
||||
use crate::dpi::{PhysicalPosition, PhysicalSize, Position, Size};
|
||||
use crate::error::{NotSupportedError, RequestError};
|
||||
use crate::monitor::MonitorHandle as CoreMonitorHandle;
|
||||
use crate::window::{self, Fullscreen, ImePurpose, Window as CoreWindow, WindowId};
|
||||
use crate::window::{self, Fullscreen, ImePurpose, Window as CoreWindow, WindowId as CoreWindowId};
|
||||
|
||||
// These values match the values uses in the `window_new` function in orbital:
|
||||
// https://gitlab.redox-os.org/redox-os/orbital/-/blob/master/src/scheme.rs
|
||||
@@ -155,8 +155,8 @@ impl Window {
|
||||
}
|
||||
|
||||
impl CoreWindow for Window {
|
||||
fn id(&self) -> WindowId {
|
||||
WindowId::from_raw(self.window_socket.fd)
|
||||
fn id(&self) -> CoreWindowId {
|
||||
CoreWindowId(WindowId { fd: self.window_socket.fd as u64 })
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -181,7 +181,7 @@ impl CoreWindow for Window {
|
||||
|
||||
#[inline]
|
||||
fn request_redraw(&self) {
|
||||
let window_id = self.id();
|
||||
let window_id = self.id().0;
|
||||
let mut redraws = self.redraws.lock().unwrap();
|
||||
if !redraws.contains(&window_id) {
|
||||
redraws.push_back(window_id);
|
||||
@@ -478,7 +478,7 @@ impl Drop for Window {
|
||||
fn drop(&mut self) {
|
||||
{
|
||||
let mut destroys = self.destroys.lock().unwrap();
|
||||
destroys.push_back(self.id());
|
||||
destroys.push_back(self.id().0);
|
||||
}
|
||||
|
||||
self.wake_socket.wake().unwrap();
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
use crate::event::{DeviceId, FingerId as RootFingerId};
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct DeviceId(i32);
|
||||
|
||||
pub(crate) fn mkdid(pointer_id: i32) -> Option<DeviceId> {
|
||||
if let Ok(pointer_id) = u32::try_from(pointer_id) {
|
||||
Some(DeviceId::from_raw(pointer_id as i64))
|
||||
} else if pointer_id == -1 {
|
||||
None
|
||||
} else {
|
||||
tracing::error!("found unexpected negative `PointerEvent.pointerId`: {pointer_id}");
|
||||
None
|
||||
impl DeviceId {
|
||||
pub fn new(pointer_id: i32) -> Self {
|
||||
Self(pointer_id)
|
||||
}
|
||||
|
||||
pub const fn dummy() -> Self {
|
||||
Self(-1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ impl FingerId {
|
||||
Self { pointer_id, primary }
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub const fn dummy() -> Self {
|
||||
Self { pointer_id: -1, primary: false }
|
||||
}
|
||||
@@ -31,9 +30,3 @@ impl FingerId {
|
||||
self.primary
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FingerId> for RootFingerId {
|
||||
fn from(id: FingerId) -> Self {
|
||||
Self(id)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use super::{backend, HasMonitorPermissionFuture, MonitorPermissionFuture};
|
||||
use super::{backend, event, window, HasMonitorPermissionFuture, MonitorPermissionFuture};
|
||||
use crate::application::ApplicationHandler;
|
||||
use crate::error::{EventLoopError, NotSupportedError};
|
||||
use crate::event::Event;
|
||||
|
||||
@@ -9,13 +9,16 @@ use wasm_bindgen::JsCast;
|
||||
use web_sys::{Document, KeyboardEvent, Navigator, PageTransitionEvent, PointerEvent, WheelEvent};
|
||||
use web_time::{Duration, Instant};
|
||||
|
||||
use super::super::event;
|
||||
use super::super::main_thread::MainThreadMarker;
|
||||
use super::super::monitor::MonitorHandler;
|
||||
use super::super::DeviceId;
|
||||
use super::backend;
|
||||
use super::state::State;
|
||||
use crate::dpi::PhysicalSize;
|
||||
use crate::event::{DeviceEvent, ElementState, Event, RawKeyEvent, StartCause, WindowEvent};
|
||||
use crate::event::{
|
||||
DeviceEvent, DeviceId as RootDeviceId, ElementState, Event, RawKeyEvent, StartCause,
|
||||
WindowEvent,
|
||||
};
|
||||
use crate::event_loop::{ControlFlow, DeviceEvents};
|
||||
use crate::platform::web::{PollStrategy, WaitUntilStrategy};
|
||||
use crate::platform_impl::platform::backend::EventListenerHandle;
|
||||
@@ -46,7 +49,7 @@ struct Execution {
|
||||
suspended: Cell<bool>,
|
||||
event_loop_recreation: Cell<bool>,
|
||||
events: RefCell<VecDeque<EventWrapper>>,
|
||||
id: Cell<usize>,
|
||||
id: RefCell<u32>,
|
||||
window: web_sys::Window,
|
||||
navigator: Navigator,
|
||||
document: Document,
|
||||
@@ -168,7 +171,7 @@ impl Shared {
|
||||
window,
|
||||
navigator,
|
||||
document,
|
||||
id: Cell::new(0),
|
||||
id: RefCell::new(0),
|
||||
all_canvases: RefCell::new(Vec::new()),
|
||||
redraw_pending: RefCell::new(HashSet::new()),
|
||||
destroy_pending: RefCell::new(VecDeque::new()),
|
||||
@@ -283,7 +286,7 @@ impl Shared {
|
||||
}
|
||||
|
||||
// chorded button event
|
||||
let device_id = event::mkdid(event.pointer_id());
|
||||
let device_id = RootDeviceId(DeviceId::new(event.pointer_id()));
|
||||
|
||||
if let Some(button) = backend::event::mouse_button(&event) {
|
||||
let state = if backend::event::mouse_buttons(&event).contains(button.into()) {
|
||||
@@ -294,7 +297,7 @@ impl Shared {
|
||||
|
||||
runner.send_event(Event::DeviceEvent {
|
||||
device_id,
|
||||
event: DeviceEvent::Button { button: button.to_id().into(), state },
|
||||
event: DeviceEvent::Button { button: button.to_id(), state },
|
||||
});
|
||||
|
||||
return;
|
||||
@@ -307,7 +310,7 @@ impl Shared {
|
||||
|
||||
Event::DeviceEvent {
|
||||
device_id,
|
||||
event: DeviceEvent::PointerMotion { delta: (delta.x, delta.y) },
|
||||
event: DeviceEvent::MouseMotion { delta: (delta.x, delta.y) },
|
||||
}
|
||||
}));
|
||||
}),
|
||||
@@ -324,7 +327,7 @@ impl Shared {
|
||||
|
||||
if let Some(delta) = backend::event::mouse_scroll_delta(&window, &event) {
|
||||
runner.send_event(Event::DeviceEvent {
|
||||
device_id: None,
|
||||
device_id: RootDeviceId(DeviceId::dummy()),
|
||||
event: DeviceEvent::MouseWheel { delta },
|
||||
});
|
||||
}
|
||||
@@ -341,9 +344,9 @@ impl Shared {
|
||||
|
||||
let button = backend::event::mouse_button(&event).expect("no mouse button pressed");
|
||||
runner.send_event(Event::DeviceEvent {
|
||||
device_id: event::mkdid(event.pointer_id()),
|
||||
device_id: RootDeviceId(DeviceId::new(event.pointer_id())),
|
||||
event: DeviceEvent::Button {
|
||||
button: button.to_id().into(),
|
||||
button: button.to_id(),
|
||||
state: ElementState::Pressed,
|
||||
},
|
||||
});
|
||||
@@ -360,9 +363,9 @@ impl Shared {
|
||||
|
||||
let button = backend::event::mouse_button(&event).expect("no mouse button pressed");
|
||||
runner.send_event(Event::DeviceEvent {
|
||||
device_id: event::mkdid(event.pointer_id()),
|
||||
device_id: RootDeviceId(DeviceId::new(event.pointer_id())),
|
||||
event: DeviceEvent::Button {
|
||||
button: button.to_id().into(),
|
||||
button: button.to_id(),
|
||||
state: ElementState::Released,
|
||||
},
|
||||
});
|
||||
@@ -378,7 +381,7 @@ impl Shared {
|
||||
}
|
||||
|
||||
runner.send_event(Event::DeviceEvent {
|
||||
device_id: None,
|
||||
device_id: RootDeviceId(DeviceId::dummy()),
|
||||
event: DeviceEvent::Key(RawKeyEvent {
|
||||
physical_key: backend::event::key_code(&event),
|
||||
state: ElementState::Pressed,
|
||||
@@ -396,7 +399,7 @@ impl Shared {
|
||||
}
|
||||
|
||||
runner.send_event(Event::DeviceEvent {
|
||||
device_id: None,
|
||||
device_id: RootDeviceId(DeviceId::dummy()),
|
||||
event: DeviceEvent::Key(RawKeyEvent {
|
||||
physical_key: backend::event::key_code(&event),
|
||||
state: ElementState::Released,
|
||||
@@ -435,11 +438,11 @@ impl Shared {
|
||||
|
||||
// Generate a strictly increasing ID
|
||||
// This is used to differentiate windows when handling events
|
||||
pub fn generate_id(&self) -> usize {
|
||||
let id = self.0.id.get();
|
||||
self.0.id.set(id.checked_add(1).expect("exhausted `WindowId`"));
|
||||
pub fn generate_id(&self) -> u32 {
|
||||
let mut id = self.0.id.borrow_mut();
|
||||
*id += 1;
|
||||
|
||||
id
|
||||
*id
|
||||
}
|
||||
|
||||
pub fn request_redraw(&self, id: WindowId) {
|
||||
|
||||
@@ -7,10 +7,15 @@ use web_sys::Element;
|
||||
|
||||
use super::super::monitor::MonitorPermissionFuture;
|
||||
use super::super::{lock, KeyEventExtra};
|
||||
use super::event::DeviceId;
|
||||
use super::runner::{EventWrapper, WeakShared};
|
||||
use super::window::WindowId;
|
||||
use super::{backend, runner, EventLoopProxy};
|
||||
use crate::error::{NotSupportedError, RequestError};
|
||||
use crate::event::{ElementState, Event, KeyEvent, TouchPhase, WindowEvent};
|
||||
use crate::event::{
|
||||
DeviceId as RootDeviceId, ElementState, Event, FingerId as RootFingerId, KeyEvent, Touch,
|
||||
TouchPhase, WindowEvent,
|
||||
};
|
||||
use crate::event_loop::{
|
||||
ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents,
|
||||
EventLoopProxy as RootEventLoopProxy, OwnedDisplayHandle as RootOwnedDisplayHandle,
|
||||
@@ -21,7 +26,9 @@ use crate::platform::web::{CustomCursorFuture, PollStrategy, WaitUntilStrategy};
|
||||
use crate::platform_impl::platform::cursor::CustomCursor;
|
||||
use crate::platform_impl::platform::r#async::Waker;
|
||||
use crate::platform_impl::Window;
|
||||
use crate::window::{CustomCursor as RootCustomCursor, CustomCursorSource, Theme, WindowId};
|
||||
use crate::window::{
|
||||
CustomCursor as RootCustomCursor, CustomCursorSource, Theme, WindowId as RootWindowId,
|
||||
};
|
||||
|
||||
#[derive(Default)]
|
||||
struct ModifiersShared(Rc<Cell<ModifiersState>>);
|
||||
@@ -63,14 +70,14 @@ impl ActiveEventLoop {
|
||||
}
|
||||
|
||||
pub fn generate_id(&self) -> WindowId {
|
||||
WindowId::from_raw(self.runner.generate_id())
|
||||
WindowId(self.runner.generate_id())
|
||||
}
|
||||
|
||||
pub fn create_custom_cursor_async(&self, source: CustomCursorSource) -> CustomCursorFuture {
|
||||
CustomCursorFuture(CustomCursor::new_async(self, source.inner))
|
||||
}
|
||||
|
||||
pub fn register(&self, canvas: &Rc<backend::Canvas>, window_id: WindowId) {
|
||||
pub fn register(&self, canvas: &Rc<backend::Canvas>, id: WindowId) {
|
||||
let canvas_clone = canvas.clone();
|
||||
|
||||
canvas.on_touch_start();
|
||||
@@ -84,13 +91,13 @@ impl ActiveEventLoop {
|
||||
let clear_modifiers = (!modifiers.get().is_empty()).then(|| {
|
||||
modifiers.set(ModifiersState::empty());
|
||||
Event::WindowEvent {
|
||||
window_id,
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ModifiersChanged(ModifiersState::empty().into()),
|
||||
}
|
||||
});
|
||||
|
||||
runner.send_events(clear_modifiers.into_iter().chain(iter::once(Event::WindowEvent {
|
||||
window_id,
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::Focused(false),
|
||||
})));
|
||||
});
|
||||
@@ -100,7 +107,7 @@ impl ActiveEventLoop {
|
||||
canvas.on_focus(move || {
|
||||
if !has_focus.replace(true) {
|
||||
runner.send_event(Event::WindowEvent {
|
||||
window_id,
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::Focused(true),
|
||||
});
|
||||
}
|
||||
@@ -119,8 +126,10 @@ impl ActiveEventLoop {
|
||||
|
||||
if focused {
|
||||
canvas.has_focus.set(true);
|
||||
self.runner
|
||||
.send_event(Event::WindowEvent { window_id, event: WindowEvent::Focused(true) })
|
||||
self.runner.send_event(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::Focused(true),
|
||||
})
|
||||
}
|
||||
|
||||
let runner = self.runner.clone();
|
||||
@@ -130,16 +139,18 @@ impl ActiveEventLoop {
|
||||
let modifiers_changed = (modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id,
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
|
||||
}
|
||||
});
|
||||
|
||||
let device_id = RootDeviceId(DeviceId::dummy());
|
||||
|
||||
runner.send_events(
|
||||
iter::once(Event::WindowEvent {
|
||||
window_id,
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::KeyboardInput {
|
||||
device_id: None,
|
||||
device_id,
|
||||
event: KeyEvent {
|
||||
physical_key,
|
||||
logical_key,
|
||||
@@ -164,16 +175,18 @@ impl ActiveEventLoop {
|
||||
let modifiers_changed = (modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id,
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
|
||||
}
|
||||
});
|
||||
|
||||
let device_id = RootDeviceId(DeviceId::dummy());
|
||||
|
||||
runner.send_events(
|
||||
iter::once(Event::WindowEvent {
|
||||
window_id,
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::KeyboardInput {
|
||||
device_id: None,
|
||||
device_id,
|
||||
event: KeyEvent {
|
||||
physical_key,
|
||||
logical_key,
|
||||
@@ -192,146 +205,286 @@ impl ActiveEventLoop {
|
||||
);
|
||||
|
||||
let has_focus = canvas.has_focus.clone();
|
||||
canvas.on_pointer_leave({
|
||||
canvas.on_cursor_leave({
|
||||
let runner = self.runner.clone();
|
||||
let has_focus = has_focus.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers, device_id, position, kind| {
|
||||
move |active_modifiers, pointer_id| {
|
||||
let focus = (has_focus.get() && modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id,
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
|
||||
}
|
||||
});
|
||||
|
||||
runner.send_events(focus.into_iter().chain(iter::once(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerLeft { device_id, position: Some(position), kind },
|
||||
})))
|
||||
}
|
||||
});
|
||||
|
||||
canvas.on_pointer_enter({
|
||||
let runner = self.runner.clone();
|
||||
let has_focus = has_focus.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers, device_id, position, kind| {
|
||||
let focus = (has_focus.get() && modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
|
||||
}
|
||||
let pointer = pointer_id.map(|device_id| Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::CursorLeft { device_id: RootDeviceId(device_id) },
|
||||
});
|
||||
|
||||
runner.send_events(focus.into_iter().chain(iter::once(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerEntered { device_id, position, kind },
|
||||
})))
|
||||
}
|
||||
});
|
||||
|
||||
canvas.on_pointer_move(
|
||||
{
|
||||
let runner = self.runner.clone();
|
||||
let has_focus = has_focus.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |device_id, events| {
|
||||
runner.send_events(events.flat_map(|(active_modifiers, position, source)| {
|
||||
let modifiers = (has_focus.get() && modifiers.get() != active_modifiers)
|
||||
.then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
|
||||
}
|
||||
});
|
||||
|
||||
modifiers.into_iter().chain(iter::once(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerMoved { device_id, position, source },
|
||||
}))
|
||||
}));
|
||||
if focus.is_some() || pointer.is_some() {
|
||||
runner.send_events(focus.into_iter().chain(pointer))
|
||||
}
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
canvas.on_cursor_enter({
|
||||
let runner = self.runner.clone();
|
||||
let has_focus = has_focus.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers, pointer_id| {
|
||||
let focus = (has_focus.get() && modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
|
||||
}
|
||||
});
|
||||
|
||||
let pointer = pointer_id.map(|device_id| Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::CursorEntered { device_id: RootDeviceId(device_id) },
|
||||
});
|
||||
|
||||
if focus.is_some() || pointer.is_some() {
|
||||
runner.send_events(focus.into_iter().chain(pointer))
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
canvas.on_cursor_move(
|
||||
{
|
||||
let runner = self.runner.clone();
|
||||
let has_focus = has_focus.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers, device_id, position, state, button| {
|
||||
move |active_modifiers, pointer_id, events| {
|
||||
let modifiers =
|
||||
(has_focus.get() && modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id,
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
|
||||
}
|
||||
});
|
||||
|
||||
runner.send_events(modifiers.into_iter().chain([Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerButton { device_id, state, position, button },
|
||||
}]));
|
||||
runner.send_events(modifiers.into_iter().chain(events.flat_map(|position| {
|
||||
let device_id = RootDeviceId(pointer_id);
|
||||
|
||||
iter::once(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::CursorMoved { device_id, position },
|
||||
})
|
||||
})));
|
||||
}
|
||||
},
|
||||
{
|
||||
let runner = self.runner.clone();
|
||||
let has_focus = has_focus.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers, device_id, finger_id, events| {
|
||||
let modifiers =
|
||||
(has_focus.get() && modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
|
||||
}
|
||||
});
|
||||
|
||||
runner.send_events(modifiers.into_iter().chain(events.map(
|
||||
|(location, force)| Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::Touch(Touch {
|
||||
finger_id: RootFingerId(finger_id),
|
||||
device_id: RootDeviceId(device_id),
|
||||
phase: TouchPhase::Moved,
|
||||
force: Some(force),
|
||||
location,
|
||||
}),
|
||||
},
|
||||
)));
|
||||
}
|
||||
},
|
||||
{
|
||||
let runner = self.runner.clone();
|
||||
let has_focus = has_focus.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers,
|
||||
device_id,
|
||||
position: crate::dpi::PhysicalPosition<f64>,
|
||||
buttons,
|
||||
button| {
|
||||
let modifiers =
|
||||
(has_focus.get() && modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
|
||||
}
|
||||
});
|
||||
|
||||
let device_id = RootDeviceId(device_id);
|
||||
|
||||
let state = if buttons.contains(button.into()) {
|
||||
ElementState::Pressed
|
||||
} else {
|
||||
ElementState::Released
|
||||
};
|
||||
|
||||
// A chorded button event may come in without any prior CursorMoved events,
|
||||
// therefore we should send a CursorMoved event to make sure that the
|
||||
// user code has the correct cursor position.
|
||||
runner.send_events(modifiers.into_iter().chain([
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::CursorMoved { device_id, position },
|
||||
},
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::MouseInput { device_id, state, button },
|
||||
},
|
||||
]));
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
canvas.on_pointer_press({
|
||||
let runner = self.runner.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
canvas.on_mouse_press(
|
||||
{
|
||||
let runner = self.runner.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers, device_id, position, button| {
|
||||
let modifiers = (modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
|
||||
}
|
||||
});
|
||||
|
||||
runner.send_events(modifiers.into_iter().chain(iter::once(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerButton {
|
||||
device_id,
|
||||
state: ElementState::Pressed,
|
||||
position,
|
||||
button,
|
||||
},
|
||||
})));
|
||||
}
|
||||
});
|
||||
|
||||
canvas.on_pointer_release({
|
||||
let runner = self.runner.clone();
|
||||
let has_focus = has_focus.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers, device_id, position, button| {
|
||||
let modifiers =
|
||||
(has_focus.get() && modifiers.get() != active_modifiers).then(|| {
|
||||
move |active_modifiers, pointer_id, position, button| {
|
||||
let modifiers = (modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id,
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
|
||||
}
|
||||
});
|
||||
|
||||
runner.send_events(modifiers.into_iter().chain(iter::once(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerButton {
|
||||
device_id,
|
||||
state: ElementState::Released,
|
||||
position,
|
||||
button,
|
||||
},
|
||||
})));
|
||||
}
|
||||
});
|
||||
let device_id: RootDeviceId = RootDeviceId(pointer_id);
|
||||
|
||||
// A mouse down event may come in without any prior CursorMoved events,
|
||||
// therefore we should send a CursorMoved event to make sure that the
|
||||
// user code has the correct cursor position.
|
||||
runner.send_events(modifiers.into_iter().chain([
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::CursorMoved { device_id, position },
|
||||
},
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::MouseInput {
|
||||
device_id,
|
||||
state: ElementState::Pressed,
|
||||
button,
|
||||
},
|
||||
},
|
||||
]));
|
||||
}
|
||||
},
|
||||
{
|
||||
let runner = self.runner.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers, device_id, finger_id, location, force| {
|
||||
let modifiers = (modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
|
||||
}
|
||||
});
|
||||
|
||||
runner.send_events(modifiers.into_iter().chain(iter::once(
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::Touch(Touch {
|
||||
finger_id: RootFingerId(finger_id),
|
||||
device_id: RootDeviceId(device_id),
|
||||
phase: TouchPhase::Started,
|
||||
force: Some(force),
|
||||
location,
|
||||
}),
|
||||
},
|
||||
)))
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
canvas.on_mouse_release(
|
||||
{
|
||||
let runner = self.runner.clone();
|
||||
let has_focus = has_focus.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers, pointer_id, position, button| {
|
||||
let modifiers =
|
||||
(has_focus.get() && modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
|
||||
}
|
||||
});
|
||||
|
||||
let device_id: RootDeviceId = RootDeviceId(pointer_id);
|
||||
|
||||
// A mouse up event may come in without any prior CursorMoved events,
|
||||
// therefore we should send a CursorMoved event to make sure that the
|
||||
// user code has the correct cursor position.
|
||||
runner.send_events(modifiers.into_iter().chain([
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::CursorMoved { device_id, position },
|
||||
},
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::MouseInput {
|
||||
device_id,
|
||||
state: ElementState::Released,
|
||||
button,
|
||||
},
|
||||
},
|
||||
]));
|
||||
}
|
||||
},
|
||||
{
|
||||
let runner_touch = self.runner.clone();
|
||||
let has_focus = has_focus.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers, device_id, finger_id, location, force| {
|
||||
let modifiers =
|
||||
(has_focus.get() && modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
|
||||
}
|
||||
});
|
||||
|
||||
runner_touch.send_events(modifiers.into_iter().chain(iter::once(
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::Touch(Touch {
|
||||
finger_id: RootFingerId(finger_id),
|
||||
device_id: RootDeviceId(device_id),
|
||||
phase: TouchPhase::Ended,
|
||||
force: Some(force),
|
||||
location,
|
||||
}),
|
||||
},
|
||||
)));
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
let runner = self.runner.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
@@ -340,16 +493,16 @@ impl ActiveEventLoop {
|
||||
(has_focus.get() && modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id,
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
|
||||
}
|
||||
});
|
||||
|
||||
runner.send_events(modifiers_changed.into_iter().chain(iter::once(
|
||||
Event::WindowEvent {
|
||||
window_id,
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::MouseWheel {
|
||||
device_id: None,
|
||||
device_id: RootDeviceId(DeviceId::dummy()),
|
||||
delta,
|
||||
phase: TouchPhase::Moved,
|
||||
},
|
||||
@@ -357,11 +510,25 @@ impl ActiveEventLoop {
|
||||
)));
|
||||
});
|
||||
|
||||
let runner = self.runner.clone();
|
||||
canvas.on_touch_cancel(move |device_id, finger_id, location, force| {
|
||||
runner.send_event(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::Touch(Touch {
|
||||
finger_id: RootFingerId(finger_id),
|
||||
device_id: RootDeviceId(device_id),
|
||||
phase: TouchPhase::Cancelled,
|
||||
force: Some(force),
|
||||
location,
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
||||
let runner = self.runner.clone();
|
||||
canvas.on_dark_mode(move |is_dark_mode| {
|
||||
let theme = if is_dark_mode { Theme::Dark } else { Theme::Light };
|
||||
runner.send_event(Event::WindowEvent {
|
||||
window_id,
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ThemeChanged(theme),
|
||||
});
|
||||
});
|
||||
@@ -388,7 +555,7 @@ impl ActiveEventLoop {
|
||||
if canvas.old_size() != new_size {
|
||||
canvas.set_old_size(new_size);
|
||||
runner.send_event(Event::WindowEvent {
|
||||
window_id,
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::SurfaceResized(new_size),
|
||||
});
|
||||
canvas.request_animation_frame();
|
||||
@@ -404,7 +571,7 @@ impl ActiveEventLoop {
|
||||
&& !(is_intersecting && canvas_clone.is_intersecting.get().is_none())
|
||||
{
|
||||
runner.send_event(Event::WindowEvent {
|
||||
window_id,
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::Occluded(!is_intersecting),
|
||||
});
|
||||
}
|
||||
@@ -413,7 +580,7 @@ impl ActiveEventLoop {
|
||||
});
|
||||
|
||||
let runner = self.runner.clone();
|
||||
canvas.on_animation_frame(move || runner.request_redraw(window_id));
|
||||
canvas.on_animation_frame(move || runner.request_redraw(RootWindowId(id)));
|
||||
|
||||
canvas.on_context_menu();
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ pub(crate) use cursor::{
|
||||
CustomCursorSource as PlatformCustomCursorSource,
|
||||
};
|
||||
|
||||
pub use self::event::FingerId;
|
||||
pub use self::event::{DeviceId, FingerId};
|
||||
pub(crate) use self::event_loop::{
|
||||
ActiveEventLoop, EventLoop, EventLoopProxy, OwnedDisplayHandle,
|
||||
PlatformSpecificEventLoopAttributes,
|
||||
@@ -48,5 +48,5 @@ pub(crate) use self::monitor::{
|
||||
VideoModeHandle,
|
||||
};
|
||||
use self::web_sys as backend;
|
||||
pub use self::window::{PlatformSpecificWindowAttributes, Window};
|
||||
pub use self::window::{PlatformSpecificWindowAttributes, Window, WindowId};
|
||||
pub(crate) use crate::icon::NoIcon as PlatformIcon;
|
||||
|
||||
@@ -12,22 +12,21 @@ use web_sys::{
|
||||
};
|
||||
|
||||
use super::super::cursor::CursorHandler;
|
||||
use super::super::event::{DeviceId, FingerId};
|
||||
use super::super::main_thread::MainThreadMarker;
|
||||
use super::super::WindowId;
|
||||
use super::animation_frame::AnimationFrameHandler;
|
||||
use super::event_handle::EventListenerHandle;
|
||||
use super::intersection_handle::IntersectionObserverHandle;
|
||||
use super::media_query_handle::MediaQueryListHandle;
|
||||
use super::pointer::PointerHandler;
|
||||
use super::{event, fullscreen, ResizeScaleHandle};
|
||||
use super::{event, fullscreen, ButtonsState, ResizeScaleHandle};
|
||||
use crate::dpi::{LogicalPosition, PhysicalPosition, PhysicalSize};
|
||||
use crate::error::RequestError;
|
||||
use crate::event::{
|
||||
ButtonSource, DeviceId, ElementState, MouseScrollDelta, PointerKind, PointerSource,
|
||||
SurfaceSizeWriter,
|
||||
};
|
||||
use crate::event::{Force, MouseButton, MouseScrollDelta, SurfaceSizeWriter};
|
||||
use crate::keyboard::{Key, KeyLocation, ModifiersState, PhysicalKey};
|
||||
use crate::platform_impl::Fullscreen;
|
||||
use crate::window::{WindowAttributes, WindowId};
|
||||
use crate::window::{WindowAttributes, WindowId as RootWindowId};
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub struct Canvas {
|
||||
@@ -329,62 +328,75 @@ impl Canvas {
|
||||
}));
|
||||
}
|
||||
|
||||
pub fn on_pointer_leave<F>(&self, handler: F)
|
||||
pub fn on_cursor_leave<F>(&self, handler: F)
|
||||
where
|
||||
F: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, PointerKind),
|
||||
F: 'static + FnMut(ModifiersState, Option<DeviceId>),
|
||||
{
|
||||
self.handlers.borrow_mut().pointer_handler.on_pointer_leave(&self.common, handler)
|
||||
self.handlers.borrow_mut().pointer_handler.on_cursor_leave(&self.common, handler)
|
||||
}
|
||||
|
||||
pub fn on_pointer_enter<F>(&self, handler: F)
|
||||
pub fn on_cursor_enter<F>(&self, handler: F)
|
||||
where
|
||||
F: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, PointerKind),
|
||||
F: 'static + FnMut(ModifiersState, Option<DeviceId>),
|
||||
{
|
||||
self.handlers.borrow_mut().pointer_handler.on_pointer_enter(&self.common, handler)
|
||||
self.handlers.borrow_mut().pointer_handler.on_cursor_enter(&self.common, handler)
|
||||
}
|
||||
|
||||
pub fn on_pointer_release<C>(&self, handler: C)
|
||||
pub fn on_mouse_release<M, T>(&self, mouse_handler: M, touch_handler: T)
|
||||
where
|
||||
C: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, ButtonSource),
|
||||
M: 'static + FnMut(ModifiersState, DeviceId, PhysicalPosition<f64>, MouseButton),
|
||||
T: 'static + FnMut(ModifiersState, DeviceId, FingerId, PhysicalPosition<f64>, Force),
|
||||
{
|
||||
self.handlers.borrow_mut().pointer_handler.on_pointer_release(&self.common, handler)
|
||||
}
|
||||
|
||||
pub fn on_pointer_press<C>(&self, handler: C)
|
||||
where
|
||||
C: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, ButtonSource),
|
||||
{
|
||||
self.handlers.borrow_mut().pointer_handler.on_pointer_press(
|
||||
self.handlers.borrow_mut().pointer_handler.on_mouse_release(
|
||||
&self.common,
|
||||
handler,
|
||||
mouse_handler,
|
||||
touch_handler,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn on_mouse_press<M, T>(&self, mouse_handler: M, touch_handler: T)
|
||||
where
|
||||
M: 'static + FnMut(ModifiersState, DeviceId, PhysicalPosition<f64>, MouseButton),
|
||||
T: 'static + FnMut(ModifiersState, DeviceId, FingerId, PhysicalPosition<f64>, Force),
|
||||
{
|
||||
self.handlers.borrow_mut().pointer_handler.on_mouse_press(
|
||||
&self.common,
|
||||
mouse_handler,
|
||||
touch_handler,
|
||||
Rc::clone(&self.prevent_default),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn on_pointer_move<C, B>(&self, cursor_handler: C, button_handler: B)
|
||||
pub fn on_cursor_move<M, T, B>(&self, mouse_handler: M, touch_handler: T, button_handler: B)
|
||||
where
|
||||
C: 'static
|
||||
+ FnMut(
|
||||
Option<DeviceId>,
|
||||
&mut dyn Iterator<Item = (ModifiersState, PhysicalPosition<f64>, PointerSource)>,
|
||||
),
|
||||
B: 'static
|
||||
M: 'static
|
||||
+ FnMut(ModifiersState, DeviceId, &mut dyn Iterator<Item = PhysicalPosition<f64>>),
|
||||
T: 'static
|
||||
+ FnMut(
|
||||
ModifiersState,
|
||||
Option<DeviceId>,
|
||||
PhysicalPosition<f64>,
|
||||
ElementState,
|
||||
ButtonSource,
|
||||
DeviceId,
|
||||
FingerId,
|
||||
&mut dyn Iterator<Item = (PhysicalPosition<f64>, Force)>,
|
||||
),
|
||||
B: 'static
|
||||
+ FnMut(ModifiersState, DeviceId, PhysicalPosition<f64>, ButtonsState, MouseButton),
|
||||
{
|
||||
self.handlers.borrow_mut().pointer_handler.on_pointer_move(
|
||||
self.handlers.borrow_mut().pointer_handler.on_cursor_move(
|
||||
&self.common,
|
||||
cursor_handler,
|
||||
mouse_handler,
|
||||
touch_handler,
|
||||
button_handler,
|
||||
Rc::clone(&self.prevent_default),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn on_touch_cancel<F>(&self, handler: F)
|
||||
where
|
||||
F: 'static + FnMut(DeviceId, FingerId, PhysicalPosition<f64>, Force),
|
||||
{
|
||||
self.handlers.borrow_mut().pointer_handler.on_touch_cancel(&self.common, handler)
|
||||
}
|
||||
|
||||
pub fn on_mouse_wheel<F>(&self, mut handler: F)
|
||||
where
|
||||
F: 'static + FnMut(MouseScrollDelta, ModifiersState),
|
||||
@@ -489,7 +501,7 @@ impl Canvas {
|
||||
let new_size = {
|
||||
let new_size = Arc::new(Mutex::new(current_size));
|
||||
event_handler(crate::event::Event::WindowEvent {
|
||||
window_id: self.id,
|
||||
window_id: RootWindowId(self.id),
|
||||
event: crate::event::WindowEvent::ScaleFactorChanged {
|
||||
scale_factor: scale,
|
||||
surface_size_writer: SurfaceSizeWriter::new(Arc::downgrade(&new_size)),
|
||||
@@ -517,7 +529,7 @@ impl Canvas {
|
||||
// Then we at least send a resized event.
|
||||
self.set_old_size(new_size);
|
||||
runner.send_event(crate::event::Event::WindowEvent {
|
||||
window_id: self.id,
|
||||
window_id: RootWindowId(self.id),
|
||||
event: crate::event::WindowEvent::SurfaceResized(new_size),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -6,9 +6,8 @@ use wasm_bindgen::prelude::wasm_bindgen;
|
||||
use wasm_bindgen::{JsCast, JsValue};
|
||||
use web_sys::{KeyboardEvent, MouseEvent, Navigator, PointerEvent, WheelEvent};
|
||||
|
||||
use super::super::FingerId;
|
||||
use super::Engine;
|
||||
use crate::event::{MouseButton, MouseScrollDelta, PointerKind};
|
||||
use crate::event::{MouseButton, MouseScrollDelta};
|
||||
use crate::keyboard::{Key, KeyLocation, ModifiersState, NamedKey, PhysicalKey};
|
||||
|
||||
bitflags::bitflags! {
|
||||
@@ -69,14 +68,14 @@ pub fn mouse_button(event: &MouseEvent) -> Option<MouseButton> {
|
||||
}
|
||||
|
||||
impl MouseButton {
|
||||
pub fn to_id(self) -> u16 {
|
||||
pub fn to_id(self) -> u32 {
|
||||
match self {
|
||||
MouseButton::Left => 0,
|
||||
MouseButton::Right => 1,
|
||||
MouseButton::Middle => 2,
|
||||
MouseButton::Back => 3,
|
||||
MouseButton::Forward => 4,
|
||||
MouseButton::Other(value) => value,
|
||||
MouseButton::Other(value) => value.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -161,14 +160,6 @@ pub fn mouse_scroll_delta(
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pointer_type(event: &PointerEvent, pointer_id: i32) -> PointerKind {
|
||||
match event.pointer_type().as_str() {
|
||||
"mouse" => PointerKind::Mouse,
|
||||
"touch" => PointerKind::Touch(FingerId::new(pointer_id, event.is_primary()).into()),
|
||||
_ => PointerKind::Unknown,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn key_code(event: &KeyboardEvent) -> PhysicalKey {
|
||||
let code = event.code();
|
||||
PhysicalKey::from_key_code_attribute_value(&code)
|
||||
|
||||
@@ -18,6 +18,7 @@ use wasm_bindgen::JsCast;
|
||||
use web_sys::{Document, HtmlCanvasElement, Navigator, PageTransitionEvent, VisibilityState};
|
||||
|
||||
pub use self::canvas::{Canvas, Style};
|
||||
pub use self::event::ButtonsState;
|
||||
pub use self::event_handle::EventListenerHandle;
|
||||
pub use self::resize_scaling::ResizeScaleHandle;
|
||||
pub use self::schedule::Schedule;
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
use std::cell::Cell;
|
||||
use std::rc::Rc;
|
||||
|
||||
use event::ButtonsState;
|
||||
use web_sys::PointerEvent;
|
||||
|
||||
use super::super::event::{DeviceId, FingerId};
|
||||
use super::canvas::Common;
|
||||
use super::event;
|
||||
use super::event_handle::EventListenerHandle;
|
||||
use crate::dpi::PhysicalPosition;
|
||||
use crate::event::{ButtonSource, DeviceId, ElementState, Force, PointerKind, PointerSource};
|
||||
use crate::event::{Force, MouseButton};
|
||||
use crate::keyboard::ModifiersState;
|
||||
use crate::platform_impl::web::event::mkdid;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(super) struct PointerHandler {
|
||||
@@ -33,78 +34,86 @@ impl PointerHandler {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_pointer_leave<F>(&mut self, canvas_common: &Common, mut handler: F)
|
||||
pub fn on_cursor_leave<F>(&mut self, canvas_common: &Common, mut handler: F)
|
||||
where
|
||||
F: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, PointerKind),
|
||||
F: 'static + FnMut(ModifiersState, Option<DeviceId>),
|
||||
{
|
||||
let window = canvas_common.window.clone();
|
||||
self.on_cursor_leave =
|
||||
Some(canvas_common.add_event("pointerout", move |event: PointerEvent| {
|
||||
let modifiers = event::mouse_modifiers(&event);
|
||||
let pointer_id = event.pointer_id();
|
||||
let device_id = mkdid(pointer_id);
|
||||
let position =
|
||||
event::mouse_position(&event).to_physical(super::scale_factor(&window));
|
||||
let kind = event::pointer_type(&event, pointer_id);
|
||||
handler(modifiers, device_id, position, kind);
|
||||
|
||||
// touch events are handled separately
|
||||
// handling them here would produce duplicate mouse events, inconsistent with
|
||||
// other platforms.
|
||||
let device_id =
|
||||
(event.pointer_type() != "touch").then(|| DeviceId::new(event.pointer_id()));
|
||||
|
||||
handler(modifiers, device_id);
|
||||
}));
|
||||
}
|
||||
|
||||
pub fn on_pointer_enter<F>(&mut self, canvas_common: &Common, mut handler: F)
|
||||
pub fn on_cursor_enter<F>(&mut self, canvas_common: &Common, mut handler: F)
|
||||
where
|
||||
F: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, PointerKind),
|
||||
F: 'static + FnMut(ModifiersState, Option<DeviceId>),
|
||||
{
|
||||
let window = canvas_common.window.clone();
|
||||
self.on_cursor_enter =
|
||||
Some(canvas_common.add_event("pointerover", move |event: PointerEvent| {
|
||||
let modifiers = event::mouse_modifiers(&event);
|
||||
let pointer_id = event.pointer_id();
|
||||
let device_id = mkdid(pointer_id);
|
||||
let position =
|
||||
event::mouse_position(&event).to_physical(super::scale_factor(&window));
|
||||
let kind = event::pointer_type(&event, pointer_id);
|
||||
handler(modifiers, device_id, position, kind);
|
||||
|
||||
// touch events are handled separately
|
||||
// handling them here would produce duplicate mouse events, inconsistent with
|
||||
// other platforms.
|
||||
let device_id =
|
||||
(event.pointer_type() != "touch").then(|| DeviceId::new(event.pointer_id()));
|
||||
|
||||
handler(modifiers, device_id);
|
||||
}));
|
||||
}
|
||||
|
||||
pub fn on_pointer_release<C>(&mut self, canvas_common: &Common, mut handler: C)
|
||||
where
|
||||
C: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, ButtonSource),
|
||||
pub fn on_mouse_release<M, T>(
|
||||
&mut self,
|
||||
canvas_common: &Common,
|
||||
mut mouse_handler: M,
|
||||
mut touch_handler: T,
|
||||
) where
|
||||
M: 'static + FnMut(ModifiersState, DeviceId, PhysicalPosition<f64>, MouseButton),
|
||||
T: 'static + FnMut(ModifiersState, DeviceId, FingerId, PhysicalPosition<f64>, Force),
|
||||
{
|
||||
let window = canvas_common.window.clone();
|
||||
self.on_pointer_release =
|
||||
Some(canvas_common.add_event("pointerup", move |event: PointerEvent| {
|
||||
let modifiers = event::mouse_modifiers(&event);
|
||||
let pointer_id = event.pointer_id();
|
||||
let kind = event::pointer_type(&event, pointer_id);
|
||||
|
||||
let button = event::mouse_button(&event).expect("no mouse button pressed");
|
||||
|
||||
let source = match kind {
|
||||
PointerKind::Mouse => ButtonSource::Mouse(button),
|
||||
PointerKind::Touch(finger_id) => ButtonSource::Touch {
|
||||
finger_id,
|
||||
force: Some(Force::Normalized(event.pressure().into())),
|
||||
match event.pointer_type().as_str() {
|
||||
"touch" => {
|
||||
let pointer_id = event.pointer_id();
|
||||
touch_handler(
|
||||
modifiers,
|
||||
DeviceId::new(pointer_id),
|
||||
FingerId::new(pointer_id, event.is_primary()),
|
||||
event::mouse_position(&event).to_physical(super::scale_factor(&window)),
|
||||
Force::Normalized(event.pressure() as f64),
|
||||
)
|
||||
},
|
||||
PointerKind::Unknown => ButtonSource::Unknown(button.to_id()),
|
||||
};
|
||||
|
||||
handler(
|
||||
modifiers,
|
||||
mkdid(pointer_id),
|
||||
event::mouse_position(&event).to_physical(super::scale_factor(&window)),
|
||||
source,
|
||||
)
|
||||
_ => mouse_handler(
|
||||
modifiers,
|
||||
DeviceId::new(event.pointer_id()),
|
||||
event::mouse_position(&event).to_physical(super::scale_factor(&window)),
|
||||
event::mouse_button(&event).expect("no mouse button released"),
|
||||
),
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
pub fn on_pointer_press<C>(
|
||||
pub fn on_mouse_press<M, T>(
|
||||
&mut self,
|
||||
canvas_common: &Common,
|
||||
mut handler: C,
|
||||
mut mouse_handler: M,
|
||||
mut touch_handler: T,
|
||||
prevent_default: Rc<Cell<bool>>,
|
||||
) where
|
||||
C: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, ButtonSource),
|
||||
M: 'static + FnMut(ModifiersState, DeviceId, PhysicalPosition<f64>, MouseButton),
|
||||
T: 'static + FnMut(ModifiersState, DeviceId, FingerId, PhysicalPosition<f64>, Force),
|
||||
{
|
||||
let window = canvas_common.window.clone();
|
||||
let canvas = canvas_common.raw().clone();
|
||||
@@ -118,65 +127,69 @@ impl PointerHandler {
|
||||
}
|
||||
|
||||
let modifiers = event::mouse_modifiers(&event);
|
||||
let pointer_id = event.pointer_id();
|
||||
let kind = event::pointer_type(&event, pointer_id);
|
||||
let button = event::mouse_button(&event).expect("no mouse button pressed");
|
||||
let pointer_type = &event.pointer_type();
|
||||
|
||||
let source = match kind {
|
||||
PointerKind::Mouse => {
|
||||
// Error is swallowed here since the error would occur every time the
|
||||
// mouse is clicked when the cursor is
|
||||
// grabbed, and there is probably not a
|
||||
// situation where this could fail, that we
|
||||
// care if it fails.
|
||||
let _e = canvas.set_pointer_capture(pointer_id);
|
||||
|
||||
ButtonSource::Mouse(button)
|
||||
match pointer_type.as_str() {
|
||||
"touch" => {
|
||||
let pointer_id = event.pointer_id();
|
||||
touch_handler(
|
||||
modifiers,
|
||||
DeviceId::new(pointer_id),
|
||||
FingerId::new(pointer_id, event.is_primary()),
|
||||
event::mouse_position(&event).to_physical(super::scale_factor(&window)),
|
||||
Force::Normalized(event.pressure() as f64),
|
||||
);
|
||||
},
|
||||
PointerKind::Touch(finger_id) => ButtonSource::Touch {
|
||||
finger_id,
|
||||
force: Some(Force::Normalized(event.pressure().into())),
|
||||
},
|
||||
PointerKind::Unknown => ButtonSource::Unknown(button.to_id()),
|
||||
};
|
||||
_ => {
|
||||
let pointer_id = event.pointer_id();
|
||||
|
||||
handler(
|
||||
modifiers,
|
||||
mkdid(pointer_id),
|
||||
event::mouse_position(&event).to_physical(super::scale_factor(&window)),
|
||||
source,
|
||||
)
|
||||
mouse_handler(
|
||||
modifiers,
|
||||
DeviceId::new(pointer_id),
|
||||
event::mouse_position(&event).to_physical(super::scale_factor(&window)),
|
||||
event::mouse_button(&event).expect("no mouse button pressed"),
|
||||
);
|
||||
|
||||
if pointer_type == "mouse" {
|
||||
// Error is swallowed here since the error would occur every time the
|
||||
// mouse is clicked when the cursor is
|
||||
// grabbed, and there is probably not a
|
||||
// situation where this could fail, that we
|
||||
// care if it fails.
|
||||
let _e = canvas.set_pointer_capture(pointer_id);
|
||||
}
|
||||
},
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
pub fn on_pointer_move<C, B>(
|
||||
pub fn on_cursor_move<M, T, B>(
|
||||
&mut self,
|
||||
canvas_common: &Common,
|
||||
mut cursor_handler: C,
|
||||
mut mouse_handler: M,
|
||||
mut touch_handler: T,
|
||||
mut button_handler: B,
|
||||
prevent_default: Rc<Cell<bool>>,
|
||||
) where
|
||||
C: 'static
|
||||
+ FnMut(
|
||||
Option<DeviceId>,
|
||||
&mut dyn Iterator<Item = (ModifiersState, PhysicalPosition<f64>, PointerSource)>,
|
||||
),
|
||||
B: 'static
|
||||
M: 'static
|
||||
+ FnMut(ModifiersState, DeviceId, &mut dyn Iterator<Item = PhysicalPosition<f64>>),
|
||||
T: 'static
|
||||
+ FnMut(
|
||||
ModifiersState,
|
||||
Option<DeviceId>,
|
||||
PhysicalPosition<f64>,
|
||||
ElementState,
|
||||
ButtonSource,
|
||||
DeviceId,
|
||||
FingerId,
|
||||
&mut dyn Iterator<Item = (PhysicalPosition<f64>, Force)>,
|
||||
),
|
||||
B: 'static
|
||||
+ FnMut(ModifiersState, DeviceId, PhysicalPosition<f64>, ButtonsState, MouseButton),
|
||||
{
|
||||
let window = canvas_common.window.clone();
|
||||
let canvas = canvas_common.raw().clone();
|
||||
self.on_cursor_move =
|
||||
Some(canvas_common.add_event("pointermove", move |event: PointerEvent| {
|
||||
let modifiers = event::mouse_modifiers(&event);
|
||||
let pointer_id = event.pointer_id();
|
||||
let device_id = mkdid(pointer_id);
|
||||
let kind = event::pointer_type(&event, pointer_id);
|
||||
let device_id = DeviceId::new(pointer_id);
|
||||
|
||||
// chorded button event
|
||||
if let Some(button) = event::mouse_button(&event) {
|
||||
@@ -187,34 +200,11 @@ impl PointerHandler {
|
||||
let _ = canvas.focus();
|
||||
}
|
||||
|
||||
let state = if event::mouse_buttons(&event).contains(button.into()) {
|
||||
ElementState::Pressed
|
||||
} else {
|
||||
ElementState::Released
|
||||
};
|
||||
|
||||
let button = match kind {
|
||||
PointerKind::Mouse => ButtonSource::Mouse(button),
|
||||
PointerKind::Touch(finger_id) => {
|
||||
let button_id = button.to_id();
|
||||
|
||||
if button_id != 1 {
|
||||
tracing::error!("unexpected touch button id: {button_id}");
|
||||
}
|
||||
|
||||
ButtonSource::Touch {
|
||||
finger_id,
|
||||
force: Some(Force::Normalized(event.pressure().into())),
|
||||
}
|
||||
},
|
||||
PointerKind::Unknown => todo!(),
|
||||
};
|
||||
|
||||
button_handler(
|
||||
event::mouse_modifiers(&event),
|
||||
modifiers,
|
||||
device_id,
|
||||
event::mouse_position(&event).to_physical(super::scale_factor(&window)),
|
||||
state,
|
||||
event::mouse_buttons(&event),
|
||||
button,
|
||||
);
|
||||
|
||||
@@ -223,24 +213,44 @@ impl PointerHandler {
|
||||
|
||||
// pointer move event
|
||||
let scale = super::scale_factor(&window);
|
||||
match event.pointer_type().as_str() {
|
||||
"touch" => touch_handler(
|
||||
modifiers,
|
||||
device_id,
|
||||
FingerId::new(pointer_id, event.is_primary()),
|
||||
&mut event::pointer_move_event(event).map(|event| {
|
||||
(
|
||||
event::mouse_position(&event).to_physical(scale),
|
||||
Force::Normalized(event.pressure() as f64),
|
||||
)
|
||||
}),
|
||||
),
|
||||
_ => mouse_handler(
|
||||
modifiers,
|
||||
device_id,
|
||||
&mut event::pointer_move_event(event)
|
||||
.map(|event| event::mouse_position(&event).to_physical(scale)),
|
||||
),
|
||||
};
|
||||
}));
|
||||
}
|
||||
|
||||
cursor_handler(
|
||||
device_id,
|
||||
&mut event::pointer_move_event(event).map(|event| {
|
||||
(
|
||||
event::mouse_modifiers(&event),
|
||||
event::mouse_position(&event).to_physical(scale),
|
||||
match kind {
|
||||
PointerKind::Mouse => PointerSource::Mouse,
|
||||
PointerKind::Touch(finger_id) => PointerSource::Touch {
|
||||
finger_id,
|
||||
force: Some(Force::Normalized(event.pressure().into())),
|
||||
},
|
||||
PointerKind::Unknown => PointerSource::Unknown,
|
||||
},
|
||||
)
|
||||
}),
|
||||
);
|
||||
pub fn on_touch_cancel<F>(&mut self, canvas_common: &Common, mut handler: F)
|
||||
where
|
||||
F: 'static + FnMut(DeviceId, FingerId, PhysicalPosition<f64>, Force),
|
||||
{
|
||||
let window = canvas_common.window.clone();
|
||||
self.on_touch_cancel =
|
||||
Some(canvas_common.add_event("pointercancel", move |event: PointerEvent| {
|
||||
if event.pointer_type() == "touch" {
|
||||
let pointer_id = event.pointer_id();
|
||||
handler(
|
||||
DeviceId::new(pointer_id),
|
||||
FingerId::new(pointer_id, event.is_primary()),
|
||||
event::mouse_position(&event).to_physical(super::scale_factor(&window)),
|
||||
Force::Normalized(event.pressure() as f64),
|
||||
);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ use crate::icon::Icon;
|
||||
use crate::monitor::MonitorHandle as RootMonitorHandle;
|
||||
use crate::window::{
|
||||
Cursor, CursorGrabMode, Fullscreen as RootFullscreen, ImePurpose, ResizeDirection, Theme,
|
||||
UserAttentionType, Window as RootWindow, WindowAttributes, WindowButtons, WindowId,
|
||||
UserAttentionType, Window as RootWindow, WindowAttributes, WindowButtons, WindowId as RootWI,
|
||||
WindowLevel,
|
||||
};
|
||||
|
||||
@@ -53,7 +53,7 @@ impl Window {
|
||||
target.register(&canvas, id);
|
||||
|
||||
let runner = target.runner.clone();
|
||||
let destroy_fn = Box::new(move || runner.notify_destroy_window(id));
|
||||
let destroy_fn = Box::new(move || runner.notify_destroy_window(RootWI(id)));
|
||||
|
||||
let inner = Inner {
|
||||
id,
|
||||
@@ -65,7 +65,7 @@ impl Window {
|
||||
|
||||
let canvas = Rc::downgrade(&inner.canvas);
|
||||
let (dispatcher, runner) = Dispatcher::new(target.runner.main_thread(), inner);
|
||||
target.runner.add_canvas(id, canvas, runner);
|
||||
target.runner.add_canvas(RootWI(id), canvas, runner);
|
||||
|
||||
Ok(Window { inner: dispatcher })
|
||||
}
|
||||
@@ -91,8 +91,8 @@ impl Window {
|
||||
}
|
||||
|
||||
impl RootWindow for Window {
|
||||
fn id(&self) -> WindowId {
|
||||
self.inner.queue(|inner| inner.id)
|
||||
fn id(&self) -> RootWI {
|
||||
RootWI(self.inner.queue(|inner| inner.id))
|
||||
}
|
||||
|
||||
fn scale_factor(&self) -> f64 {
|
||||
@@ -429,6 +429,27 @@ impl Drop for Inner {
|
||||
}
|
||||
}
|
||||
}
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct WindowId(pub(crate) u32);
|
||||
|
||||
impl WindowId {
|
||||
pub const fn dummy() -> Self {
|
||||
Self(0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<WindowId> for u64 {
|
||||
fn from(window_id: WindowId) -> Self {
|
||||
window_id.0 as u64
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u64> for WindowId {
|
||||
fn from(raw_id: u64) -> Self {
|
||||
Self(raw_id as u32)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PlatformSpecificWindowAttributes {
|
||||
pub(crate) canvas: Option<Arc<MainThreadSafe<backend::RawCanvasType>>>,
|
||||
|
||||
@@ -15,7 +15,8 @@ use crate::event::Event;
|
||||
use crate::platform_impl::platform::definitions::{
|
||||
IDataObjectVtbl, IDropTarget, IDropTargetVtbl, IUnknownVtbl,
|
||||
};
|
||||
use crate::window::WindowId;
|
||||
use crate::platform_impl::platform::WindowId;
|
||||
use crate::window::WindowId as RootWindowId;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct FileDropHandlerData {
|
||||
@@ -85,7 +86,7 @@ impl FileDropHandler {
|
||||
let hdrop = unsafe {
|
||||
Self::iterate_filenames(pDataObj, |filename| {
|
||||
drop_handler.send_event(Event::WindowEvent {
|
||||
window_id: WindowId::from_raw(drop_handler.window as usize),
|
||||
window_id: RootWindowId(WindowId(drop_handler.window)),
|
||||
event: HoveredFile(filename),
|
||||
});
|
||||
})
|
||||
@@ -119,7 +120,7 @@ impl FileDropHandler {
|
||||
let drop_handler = unsafe { Self::from_interface(this) };
|
||||
if drop_handler.hovered_is_valid {
|
||||
drop_handler.send_event(Event::WindowEvent {
|
||||
window_id: WindowId::from_raw(drop_handler.window as usize),
|
||||
window_id: RootWindowId(WindowId(drop_handler.window)),
|
||||
event: HoveredFileCancelled,
|
||||
});
|
||||
}
|
||||
@@ -139,7 +140,7 @@ impl FileDropHandler {
|
||||
let hdrop = unsafe {
|
||||
Self::iterate_filenames(pDataObj, |filename| {
|
||||
drop_handler.send_event(Event::WindowEvent {
|
||||
window_id: WindowId::from_raw(drop_handler.window as usize),
|
||||
window_id: RootWindowId(WindowId(drop_handler.window)),
|
||||
event: DroppedFile(filename),
|
||||
});
|
||||
})
|
||||
|
||||
@@ -37,9 +37,9 @@ use windows_sys::Win32::UI::WindowsAndMessaging::{
|
||||
GetMenu, GetMessageW, KillTimer, LoadCursorW, PeekMessageW, PostMessageW, RegisterClassExW,
|
||||
RegisterWindowMessageA, SetCursor, SetTimer, SetWindowPos, TranslateMessage, CREATESTRUCTW,
|
||||
GWL_STYLE, GWL_USERDATA, HTCAPTION, HTCLIENT, MINMAXINFO, MNC_CLOSE, MSG, NCCALCSIZE_PARAMS,
|
||||
PM_REMOVE, PT_TOUCH, RI_MOUSE_HWHEEL, RI_MOUSE_WHEEL, SC_MINIMIZE, SC_RESTORE, SIZE_MAXIMIZED,
|
||||
SWP_NOACTIVATE, SWP_NOMOVE, SWP_NOSIZE, SWP_NOZORDER, WHEEL_DELTA, WINDOWPOS, WMSZ_BOTTOM,
|
||||
WMSZ_BOTTOMLEFT, WMSZ_BOTTOMRIGHT, WMSZ_LEFT, WMSZ_RIGHT, WMSZ_TOP, WMSZ_TOPLEFT,
|
||||
PM_REMOVE, PT_PEN, PT_TOUCH, RI_MOUSE_HWHEEL, RI_MOUSE_WHEEL, SC_MINIMIZE, SC_RESTORE,
|
||||
SIZE_MAXIMIZED, SWP_NOACTIVATE, SWP_NOMOVE, SWP_NOSIZE, SWP_NOZORDER, WHEEL_DELTA, WINDOWPOS,
|
||||
WMSZ_BOTTOM, WMSZ_BOTTOMLEFT, WMSZ_BOTTOMRIGHT, WMSZ_LEFT, WMSZ_RIGHT, WMSZ_TOP, WMSZ_TOPLEFT,
|
||||
WMSZ_TOPRIGHT, WM_CAPTURECHANGED, WM_CLOSE, WM_CREATE, WM_DESTROY, WM_DPICHANGED,
|
||||
WM_ENTERSIZEMOVE, WM_EXITSIZEMOVE, WM_GETMINMAXINFO, WM_IME_COMPOSITION, WM_IME_ENDCOMPOSITION,
|
||||
WM_IME_SETCONTEXT, WM_IME_STARTCOMPOSITION, WM_INPUT, WM_KEYDOWN, WM_KEYUP, WM_KILLFOCUS,
|
||||
@@ -58,7 +58,7 @@ use crate::application::ApplicationHandler;
|
||||
use crate::dpi::{PhysicalPosition, PhysicalSize};
|
||||
use crate::error::{EventLoopError, RequestError};
|
||||
use crate::event::{
|
||||
Event, FingerId as RootFingerId, Force, Ime, RawKeyEvent, SurfaceSizeWriter, TouchPhase,
|
||||
Event, FingerId as RootFingerId, Force, Ime, RawKeyEvent, SurfaceSizeWriter, Touch, TouchPhase,
|
||||
WindowEvent,
|
||||
};
|
||||
use crate::event_loop::{
|
||||
@@ -80,12 +80,14 @@ use crate::platform_impl::platform::window::InitData;
|
||||
use crate::platform_impl::platform::window_state::{
|
||||
CursorFlags, ImeState, WindowFlags, WindowState,
|
||||
};
|
||||
use crate::platform_impl::platform::{raw_input, util, wrap_device_id, FingerId, Fullscreen};
|
||||
use crate::platform_impl::platform::{
|
||||
raw_input, util, wrap_device_id, FingerId, Fullscreen, WindowId, DEVICE_ID,
|
||||
};
|
||||
use crate::platform_impl::Window;
|
||||
use crate::utils::Lazy;
|
||||
use crate::window::{
|
||||
CustomCursor as RootCustomCursor, CustomCursorSource, Theme, Window as CoreWindow,
|
||||
WindowAttributes, WindowId,
|
||||
WindowAttributes, WindowId as CoreWindowId,
|
||||
};
|
||||
|
||||
pub(crate) struct WindowData {
|
||||
@@ -180,7 +182,7 @@ impl EventLoop {
|
||||
"Initializing the event loop outside of the main thread is a significant \
|
||||
cross-platform compatibility hazard. If you absolutely need to create an \
|
||||
EventLoop on a different thread, you can use the \
|
||||
`EventLoopBuilderExtWindows::with_any_thread` function."
|
||||
`EventLoopBuilderExtWindows::any_thread` function."
|
||||
);
|
||||
}
|
||||
|
||||
@@ -918,7 +920,7 @@ fn update_modifiers(window: HWND, userdata: &WindowData) {
|
||||
drop(window_state);
|
||||
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: WindowId::from_raw(window as usize),
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: ModifiersChanged(modifiers.into()),
|
||||
});
|
||||
}
|
||||
@@ -930,7 +932,7 @@ unsafe fn gain_active_focus(window: HWND, userdata: &WindowData) {
|
||||
update_modifiers(window, userdata);
|
||||
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: WindowId::from_raw(window as usize),
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: Focused(true),
|
||||
});
|
||||
}
|
||||
@@ -940,12 +942,12 @@ unsafe fn lose_active_focus(window: HWND, userdata: &WindowData) {
|
||||
|
||||
userdata.window_state_lock().modifiers_state = ModifiersState::empty();
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: WindowId::from_raw(window as usize),
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: ModifiersChanged(ModifiersState::empty().into()),
|
||||
});
|
||||
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: WindowId::from_raw(window as usize),
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: Focused(false),
|
||||
});
|
||||
}
|
||||
@@ -1043,9 +1045,9 @@ unsafe fn public_window_callback_inner(
|
||||
userdata.key_event_builder.process_message(window, msg, wparam, lparam, &mut result);
|
||||
for event in events {
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: WindowId::from_raw(window as usize),
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: KeyboardInput {
|
||||
device_id: None,
|
||||
device_id: DEVICE_ID,
|
||||
event: event.event,
|
||||
is_synthetic: event.is_synthetic,
|
||||
},
|
||||
@@ -1128,7 +1130,7 @@ unsafe fn public_window_callback_inner(
|
||||
WM_CLOSE => {
|
||||
use crate::event::WindowEvent::CloseRequested;
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: WindowId::from_raw(window as usize),
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: CloseRequested,
|
||||
});
|
||||
result = ProcResult::Value(0);
|
||||
@@ -1138,7 +1140,7 @@ unsafe fn public_window_callback_inner(
|
||||
use crate::event::WindowEvent::Destroyed;
|
||||
unsafe { RevokeDragDrop(window) };
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: WindowId::from_raw(window as usize),
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: Destroyed,
|
||||
});
|
||||
result = ProcResult::Value(0);
|
||||
@@ -1159,7 +1161,7 @@ unsafe fn public_window_callback_inner(
|
||||
// and request a normal redraw with `RedrawWindow`.
|
||||
if !userdata.event_loop_runner.should_buffer() {
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: WindowId::from_raw(window as usize),
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: WindowEvent::RedrawRequested,
|
||||
});
|
||||
}
|
||||
@@ -1262,7 +1264,7 @@ unsafe fn public_window_callback_inner(
|
||||
let physical_position =
|
||||
unsafe { PhysicalPosition::new((*windowpos).x, (*windowpos).y) };
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: WindowId::from_raw(window as usize),
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: Moved(physical_position),
|
||||
});
|
||||
}
|
||||
@@ -1278,7 +1280,7 @@ unsafe fn public_window_callback_inner(
|
||||
|
||||
let physical_size = PhysicalSize::new(w, h);
|
||||
let event = Event::WindowEvent {
|
||||
window_id: WindowId::from_raw(window as usize),
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: SurfaceResized(physical_size),
|
||||
};
|
||||
|
||||
@@ -1393,7 +1395,7 @@ unsafe fn public_window_callback_inner(
|
||||
userdata.window_state_lock().ime_state = ImeState::Enabled;
|
||||
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: WindowId::from_raw(window as usize),
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: WindowEvent::Ime(Ime::Enabled),
|
||||
});
|
||||
}
|
||||
@@ -1413,7 +1415,7 @@ unsafe fn public_window_callback_inner(
|
||||
|
||||
if lparam == 0 {
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: WindowId::from_raw(window as usize),
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: WindowEvent::Ime(Ime::Preedit(String::new(), None)),
|
||||
});
|
||||
}
|
||||
@@ -1425,11 +1427,11 @@ unsafe fn public_window_callback_inner(
|
||||
userdata.window_state_lock().ime_state = ImeState::Enabled;
|
||||
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: WindowId::from_raw(window as usize),
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: WindowEvent::Ime(Ime::Preedit(String::new(), None)),
|
||||
});
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: WindowId::from_raw(window as usize),
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: WindowEvent::Ime(Ime::Commit(text)),
|
||||
});
|
||||
}
|
||||
@@ -1444,7 +1446,7 @@ unsafe fn public_window_callback_inner(
|
||||
let cursor_range = first.map(|f| (f, last.unwrap_or(f)));
|
||||
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: WindowId::from_raw(window as usize),
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: WindowEvent::Ime(Ime::Preedit(text, cursor_range)),
|
||||
});
|
||||
}
|
||||
@@ -1467,11 +1469,11 @@ unsafe fn public_window_callback_inner(
|
||||
let ime_context = unsafe { ImeContext::current(window) };
|
||||
if let Some(text) = unsafe { ime_context.get_composed_text() } {
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: WindowId::from_raw(window as usize),
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: WindowEvent::Ime(Ime::Preedit(String::new(), None)),
|
||||
});
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: WindowId::from_raw(window as usize),
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: WindowEvent::Ime(Ime::Commit(text)),
|
||||
});
|
||||
}
|
||||
@@ -1480,7 +1482,7 @@ unsafe fn public_window_callback_inner(
|
||||
userdata.window_state_lock().ime_state = ImeState::Disabled;
|
||||
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: WindowId::from_raw(window as usize),
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: WindowEvent::Ime(Ime::Disabled),
|
||||
});
|
||||
}
|
||||
@@ -1518,8 +1520,7 @@ unsafe fn public_window_callback_inner(
|
||||
},
|
||||
|
||||
WM_MOUSEMOVE => {
|
||||
use crate::event::WindowEvent::{PointerEntered, PointerLeft, PointerMoved};
|
||||
use crate::event::{PointerKind, PointerSource};
|
||||
use crate::event::WindowEvent::{CursorEntered, CursorLeft, CursorMoved};
|
||||
|
||||
let x = super::get_x_lparam(lparam as u32) as i32;
|
||||
let y = super::get_y_lparam(lparam as u32) as i32;
|
||||
@@ -1539,12 +1540,8 @@ unsafe fn public_window_callback_inner(
|
||||
|
||||
drop(w);
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: WindowId::from_raw(window as usize),
|
||||
event: PointerEntered {
|
||||
device_id: None,
|
||||
position,
|
||||
kind: PointerKind::Mouse,
|
||||
},
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: CursorEntered { device_id: DEVICE_ID },
|
||||
});
|
||||
|
||||
// Calling TrackMouseEvent in order to receive mouse leave events.
|
||||
@@ -1564,12 +1561,8 @@ unsafe fn public_window_callback_inner(
|
||||
|
||||
drop(w);
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: WindowId::from_raw(window as usize),
|
||||
event: PointerLeft {
|
||||
device_id: None,
|
||||
position: Some(position),
|
||||
kind: PointerKind::Mouse,
|
||||
},
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: CursorLeft { device_id: DEVICE_ID },
|
||||
});
|
||||
},
|
||||
PointerMoveKind::None => drop(w),
|
||||
@@ -1587,8 +1580,8 @@ unsafe fn public_window_callback_inner(
|
||||
update_modifiers(window, userdata);
|
||||
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: WindowId::from_raw(window as usize),
|
||||
event: PointerMoved { device_id: None, position, source: PointerSource::Mouse },
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: CursorMoved { device_id: DEVICE_ID, position },
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1596,17 +1589,15 @@ unsafe fn public_window_callback_inner(
|
||||
},
|
||||
|
||||
WM_MOUSELEAVE => {
|
||||
use crate::event::PointerKind::Mouse;
|
||||
use crate::event::WindowEvent::PointerLeft;
|
||||
|
||||
use crate::event::WindowEvent::CursorLeft;
|
||||
{
|
||||
let mut w = userdata.window_state_lock();
|
||||
w.mouse.set_cursor_flags(window, |f| f.set(CursorFlags::IN_WINDOW, false)).ok();
|
||||
}
|
||||
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: WindowId::from_raw(window as usize),
|
||||
event: PointerLeft { device_id: None, position: None, kind: Mouse },
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: CursorLeft { device_id: DEVICE_ID },
|
||||
});
|
||||
|
||||
result = ProcResult::Value(0);
|
||||
@@ -1621,9 +1612,9 @@ unsafe fn public_window_callback_inner(
|
||||
update_modifiers(window, userdata);
|
||||
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: WindowId::from_raw(window as usize),
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: WindowEvent::MouseWheel {
|
||||
device_id: None,
|
||||
device_id: DEVICE_ID,
|
||||
delta: LineDelta(0.0, value),
|
||||
phase: TouchPhase::Moved,
|
||||
},
|
||||
@@ -1641,9 +1632,9 @@ unsafe fn public_window_callback_inner(
|
||||
update_modifiers(window, userdata);
|
||||
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: WindowId::from_raw(window as usize),
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: WindowEvent::MouseWheel {
|
||||
device_id: None,
|
||||
device_id: DEVICE_ID,
|
||||
delta: LineDelta(value, 0.0),
|
||||
phase: TouchPhase::Moved,
|
||||
},
|
||||
@@ -1669,24 +1660,15 @@ unsafe fn public_window_callback_inner(
|
||||
WM_LBUTTONDOWN => {
|
||||
use crate::event::ElementState::Pressed;
|
||||
use crate::event::MouseButton::Left;
|
||||
use crate::event::WindowEvent::PointerButton;
|
||||
use crate::event::WindowEvent::MouseInput;
|
||||
|
||||
unsafe { capture_mouse(window, &mut userdata.window_state_lock()) };
|
||||
|
||||
update_modifiers(window, userdata);
|
||||
|
||||
let x = super::get_x_lparam(lparam as u32) as i32;
|
||||
let y = super::get_y_lparam(lparam as u32) as i32;
|
||||
let position = PhysicalPosition::new(x as f64, y as f64);
|
||||
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: WindowId::from_raw(window as usize),
|
||||
event: PointerButton {
|
||||
device_id: None,
|
||||
state: Pressed,
|
||||
position,
|
||||
button: Left.into(),
|
||||
},
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: MouseInput { device_id: DEVICE_ID, state: Pressed, button: Left },
|
||||
});
|
||||
result = ProcResult::Value(0);
|
||||
},
|
||||
@@ -1694,24 +1676,15 @@ unsafe fn public_window_callback_inner(
|
||||
WM_LBUTTONUP => {
|
||||
use crate::event::ElementState::Released;
|
||||
use crate::event::MouseButton::Left;
|
||||
use crate::event::WindowEvent::PointerButton;
|
||||
use crate::event::WindowEvent::MouseInput;
|
||||
|
||||
unsafe { release_mouse(userdata.window_state_lock()) };
|
||||
|
||||
update_modifiers(window, userdata);
|
||||
|
||||
let x = super::get_x_lparam(lparam as u32) as i32;
|
||||
let y = super::get_y_lparam(lparam as u32) as i32;
|
||||
let position = PhysicalPosition::new(x as f64, y as f64);
|
||||
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: WindowId::from_raw(window as usize),
|
||||
event: PointerButton {
|
||||
device_id: None,
|
||||
state: Released,
|
||||
position,
|
||||
button: Left.into(),
|
||||
},
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: MouseInput { device_id: DEVICE_ID, state: Released, button: Left },
|
||||
});
|
||||
result = ProcResult::Value(0);
|
||||
},
|
||||
@@ -1719,24 +1692,15 @@ unsafe fn public_window_callback_inner(
|
||||
WM_RBUTTONDOWN => {
|
||||
use crate::event::ElementState::Pressed;
|
||||
use crate::event::MouseButton::Right;
|
||||
use crate::event::WindowEvent::PointerButton;
|
||||
use crate::event::WindowEvent::MouseInput;
|
||||
|
||||
unsafe { capture_mouse(window, &mut userdata.window_state_lock()) };
|
||||
|
||||
update_modifiers(window, userdata);
|
||||
|
||||
let x = super::get_x_lparam(lparam as u32) as i32;
|
||||
let y = super::get_y_lparam(lparam as u32) as i32;
|
||||
let position = PhysicalPosition::new(x as f64, y as f64);
|
||||
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: WindowId::from_raw(window as usize),
|
||||
event: PointerButton {
|
||||
device_id: None,
|
||||
state: Pressed,
|
||||
position,
|
||||
button: Right.into(),
|
||||
},
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: MouseInput { device_id: DEVICE_ID, state: Pressed, button: Right },
|
||||
});
|
||||
result = ProcResult::Value(0);
|
||||
},
|
||||
@@ -1744,24 +1708,15 @@ unsafe fn public_window_callback_inner(
|
||||
WM_RBUTTONUP => {
|
||||
use crate::event::ElementState::Released;
|
||||
use crate::event::MouseButton::Right;
|
||||
use crate::event::WindowEvent::PointerButton;
|
||||
use crate::event::WindowEvent::MouseInput;
|
||||
|
||||
unsafe { release_mouse(userdata.window_state_lock()) };
|
||||
|
||||
update_modifiers(window, userdata);
|
||||
|
||||
let x = super::get_x_lparam(lparam as u32) as i32;
|
||||
let y = super::get_y_lparam(lparam as u32) as i32;
|
||||
let position = PhysicalPosition::new(x as f64, y as f64);
|
||||
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: WindowId::from_raw(window as usize),
|
||||
event: PointerButton {
|
||||
device_id: None,
|
||||
state: Released,
|
||||
position,
|
||||
button: Right.into(),
|
||||
},
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: MouseInput { device_id: DEVICE_ID, state: Released, button: Right },
|
||||
});
|
||||
result = ProcResult::Value(0);
|
||||
},
|
||||
@@ -1769,24 +1724,15 @@ unsafe fn public_window_callback_inner(
|
||||
WM_MBUTTONDOWN => {
|
||||
use crate::event::ElementState::Pressed;
|
||||
use crate::event::MouseButton::Middle;
|
||||
use crate::event::WindowEvent::PointerButton;
|
||||
use crate::event::WindowEvent::MouseInput;
|
||||
|
||||
unsafe { capture_mouse(window, &mut userdata.window_state_lock()) };
|
||||
|
||||
update_modifiers(window, userdata);
|
||||
|
||||
let x = super::get_x_lparam(lparam as u32) as i32;
|
||||
let y = super::get_y_lparam(lparam as u32) as i32;
|
||||
let position = PhysicalPosition::new(x as f64, y as f64);
|
||||
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: WindowId::from_raw(window as usize),
|
||||
event: PointerButton {
|
||||
device_id: None,
|
||||
state: Pressed,
|
||||
position,
|
||||
button: Middle.into(),
|
||||
},
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: MouseInput { device_id: DEVICE_ID, state: Pressed, button: Middle },
|
||||
});
|
||||
result = ProcResult::Value(0);
|
||||
},
|
||||
@@ -1794,24 +1740,15 @@ unsafe fn public_window_callback_inner(
|
||||
WM_MBUTTONUP => {
|
||||
use crate::event::ElementState::Released;
|
||||
use crate::event::MouseButton::Middle;
|
||||
use crate::event::WindowEvent::PointerButton;
|
||||
use crate::event::WindowEvent::MouseInput;
|
||||
|
||||
unsafe { release_mouse(userdata.window_state_lock()) };
|
||||
|
||||
update_modifiers(window, userdata);
|
||||
|
||||
let x = super::get_x_lparam(lparam as u32) as i32;
|
||||
let y = super::get_y_lparam(lparam as u32) as i32;
|
||||
let position = PhysicalPosition::new(x as f64, y as f64);
|
||||
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: WindowId::from_raw(window as usize),
|
||||
event: PointerButton {
|
||||
device_id: None,
|
||||
state: Released,
|
||||
position,
|
||||
button: Middle.into(),
|
||||
},
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: MouseInput { device_id: DEVICE_ID, state: Released, button: Middle },
|
||||
});
|
||||
result = ProcResult::Value(0);
|
||||
},
|
||||
@@ -1819,29 +1756,23 @@ unsafe fn public_window_callback_inner(
|
||||
WM_XBUTTONDOWN => {
|
||||
use crate::event::ElementState::Pressed;
|
||||
use crate::event::MouseButton::{Back, Forward, Other};
|
||||
use crate::event::WindowEvent::PointerButton;
|
||||
use crate::event::WindowEvent::MouseInput;
|
||||
let xbutton = super::get_xbutton_wparam(wparam as u32);
|
||||
|
||||
unsafe { capture_mouse(window, &mut userdata.window_state_lock()) };
|
||||
|
||||
update_modifiers(window, userdata);
|
||||
|
||||
let x = super::get_x_lparam(lparam as u32) as i32;
|
||||
let y = super::get_y_lparam(lparam as u32) as i32;
|
||||
let position = PhysicalPosition::new(x as f64, y as f64);
|
||||
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: WindowId::from_raw(window as usize),
|
||||
event: PointerButton {
|
||||
device_id: None,
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: MouseInput {
|
||||
device_id: DEVICE_ID,
|
||||
state: Pressed,
|
||||
position,
|
||||
button: match xbutton {
|
||||
1 => Back,
|
||||
2 => Forward,
|
||||
_ => Other(xbutton),
|
||||
}
|
||||
.into(),
|
||||
},
|
||||
},
|
||||
});
|
||||
result = ProcResult::Value(0);
|
||||
@@ -1850,29 +1781,23 @@ unsafe fn public_window_callback_inner(
|
||||
WM_XBUTTONUP => {
|
||||
use crate::event::ElementState::Released;
|
||||
use crate::event::MouseButton::{Back, Forward, Other};
|
||||
use crate::event::WindowEvent::PointerButton;
|
||||
use crate::event::WindowEvent::MouseInput;
|
||||
let xbutton = super::get_xbutton_wparam(wparam as u32);
|
||||
|
||||
unsafe { release_mouse(userdata.window_state_lock()) };
|
||||
|
||||
update_modifiers(window, userdata);
|
||||
|
||||
let x = super::get_x_lparam(lparam as u32) as i32;
|
||||
let y = super::get_y_lparam(lparam as u32) as i32;
|
||||
let position = PhysicalPosition::new(x as f64, y as f64);
|
||||
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: WindowId::from_raw(window as usize),
|
||||
event: PointerButton {
|
||||
device_id: None,
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: MouseInput {
|
||||
device_id: DEVICE_ID,
|
||||
state: Released,
|
||||
position,
|
||||
button: match xbutton {
|
||||
1 => Back,
|
||||
2 => Forward,
|
||||
_ => Other(xbutton),
|
||||
}
|
||||
.into(),
|
||||
},
|
||||
},
|
||||
});
|
||||
result = ProcResult::Value(0);
|
||||
@@ -1890,10 +1815,6 @@ unsafe fn public_window_callback_inner(
|
||||
},
|
||||
|
||||
WM_TOUCH => {
|
||||
use crate::event::ButtonSource::Touch;
|
||||
use crate::event::ElementState::{Pressed, Released};
|
||||
use crate::event::{PointerKind, PointerSource};
|
||||
|
||||
let pcount = super::loword(wparam as u32) as usize;
|
||||
let mut inputs = Vec::with_capacity(pcount);
|
||||
let htouch = lparam;
|
||||
@@ -1907,70 +1828,36 @@ unsafe fn public_window_callback_inner(
|
||||
} {
|
||||
unsafe { inputs.set_len(pcount) };
|
||||
for input in &inputs {
|
||||
let mut position = POINT { x: input.x / 100, y: input.y / 100 };
|
||||
let mut location = POINT { x: input.x / 100, y: input.y / 100 };
|
||||
|
||||
if unsafe { ScreenToClient(window, &mut position) } == false.into() {
|
||||
if unsafe { ScreenToClient(window, &mut location) } == false.into() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let x = position.x as f64 + (input.x % 100) as f64 / 100f64;
|
||||
let y = position.y as f64 + (input.y % 100) as f64 / 100f64;
|
||||
let position = PhysicalPosition::new(x, y);
|
||||
|
||||
let window_id = WindowId::from_raw(window as usize);
|
||||
let finger_id = RootFingerId(FingerId {
|
||||
id: input.dwID,
|
||||
primary: util::has_flag(input.dwFlags, TOUCHEVENTF_PRIMARY),
|
||||
let x = location.x as f64 + (input.x % 100) as f64 / 100f64;
|
||||
let y = location.y as f64 + (input.y % 100) as f64 / 100f64;
|
||||
let location = PhysicalPosition::new(x, y);
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: WindowEvent::Touch(Touch {
|
||||
phase: if util::has_flag(input.dwFlags, TOUCHEVENTF_DOWN) {
|
||||
TouchPhase::Started
|
||||
} else if util::has_flag(input.dwFlags, TOUCHEVENTF_UP) {
|
||||
TouchPhase::Ended
|
||||
} else if util::has_flag(input.dwFlags, TOUCHEVENTF_MOVE) {
|
||||
TouchPhase::Moved
|
||||
} else {
|
||||
continue;
|
||||
},
|
||||
location,
|
||||
force: None, // WM_TOUCH doesn't support pressure information
|
||||
finger_id: RootFingerId(FingerId {
|
||||
id: input.dwID,
|
||||
primary: util::has_flag(input.dwFlags, TOUCHEVENTF_PRIMARY),
|
||||
}),
|
||||
device_id: DEVICE_ID,
|
||||
}),
|
||||
});
|
||||
|
||||
if util::has_flag(input.dwFlags, TOUCHEVENTF_DOWN) {
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerEntered {
|
||||
device_id: None,
|
||||
position,
|
||||
kind: PointerKind::Touch(finger_id),
|
||||
},
|
||||
});
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerButton {
|
||||
device_id: None,
|
||||
state: Pressed,
|
||||
position,
|
||||
button: Touch { finger_id, force: None },
|
||||
},
|
||||
});
|
||||
} else if util::has_flag(input.dwFlags, TOUCHEVENTF_UP) {
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerButton {
|
||||
device_id: None,
|
||||
state: Released,
|
||||
position,
|
||||
button: Touch { finger_id, force: None },
|
||||
},
|
||||
});
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerLeft {
|
||||
device_id: None,
|
||||
position: Some(position),
|
||||
kind: PointerKind::Touch(finger_id),
|
||||
},
|
||||
});
|
||||
} else if util::has_flag(input.dwFlags, TOUCHEVENTF_MOVE) {
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerMoved {
|
||||
device_id: None,
|
||||
position,
|
||||
source: PointerSource::Touch { finger_id, force: None },
|
||||
},
|
||||
});
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
unsafe { CloseTouchInputHandle(htouch) };
|
||||
@@ -1978,9 +1865,6 @@ unsafe fn public_window_callback_inner(
|
||||
},
|
||||
|
||||
WM_POINTERDOWN | WM_POINTERUPDATE | WM_POINTERUP => {
|
||||
use crate::event::ElementState::{Pressed, Released};
|
||||
use crate::event::{ButtonSource, PointerKind, PointerSource};
|
||||
|
||||
if let (
|
||||
Some(GetPointerFrameInfoHistory),
|
||||
Some(SkipPointerFrameMessages),
|
||||
@@ -2065,100 +1949,67 @@ unsafe fn public_window_callback_inner(
|
||||
continue;
|
||||
}
|
||||
|
||||
let force = if let PT_TOUCH = pointer_info.pointerType {
|
||||
let mut touch_info = mem::MaybeUninit::uninit();
|
||||
util::GET_POINTER_TOUCH_INFO.and_then(|GetPointerTouchInfo| {
|
||||
match unsafe {
|
||||
GetPointerTouchInfo(pointer_info.pointerId, touch_info.as_mut_ptr())
|
||||
} {
|
||||
0 => None,
|
||||
_ => normalize_pointer_pressure(unsafe {
|
||||
touch_info.assume_init().pressure
|
||||
}),
|
||||
}
|
||||
})
|
||||
} else {
|
||||
None
|
||||
let force = match pointer_info.pointerType {
|
||||
PT_TOUCH => {
|
||||
let mut touch_info = mem::MaybeUninit::uninit();
|
||||
util::GET_POINTER_TOUCH_INFO.and_then(|GetPointerTouchInfo| {
|
||||
match unsafe {
|
||||
GetPointerTouchInfo(
|
||||
pointer_info.pointerId,
|
||||
touch_info.as_mut_ptr(),
|
||||
)
|
||||
} {
|
||||
0 => None,
|
||||
_ => normalize_pointer_pressure(unsafe {
|
||||
touch_info.assume_init().pressure
|
||||
}),
|
||||
}
|
||||
})
|
||||
},
|
||||
PT_PEN => {
|
||||
let mut pen_info = mem::MaybeUninit::uninit();
|
||||
util::GET_POINTER_PEN_INFO.and_then(|GetPointerPenInfo| {
|
||||
match unsafe {
|
||||
GetPointerPenInfo(pointer_info.pointerId, pen_info.as_mut_ptr())
|
||||
} {
|
||||
0 => None,
|
||||
_ => normalize_pointer_pressure(unsafe {
|
||||
pen_info.assume_init().pressure
|
||||
}),
|
||||
}
|
||||
})
|
||||
},
|
||||
_ => None,
|
||||
};
|
||||
|
||||
let x = location.x as f64 + x.fract();
|
||||
let y = location.y as f64 + y.fract();
|
||||
let position = PhysicalPosition::new(x, y);
|
||||
|
||||
let window_id = WindowId::from_raw(window as usize);
|
||||
let finger_id = RootFingerId(FingerId {
|
||||
id: pointer_info.pointerId,
|
||||
primary: util::has_flag(pointer_info.pointerFlags, POINTER_FLAG_PRIMARY),
|
||||
let location = PhysicalPosition::new(x, y);
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: WindowEvent::Touch(Touch {
|
||||
phase: if util::has_flag(pointer_info.pointerFlags, POINTER_FLAG_DOWN) {
|
||||
TouchPhase::Started
|
||||
} else if util::has_flag(pointer_info.pointerFlags, POINTER_FLAG_UP) {
|
||||
TouchPhase::Ended
|
||||
} else if util::has_flag(pointer_info.pointerFlags, POINTER_FLAG_UPDATE)
|
||||
{
|
||||
TouchPhase::Moved
|
||||
} else {
|
||||
continue;
|
||||
},
|
||||
location,
|
||||
force,
|
||||
finger_id: RootFingerId(FingerId {
|
||||
id: pointer_info.pointerId,
|
||||
primary: util::has_flag(
|
||||
pointer_info.pointerFlags,
|
||||
POINTER_FLAG_PRIMARY,
|
||||
),
|
||||
}),
|
||||
device_id: DEVICE_ID,
|
||||
}),
|
||||
});
|
||||
|
||||
if util::has_flag(pointer_info.pointerFlags, POINTER_FLAG_DOWN) {
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerEntered {
|
||||
device_id: None,
|
||||
position,
|
||||
kind: if let PT_TOUCH = pointer_info.pointerType {
|
||||
PointerKind::Touch(finger_id)
|
||||
} else {
|
||||
PointerKind::Unknown
|
||||
},
|
||||
},
|
||||
});
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerButton {
|
||||
device_id: None,
|
||||
state: Pressed,
|
||||
position,
|
||||
button: if let PT_TOUCH = pointer_info.pointerType {
|
||||
ButtonSource::Touch { finger_id, force }
|
||||
} else {
|
||||
ButtonSource::Unknown(0)
|
||||
},
|
||||
},
|
||||
});
|
||||
} else if util::has_flag(pointer_info.pointerFlags, POINTER_FLAG_UP) {
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerButton {
|
||||
device_id: None,
|
||||
state: Released,
|
||||
position,
|
||||
button: if let PT_TOUCH = pointer_info.pointerType {
|
||||
ButtonSource::Touch { finger_id, force }
|
||||
} else {
|
||||
ButtonSource::Unknown(0)
|
||||
},
|
||||
},
|
||||
});
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerLeft {
|
||||
device_id: None,
|
||||
position: Some(position),
|
||||
kind: if let PT_TOUCH = pointer_info.pointerType {
|
||||
PointerKind::Touch(finger_id)
|
||||
} else {
|
||||
PointerKind::Unknown
|
||||
},
|
||||
},
|
||||
});
|
||||
} else if util::has_flag(pointer_info.pointerFlags, POINTER_FLAG_UPDATE) {
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerMoved {
|
||||
device_id: None,
|
||||
position,
|
||||
source: if let PT_TOUCH = pointer_info.pointerType {
|
||||
PointerSource::Touch { finger_id, force }
|
||||
} else {
|
||||
PointerSource::Unknown
|
||||
},
|
||||
},
|
||||
});
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
unsafe { SkipPointerFrameMessages(pointer_id) };
|
||||
@@ -2318,7 +2169,7 @@ unsafe fn public_window_callback_inner(
|
||||
|
||||
let new_surface_size = Arc::new(Mutex::new(new_physical_surface_size));
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: WindowId::from_raw(window as usize),
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: ScaleFactorChanged {
|
||||
scale_factor: new_scale_factor,
|
||||
surface_size_writer: SurfaceSizeWriter::new(Arc::downgrade(&new_surface_size)),
|
||||
@@ -2470,7 +2321,7 @@ unsafe fn public_window_callback_inner(
|
||||
window_state.current_theme = new_theme;
|
||||
drop(window_state);
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: WindowId::from_raw(window as usize),
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: ThemeChanged(new_theme),
|
||||
});
|
||||
}
|
||||
@@ -2580,11 +2431,11 @@ unsafe extern "system" fn thread_event_target_callback(
|
||||
}
|
||||
|
||||
unsafe fn handle_raw_input(userdata: &ThreadMsgTargetData, data: RAWINPUT) {
|
||||
use crate::event::DeviceEvent::{Button, Key, MouseWheel, PointerMotion};
|
||||
use crate::event::DeviceEvent::{Button, Key, MouseMotion, MouseWheel};
|
||||
use crate::event::ElementState::{Pressed, Released};
|
||||
use crate::event::MouseScrollDelta::LineDelta;
|
||||
|
||||
let device_id = Some(wrap_device_id(data.header.hDevice as _));
|
||||
let device_id = wrap_device_id(data.header.hDevice as _);
|
||||
|
||||
if data.header.dwType == RIM_TYPEMOUSE {
|
||||
let mouse = unsafe { data.data.mouse };
|
||||
@@ -2596,7 +2447,7 @@ unsafe fn handle_raw_input(userdata: &ThreadMsgTargetData, data: RAWINPUT) {
|
||||
if x != 0.0 || y != 0.0 {
|
||||
userdata.send_event(Event::DeviceEvent {
|
||||
device_id,
|
||||
event: PointerMotion { delta: (x, y) },
|
||||
event: MouseMotion { delta: (x, y) },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ pub(crate) enum RunnerState {
|
||||
|
||||
enum BufferedEvent {
|
||||
Event(Event),
|
||||
ScaleFactorChanged(HWND, f64, PhysicalSize<u32>),
|
||||
ScaleFactorChanged(WindowId, f64, PhysicalSize<u32>),
|
||||
}
|
||||
|
||||
impl EventLoopRunner {
|
||||
@@ -360,7 +360,7 @@ impl BufferedEvent {
|
||||
event: WindowEvent::ScaleFactorChanged { scale_factor, surface_size_writer },
|
||||
window_id,
|
||||
} => BufferedEvent::ScaleFactorChanged(
|
||||
window_id.into_raw() as HWND,
|
||||
window_id,
|
||||
scale_factor,
|
||||
*surface_size_writer.new_surface_size.upgrade().unwrap().lock().unwrap(),
|
||||
),
|
||||
@@ -371,10 +371,10 @@ impl BufferedEvent {
|
||||
pub fn dispatch_event(self, dispatch: impl FnOnce(Event)) {
|
||||
match self {
|
||||
Self::Event(event) => dispatch(event),
|
||||
Self::ScaleFactorChanged(window, scale_factor, new_surface_size) => {
|
||||
Self::ScaleFactorChanged(window_id, scale_factor, new_surface_size) => {
|
||||
let user_new_surface_size = Arc::new(Mutex::new(new_surface_size));
|
||||
dispatch(Event::WindowEvent {
|
||||
window_id: WindowId::from_raw(window as usize),
|
||||
window_id,
|
||||
event: WindowEvent::ScaleFactorChanged {
|
||||
scale_factor,
|
||||
surface_size_writer: SurfaceSizeWriter::new(Arc::downgrade(
|
||||
@@ -388,11 +388,12 @@ impl BufferedEvent {
|
||||
|
||||
if surface_size != new_surface_size {
|
||||
let window_flags = unsafe {
|
||||
let userdata = get_window_long(window, GWL_USERDATA) as *mut WindowData;
|
||||
let userdata =
|
||||
get_window_long(window_id.0.into(), GWL_USERDATA) as *mut WindowData;
|
||||
(*userdata).window_state_lock().window_flags
|
||||
};
|
||||
|
||||
window_flags.set_size(window, surface_size);
|
||||
window_flags.set_size((window_id.0).0, surface_size);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use smol_str::SmolStr;
|
||||
use windows_sys::Win32::Foundation::HWND;
|
||||
use windows_sys::Win32::Foundation::{HANDLE, HWND};
|
||||
use windows_sys::Win32::UI::WindowsAndMessaging::{HMENU, WINDOW_LONG_PTR_INDEX};
|
||||
|
||||
pub(crate) use self::event_loop::{
|
||||
@@ -11,7 +11,7 @@ pub(crate) use self::keyboard::{physicalkey_to_scancode, scancode_to_physicalkey
|
||||
pub(crate) use self::monitor::{MonitorHandle, VideoModeHandle};
|
||||
pub(crate) use self::window::Window;
|
||||
pub(crate) use crate::cursor::OnlyCursorImageSource as PlatformCustomCursorSource;
|
||||
use crate::event::DeviceId;
|
||||
use crate::event::DeviceId as RootDeviceId;
|
||||
use crate::icon::Icon;
|
||||
use crate::keyboard::Key;
|
||||
use crate::platform::windows::{BackdropType, Color, CornerPreference};
|
||||
@@ -59,6 +59,25 @@ impl Default for PlatformSpecificWindowAttributes {
|
||||
unsafe impl Send for PlatformSpecificWindowAttributes {}
|
||||
unsafe impl Sync for PlatformSpecificWindowAttributes {}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct DeviceId(u32);
|
||||
|
||||
impl DeviceId {
|
||||
pub const fn dummy() -> Self {
|
||||
DeviceId(0)
|
||||
}
|
||||
}
|
||||
|
||||
impl DeviceId {
|
||||
pub fn persistent_identifier(&self) -> Option<String> {
|
||||
if self.0 != 0 {
|
||||
raw_input::get_raw_input_device_name(self.0 as HANDLE)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct FingerId {
|
||||
id: u32,
|
||||
@@ -66,7 +85,6 @@ pub struct FingerId {
|
||||
}
|
||||
|
||||
impl FingerId {
|
||||
#[cfg(test)]
|
||||
pub const fn dummy() -> Self {
|
||||
FingerId { id: 0, primary: false }
|
||||
}
|
||||
@@ -78,8 +96,11 @@ impl FingerId {
|
||||
}
|
||||
}
|
||||
|
||||
fn wrap_device_id(id: u32) -> DeviceId {
|
||||
DeviceId::from_raw(id as i64)
|
||||
// Constant device ID, to be removed when this backend is updated to report real device IDs.
|
||||
const DEVICE_ID: RootDeviceId = RootDeviceId(DeviceId(0));
|
||||
|
||||
fn wrap_device_id(id: u32) -> RootDeviceId {
|
||||
RootDeviceId(DeviceId(id))
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||
@@ -88,6 +109,35 @@ pub struct KeyEventExtra {
|
||||
pub key_without_modifiers: Key,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct WindowId(HWND);
|
||||
unsafe impl Send for WindowId {}
|
||||
unsafe impl Sync for WindowId {}
|
||||
|
||||
impl WindowId {
|
||||
pub const fn dummy() -> Self {
|
||||
WindowId(0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<WindowId> for u64 {
|
||||
fn from(window_id: WindowId) -> Self {
|
||||
window_id.0 as u64
|
||||
}
|
||||
}
|
||||
|
||||
impl From<WindowId> for HWND {
|
||||
fn from(window_id: WindowId) -> Self {
|
||||
window_id.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u64> for WindowId {
|
||||
fn from(raw_id: u64) -> Self {
|
||||
Self(raw_id as HWND)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
const fn get_xbutton_wparam(x: u32) -> u16 {
|
||||
hiword(x)
|
||||
@@ -153,6 +203,6 @@ mod ime;
|
||||
mod keyboard;
|
||||
mod keyboard_layout;
|
||||
mod monitor;
|
||||
pub(crate) mod raw_input;
|
||||
mod raw_input;
|
||||
mod window;
|
||||
mod window_state;
|
||||
|
||||
@@ -14,7 +14,7 @@ use windows_sys::Win32::UI::HiDpi::{
|
||||
DPI_AWARENESS_CONTEXT, MONITOR_DPI_TYPE, PROCESS_DPI_AWARENESS,
|
||||
};
|
||||
use windows_sys::Win32::UI::Input::KeyboardAndMouse::GetActiveWindow;
|
||||
use windows_sys::Win32::UI::Input::Pointer::{POINTER_INFO, POINTER_TOUCH_INFO};
|
||||
use windows_sys::Win32::UI::Input::Pointer::{POINTER_INFO, POINTER_PEN_INFO, POINTER_TOUCH_INFO};
|
||||
use windows_sys::Win32::UI::WindowsAndMessaging::{
|
||||
ClipCursor, GetClientRect, GetClipCursor, GetSystemMetrics, GetWindowPlacement, GetWindowRect,
|
||||
IsIconic, ShowCursor, IDC_APPSTARTING, IDC_ARROW, IDC_CROSS, IDC_HAND, IDC_HELP, IDC_IBEAM,
|
||||
@@ -244,6 +244,9 @@ pub type GetPointerDeviceRects = unsafe extern "system" fn(
|
||||
pub type GetPointerTouchInfo =
|
||||
unsafe extern "system" fn(pointerId: u32, touchInfo: *mut POINTER_TOUCH_INFO) -> BOOL;
|
||||
|
||||
pub type GetPointerPenInfo =
|
||||
unsafe extern "system" fn(pointId: u32, penInfo: *mut POINTER_PEN_INFO) -> BOOL;
|
||||
|
||||
pub(crate) static GET_DPI_FOR_WINDOW: Lazy<Option<GetDpiForWindow>> =
|
||||
Lazy::new(|| get_function!("user32.dll", GetDpiForWindow));
|
||||
pub(crate) static ADJUST_WINDOW_RECT_EX_FOR_DPI: Lazy<Option<AdjustWindowRectExForDpi>> =
|
||||
@@ -266,3 +269,5 @@ pub(crate) static GET_POINTER_DEVICE_RECTS: Lazy<Option<GetPointerDeviceRects>>
|
||||
Lazy::new(|| get_function!("user32.dll", GetPointerDeviceRects));
|
||||
pub(crate) static GET_POINTER_TOUCH_INFO: Lazy<Option<GetPointerTouchInfo>> =
|
||||
Lazy::new(|| get_function!("user32.dll", GetPointerTouchInfo));
|
||||
pub(crate) static GET_POINTER_PEN_INFO: Lazy<Option<GetPointerPenInfo>> =
|
||||
Lazy::new(|| get_function!("user32.dll", GetPointerPenInfo));
|
||||
|
||||
@@ -66,11 +66,11 @@ use crate::platform_impl::platform::keyboard::KeyEventBuilder;
|
||||
use crate::platform_impl::platform::window_state::{
|
||||
CursorFlags, SavedWindow, WindowFlags, WindowState,
|
||||
};
|
||||
use crate::platform_impl::platform::{monitor, util, Fullscreen, SelectedCursor};
|
||||
use crate::platform_impl::platform::{monitor, util, Fullscreen, SelectedCursor, WindowId};
|
||||
use crate::window::{
|
||||
CursorGrabMode, Fullscreen as CoreFullscreen, ImePurpose, ResizeDirection, Theme,
|
||||
UserAttentionType, Window as CoreWindow, WindowAttributes, WindowButtons, WindowId,
|
||||
WindowLevel,
|
||||
UserAttentionType, Window as CoreWindow, WindowAttributes, WindowButtons,
|
||||
WindowId as CoreWindowId, WindowLevel,
|
||||
};
|
||||
|
||||
/// The Win32 implementation of the main `Window` object.
|
||||
@@ -696,8 +696,8 @@ impl CoreWindow for Window {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn id(&self) -> WindowId {
|
||||
WindowId::from_raw(self.hwnd() as usize)
|
||||
fn id(&self) -> CoreWindowId {
|
||||
CoreWindowId(WindowId(self.hwnd()))
|
||||
}
|
||||
|
||||
fn set_minimized(&self, minimized: bool) {
|
||||
|
||||
@@ -11,7 +11,7 @@ use crate::dpi::{PhysicalPosition, PhysicalSize, Position, Size};
|
||||
use crate::error::RequestError;
|
||||
pub use crate::icon::{BadIcon, Icon};
|
||||
use crate::monitor::{MonitorHandle, VideoModeHandle};
|
||||
use crate::platform_impl::PlatformSpecificWindowAttributes;
|
||||
use crate::platform_impl::{self, PlatformSpecificWindowAttributes};
|
||||
use crate::utils::AsAny;
|
||||
|
||||
/// Identifier of a window. Unique for each window.
|
||||
@@ -21,21 +21,18 @@ use crate::utils::AsAny;
|
||||
/// Whenever you receive an event specific to a window, this event contains a `WindowId` which you
|
||||
/// can then compare to the ids of your windows.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct WindowId(usize);
|
||||
pub struct WindowId(pub(crate) platform_impl::WindowId);
|
||||
|
||||
impl WindowId {
|
||||
/// Convert the `WindowId` into the underlying integer.
|
||||
/// Returns a dummy id, useful for unit testing.
|
||||
///
|
||||
/// This is useful if you need to pass the ID across an FFI boundary, or store it in an atomic.
|
||||
pub const fn into_raw(self) -> usize {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Construct a `WindowId` from the underlying integer.
|
||||
/// # Notes
|
||||
///
|
||||
/// This should only be called with integers returned from [`WindowId::into_raw`].
|
||||
pub const fn from_raw(id: usize) -> Self {
|
||||
Self(id)
|
||||
/// 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 [`WindowId`].
|
||||
pub const fn dummy() -> Self {
|
||||
WindowId(platform_impl::WindowId::dummy())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +42,18 @@ impl fmt::Debug for WindowId {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<WindowId> for u64 {
|
||||
fn from(window_id: WindowId) -> Self {
|
||||
window_id.0.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u64> for WindowId {
|
||||
fn from(raw_id: u64) -> Self {
|
||||
Self(raw_id.into())
|
||||
}
|
||||
}
|
||||
|
||||
/// Attributes used when creating a window.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct WindowAttributes {
|
||||
|
||||
Reference in New Issue
Block a user