From d691a3bbb58862ec352fd9970fa5e2e7cb858f79 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Thu, 28 Apr 2022 21:45:04 -0400 Subject: [PATCH 001/151] Initial kmsdrm support --- Cargo.toml | 146 +-- src/platform/unix.rs | 90 +- src/platform_impl/linux/drm/event_loop.rs | 964 ++++++++++++++++++ src/platform_impl/linux/drm/input_to_vk.rs | 238 +++++ src/platform_impl/linux/drm/mod.rs | 141 +++ src/platform_impl/linux/drm/window.rs | 323 ++++++ src/platform_impl/linux/mod.rs | 254 ++++- .../linux/wayland/event_loop/mod.rs | 8 +- .../linux/wayland/event_loop/proxy.rs | 2 +- .../linux/wayland/seat/keyboard/mod.rs | 2 +- src/platform_impl/linux/wayland/seat/mod.rs | 2 +- src/platform_impl/linux/wayland/window/mod.rs | 6 +- 12 files changed, 2034 insertions(+), 142 deletions(-) create mode 100644 src/platform_impl/linux/drm/event_loop.rs create mode 100644 src/platform_impl/linux/drm/input_to_vk.rs create mode 100644 src/platform_impl/linux/drm/mod.rs create mode 100644 src/platform_impl/linux/drm/window.rs diff --git a/Cargo.toml b/Cargo.toml index 0fee93fe47..cb4250f961 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,9 +17,10 @@ default-target = "x86_64-unknown-linux-gnu" targets = ["i686-pc-windows-msvc", "x86_64-pc-windows-msvc", "i686-unknown-linux-gnu", "x86_64-unknown-linux-gnu", "x86_64-apple-darwin", "wasm32-unknown-unknown"] [features] -default = ["x11", "wayland", "wayland-dlopen"] +default = ["x11", "wayland", "wayland-dlopen", "kmsdrm"] x11 = ["x11-dl", "mio", "percent-encoding", "parking_lot"] -wayland = ["wayland-client", "wayland-protocols", "sctk"] +wayland = ["wayland-client", "wayland-protocols", "sctk", "calloop"] +kmsdrm = ["drm", "gbm", "input", "calloop"] wayland-dlopen = ["sctk/dlopen", "wayland-client/dlopen"] [dependencies] @@ -27,7 +28,8 @@ instant = { version = "0.1", features = ["wasm-bindgen"] } lazy_static = "1" log = "0.4" serde = { version = "1", optional = true, features = ["serde_derive"] } -raw-window-handle = "0.4.2" +# raw-window-handle = "0.4.2" +raw-window-handle = "0.4.3" bitflags = "1" mint = { version = "0.5.6", optional = true } @@ -60,75 +62,79 @@ parking_lot = "0.12" [target.'cfg(target_os = "windows")'.dependencies.windows-sys] version = "0.33" features = [ - "Win32_Devices_HumanInterfaceDevice", - "Win32_Foundation", - "Win32_Globalization", - "Win32_Graphics_Dwm", - "Win32_Graphics_Gdi", - "Win32_Media", - "Win32_System_Com_StructuredStorage", - "Win32_System_Com", - "Win32_System_LibraryLoader", - "Win32_System_Ole", - "Win32_System_SystemInformation", - "Win32_System_SystemServices", - "Win32_System_Threading", - "Win32_System_WindowsProgramming", - "Win32_UI_Accessibility", - "Win32_UI_Controls", - "Win32_UI_HiDpi", - "Win32_UI_Input_Ime", - "Win32_UI_Input_KeyboardAndMouse", - "Win32_UI_Input_Pointer", - "Win32_UI_Input_Touch", - "Win32_UI_Shell", - "Win32_UI_TextServices", - "Win32_UI_WindowsAndMessaging", -] + "Win32_Devices_HumanInterfaceDevice", + "Win32_Foundation", + "Win32_Globalization", + "Win32_Graphics_Dwm", + "Win32_Graphics_Gdi", + "Win32_Media", + "Win32_System_Com_StructuredStorage", + "Win32_System_Com", + "Win32_System_LibraryLoader", + "Win32_System_Ole", + "Win32_System_SystemInformation", + "Win32_System_SystemServices", + "Win32_System_Threading", + "Win32_System_WindowsProgramming", + "Win32_UI_Accessibility", + "Win32_UI_Controls", + "Win32_UI_HiDpi", + "Win32_UI_Input_Ime", + "Win32_UI_Input_KeyboardAndMouse", + "Win32_UI_Input_Pointer", + "Win32_UI_Input_Touch", + "Win32_UI_Shell", + "Win32_UI_TextServices", + "Win32_UI_WindowsAndMessaging", + ] -[target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))'.dependencies] -wayland-client = { version = "0.29", default_features = false, features = ["use_system_lib"], optional = true } -wayland-protocols = { version = "0.29", features = [ "staging_protocols"], optional = true } -sctk = { package = "smithay-client-toolkit", version = "0.15.4", default_features = false, features = ["calloop"], optional = true } -mio = { version = "0.8", features = ["os-ext"], optional = true } -x11-dl = { version = "2.18.5", optional = true } -percent-encoding = { version = "2.0", optional = true } -parking_lot = { version = "0.12.0", optional = true } -libc = "0.2.64" + [target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))'.dependencies] + wayland-client = { version = "0.29", default_features = false, features = ["use_system_lib"], optional = true } + wayland-protocols = { version = "0.29", features = [ "staging_protocols"], optional = true } + calloop = { version = "0.9.3", optional = true } + sctk = { package = "smithay-client-toolkit", version = "0.15.4", default_features = false, features = ["calloop"], optional = true } + mio = { version = "0.8", features = ["os-ext"], optional = true } + x11-dl = { version = "2.18.5", optional = true } + percent-encoding = { version = "2.0", optional = true } + parking_lot = { version = "0.12.0", optional = true } + libc = "0.2.64" + drm = { version = "0.6.2", optional = true } + gbm = { version = "0.8.0", optional = true } + input = { version = "0.7.1", optional = true } -[target.'cfg(target_arch = "wasm32")'.dependencies.web_sys] -package = "web-sys" -version = "0.3.22" -features = [ - 'console', - "AddEventListenerOptions", - 'CssStyleDeclaration', - 'BeforeUnloadEvent', - 'Document', - 'DomRect', - 'Element', - 'Event', - 'EventTarget', - 'FocusEvent', - 'HtmlCanvasElement', - 'HtmlElement', - 'KeyboardEvent', - 'MediaQueryList', - 'MediaQueryListEvent', - 'MouseEvent', - 'Node', - 'PointerEvent', - 'Window', - 'WheelEvent' -] + [target.'cfg(target_arch = "wasm32")'.dependencies.web_sys] + package = "web-sys" + version = "0.3.22" + features = [ + 'console', + "AddEventListenerOptions", + 'CssStyleDeclaration', + 'BeforeUnloadEvent', + 'Document', + 'DomRect', + 'Element', + 'Event', + 'EventTarget', + 'FocusEvent', + 'HtmlCanvasElement', + 'HtmlElement', + 'KeyboardEvent', + 'MediaQueryList', + 'MediaQueryListEvent', + 'MouseEvent', + 'Node', + 'PointerEvent', + 'Window', + 'WheelEvent' + ] -[target.'cfg(target_arch = "wasm32")'.dependencies.wasm-bindgen] -version = "0.2.45" + [target.'cfg(target_arch = "wasm32")'.dependencies.wasm-bindgen] + version = "0.2.45" -[target.'cfg(target_arch = "wasm32")'.dev-dependencies] -console_log = "0.2" + [target.'cfg(target_arch = "wasm32")'.dev-dependencies] + console_log = "0.2" -[workspace] -members = [ - "run-wasm", -] + [workspace] + members = [ + "run-wasm", + ] diff --git a/src/platform/unix.rs b/src/platform/unix.rs index 508cafb54e..2b0173990e 100644 --- a/src/platform/unix.rs +++ b/src/platform/unix.rs @@ -42,6 +42,9 @@ pub trait EventLoopWindowTargetExtUnix { #[cfg(feature = "x11")] fn is_x11(&self) -> bool; + #[cfg(feature = "kmsdrm")] + fn is_drm(&self) -> bool; + #[doc(hidden)] #[cfg(feature = "x11")] fn xlib_xconnection(&self) -> Option>; @@ -54,6 +57,23 @@ pub trait EventLoopWindowTargetExtUnix { /// The pointer will become invalid when the winit `EventLoop` is destroyed. #[cfg(feature = "wayland")] fn wayland_display(&self) -> Option<*mut raw::c_void>; + + /// Returns the gbm device of the event loop's fd + /// + /// Returns `None` if the `EventLoop` doesn't use kmsdrm (if it uses wayland for example). + #[cfg(feature = "kmsdrm")] + fn gbm_device( + &self, + ) -> Option< + &parking_lot::Mutex< + crate::platform_impl::AssertSync< + Result< + std::sync::Arc>, + std::io::Error, + >, + >, + >, + >; } impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { @@ -66,7 +86,13 @@ impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { #[inline] #[cfg(feature = "x11")] fn is_x11(&self) -> bool { - !self.p.is_wayland() + self.p.is_x11() + } + + #[inline] + #[cfg(feature = "kmsdrm")] + fn is_drm(&self) -> bool { + self.p.is_drm() } #[inline] @@ -75,7 +101,7 @@ impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { fn xlib_xconnection(&self) -> Option> { match self.p { LinuxEventLoopWindowTarget::X(ref e) => Some(e.x_connection().clone()), - #[cfg(feature = "wayland")] + #[cfg(any(feature = "wayland", feature = "kmsdrm"))] _ => None, } } @@ -87,7 +113,30 @@ impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { LinuxEventLoopWindowTarget::Wayland(ref p) => { Some(p.display().get_display_ptr() as *mut _) } - #[cfg(feature = "x11")] + #[cfg(any(feature = "x11", feature = "kmsdrm"))] + _ => None, + } + } + + #[inline] + #[cfg(feature = "kmsdrm")] + fn gbm_device( + &self, + ) -> Option< + &parking_lot::Mutex< + crate::platform_impl::AssertSync< + Result< + std::sync::Arc>, + std::io::Error, + >, + >, + >, + > { + use crate::platform_impl::GBM_DEVICE; + + match self.p { + crate::platform_impl::EventLoopWindowTarget::Drm(_) => Some(&*GBM_DEVICE), + #[cfg(any(feature = "x11", feature = "wayland"))] _ => None, } } @@ -103,6 +152,10 @@ pub trait EventLoopBuilderExtUnix { #[cfg(feature = "wayland")] fn with_wayland(&mut self) -> &mut Self; + /// Force using kmsdrm + #[cfg(feature = "kmsdrm")] + fn with_drm(&mut self) -> &mut Self; + /// Whether to allow the event loop to be created off of the main thread. /// /// By default, the window is only allowed to be created on the main @@ -125,6 +178,13 @@ impl EventLoopBuilderExtUnix for EventLoopBuilder { self } + #[inline] + #[cfg(feature = "kmsdrm")] + fn with_drm(&mut self) -> &mut Self { + self.platform_specific.forced_backend = Some(Backend::Drm); + self + } + #[inline] fn with_any_thread(&mut self, any_thread: bool) -> &mut Self { self.platform_specific.any_thread = any_thread; @@ -179,6 +239,16 @@ pub trait WindowExtUnix { #[cfg(feature = "wayland")] fn wayland_display(&self) -> Option<*mut raw::c_void>; + /* + /// Returns the gbm device that is used by this window. + /// + /// Returns `None` if the window doesn't use kmsdrm (if it uses wayland for example). + /// + /// The pointer will become invalid when the glutin `Window` is destroyed. + #[cfg(feature = "kmsdrm")] + fn gbm_device(&self) -> Option<&gbm::Device>; + */ + /// Check if the window is ready for drawing /// /// It is a remnant of a previous implementation detail for the @@ -195,7 +265,7 @@ impl WindowExtUnix for Window { fn xlib_window(&self) -> Option { match self.window { LinuxWindow::X(ref w) => Some(w.xlib_window()), - #[cfg(feature = "wayland")] + #[cfg(any(feature = "wayland", feature = "kmsdrm"))] _ => None, } } @@ -205,7 +275,7 @@ impl WindowExtUnix for Window { fn xlib_display(&self) -> Option<*mut raw::c_void> { match self.window { LinuxWindow::X(ref w) => Some(w.xlib_display()), - #[cfg(feature = "wayland")] + #[cfg(any(feature = "wayland", feature = "kmsdrm"))] _ => None, } } @@ -215,7 +285,7 @@ impl WindowExtUnix for Window { fn xlib_screen_id(&self) -> Option { match self.window { LinuxWindow::X(ref w) => Some(w.xlib_screen_id()), - #[cfg(feature = "wayland")] + #[cfg(any(feature = "wayland", feature = "kmsdrm"))] _ => None, } } @@ -226,7 +296,7 @@ impl WindowExtUnix for Window { fn xlib_xconnection(&self) -> Option> { match self.window { LinuxWindow::X(ref w) => Some(w.xlib_xconnection()), - #[cfg(feature = "wayland")] + #[cfg(any(feature = "wayland", feature = "kmsdrm"))] _ => None, } } @@ -236,7 +306,7 @@ impl WindowExtUnix for Window { fn xcb_connection(&self) -> Option<*mut raw::c_void> { match self.window { LinuxWindow::X(ref w) => Some(w.xcb_connection()), - #[cfg(feature = "wayland")] + #[cfg(any(feature = "wayland", feature = "kmsdrm"))] _ => None, } } @@ -246,7 +316,7 @@ impl WindowExtUnix for Window { fn wayland_surface(&self) -> Option<*mut raw::c_void> { match self.window { LinuxWindow::Wayland(ref w) => Some(w.surface().as_ref().c_ptr() as *mut _), - #[cfg(feature = "x11")] + #[cfg(any(feature = "x11", feature = "kmsdrm"))] _ => None, } } @@ -256,7 +326,7 @@ impl WindowExtUnix for Window { fn wayland_display(&self) -> Option<*mut raw::c_void> { match self.window { LinuxWindow::Wayland(ref w) => Some(w.display().get_display_ptr() as *mut _), - #[cfg(feature = "x11")] + #[cfg(any(feature = "x11", feature = "kmsdrm"))] _ => None, } } diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs new file mode 100644 index 0000000000..7513447879 --- /dev/null +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -0,0 +1,964 @@ +use std::{ + cell::RefCell, + collections::VecDeque, + marker::PhantomData, + os::unix::prelude::{AsRawFd, FromRawFd, IntoRawFd, OpenOptionsExt, RawFd}, + path::Path, + sync::mpsc::SendError, +}; + +use calloop::{EventSource, Interest, Mode, Poll, PostAction, Readiness, Token, TokenFactory}; +use drm::control::{property, Device, ResourceHandle}; +use input::{ + event::{ + keyboard::KeyboardEventTrait, + pointer::PointerScrollEvent, + tablet_pad::{ButtonState, KeyState}, + tablet_tool::{TabletToolEventTrait, TipState}, + touch::{TouchEventPosition, TouchEventSlot}, + }, + LibinputInterface, +}; +use instant::{Duration, Instant}; +use libc::{O_RDONLY, O_RDWR, O_WRONLY}; + +use crate::{ + dpi::PhysicalPosition, + event::{Force, KeyboardInput, ModifiersState, MouseScrollDelta, StartCause}, + event_loop::{ControlFlow, EventLoopClosed}, + platform_impl::{platform::sticky_exit_callback, GBM_DEVICE}, +}; + +use super::input_to_vk::CHAR_MAPPINGS; + +struct Interface; + +impl LibinputInterface for Interface { + fn open_restricted(&mut self, path: &Path, flags: i32) -> Result { + std::fs::OpenOptions::new() + .custom_flags(flags) + .read((flags & O_RDONLY != 0) | (flags & O_RDWR != 0)) + .write((flags & O_WRONLY != 0) | (flags & O_RDWR != 0)) + .open(path) + .map(|file| file.into_raw_fd()) + .map_err(|err| err.raw_os_error().unwrap()) + } + fn close_restricted(&mut self, fd: RawFd) { + unsafe { + std::fs::File::from_raw_fd(fd); + } + } +} + +#[derive(Debug)] +pub struct LibinputInputBackend { + context: input::Libinput, + token: Token, + touch_location: PhysicalPosition, + screen_size: (u32, u32), + modifiers: ModifiersState, + cursor_positon: PhysicalPosition, +} + +impl LibinputInputBackend { + /// Initialize a new [`LibinputInputBackend`] from a given already initialized + /// [libinput context](libinput::Libinput). + pub fn new(context: input::Libinput, screen_size: (u32, u32)) -> Self { + LibinputInputBackend { + context, + token: Token::invalid(), + touch_location: PhysicalPosition::new(0.0, 0.0), + cursor_positon: PhysicalPosition::new(0.0, 0.0), + modifiers: ModifiersState::empty(), + screen_size, + } + } +} + +impl AsRawFd for LibinputInputBackend { + fn as_raw_fd(&self) -> RawFd { + self.context.as_raw_fd() + } +} + +impl EventSource for LibinputInputBackend { + type Event = crate::event::Event<'static, ()>; + type Metadata = (); + type Ret = (); + + fn process_events( + &mut self, + _: Readiness, + token: Token, + mut callback: F, + ) -> std::io::Result + where + F: FnMut(Self::Event, &mut ()) -> Self::Ret, + { + if token == self.token { + self.context.dispatch()?; + + for event in &mut self.context { + match event { + input::Event::Device(ev) => match ev { + input::event::DeviceEvent::Added(_) => { + callback( + crate::event::Event::DeviceEvent { + device_id: crate::event::DeviceId( + crate::platform_impl::DeviceId::Drm(super::DeviceId), + ), + event: crate::event::DeviceEvent::Added, + }, + &mut (), + ); + } + input::event::DeviceEvent::Removed(_) => { + callback( + crate::event::Event::DeviceEvent { + device_id: crate::event::DeviceId( + crate::platform_impl::DeviceId::Drm(super::DeviceId), + ), + event: crate::event::DeviceEvent::Removed, + }, + &mut (), + ); + } + _ => {} + }, + input::Event::Touch(ev) => match ev { + input::event::TouchEvent::Up(e) => callback( + crate::event::Event::WindowEvent { + window_id: crate::window::WindowId( + crate::platform_impl::WindowId::Drm(super::WindowId), + ), + event: crate::event::WindowEvent::Touch(crate::event::Touch { + device_id: crate::event::DeviceId( + crate::platform_impl::DeviceId::Drm(super::DeviceId), + ), + phase: crate::event::TouchPhase::Ended, + location: self.touch_location, + force: None, + id: e.slot().unwrap() as u64, + }), + }, + &mut (), + ), + input::event::TouchEvent::Down(e) => { + self.touch_location.x = e.x_transformed(self.screen_size.0); + self.touch_location.y = e.y_transformed(self.screen_size.1); + callback( + crate::event::Event::WindowEvent { + window_id: crate::window::WindowId( + crate::platform_impl::WindowId::Drm(super::WindowId), + ), + event: crate::event::WindowEvent::Touch(crate::event::Touch { + device_id: crate::event::DeviceId( + crate::platform_impl::DeviceId::Drm(super::DeviceId), + ), + phase: crate::event::TouchPhase::Started, + location: self.touch_location, + force: None, + id: e.slot().unwrap() as u64, + }), + }, + &mut (), + ) + } + input::event::TouchEvent::Motion(e) => { + self.touch_location.x = e.x_transformed(self.screen_size.0); + self.touch_location.y = e.y_transformed(self.screen_size.1); + callback( + crate::event::Event::WindowEvent { + window_id: crate::window::WindowId( + crate::platform_impl::WindowId::Drm(super::WindowId), + ), + event: crate::event::WindowEvent::Touch(crate::event::Touch { + device_id: crate::event::DeviceId( + crate::platform_impl::DeviceId::Drm(super::DeviceId), + ), + phase: crate::event::TouchPhase::Moved, + location: self.touch_location, + force: None, + id: e.slot().unwrap() as u64, + }), + }, + &mut (), + ); + } + input::event::TouchEvent::Cancel(e) => callback( + crate::event::Event::WindowEvent { + window_id: crate::window::WindowId( + crate::platform_impl::WindowId::Drm(super::WindowId), + ), + event: crate::event::WindowEvent::Touch(crate::event::Touch { + device_id: crate::event::DeviceId( + crate::platform_impl::DeviceId::Drm(super::DeviceId), + ), + phase: crate::event::TouchPhase::Cancelled, + location: self.touch_location, + force: None, + id: e.slot().unwrap() as u64, + }), + }, + &mut (), + ), + input::event::TouchEvent::Frame(_) => callback( + crate::event::Event::WindowEvent { + window_id: crate::window::WindowId( + crate::platform_impl::WindowId::Drm(super::WindowId), + ), + event: crate::event::WindowEvent::Touch(crate::event::Touch { + device_id: crate::event::DeviceId( + crate::platform_impl::DeviceId::Drm(super::DeviceId), + ), + phase: crate::event::TouchPhase::Ended, + location: self.touch_location, + force: None, + id: 0, // e.slot().unwrap() as u64, + }), + }, + &mut (), + ), + _ => {} + }, + input::Event::Tablet(ev) => match ev { + input::event::TabletToolEvent::Tip(e) => callback( + crate::event::Event::WindowEvent { + window_id: crate::window::WindowId( + crate::platform_impl::WindowId::Drm(super::WindowId), + ), + event: crate::event::WindowEvent::Touch(crate::event::Touch { + device_id: crate::event::DeviceId( + crate::platform_impl::DeviceId::Drm(super::DeviceId), + ), + phase: match e.tip_state() { + TipState::Down => crate::event::TouchPhase::Started, + TipState::Up => crate::event::TouchPhase::Ended, + }, + location: PhysicalPosition::new( + e.x_transformed(self.screen_size.0), + e.y_transformed(self.screen_size.1), + ), + force: Some(Force::Calibrated { + force: e.pressure(), + max_possible_force: 1.0, + altitude_angle: None, + }), + id: 0, + }), + }, + &mut (), + ), + input::event::TabletToolEvent::Button(e) => { + callback( + crate::event::Event::WindowEvent { + window_id: crate::window::WindowId( + crate::platform_impl::WindowId::Drm(super::WindowId), + ), + event: crate::event::WindowEvent::MouseInput { + device_id: crate::event::DeviceId( + crate::platform_impl::DeviceId::Drm(super::DeviceId), + ), + state: match e.button_state() { + ButtonState::Pressed => { + crate::event::ElementState::Pressed + } + ButtonState::Released => { + crate::event::ElementState::Released + } + }, + button: match e.button() { + 1 => crate::event::MouseButton::Right, + 2 => crate::event::MouseButton::Middle, + _ => crate::event::MouseButton::Left, + }, + modifiers: self.modifiers, + }, + }, + &mut (), + ); + callback( + crate::event::Event::DeviceEvent { + device_id: crate::event::DeviceId( + crate::platform_impl::DeviceId::Drm(super::DeviceId), + ), + event: crate::event::DeviceEvent::Button { + button: e.button(), + state: match e.button_state() { + ButtonState::Pressed => { + crate::event::ElementState::Pressed + } + ButtonState::Released => { + crate::event::ElementState::Released + } + }, + }, + }, + &mut (), + ); + } + _ => {} + }, + input::Event::Pointer(e) => match e { + input::event::PointerEvent::Motion(e) => { + self.cursor_positon.x += e.dx(); + self.cursor_positon.x = + self.cursor_positon.x.clamp(0.0, self.screen_size.0 as f64); + self.cursor_positon.y += e.dy(); + self.cursor_positon.y = + self.cursor_positon.y.clamp(0.0, self.screen_size.1 as f64); + callback( + crate::event::Event::WindowEvent { + window_id: crate::window::WindowId( + crate::platform_impl::WindowId::Drm(super::WindowId), + ), + event: crate::event::WindowEvent::CursorMoved { + device_id: crate::event::DeviceId( + crate::platform_impl::DeviceId::Drm(super::DeviceId), + ), + position: self.cursor_positon, + modifiers: self.modifiers, + }, + }, + &mut (), + ); + callback( + crate::event::Event::DeviceEvent { + device_id: crate::event::DeviceId( + crate::platform_impl::DeviceId::Drm(super::DeviceId), + ), + event: crate::event::DeviceEvent::MouseMotion { + delta: (e.dx(), e.dy()), + }, + }, + &mut (), + ); + } + input::event::PointerEvent::Button(e) => { + callback( + crate::event::Event::WindowEvent { + window_id: crate::window::WindowId( + crate::platform_impl::WindowId::Drm(super::WindowId), + ), + event: crate::event::WindowEvent::MouseInput { + device_id: crate::event::DeviceId( + crate::platform_impl::DeviceId::Drm(super::DeviceId), + ), + state: match e.button_state() { + ButtonState::Pressed => { + crate::event::ElementState::Pressed + } + ButtonState::Released => { + crate::event::ElementState::Released + } + }, + button: match e.button() { + 1 => crate::event::MouseButton::Right, + 2 => crate::event::MouseButton::Middle, + _ => crate::event::MouseButton::Left, + }, + modifiers: self.modifiers, + }, + }, + &mut (), + ); + callback( + crate::event::Event::DeviceEvent { + device_id: crate::event::DeviceId( + crate::platform_impl::DeviceId::Drm(super::DeviceId), + ), + event: crate::event::DeviceEvent::Button { + button: e.button(), + state: match e.button_state() { + ButtonState::Pressed => { + crate::event::ElementState::Pressed + } + ButtonState::Released => { + crate::event::ElementState::Released + } + }, + }, + }, + &mut (), + ); + } + input::event::PointerEvent::ScrollWheel(e) => { + callback( + crate::event::Event::WindowEvent { + window_id: crate::window::WindowId( + crate::platform_impl::WindowId::Drm(super::WindowId), + ), + event: crate::event::WindowEvent::MouseWheel { + device_id: crate::event::DeviceId( + crate::platform_impl::DeviceId::Drm(super::DeviceId), + ), + delta: MouseScrollDelta::LineDelta( + if e.has_axis(input::event::pointer::Axis::Horizontal) { + e.scroll_value( + input::event::pointer::Axis::Horizontal, + ) + as f32 + } else { + 0.0 + }, + if e.has_axis(input::event::pointer::Axis::Vertical) { + e.scroll_value( + input::event::pointer::Axis::Vertical, + ) + as f32 + } else { + 0.0 + }, + ), + phase: crate::event::TouchPhase::Moved, + modifiers: self.modifiers, + }, + }, + &mut (), + ); + } + input::event::PointerEvent::ScrollFinger(e) => { + callback( + crate::event::Event::WindowEvent { + window_id: crate::window::WindowId( + crate::platform_impl::WindowId::Drm(super::WindowId), + ), + event: crate::event::WindowEvent::MouseWheel { + device_id: crate::event::DeviceId( + crate::platform_impl::DeviceId::Drm(super::DeviceId), + ), + delta: MouseScrollDelta::PixelDelta(PhysicalPosition::new( + if e.has_axis(input::event::pointer::Axis::Horizontal) { + e.scroll_value( + input::event::pointer::Axis::Horizontal, + ) + } else { + 0.0 + }, + if e.has_axis(input::event::pointer::Axis::Vertical) { + e.scroll_value( + input::event::pointer::Axis::Vertical, + ) + } else { + 0.0 + }, + )), + phase: crate::event::TouchPhase::Moved, + modifiers: self.modifiers, + }, + }, + &mut (), + ); + } + input::event::PointerEvent::MotionAbsolute(e) => { + self.cursor_positon.x = e.absolute_x_transformed(self.screen_size.0); + self.cursor_positon.y = e.absolute_y_transformed(self.screen_size.1); + callback( + crate::event::Event::WindowEvent { + window_id: crate::window::WindowId( + crate::platform_impl::WindowId::Drm(super::WindowId), + ), + event: crate::event::WindowEvent::CursorMoved { + device_id: crate::event::DeviceId( + crate::platform_impl::DeviceId::Drm(super::DeviceId), + ), + position: self.cursor_positon, + modifiers: self.modifiers, + }, + }, + &mut (), + ); + } + _ => {} + }, + input::Event::Keyboard(ev) => match &ev { + input::event::KeyboardEvent::Key(key) => match key.key() { + 56 // LAlt + | 100 // RAlt + => { + match key.key_state() { + KeyState::Pressed => self.modifiers |= ModifiersState::ALT, + KeyState::Released => self.modifiers.remove(ModifiersState::ALT) + } + callback(crate::event::Event::WindowEvent { + window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), + event:crate::event::WindowEvent::ModifiersChanged(self.modifiers)}, &mut ()); + } + | 42 // LShift + | 54 // RShift + => { + match key.key_state() { + KeyState::Pressed => self.modifiers |= ModifiersState::SHIFT, + KeyState::Released => self.modifiers.remove(ModifiersState::SHIFT) + } + callback(crate::event::Event::WindowEvent { + window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), + event:crate::event::WindowEvent::ModifiersChanged(self.modifiers)}, &mut ()); + } + + | 29 // LCtrl + | 97 // RCtrl + => { + match key.key_state() { + KeyState::Pressed => self.modifiers |= ModifiersState::CTRL, + KeyState::Released => self.modifiers.remove(ModifiersState::CTRL) + } + callback(crate::event::Event::WindowEvent { + window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), + event:crate::event::WindowEvent::ModifiersChanged(self.modifiers)}, &mut ()); + } + + | 125 // LMeta + | 126 // RMeta + => { + match key.key_state() { + KeyState::Pressed => self.modifiers |= ModifiersState::LOGO, + KeyState::Released => self.modifiers.remove(ModifiersState::LOGO) + } + callback(crate::event::Event::WindowEvent { + window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), + event:crate::event::WindowEvent::ModifiersChanged(self.modifiers)}, &mut ()); + } + + k => { + callback(crate::event::Event::WindowEvent { + window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), + event: crate::event::WindowEvent::KeyboardInput { device_id: crate::event::DeviceId(crate:: platform_impl::DeviceId::Drm( super::DeviceId)), + input: KeyboardInput { scancode: k, state: match ev.key_state() { + KeyState::Pressed => crate::event::ElementState::Pressed, + KeyState::Released => crate::event::ElementState::Released + }, virtual_keycode: CHAR_MAPPINGS[k as usize], modifiers: self.modifiers } , is_synthetic: false }}, &mut ()); + } + }, + _ => {} + }, + _ => {} + } + } + } + Ok(PostAction::Continue) + } + + fn register(&mut self, poll: &mut Poll, factory: &mut TokenFactory) -> std::io::Result<()> { + self.token = factory.token(); + poll.register(self.as_raw_fd(), Interest::READ, Mode::Level, self.token) + } + + fn reregister(&mut self, poll: &mut Poll, factory: &mut TokenFactory) -> std::io::Result<()> { + self.token = factory.token(); + poll.reregister(self.as_raw_fd(), Interest::READ, Mode::Level, self.token) + } + + fn unregister(&mut self, poll: &mut Poll) -> std::io::Result<()> { + self.token = Token::invalid(); + poll.unregister(self.as_raw_fd()) + } +} + +/// An event loop's sink to deliver events from the Wayland event callbacks +/// to the winit's user. +#[derive(Default)] +pub struct EventSink { + pub window_events: Vec>, +} + +impl EventSink { + pub fn new() -> Self { + Default::default() + } +} + +pub struct EventLoopWindowTarget { + /// gbm Connector + pub connector: drm::control::connector::Info, + + /// Event loop handle. + pub event_loop_handle: calloop::LoopHandle<'static, EventSink>, + + pub(crate) event_sink: EventSink, + + /// A proxy to wake up event loop. + pub event_loop_awakener: calloop::ping::Ping, + + _marker: std::marker::PhantomData, +} + +impl EventLoopWindowTarget { + #[inline] + pub fn primary_monitor(&self) -> Option { + Some(crate::monitor::MonitorHandle { + inner: crate::platform_impl::MonitorHandle::Drm(super::MonitorHandle( + self.connector.clone(), + )), + }) + } + + #[inline] + pub fn available_monitors(&self) -> VecDeque { + if let Ok(gbm) = &**GBM_DEVICE.lock() { + gbm.resource_handles() + .unwrap() + .connectors() + .iter() + .map(|f| super::MonitorHandle(gbm.get_connector(*f).unwrap())) + .collect() + } else { + VecDeque::new() + } + } +} + +pub struct EventLoop { + /// Event loop. + event_loop: calloop::EventLoop<'static, EventSink>, + + /// Pending user events. + pending_user_events: std::rc::Rc>>, + + /// Sender of user events. + user_events_sender: calloop::channel::Sender, + + /// Window target. + window_target: crate::event_loop::EventLoopWindowTarget, +} + +pub(crate) fn find_prop_id( + card: &std::sync::Arc>, + handle: T, + name: &'static str, +) -> Option { + let props = card + .get_properties(handle) + .expect("Could not get props of connector"); + let (ids, _vals) = props.as_props_and_values(); + ids.iter() + .find(|&id| { + let info = card.get_property(*id).unwrap(); + info.name().to_str().map(|x| x == name).unwrap_or(false) + }) + .cloned() +} + +impl EventLoop { + pub fn new() -> Result, ()> { + match GBM_DEVICE.lock().as_ref() { + Ok(gbm) => { + drm::Device::set_client_capability( + gbm.as_ref(), + drm::ClientCapability::UniversalPlanes, + true, + ) + .expect("kmsdrm device does not support universal planes"); + drm::Device::set_client_capability( + gbm.as_ref(), + drm::ClientCapability::Atomic, + true, + ) + .expect("kmsdrm device does not support atomic modesetting"); + + // Load the information. + let res = gbm + .resource_handles() + .expect("Could not load normal resource ids."); + let coninfo: Vec = res + .connectors() + .iter() + .flat_map(|con| gbm.get_connector(*con)) + .collect(); + + // Filter each connector until we find one that's connected. + let con = coninfo + .iter() + .find(|&i| i.state() == drm::control::connector::State::Connected) + .expect("No connected connectors"); + + // Get the first (usually best) mode + let &mode = con.modes().get(0).expect("No modes found on connector"); + + let (disp_width, disp_height) = mode.size(); + + let mut input = input::Libinput::new_with_udev(Interface); + input.udev_assign_seat("seat0").unwrap(); + let event_loop: calloop::EventLoop<'static, EventSink> = + calloop::EventLoop::try_new().unwrap(); + + let handle = event_loop.handle(); + + // A source of user events. + let pending_user_events = std::rc::Rc::new(std::cell::RefCell::new(Vec::new())); + let pending_user_events_clone = pending_user_events.clone(); + let (user_events_sender, user_events_channel) = calloop::channel::channel(); + + // User events channel. + handle + .insert_source(user_events_channel, move |event, _, _| { + if let calloop::channel::Event::Msg(msg) = event { + pending_user_events_clone.borrow_mut().push(msg); + } + }) + .unwrap(); + + // An event's loop awakener to wake up for window events from winit's windows. + let (event_loop_awakener, event_loop_awakener_source) = + calloop::ping::make_ping().unwrap(); + + let event_sink = EventSink::new(); + + // Handler of window requests. + handle + .insert_source( + event_loop_awakener_source, + move |_event, _metadata, data| { + data.window_events + .push(crate::event::Event::RedrawRequested( + crate::window::WindowId(crate::platform_impl::WindowId::Drm( + super::WindowId, + )), + )); + }, + ) + .unwrap(); + + let input_backend: LibinputInputBackend = + LibinputInputBackend::new(input, (disp_width.into(), disp_height.into())); + + let input_loop: calloop::Dispatcher<'static, LibinputInputBackend, EventSink> = + calloop::Dispatcher::new( + input_backend, + move |event, _metadata, data: &mut EventSink| { + data.window_events.push(event); + }, + ); + + handle.register_dispatcher(input_loop).unwrap(); + + let window_target = crate::event_loop::EventLoopWindowTarget { + p: crate::platform_impl::EventLoopWindowTarget::Drm(EventLoopWindowTarget { + connector: con.clone(), + event_loop_handle: handle, + event_sink, + event_loop_awakener, + _marker: PhantomData, + }), + _marker: PhantomData, + }; + + Ok(EventLoop { + event_loop, + pending_user_events, + user_events_sender, + window_target, + }) + } + Err(_) => Err(()), + } + } + + pub fn run(mut self, callback: F) -> ! + where + F: FnMut( + crate::event::Event<'_, T>, + &crate::event_loop::EventLoopWindowTarget, + &mut ControlFlow, + ) + 'static, + { + let exit_code = self.run_return(callback); + std::process::exit(exit_code); + } + + pub fn run_return(&mut self, mut callback: F) -> i32 + where + F: FnMut( + crate::event::Event<'_, T>, + &crate::event_loop::EventLoopWindowTarget, + &mut ControlFlow, + ), + { + let mut control_flow = ControlFlow::Poll; + let pending_user_events = self.pending_user_events.clone(); + let mut event_sink_back_buffer = Vec::new(); + + callback( + crate::event::Event::NewEvents(StartCause::Init), + &self.window_target, + &mut control_flow, + ); + + let exit_code = loop { + match control_flow { + ControlFlow::ExitWithCode(code) => break code, + ControlFlow::Poll => { + // Non-blocking dispatch. + let timeout = Duration::from_millis(0); + if let Err(error) = self.loop_dispatch(Some(timeout)) { + break error.raw_os_error().unwrap_or(1); + } + + callback( + crate::event::Event::NewEvents(StartCause::Poll), + &self.window_target, + &mut control_flow, + ); + } + ControlFlow::Wait => { + if let Err(error) = self.loop_dispatch(None) { + break error.raw_os_error().unwrap_or(1); + } + + callback( + crate::event::Event::NewEvents(StartCause::WaitCancelled { + start: Instant::now(), + requested_resume: None, + }), + &self.window_target, + &mut control_flow, + ); + } + ControlFlow::WaitUntil(deadline) => { + let start = Instant::now(); + + // Compute the amount of time we'll block for. + let duration = if deadline > start { + deadline - start + } else { + Duration::from_millis(0) + }; + + if let Err(error) = self.loop_dispatch(Some(duration)) { + break error.raw_os_error().unwrap_or(1); + } + + let now = Instant::now(); + + if now < deadline { + callback( + crate::event::Event::NewEvents(StartCause::WaitCancelled { + start, + requested_resume: Some(deadline), + }), + &self.window_target, + &mut control_flow, + ) + } else { + callback( + crate::event::Event::NewEvents(StartCause::ResumeTimeReached { + start, + requested_resume: deadline, + }), + &self.window_target, + &mut control_flow, + ) + } + } + } + + // Handle pending user events. We don't need back buffer, since we can't dispatch + // user events indirectly via callback to the user. + for user_event in pending_user_events.borrow_mut().drain(..) { + sticky_exit_callback( + crate::event::Event::UserEvent(user_event), + &self.window_target, + &mut control_flow, + &mut callback, + ); + } + + // The purpose of the back buffer and that swap is to not hold borrow_mut when + // we're doing callback to the user, since we can double borrow if the user decides + // to create a window in one of those callbacks. + self.with_window_target(|window_target| { + let state = &mut window_target.event_sink.window_events; + std::mem::swap(&mut event_sink_back_buffer, state) + }); + + // Handle pending window events. + for event in event_sink_back_buffer.drain(..) { + let event = event.map_nonuser_event().unwrap(); + sticky_exit_callback(event, &self.window_target, &mut control_flow, &mut callback); + } + + // Send events cleared. + sticky_exit_callback( + crate::event::Event::MainEventsCleared, + &self.window_target, + &mut control_flow, + &mut callback, + ); + + // Send RedrawEventCleared. + sticky_exit_callback( + crate::event::Event::RedrawEventsCleared, + &self.window_target, + &mut control_flow, + &mut callback, + ); + }; + + callback( + crate::event::Event::LoopDestroyed, + &self.window_target, + &mut control_flow, + ); + exit_code + } + + #[inline] + pub fn create_proxy(&self) -> EventLoopProxy { + EventLoopProxy::new(self.user_events_sender.clone()) + } + + #[inline] + pub fn window_target(&self) -> &crate::event_loop::EventLoopWindowTarget { + &self.window_target + } + + fn with_window_target) -> U>(&mut self, f: F) -> U { + let state = match &mut self.window_target.p { + crate::platform_impl::EventLoopWindowTarget::Drm(window_target) => window_target, + #[cfg(any(feature = "x11", feature = "wayland"))] + _ => unreachable!(), + }; + + f(state) + } + + fn loop_dispatch>>( + &mut self, + timeout: D, + ) -> std::io::Result<()> { + let mut state = match &mut self.window_target.p { + crate::platform_impl::EventLoopWindowTarget::Drm(window_target) => { + &mut window_target.event_sink + } + #[cfg(any(feature = "x11", feature = "kmsdrm"))] + _ => unreachable!(), + }; + + self.event_loop.dispatch(timeout, &mut state) + } +} + +/// A handle that can be sent across the threads and used to wake up the `EventLoop`. +pub struct EventLoopProxy { + user_events_sender: calloop::channel::Sender, +} + +impl Clone for EventLoopProxy { + fn clone(&self) -> Self { + EventLoopProxy { + user_events_sender: self.user_events_sender.clone(), + } + } +} + +impl EventLoopProxy { + pub fn new(user_events_sender: calloop::channel::Sender) -> Self { + Self { user_events_sender } + } + + pub fn send_event(&self, event: T) -> Result<(), EventLoopClosed> { + self.user_events_sender + .send(event) + .map_err(|SendError(error)| EventLoopClosed(error)) + } +} diff --git a/src/platform_impl/linux/drm/input_to_vk.rs b/src/platform_impl/linux/drm/input_to_vk.rs new file mode 100644 index 0000000000..561f7ba7fa --- /dev/null +++ b/src/platform_impl/linux/drm/input_to_vk.rs @@ -0,0 +1,238 @@ +use crate::event::VirtualKeyCode; + +pub const CHAR_MAPPINGS: [Option; 234] = [ + Some(VirtualKeyCode::Space), + Some(VirtualKeyCode::Escape), + Some(VirtualKeyCode::Key1), + Some(VirtualKeyCode::Key2), + Some(VirtualKeyCode::Key3), + Some(VirtualKeyCode::Key4), + Some(VirtualKeyCode::Key5), + Some(VirtualKeyCode::Key6), + Some(VirtualKeyCode::Key7), + Some(VirtualKeyCode::Key8), + Some(VirtualKeyCode::Key9), + Some(VirtualKeyCode::Key0), + Some(VirtualKeyCode::Minus), + Some(VirtualKeyCode::Equals), + Some(VirtualKeyCode::Back), + Some(VirtualKeyCode::Tab), + Some(VirtualKeyCode::Q), + Some(VirtualKeyCode::W), + Some(VirtualKeyCode::E), + Some(VirtualKeyCode::R), + Some(VirtualKeyCode::T), + Some(VirtualKeyCode::Y), + Some(VirtualKeyCode::U), + Some(VirtualKeyCode::I), + Some(VirtualKeyCode::O), + Some(VirtualKeyCode::P), + Some(VirtualKeyCode::LBracket), + Some(VirtualKeyCode::RBracket), + Some(VirtualKeyCode::Return), + Some(VirtualKeyCode::LControl), + Some(VirtualKeyCode::A), + Some(VirtualKeyCode::S), + Some(VirtualKeyCode::D), + Some(VirtualKeyCode::F), + Some(VirtualKeyCode::G), + Some(VirtualKeyCode::H), + Some(VirtualKeyCode::J), + Some(VirtualKeyCode::K), + Some(VirtualKeyCode::L), + Some(VirtualKeyCode::Semicolon), + Some(VirtualKeyCode::Apostrophe), + Some(VirtualKeyCode::Grave), + Some(VirtualKeyCode::LShift), + Some(VirtualKeyCode::Backslash), + Some(VirtualKeyCode::Z), + Some(VirtualKeyCode::X), + Some(VirtualKeyCode::C), + Some(VirtualKeyCode::V), + Some(VirtualKeyCode::B), + Some(VirtualKeyCode::N), + Some(VirtualKeyCode::M), + Some(VirtualKeyCode::Comma), + Some(VirtualKeyCode::Period), + Some(VirtualKeyCode::Slash), + Some(VirtualKeyCode::RShift), + Some(VirtualKeyCode::Asterisk), + Some(VirtualKeyCode::LAlt), + Some(VirtualKeyCode::Space), + Some(VirtualKeyCode::Capital), + Some(VirtualKeyCode::F1), + Some(VirtualKeyCode::F2), + Some(VirtualKeyCode::F3), + Some(VirtualKeyCode::F4), + Some(VirtualKeyCode::F5), + Some(VirtualKeyCode::F6), + Some(VirtualKeyCode::F7), + Some(VirtualKeyCode::F8), + Some(VirtualKeyCode::F9), + Some(VirtualKeyCode::F10), + Some(VirtualKeyCode::Numlock), + Some(VirtualKeyCode::Scroll), + Some(VirtualKeyCode::Numpad7), + Some(VirtualKeyCode::Numpad8), + Some(VirtualKeyCode::Numpad9), + Some(VirtualKeyCode::NumpadSubtract), + Some(VirtualKeyCode::Numpad4), + Some(VirtualKeyCode::Numpad5), + Some(VirtualKeyCode::Numpad6), + Some(VirtualKeyCode::NumpadEquals), + Some(VirtualKeyCode::Numpad1), + Some(VirtualKeyCode::Numpad2), + Some(VirtualKeyCode::Numpad3), + Some(VirtualKeyCode::Numpad0), + Some(VirtualKeyCode::NumpadDecimal), + None, // NULL KEY + None, // KEY_ZENKAKUHANKAKU + Some(VirtualKeyCode::OEM102), + Some(VirtualKeyCode::F11), + Some(VirtualKeyCode::F12), + None, // Rollover key + Some(VirtualKeyCode::Kana), + None, // KEY_HIRAGANA + None, // KEY_HENKAN + None, // KEY_KATAKANAHIRAGANA + None, // KEY_MUHENKAN + None, // KEY_KPJPCOMMA + None, // KEY_KPENTER + Some(VirtualKeyCode::RControl), + None, // KEY_KPSLASH + Some(VirtualKeyCode::Sysrq), + Some(VirtualKeyCode::RAlt), + None, // KEY_LINEFEED + Some(VirtualKeyCode::Home), + Some(VirtualKeyCode::Up), + Some(VirtualKeyCode::PageUp), + Some(VirtualKeyCode::Left), + Some(VirtualKeyCode::Right), + Some(VirtualKeyCode::End), + Some(VirtualKeyCode::Down), + Some(VirtualKeyCode::PageDown), + Some(VirtualKeyCode::Insert), + Some(VirtualKeyCode::Delete), + None, // KEY_MACRO + Some(VirtualKeyCode::Mute), + Some(VirtualKeyCode::VolumeDown), + Some(VirtualKeyCode::VolumeUp), + Some(VirtualKeyCode::Power), + None, // KEY_KPEQUAL + None, // KEY_KPPLUSMINUS + Some(VirtualKeyCode::Pause), + None, // KEY_SCALE + None, // KEY_KPCOMMA + None, // KEY_HANGEUL + None, // KEY_HANJA + Some(VirtualKeyCode::Yen), + Some(VirtualKeyCode::LWin), + Some(VirtualKeyCode::RWin), + Some(VirtualKeyCode::Compose), + Some(VirtualKeyCode::Stop), + None, // KEY_AGAIN + None, // KEY_PROPS + None, // KEY_UNDO + None, // KEY_FRONT + Some(VirtualKeyCode::Copy), + None, // KEY_OPEN + Some(VirtualKeyCode::Paste), + None, // KEY_FIND + Some(VirtualKeyCode::Cut), + None, // KEY_HELP + None, // KEY_MENU + Some(VirtualKeyCode::Calculator), + None, // KEY_SETUP + Some(VirtualKeyCode::Sleep), + Some(VirtualKeyCode::Wake), + None, // KEY_FILE + None, // KEY_SENDFILE + None, // KEY_DELETEFILE + None, // KEY_XFER + None, // KEY_PROG1 + None, // KEY_PROG1 + None, // KEY_PROG2 + None, // KEY_WWW + None, // KEY_MSDOS + None, // KEY_COFFEE + None, // KEY_ROTATE_DISPLAY + None, // KEY_CYCLEWINDOWS + Some(VirtualKeyCode::Mail), + None, // KEY_BOOKMARKS + Some(VirtualKeyCode::MyComputer), + Some(VirtualKeyCode::NavigateBackward), + Some(VirtualKeyCode::NavigateForward), + None, // KEY_CLOSECD + None, // KEY_EJECTCD + None, // KEY_EJECTCLOSECD + Some(VirtualKeyCode::NextTrack), + Some(VirtualKeyCode::PlayPause), + Some(VirtualKeyCode::PrevTrack), + None, // KEY_STOPCD + Some(VirtualKeyCode::MediaStop), + None, // KEY_RECORD + None, // KEY_REWIND + None, // KEY_PHONE + None, // KEY_ISO + None, // KEY_CONFIG + Some(VirtualKeyCode::WebHome), + Some(VirtualKeyCode::WebRefresh), + None, // KEY_EXIT + None, // KEY_MOVE + None, // KEY_EDIT + None, // KEY_SCROLLUP + None, // KEY_SCROLLDOWN + None, // KEY_KPLEFTPAREN + None, // KEY_KPRIGHTPAREN + None, // KEY_NEW + None, // KEY_REDO + Some(VirtualKeyCode::F13), + Some(VirtualKeyCode::F14), + Some(VirtualKeyCode::F15), + Some(VirtualKeyCode::F16), + Some(VirtualKeyCode::F17), + Some(VirtualKeyCode::F18), + Some(VirtualKeyCode::F19), + Some(VirtualKeyCode::F20), + Some(VirtualKeyCode::F21), + Some(VirtualKeyCode::F22), + Some(VirtualKeyCode::F23), + Some(VirtualKeyCode::F24), + None, // KEY_PLAYCD + None, // KEY_PAUSECD + None, // KEY_PROG3 + None, // KEY_PROG4 + None, // KEY_DASHBOARD + None, // KEY_SUSPEND + None, // KEY_CLOSE + None, // KEY_PLAY + None, // KEY_FASTFORWARD + None, // KEY_BASSBOOST + None, // KEY_PRINT + None, // KEY_HP + None, // KEY_CAMERA + None, // KEY_SOUND + None, // KEY_QUESTION + None, // KEY_EMAIL + None, // KEY_CHAT + Some(VirtualKeyCode::WebSearch), + None, // KEY_CONNECT + None, // KEY_FINANCE + None, // KEY_SPORT + None, // KEY_SHOP + None, // KEY_ALTERASE + None, // KEY_CANCEL + None, // KEY_BRIGHTNESSDOWN + None, // KEY_BRIGHTNESSUP + Some(VirtualKeyCode::MediaSelect), + None, // KEY_SWITCHVIDEOMODE + None, // KEY_KBDILLUMTOGGLE + None, // KEY_KBDILLUMDOWN + None, // KEY_KBDILLUMUP + None, // KEY_SEND + None, // KEY_REPLY + None, // KEY_FORWARDMAIL + None, // KEY_SAVE + None, // KEY_DOCUMENTS + None, // KEY_BATTERY +]; diff --git a/src/platform_impl/linux/drm/mod.rs b/src/platform_impl/linux/drm/mod.rs new file mode 100644 index 0000000000..782d5d30ac --- /dev/null +++ b/src/platform_impl/linux/drm/mod.rs @@ -0,0 +1,141 @@ +use drm::control::Device as ControlDevice; +use drm::Device; + +use crate::dpi::{PhysicalPosition, PhysicalSize}; + +pub mod event_loop; +mod input_to_vk; +pub mod window; +pub use drm::SystemError; +pub use event_loop::EventLoop; +pub use event_loop::EventLoopProxy; +pub use event_loop::EventLoopWindowTarget; +pub use window::Window; + +#[derive(Debug)] +/// A simple wrapper for a device node. +pub struct Card(std::fs::File); + +/// Implementing `AsRawFd` is a prerequisite to implementing the traits found +/// in this crate. Here, we are just calling `as_raw_fd()` on the inner File. +impl std::os::unix::io::AsRawFd for Card { + fn as_raw_fd(&self) -> std::os::unix::io::RawFd { + self.0.as_raw_fd() + } +} + +/// With `AsRawFd` implemented, we can now implement `drm::Device`. +impl Device for Card {} +impl ControlDevice for Card {} + +/// Simple helper methods for opening a `Card`. +impl Card { + pub fn open(path: &str) -> Self { + let mut options = std::fs::OpenOptions::new(); + options.read(true); + options.write(true); + Card(options.open(path).unwrap()) + } + + pub fn open_global() -> Self { + Self::open("/dev/dri/card0") + } +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct DeviceId; + +impl DeviceId { + pub const unsafe fn dummy() -> Self { + DeviceId + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct MonitorHandle(drm::control::connector::Info); + +impl PartialOrd for MonitorHandle { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.0.interface_id().cmp(&other.0.interface_id())) + } +} + +impl Ord for MonitorHandle { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.0.interface_id().cmp(&other.0.interface_id()) + } +} + +impl MonitorHandle { + #[inline] + pub fn name(&self) -> Option { + Some(String::from("card0")) + } + + #[inline] + pub fn native_identifier(&self) -> u32 { + self.0.interface_id() + } + + #[inline] + pub fn size(&self) -> PhysicalSize { + let size = self.0.modes()[0].size(); + PhysicalSize::new(size.0 as u32, size.1 as u32) + } + + #[inline] + pub fn position(&self) -> PhysicalPosition { + PhysicalPosition::new(0, 0) + } + + #[inline] + pub fn scale_factor(&self) -> f64 { + 1.0 + } + + #[inline] + pub fn video_modes(&self) -> impl Iterator { + let modes = self.0.modes().to_vec(); + let monitor = self.0.clone(); + modes.into_iter().map(move |f| crate::monitor::VideoMode { + video_mode: crate::platform_impl::VideoMode::Drm(VideoMode(f, monitor.clone())), + }) + } +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct VideoMode(drm::control::Mode, drm::control::connector::Info); + +impl VideoMode { + #[inline] + pub fn size(&self) -> PhysicalSize { + let size = self.0.size(); + PhysicalSize::new(size.0 as u32, size.1 as u32) + } + + #[inline] + pub fn bit_depth(&self) -> u16 { + 32 + } + + #[inline] + pub fn refresh_rate(&self) -> u16 { + self.0.vrefresh() as u16 + } + + #[inline] + pub fn monitor(&self) -> crate::monitor::MonitorHandle { + crate::monitor::MonitorHandle { + inner: crate::platform_impl::MonitorHandle::Drm(MonitorHandle(self.1.clone())), + } + } +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct WindowId; + +impl WindowId { + pub const unsafe fn dummy() -> Self { + Self + } +} diff --git a/src/platform_impl/linux/drm/window.rs b/src/platform_impl/linux/drm/window.rs new file mode 100644 index 0000000000..a748627912 --- /dev/null +++ b/src/platform_impl/linux/drm/window.rs @@ -0,0 +1,323 @@ +use std::collections::VecDeque; + +use drm::control::{atomic, property, AtomicCommitFlags, Device}; + +use crate::{ + dpi::{PhysicalPosition, PhysicalSize, Position, Size}, + error::{ExternalError, NotSupportedError}, + platform_impl::GBM_DEVICE, + window::{CursorIcon, Fullscreen}, +}; + +use super::event_loop::find_prop_id; + +pub struct Window( + drm::control::Mode, + drm::control::connector::Info, + calloop::ping::Ping, +); + +impl Window { + pub fn new( + event_loop_window_target: &super::event_loop::EventLoopWindowTarget, + _attributes: crate::window::WindowAttributes, + _platform_attributes: crate::platform_impl::PlatformSpecificWindowBuilderAttributes, + ) -> Result { + let gbm = GBM_DEVICE.lock(); + let gbm = gbm.as_ref().map_err(|_| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Failed to acquire gbm lock"), + ) + })?; + let res = gbm.resource_handles().map_err(|_| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Could not get resource handles"), + ) + })?; + let coninfo: Vec = res + .connectors() + .iter() + .flat_map(|con| gbm.get_connector(*con)) + .collect(); + + // Filter each connector until we find one that's connected. + let con = coninfo + .iter() + .find(|&i| i.state() == drm::control::connector::State::Connected) + .ok_or_else(|| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("No connected connectors"), + ) + })?; + let crtcinfo: Vec = res + .crtcs() + .iter() + .flat_map(|crtc| gbm.get_crtc(*crtc)) + .collect(); + + let crtc = crtcinfo.get(0).ok_or_else(|| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("No crtcs found"), + ) + })?; + let &mode = con.modes().get(0).ok_or_else(|| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("No modes found on connector"), + ) + })?; + + let mut atomic_req = atomic::AtomicModeReq::new(); + atomic_req.add_property( + con.handle(), + find_prop_id(&gbm, con.handle(), "CRTC_ID").ok_or_else(|| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Could not get CRTC_ID"), + ) + })?, + property::Value::CRTC(Some(crtc.handle())), + ); + let blob = gbm.create_property_blob(&mode).map_err(|_| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Failed to create blob"), + ) + })?; + atomic_req.add_property( + crtc.handle(), + find_prop_id(&gbm, crtc.handle(), "MODE_ID").ok_or_else(|| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Could not get MODE_ID"), + ) + })?, + blob, + ); + atomic_req.add_property( + crtc.handle(), + find_prop_id(&gbm, crtc.handle(), "ACTIVE").ok_or_else(|| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Could not get ACTIVE"), + ) + })?, + property::Value::Boolean(true), + ); + + gbm.atomic_commit(AtomicCommitFlags::ALLOW_MODESET, atomic_req) + .map_err(|_| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Failed to set mode"), + ) + })?; + + Ok(Self( + mode, + con.clone(), + event_loop_window_target.event_loop_awakener.clone(), + )) + } + #[inline] + pub fn id(&self) -> super::WindowId { + super::WindowId + } + + #[inline] + pub fn set_title(&self, _title: &str) {} + + #[inline] + pub fn set_visible(&self, visible: bool) { + if !visible { + eprintln!("It is not possible to make a window not visible in kmsdrm mode"); + } + } + + #[inline] + pub fn is_visible(&self) -> Option { + Some(true) + } + + #[inline] + pub fn outer_position(&self) -> Result, NotSupportedError> { + Err(NotSupportedError::new()) + } + + #[inline] + pub fn inner_position(&self) -> Result, NotSupportedError> { + Err(NotSupportedError::new()) + } + + #[inline] + pub fn set_outer_position(&self, _position: Position) { + eprintln!("The window cannot be moved in kmsdrm mode"); + } + + #[inline] + pub fn inner_size(&self) -> PhysicalSize { + let size = self.0.size(); + PhysicalSize::new(size.0 as u32, size.1 as u32) + } + + #[inline] + pub fn outer_size(&self) -> PhysicalSize { + self.inner_size() + } + + #[inline] + pub fn set_inner_size(&self, _size: Size) { + // It's technically possible to do this by changing video modes but that seems a little + // restrictive + eprintln!("The window cannot be resized in kmsdrm mode"); + } + + #[inline] + pub fn set_min_inner_size(&self, _dimensions: Option) { + eprintln!("The window cannot be resized in kmsdrm mode"); + } + + #[inline] + pub fn set_max_inner_size(&self, _dimensions: Option) { + // It's technically possible to do this by changing video modes but that seems a little + // restrictive + eprintln!("The window cannot be resized in kmsdrm mode"); + } + + #[inline] + pub fn set_resizable(&self, _resizable: bool) { + eprintln!("The window cannot be resized in kmsdrm mode"); + } + + #[inline] + pub fn is_resizable(&self) -> bool { + false + } + + #[inline] + pub fn set_cursor_icon(&self, _cursor: CursorIcon) { + unimplemented!() + } + + #[inline] + pub fn set_cursor_grab(&self, _grab: bool) -> Result<(), ExternalError> { + eprintln!("The cursor is always grabbed in kmsdrm mode"); + Ok(()) + } + + #[inline] + pub fn set_cursor_visible(&self, _visible: bool) { + unimplemented!() + } + + #[inline] + pub fn drag_window(&self) -> Result<(), ExternalError> { + eprintln!("The window cannot be dragged in kmsdrm mode"); + Ok(()) + } + + #[inline] + pub fn set_cursor_hittest(&self, _hittest: bool) -> Result<(), ExternalError> { + unimplemented!() + } + + #[inline] + pub fn scale_factor(&self) -> f64 { + 1.0 + } + + #[inline] + pub fn set_cursor_position(&self, _position: Position) -> Result<(), ExternalError> { + unimplemented!() + } + + #[inline] + pub fn set_maximized(&self, _maximized: bool) { + eprintln!("The window is always maximized in kmsdrm mode"); + } + + #[inline] + pub fn is_maximized(&self) -> bool { + true + } + + #[inline] + pub fn set_minimized(&self, _minimized: bool) { + // By switching the crtc to the tty you can technically hide the "window". + eprintln!("The window cannot be minimized in kmsdrm mode"); + } + + #[inline] + pub fn fullscreen(&self) -> Option { + Some(Fullscreen::Exclusive(crate::monitor::VideoMode { + video_mode: crate::platform_impl::VideoMode::Drm(super::VideoMode( + self.0, + self.1.clone(), + )), + })) + } + + #[inline] + pub fn set_fullscreen(&self, _monitor: Option) { + eprintln!("The window is always in fullscreen in kmsdrm mode"); + } + + #[inline] + pub fn set_decorations(&self, _decorations: bool) { + eprintln!("The window cannot be decorated in kmsdrm mode"); + } + + pub fn is_decorated(&self) -> bool { + false + } + + #[inline] + pub fn set_ime_position(&self, _position: Position) { + eprintln!("The window cannot be moved in kmsdrm mode"); + } + + #[inline] + pub fn request_redraw(&self) { + self.2.ping(); + } + + #[inline] + pub fn current_monitor(&self) -> Option { + Some(super::MonitorHandle(self.1.clone())) + } + + #[inline] + pub fn available_monitors(&self) -> VecDeque { + if let Ok(gbm) = &**GBM_DEVICE.lock() { + gbm.resource_handles() + .unwrap() + .connectors() + .iter() + .map(|f| super::MonitorHandle(gbm.get_connector(*f).unwrap())) + .collect() + } else { + VecDeque::new() + } + } + + #[inline] + pub fn primary_monitor(&self) -> Option { + Some(crate::monitor::MonitorHandle { + inner: crate::platform_impl::MonitorHandle::Drm(super::MonitorHandle(self.1.clone())), + }) + } +} diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index 78765756ce..a2d65afe94 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -6,8 +6,12 @@ target_os = "openbsd" ))] -#[cfg(all(not(feature = "x11"), not(feature = "wayland")))] -compile_error!("Please select a feature to build for unix: `x11`, `wayland`"); +#[cfg(all( + not(feature = "x11"), + not(feature = "wayland"), + not(feature = "kmsdrm") +))] +compile_error!("Please select a feature to build for unix: `x11`, `wayland`, `kmsdrm`"); #[cfg(feature = "wayland")] use std::error::Error; @@ -35,6 +39,8 @@ use crate::{ pub(crate) use crate::icon::RgbaIcon as PlatformIcon; +#[cfg(feature = "kmsdrm")] +pub mod drm; #[cfg(feature = "wayland")] pub mod wayland; #[cfg(feature = "x11")] @@ -55,6 +61,8 @@ pub(crate) enum Backend { X, #[cfg(feature = "wayland")] Wayland, + #[cfg(feature = "kmsdrm")] + Drm, } #[derive(Debug, Copy, Clone, PartialEq, Hash)] @@ -131,6 +139,37 @@ lazy_static! { Mutex::new(XConnection::new(Some(x_error_callback)).map(Arc::new)); } +#[cfg(feature = "kmsdrm")] +#[repr(transparent)] +pub struct AssertSync(pub T); + +#[cfg(feature = "kmsdrm")] +unsafe impl Sync for AssertSync {} +#[cfg(feature = "kmsdrm")] +unsafe impl Send for AssertSync {} +#[cfg(feature = "kmsdrm")] +impl std::ops::Deref for AssertSync { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} +#[cfg(feature = "kmsdrm")] +impl std::ops::DerefMut for AssertSync { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +#[cfg(feature = "kmsdrm")] +lazy_static! { + pub static ref GBM_DEVICE: Mutex>, std::io::Error>>> = + Mutex::new(AssertSync( + gbm::Device::new(drm::Card::open_global()).map(Arc::new) + )); +} + #[derive(Debug, Clone)] pub enum OsError { #[cfg(feature = "x11")] @@ -139,6 +178,8 @@ pub enum OsError { XMisc(&'static str), #[cfg(feature = "wayland")] WaylandMisc(&'static str), + #[cfg(feature = "kmsdrm")] + DrmMisc(&'static str), } impl fmt::Display for OsError { @@ -150,6 +191,8 @@ impl fmt::Display for OsError { OsError::XMisc(e) => _f.pad(e), #[cfg(feature = "wayland")] OsError::WaylandMisc(e) => _f.pad(e), + #[cfg(feature = "kmsdrm")] + OsError::DrmMisc(e) => _f.pad(e), } } } @@ -159,6 +202,8 @@ pub enum Window { X(x11::Window), #[cfg(feature = "wayland")] Wayland(wayland::Window), + #[cfg(feature = "kmsdrm")] + Drm(drm::Window), } #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -167,14 +212,18 @@ pub enum WindowId { X(x11::WindowId), #[cfg(feature = "wayland")] Wayland(wayland::WindowId), + #[cfg(feature = "kmsdrm")] + Drm(drm::WindowId), } impl WindowId { pub const unsafe fn dummy() -> Self { #[cfg(feature = "wayland")] return WindowId::Wayland(wayland::WindowId::dummy()); - #[cfg(all(not(feature = "wayland"), feature = "x11"))] + #[cfg(all(not(all(feature = "wayland", feature = "kmsdrm")), feature = "x11"))] return WindowId::X(x11::WindowId::dummy()); + #[cfg(all(not(all(feature = "wayland", feature = "x11")), feature = "kmsdrm"))] + return WindowId::Drm(drm::WindowId::dummy()); } } @@ -184,6 +233,8 @@ pub enum DeviceId { X(x11::DeviceId), #[cfg(feature = "wayland")] Wayland(wayland::DeviceId), + #[cfg(feature = "kmsdrm")] + Drm(drm::DeviceId), } impl DeviceId { @@ -192,6 +243,8 @@ impl DeviceId { return DeviceId::Wayland(wayland::DeviceId::dummy()); #[cfg(all(not(feature = "wayland"), feature = "x11"))] return DeviceId::X(x11::DeviceId::dummy()); + #[cfg(all(not(all(feature = "wayland", feature = "x11")), feature = "kmsdrm"))] + return DeviceId::Drm(drm::DeviceId::dummy()); } } @@ -201,6 +254,8 @@ pub enum MonitorHandle { X(x11::MonitorHandle), #[cfg(feature = "wayland")] Wayland(wayland::MonitorHandle), + #[cfg(feature = "kmsdrm")] + Drm(drm::MonitorHandle), } /// `x11_or_wayland!(match expr; Enum(foo) => foo.something())` @@ -212,13 +267,15 @@ pub enum MonitorHandle { /// } /// ``` /// The result can be converted to another enum by adding `; as AnotherEnum` -macro_rules! x11_or_wayland { +macro_rules! x11_or_wayland_or_drm { (match $what:expr; $enum:ident ( $($c1:tt)* ) => $x:expr; as $enum2:ident ) => { match $what { #[cfg(feature = "x11")] $enum::X($($c1)*) => $enum2::X($x), #[cfg(feature = "wayland")] $enum::Wayland($($c1)*) => $enum2::Wayland($x), + #[cfg(feature = "kmsdrm")] + $enum::Drm($($c1)*) => $enum2::Drm($x) } }; (match $what:expr; $enum:ident ( $($c1:tt)* ) => $x:expr) => { @@ -227,6 +284,8 @@ macro_rules! x11_or_wayland { $enum::X($($c1)*) => $x, #[cfg(feature = "wayland")] $enum::Wayland($($c1)*) => $x, + #[cfg(feature = "kmsdrm")] + $enum::Drm($($c1)*) => $x } }; } @@ -234,32 +293,32 @@ macro_rules! x11_or_wayland { impl MonitorHandle { #[inline] pub fn name(&self) -> Option { - x11_or_wayland!(match self; MonitorHandle(m) => m.name()) + x11_or_wayland_or_drm!(match self; MonitorHandle(m) => m.name()) } #[inline] pub fn native_identifier(&self) -> u32 { - x11_or_wayland!(match self; MonitorHandle(m) => m.native_identifier()) + x11_or_wayland_or_drm!(match self; MonitorHandle(m) => m.native_identifier()) } #[inline] pub fn size(&self) -> PhysicalSize { - x11_or_wayland!(match self; MonitorHandle(m) => m.size()) + x11_or_wayland_or_drm!(match self; MonitorHandle(m) => m.size()) } #[inline] pub fn position(&self) -> PhysicalPosition { - x11_or_wayland!(match self; MonitorHandle(m) => m.position()) + x11_or_wayland_or_drm!(match self; MonitorHandle(m) => m.position()) } #[inline] pub fn scale_factor(&self) -> f64 { - x11_or_wayland!(match self; MonitorHandle(m) => m.scale_factor() as f64) + x11_or_wayland_or_drm!(match self; MonitorHandle(m) => m.scale_factor() as f64) } #[inline] pub fn video_modes(&self) -> Box> { - x11_or_wayland!(match self; MonitorHandle(m) => Box::new(m.video_modes())) + x11_or_wayland_or_drm!(match self; MonitorHandle(m) => Box::new(m.video_modes())) } } @@ -269,27 +328,29 @@ pub enum VideoMode { X(x11::VideoMode), #[cfg(feature = "wayland")] Wayland(wayland::VideoMode), + #[cfg(feature = "kmsdrm")] + Drm(drm::VideoMode), } impl VideoMode { #[inline] pub fn size(&self) -> PhysicalSize { - x11_or_wayland!(match self; VideoMode(m) => m.size()) + x11_or_wayland_or_drm!(match self; VideoMode(m) => m.size()) } #[inline] pub fn bit_depth(&self) -> u16 { - x11_or_wayland!(match self; VideoMode(m) => m.bit_depth()) + x11_or_wayland_or_drm!(match self; VideoMode(m) => m.bit_depth()) } #[inline] pub fn refresh_rate(&self) -> u16 { - x11_or_wayland!(match self; VideoMode(m) => m.refresh_rate()) + x11_or_wayland_or_drm!(match self; VideoMode(m) => m.refresh_rate()) } #[inline] pub fn monitor(&self) -> RootMonitorHandle { - x11_or_wayland!(match self; VideoMode(m) => m.monitor()) + x11_or_wayland_or_drm!(match self; VideoMode(m) => m.monitor()) } } @@ -309,147 +370,151 @@ impl Window { EventLoopWindowTarget::X(ref window_target) => { x11::Window::new(window_target, attribs, pl_attribs).map(Window::X) } + #[cfg(feature = "kmsdrm")] + EventLoopWindowTarget::Drm(ref window_target) => { + drm::Window::new(window_target, attribs, pl_attribs).map(Window::Drm) + } } } #[inline] pub fn id(&self) -> WindowId { - x11_or_wayland!(match self; Window(w) => w.id(); as WindowId) + x11_or_wayland_or_drm!(match self; Window(w) => w.id(); as WindowId) } #[inline] pub fn set_title(&self, title: &str) { - x11_or_wayland!(match self; Window(w) => w.set_title(title)); + x11_or_wayland_or_drm!(match self; Window(w) => w.set_title(title)); } #[inline] pub fn set_visible(&self, visible: bool) { - x11_or_wayland!(match self; Window(w) => w.set_visible(visible)) + x11_or_wayland_or_drm!(match self; Window(w) => w.set_visible(visible)) } #[inline] pub fn is_visible(&self) -> Option { - x11_or_wayland!(match self; Window(w) => w.is_visible()) + x11_or_wayland_or_drm!(match self; Window(w) => w.is_visible()) } #[inline] pub fn outer_position(&self) -> Result, NotSupportedError> { - x11_or_wayland!(match self; Window(w) => w.outer_position()) + x11_or_wayland_or_drm!(match self; Window(w) => w.outer_position()) } #[inline] pub fn inner_position(&self) -> Result, NotSupportedError> { - x11_or_wayland!(match self; Window(w) => w.inner_position()) + x11_or_wayland_or_drm!(match self; Window(w) => w.inner_position()) } #[inline] pub fn set_outer_position(&self, position: Position) { - x11_or_wayland!(match self; Window(w) => w.set_outer_position(position)) + x11_or_wayland_or_drm!(match self; Window(w) => w.set_outer_position(position)) } #[inline] pub fn inner_size(&self) -> PhysicalSize { - x11_or_wayland!(match self; Window(w) => w.inner_size()) + x11_or_wayland_or_drm!(match self; Window(w) => w.inner_size()) } #[inline] pub fn outer_size(&self) -> PhysicalSize { - x11_or_wayland!(match self; Window(w) => w.outer_size()) + x11_or_wayland_or_drm!(match self; Window(w) => w.outer_size()) } #[inline] pub fn set_inner_size(&self, size: Size) { - x11_or_wayland!(match self; Window(w) => w.set_inner_size(size)) + x11_or_wayland_or_drm!(match self; Window(w) => w.set_inner_size(size)) } #[inline] pub fn set_min_inner_size(&self, dimensions: Option) { - x11_or_wayland!(match self; Window(w) => w.set_min_inner_size(dimensions)) + x11_or_wayland_or_drm!(match self; Window(w) => w.set_min_inner_size(dimensions)) } #[inline] pub fn set_max_inner_size(&self, dimensions: Option) { - x11_or_wayland!(match self; Window(w) => w.set_max_inner_size(dimensions)) + x11_or_wayland_or_drm!(match self; Window(w) => w.set_max_inner_size(dimensions)) } #[inline] pub fn set_resizable(&self, resizable: bool) { - x11_or_wayland!(match self; Window(w) => w.set_resizable(resizable)) + x11_or_wayland_or_drm!(match self; Window(w) => w.set_resizable(resizable)) } #[inline] pub fn is_resizable(&self) -> bool { - x11_or_wayland!(match self; Window(w) => w.is_resizable()) + x11_or_wayland_or_drm!(match self; Window(w) => w.is_resizable()) } #[inline] pub fn set_cursor_icon(&self, cursor: CursorIcon) { - x11_or_wayland!(match self; Window(w) => w.set_cursor_icon(cursor)) + x11_or_wayland_or_drm!(match self; Window(w) => w.set_cursor_icon(cursor)) } #[inline] pub fn set_cursor_grab(&self, grab: bool) -> Result<(), ExternalError> { - x11_or_wayland!(match self; Window(window) => window.set_cursor_grab(grab)) + x11_or_wayland_or_drm!(match self; Window(window) => window.set_cursor_grab(grab)) } #[inline] pub fn set_cursor_visible(&self, visible: bool) { - x11_or_wayland!(match self; Window(window) => window.set_cursor_visible(visible)) + x11_or_wayland_or_drm!(match self; Window(window) => window.set_cursor_visible(visible)) } #[inline] pub fn drag_window(&self) -> Result<(), ExternalError> { - x11_or_wayland!(match self; Window(window) => window.drag_window()) + x11_or_wayland_or_drm!(match self; Window(window) => window.drag_window()) } #[inline] pub fn set_cursor_hittest(&self, hittest: bool) -> Result<(), ExternalError> { - x11_or_wayland!(match self; Window(w) => w.set_cursor_hittest(hittest)) + x11_or_wayland_or_drm!(match self; Window(w) => w.set_cursor_hittest(hittest)) } #[inline] pub fn scale_factor(&self) -> f64 { - x11_or_wayland!(match self; Window(w) => w.scale_factor() as f64) + x11_or_wayland_or_drm!(match self; Window(w) => w.scale_factor() as f64) } #[inline] pub fn set_cursor_position(&self, position: Position) -> Result<(), ExternalError> { - x11_or_wayland!(match self; Window(w) => w.set_cursor_position(position)) + x11_or_wayland_or_drm!(match self; Window(w) => w.set_cursor_position(position)) } #[inline] pub fn set_maximized(&self, maximized: bool) { - x11_or_wayland!(match self; Window(w) => w.set_maximized(maximized)) + x11_or_wayland_or_drm!(match self; Window(w) => w.set_maximized(maximized)) } #[inline] pub fn is_maximized(&self) -> bool { - x11_or_wayland!(match self; Window(w) => w.is_maximized()) + x11_or_wayland_or_drm!(match self; Window(w) => w.is_maximized()) } #[inline] pub fn set_minimized(&self, minimized: bool) { - x11_or_wayland!(match self; Window(w) => w.set_minimized(minimized)) + x11_or_wayland_or_drm!(match self; Window(w) => w.set_minimized(minimized)) } #[inline] pub fn fullscreen(&self) -> Option { - x11_or_wayland!(match self; Window(w) => w.fullscreen()) + x11_or_wayland_or_drm!(match self; Window(w) => w.fullscreen()) } #[inline] pub fn set_fullscreen(&self, monitor: Option) { - x11_or_wayland!(match self; Window(w) => w.set_fullscreen(monitor)) + x11_or_wayland_or_drm!(match self; Window(w) => w.set_fullscreen(monitor)) } #[inline] pub fn set_decorations(&self, decorations: bool) { - x11_or_wayland!(match self; Window(w) => w.set_decorations(decorations)) + x11_or_wayland_or_drm!(match self; Window(w) => w.set_decorations(decorations)) } #[inline] pub fn is_decorated(&self) -> bool { - x11_or_wayland!(match self; Window(w) => w.is_decorated()) + x11_or_wayland_or_drm!(match self; Window(w) => w.is_decorated()) } #[inline] @@ -459,6 +524,8 @@ impl Window { Window::X(ref w) => w.set_always_on_top(_always_on_top), #[cfg(feature = "wayland")] Window::Wayland(_) => (), + #[cfg(feature = "kmsdrm")] + Window::Drm(_) => (), } } @@ -469,12 +536,14 @@ impl Window { Window::X(ref w) => w.set_window_icon(_window_icon), #[cfg(feature = "wayland")] Window::Wayland(_) => (), + #[cfg(feature = "kmsdrm")] + Window::Drm(_) => (), } } #[inline] pub fn set_ime_position(&self, position: Position) { - x11_or_wayland!(match self; Window(w) => w.set_ime_position(position)) + x11_or_wayland_or_drm!(match self; Window(w) => w.set_ime_position(position)) } #[inline] @@ -484,6 +553,8 @@ impl Window { Window::X(ref w) => w.focus_window(), #[cfg(feature = "wayland")] Window::Wayland(_) => (), + #[cfg(feature = "kmsdrm")] + Window::Drm(_) => (), } } pub fn request_user_attention(&self, request_type: Option) { @@ -492,12 +563,14 @@ impl Window { Window::X(ref w) => w.request_user_attention(request_type), #[cfg(feature = "wayland")] Window::Wayland(ref w) => w.request_user_attention(request_type), + #[cfg(feature = "kmsdrm")] + Window::Drm(_) => (), } } #[inline] pub fn request_redraw(&self) { - x11_or_wayland!(match self; Window(w) => w.request_redraw()) + x11_or_wayland_or_drm!(match self; Window(w) => w.request_redraw()) } #[inline] @@ -517,6 +590,13 @@ impl Window { inner: current_monitor, }) } + #[cfg(feature = "kmsdrm")] + Window::Drm(ref window) => { + let current_monitor = MonitorHandle::Drm(window.current_monitor()?); + Some(RootMonitorHandle { + inner: current_monitor, + }) + } } } @@ -535,6 +615,12 @@ impl Window { .into_iter() .map(MonitorHandle::Wayland) .collect(), + #[cfg(feature = "kmsdrm")] + Window::Drm(ref window) => window + .available_monitors() + .into_iter() + .map(MonitorHandle::Drm) + .collect(), } } @@ -550,6 +636,8 @@ impl Window { } #[cfg(feature = "wayland")] Window::Wayland(ref window) => window.primary_monitor(), + #[cfg(feature = "kmsdrm")] + Window::Drm(ref window) => window.primary_monitor(), } } @@ -559,6 +647,8 @@ impl Window { Window::X(ref window) => RawWindowHandle::Xlib(window.raw_window_handle()), #[cfg(feature = "wayland")] Window::Wayland(ref window) => RawWindowHandle::Wayland(window.raw_window_handle()), + #[cfg(feature = "kmsdrm")] + Window::Drm(_) => unimplemented!(), } } } @@ -601,6 +691,8 @@ pub enum EventLoop { Wayland(wayland::EventLoop), #[cfg(feature = "x11")] X(x11::EventLoop), + #[cfg(feature = "kmsdrm")] + Drm(drm::EventLoop), } pub enum EventLoopProxy { @@ -608,11 +700,13 @@ pub enum EventLoopProxy { X(x11::EventLoopProxy), #[cfg(feature = "wayland")] Wayland(wayland::EventLoopProxy), + #[cfg(feature = "kmsdrm")] + Drm(drm::EventLoopProxy), } impl Clone for EventLoopProxy { fn clone(&self) -> Self { - x11_or_wayland!(match self; EventLoopProxy(proxy) => proxy.clone(); as EventLoopProxy) + x11_or_wayland_or_drm!(match self; EventLoopProxy(proxy) => proxy.clone(); as EventLoopProxy) } } @@ -639,6 +733,12 @@ impl EventLoop { return EventLoop::new_wayland_any_thread().expect("failed to open Wayland connection"); } + #[cfg(feature = "kmsdrm")] + if attributes.forced_backend == Some(Backend::Drm) { + // TODO: Propagate + return EventLoop::new_drm_any_thread().expect("failed to open drm connection"); + } + if let Ok(env_var) = env::var(BACKEND_PREFERENCE_ENV_VAR) { match env_var.as_str() { "x11" => { @@ -656,6 +756,13 @@ impl EventLoop { #[cfg(not(feature = "wayland"))] panic!("wayland feature is not enabled"); } + "drm" | "kmsdrm" | "gbm" | "tty" => { + #[cfg(feature = "kmsdrm")] + return EventLoop::new_drm_any_thread() + .expect("Failed to initialize drm backend"); + #[cfg(not(feature = "kmsdrm"))] + panic!("kmsdrm feature is not enabled"); + } _ => panic!( "Unknown environment variable value for {}, try one of `x11`,`wayland`", BACKEND_PREFERENCE_ENV_VAR, @@ -675,14 +782,22 @@ impl EventLoop { Err(err) => err, }; + #[cfg(feature = "kmsdrm")] + let drm_err = match EventLoop::new_drm_any_thread() { + Ok(event_loop) => return event_loop, + Err(err) => err, + }; + #[cfg(not(feature = "wayland"))] let wayland_err = "backend disabled"; #[cfg(not(feature = "x11"))] let x11_err = "backend disabled"; + #[cfg(not(feature = "kmsdrm"))] + let drm_err = "backend disabled"; panic!( - "Failed to initialize any backend! Wayland status: {:?} X11 status: {:?}", - wayland_err, x11_err, + "Failed to initialize any backend! Wayland status: {:?} X11 status: {:?} DRM status: {:?}", + wayland_err, x11_err, drm_err ); } @@ -701,32 +816,37 @@ impl EventLoop { Ok(EventLoop::X(x11::EventLoop::new(xconn))) } + #[cfg(feature = "kmsdrm")] + fn new_drm_any_thread() -> Result, ()> { + drm::EventLoop::new().map(EventLoop::Drm) + } + pub fn create_proxy(&self) -> EventLoopProxy { - x11_or_wayland!(match self; EventLoop(evlp) => evlp.create_proxy(); as EventLoopProxy) + x11_or_wayland_or_drm!(match self; EventLoop(evlp) => evlp.create_proxy(); as EventLoopProxy) } pub fn run_return(&mut self, callback: F) -> i32 where F: FnMut(crate::event::Event<'_, T>, &RootELW, &mut ControlFlow), { - x11_or_wayland!(match self; EventLoop(evlp) => evlp.run_return(callback)) + x11_or_wayland_or_drm!(match self; EventLoop(evlp) => evlp.run_return(callback)) } pub fn run(self, callback: F) -> ! where F: 'static + FnMut(crate::event::Event<'_, T>, &RootELW, &mut ControlFlow), { - x11_or_wayland!(match self; EventLoop(evlp) => evlp.run(callback)) + x11_or_wayland_or_drm!(match self; EventLoop(evlp) => evlp.run(callback)) } pub fn window_target(&self) -> &crate::event_loop::EventLoopWindowTarget { - x11_or_wayland!(match self; EventLoop(evl) => evl.window_target()) + x11_or_wayland_or_drm!(match self; EventLoop(evl) => evl.window_target()) } } impl EventLoopProxy { pub fn send_event(&self, event: T) -> Result<(), EventLoopClosed> { - x11_or_wayland!(match self; EventLoopProxy(proxy) => proxy.send_event(event)) + x11_or_wayland_or_drm!(match self; EventLoopProxy(proxy) => proxy.send_event(event)) } } @@ -735,6 +855,8 @@ pub enum EventLoopWindowTarget { Wayland(wayland::EventLoopWindowTarget), #[cfg(feature = "x11")] X(x11::EventLoopWindowTarget), + #[cfg(feature = "kmsdrm")] + Drm(drm::EventLoopWindowTarget), } impl EventLoopWindowTarget { @@ -743,7 +865,27 @@ impl EventLoopWindowTarget { match *self { #[cfg(feature = "wayland")] EventLoopWindowTarget::Wayland(_) => true, + #[cfg(any(feature = "x11", feature = "kmsdrm"))] + _ => false, + } + } + + #[inline] + pub fn is_x11(&self) -> bool { + match *self { #[cfg(feature = "x11")] + EventLoopWindowTarget::X(_) => true, + #[cfg(any(feature = "kmsdrm", feature = "wayland"))] + _ => false, + } + } + + #[inline] + pub fn is_drm(&self) -> bool { + match *self { + #[cfg(feature = "kmsdrm")] + EventLoopWindowTarget::Drm(_) => true, + #[cfg(any(feature = "x11", feature = "wayland"))] _ => false, } } @@ -764,6 +906,12 @@ impl EventLoopWindowTarget { .into_iter() .map(MonitorHandle::X) .collect(), + #[cfg(feature = "kmsdrm")] + EventLoopWindowTarget::Drm(ref evlp) => evlp + .available_monitors() + .into_iter() + .map(MonitorHandle::Drm) + .collect(), } } @@ -779,6 +927,8 @@ impl EventLoopWindowTarget { inner: primary_monitor, }) } + #[cfg(feature = "kmsdrm")] + EventLoopWindowTarget::Drm(ref evlp) => evlp.primary_monitor(), } } } diff --git a/src/platform_impl/linux/wayland/event_loop/mod.rs b/src/platform_impl/linux/wayland/event_loop/mod.rs index 0a69365b60..05aac6a186 100644 --- a/src/platform_impl/linux/wayland/event_loop/mod.rs +++ b/src/platform_impl/linux/wayland/event_loop/mod.rs @@ -10,8 +10,6 @@ use sctk::reexports::client::protocol::wl_compositor::WlCompositor; use sctk::reexports::client::protocol::wl_shm::WlShm; use sctk::reexports::client::Display; -use sctk::reexports::calloop; - use sctk::environment::Environment; use sctk::seat::pointer::{ThemeManager, ThemeSpec}; use sctk::WaylandSource; @@ -250,7 +248,7 @@ impl EventLoop { PlatformEventLoopWindowTarget::Wayland(window_target) => { window_target.state.get_mut() } - #[cfg(feature = "x11")] + #[cfg(any(feature = "x11", feature = "kmsdrm"))] _ => unreachable!(), }; @@ -539,7 +537,7 @@ impl EventLoop { fn with_window_target) -> U>(&mut self, f: F) -> U { let state = match &mut self.window_target.p { PlatformEventLoopWindowTarget::Wayland(window_target) => window_target, - #[cfg(feature = "x11")] + #[cfg(any(feature = "x11", feature = "kmsdrm"))] _ => unreachable!(), }; @@ -549,7 +547,7 @@ impl EventLoop { fn loop_dispatch>>(&mut self, timeout: D) -> IOResult<()> { let state = match &mut self.window_target.p { PlatformEventLoopWindowTarget::Wayland(window_target) => window_target.state.get_mut(), - #[cfg(feature = "x11")] + #[cfg(any(feature = "x11", feature = "kmsdrm"))] _ => unreachable!(), }; diff --git a/src/platform_impl/linux/wayland/event_loop/proxy.rs b/src/platform_impl/linux/wayland/event_loop/proxy.rs index dad64ef2c9..0abd8cd7ca 100644 --- a/src/platform_impl/linux/wayland/event_loop/proxy.rs +++ b/src/platform_impl/linux/wayland/event_loop/proxy.rs @@ -2,7 +2,7 @@ use std::sync::mpsc::SendError; -use sctk::reexports::calloop::channel::Sender; +use calloop::channel::Sender; use crate::event_loop::EventLoopClosed; diff --git a/src/platform_impl/linux/wayland/seat/keyboard/mod.rs b/src/platform_impl/linux/wayland/seat/keyboard/mod.rs index c6e0ad456e..368906a8cc 100644 --- a/src/platform_impl/linux/wayland/seat/keyboard/mod.rs +++ b/src/platform_impl/linux/wayland/seat/keyboard/mod.rs @@ -7,7 +7,7 @@ use sctk::reexports::client::protocol::wl_keyboard::WlKeyboard; use sctk::reexports::client::protocol::wl_seat::WlSeat; use sctk::reexports::client::Attached; -use sctk::reexports::calloop::{LoopHandle, RegistrationToken}; +use calloop::{LoopHandle, RegistrationToken}; use sctk::seat::keyboard; diff --git a/src/platform_impl/linux/wayland/seat/mod.rs b/src/platform_impl/linux/wayland/seat/mod.rs index 2d7b7533d0..68c0cad27b 100644 --- a/src/platform_impl/linux/wayland/seat/mod.rs +++ b/src/platform_impl/linux/wayland/seat/mod.rs @@ -10,8 +10,8 @@ use sctk::reexports::protocols::unstable::text_input::v3::client::zwp_text_input use sctk::reexports::client::protocol::wl_seat::WlSeat; use sctk::reexports::client::Attached; +use calloop::LoopHandle; use sctk::environment::Environment; -use sctk::reexports::calloop::LoopHandle; use sctk::seat::pointer::ThemeManager; use sctk::seat::{SeatData, SeatListener}; diff --git a/src/platform_impl/linux/wayland/window/mod.rs b/src/platform_impl/linux/wayland/window/mod.rs index 4cff918f3e..36cac4aea0 100644 --- a/src/platform_impl/linux/wayland/window/mod.rs +++ b/src/platform_impl/linux/wayland/window/mod.rs @@ -5,8 +5,6 @@ use std::sync::{Arc, Mutex}; use sctk::reexports::client::protocol::wl_surface::WlSurface; use sctk::reexports::client::Display; -use sctk::reexports::calloop; - use raw_window_handle::WaylandHandle; use sctk::window::{Decorations, FallbackFrame}; @@ -181,6 +179,8 @@ impl Window { PlatformMonitorHandle::Wayland(monitor) => Some(monitor.proxy), #[cfg(feature = "x11")] PlatformMonitorHandle::X(_) => None, + #[cfg(feature = "kmsdrm")] + PlatformMonitorHandle::Drm(_) => None, }); window.set_fullscreen(monitor.as_ref()); @@ -426,6 +426,8 @@ impl Window { PlatformMonitorHandle::Wayland(monitor) => Some(monitor.proxy), #[cfg(feature = "x11")] PlatformMonitorHandle::X(_) => None, + #[cfg(feature = "kmsdrm")] + PlatformMonitorHandle::Drm(_) => None, }); WindowRequest::Fullscreen(monitor) From 2f8537ec41b8acbf0d4ff2f57d7ac9e8fa1605d1 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Thu, 28 Apr 2022 21:47:37 -0400 Subject: [PATCH 002/151] Add to CHANGELOG --- CHANGELOG.md | 1311 +++++++++++++++++++++++++------------------------- 1 file changed, 656 insertions(+), 655 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 760439ab2f..ec5f2fe5c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,787 +8,788 @@ And please only add new entries to the top of this list, right below the `# Unre # Unreleased -- On macOS, Windows, and Wayland, add `set_cursor_hittest` to let the window ignore mouse events. -- On Windows, added `WindowExtWindows::set_skip_taskbar` and `WindowBuilderExtWindows::with_skip_taskbar`. -- On Windows, added `EventLoopBuilderExtWindows::with_msg_hook`. -- On Windows, remove internally unique DC per window. -- On macOS, remove the need to call `set_ime_position` after moving the window. -- Added `Window::is_visible`. -- Added `Window::is_resizable`. -- Added `Window::is_decorated`. -- On X11, fix for repeated event loop iteration when `ControlFlow` was `Wait` -- On X11, fix scale factor calculation when the only monitor is reconnected -- On Wayland, report unaccelerated mouse deltas in `DeviceEvent::MouseMotion`. -- **Breaking:** Bump `ndk` version to 0.6, ndk-sys to `v0.3`, `ndk-glue` to `0.6`. -- Remove no longer needed `WINIT_LINK_COLORSYNC` environment variable. -- **Breaking:** Rename the `Exit` variant of `ControlFlow` to `ExitWithCode`, which holds a value to control the exit code after running. Add an `Exit` constant which aliases to `ExitWithCode(0)` instead to avoid major breakage. This shouldn't affect most existing programs. -- Add `EventLoopBuilder`, which allows you to create and tweak the settings of an event loop before creating it. -- Deprecated `EventLoop::with_user_event`; use `EventLoopBuilder::with_user_event` instead. -- **Breaking:** Replaced `EventLoopExtMacOS` with `EventLoopBuilderExtMacOS` (which also has renamed methods). -- **Breaking:** Replaced `EventLoopExtWindows` with `EventLoopBuilderExtWindows` (which also has renamed methods). -- **Breaking:** Replaced `EventLoopExtUnix` with `EventLoopBuilderExtUnix` (which also has renamed methods). -- **Breaking:** The platform specific extensions for Windows `winit::platform::windows` have changed. All `HANDLE`-like types e.g. `HWND` and `HMENU` were converted from winapi types or `*mut c_void` to `isize`. This was done to be consistent with the type definitions in windows-sys and to not expose internal dependencies. -- The internal bindings to the [Windows API](https://docs.microsoft.com/en-us/windows/) were changed from the unofficial [winapi](https://github.com/retep998/winapi-rs) bindings to the official Microsoft [windows-sys](https://github.com/microsoft/windows-rs) bindings. -- On Wayland, fix resize and scale factor changes not being propagated properly. -- On Wayland, fix polling during consecutive `EventLoop::run_return` invocations. -- On Windows, fix race issue creating fullscreen windows with `WindowBuilder::with_fullscreen` -- On Android, `virtual_keycode` for `KeyboardInput` events is now filled in where a suitable match is found. -- Added helper methods on `ControlFlow` to set its value. -- On Wayland, fix `TouchPhase::Ended` always reporting the location of the first touch down, unless the compositor - sent a cancel or frame event. -- On iOS, send `RedrawEventsCleared` even if there are no redraw events, consistent with other platforms. -- **Breaking:** Replaced `Window::with_app_id` and `Window::with_class` with `Window::with_name` on `WindowBuilderExtUnix`. -- On Wayland and X11, fix window not resizing with `Window::set_inner_size` after calling `Window:set_resizable(false)`. +* On Linux kmsdrm support is being worked on +* On macOS, Windows, and Wayland, add `set_cursor_hittest` to let the window ignore mouse events. +* On Windows, added `WindowExtWindows::set_skip_taskbar` and `WindowBuilderExtWindows::with_skip_taskbar`. +* On Windows, added `EventLoopBuilderExtWindows::with_msg_hook`. +* On Windows, remove internally unique DC per window. +* On macOS, remove the need to call `set_ime_position` after moving the window. +* Added `Window::is_visible`. +* Added `Window::is_resizable`. +* Added `Window::is_decorated`. +* On X11, fix for repeated event loop iteration when `ControlFlow` was `Wait` +* On X11, fix scale factor calculation when the only monitor is reconnected +* On Wayland, report unaccelerated mouse deltas in `DeviceEvent::MouseMotion`. +* **Breaking:** Bump `ndk` version to 0.6, ndk-sys to `v0.3`, `ndk-glue` to `0.6`. +* Remove no longer needed `WINIT_LINK_COLORSYNC` environment variable. +* **Breaking:** Rename the `Exit` variant of `ControlFlow` to `ExitWithCode`, which holds a value to control the exit code after running. Add an `Exit` constant which aliases to `ExitWithCode(0)` instead to avoid major breakage. This shouldn't affect most existing programs. +* Add `EventLoopBuilder`, which allows you to create and tweak the settings of an event loop before creating it. +* Deprecated `EventLoop::with_user_event`; use `EventLoopBuilder::with_user_event` instead. +* **Breaking:** Replaced `EventLoopExtMacOS` with `EventLoopBuilderExtMacOS` (which also has renamed methods). +* **Breaking:** Replaced `EventLoopExtWindows` with `EventLoopBuilderExtWindows` (which also has renamed methods). +* **Breaking:** Replaced `EventLoopExtUnix` with `EventLoopBuilderExtUnix` (which also has renamed methods). +* **Breaking:** The platform specific extensions for Windows `winit::platform::windows` have changed. All `HANDLE`-like types e.g. `HWND` and `HMENU` were converted from winapi types or `*mut c_void` to `isize`. This was done to be consistent with the type definitions in windows-sys and to not expose internal dependencies. +* The internal bindings to the [Windows API](https://docs.microsoft.com/en-us/windows/) were changed from the unofficial [winapi](https://github.com/retep998/winapi-rs) bindings to the official Microsoft [windows-sys](https://github.com/microsoft/windows-rs) bindings. +* On Wayland, fix resize and scale factor changes not being propagated properly. +* On Wayland, fix polling during consecutive `EventLoop::run_return` invocations. +* On Windows, fix race issue creating fullscreen windows with `WindowBuilder::with_fullscreen` +* On Android, `virtual_keycode` for `KeyboardInput` events is now filled in where a suitable match is found. +* Added helper methods on `ControlFlow` to set its value. +* On Wayland, fix `TouchPhase::Ended` always reporting the location of the first touch down, unless the compositor + sent a cancel or frame event. +* On iOS, send `RedrawEventsCleared` even if there are no redraw events, consistent with other platforms. +* **Breaking:** Replaced `Window::with_app_id` and `Window::with_class` with `Window::with_name` on `WindowBuilderExtUnix`. +* On Wayland and X11, fix window not resizing with `Window::set_inner_size` after calling `Window:set_resizable(false)`. # 0.26.1 (2022-01-05) -- Fix linking to the `ColorSync` framework on macOS 10.7, and in newer Rust versions. -- On Web, implement cursor grabbing through the pointer lock API. -- On X11, add mappings for numpad comma, numpad enter, numlock and pause. -- On macOS, fix Pinyin IME input by reverting a change that intended to improve IME. -- On Windows, fix a crash with transparent windows on Windows 11. -- **Breaking:**: Reverse horizontal scrolling sign in `MouseScrollDelta` to match the direction of vertical scrolling. A positive X value now means moving the content to the right. The meaning of vertical scrolling stays the same: a positive Y value means moving the content down. +* Fix linking to the `ColorSync` framework on macOS 10.7, and in newer Rust versions. +* On Web, implement cursor grabbing through the pointer lock API. +* On X11, add mappings for numpad comma, numpad enter, numlock and pause. +* On macOS, fix Pinyin IME input by reverting a change that intended to improve IME. +* On Windows, fix a crash with transparent windows on Windows 11. +* **Breaking:**: Reverse horizontal scrolling sign in `MouseScrollDelta` to match the direction of vertical scrolling. A positive X value now means moving the content to the right. The meaning of vertical scrolling stays the same: a positive Y value means moving the content down. # 0.26.0 (2021-12-01) -- Update `raw-window-handle` to `v0.4`. This is _not_ a breaking change, we still implement `HasRawWindowHandle` from `v0.3`, see [rust-windowing/raw-window-handle#74](https://github.com/rust-windowing/raw-window-handle/pull/74). Note that you might have to run `cargo update -p raw-window-handle` after upgrading. -- On X11, bump `mio` to 0.8. -- On Android, fixed `WindowExtAndroid::config` initially returning an empty `Configuration`. -- On Android, fixed `Window::scale_factor` and `MonitorHandle::scale_factor` initially always returning 1.0. -- On X11, select an appropriate visual for transparency if is requested -- On Wayland and X11, fix diagonal window resize cursor orientation. -- On macOS, drop the event callback before exiting. -- On Android, implement `Window::request_redraw` -- **Breaking:** On Web, remove the `stdweb` backend. -- Added `Window::focus_window`to bring the window to the front and set input focus. -- On Wayland and X11, implement `is_maximized` method on `Window`. -- On Windows, prevent ghost window from showing up in the taskbar after either several hours of use or restarting `explorer.exe`. -- On macOS, fix issue where `ReceivedCharacter` was not being emitted during some key repeat events. -- On Wayland, load cursor icons `hand2` and `hand1` for `CursorIcon::Hand`. -- **Breaking:** On Wayland, Theme trait and its support types are dropped. -- On Wayland, bump `smithay-client-toolkit` to 0.15.1. -- On Wayland, implement `request_user_attention` with `xdg_activation_v1`. -- On X11, emit missing `WindowEvent::ScaleFactorChanged` when the only monitor gets reconnected. -- On X11, if RANDR based scale factor is higher than 20 reset it to 1 -- On Wayland, add an enabled-by-default feature called `wayland-dlopen` so users can opt out of using `dlopen` to load system libraries. -- **Breaking:** On Android, bump `ndk` and `ndk-glue` to 0.5. -- On Windows, increase wait timer resolution for more accurate timing when using `WaitUntil`. -- On macOS, fix native file dialogs hanging the event loop. -- On Wayland, implement a workaround for wrong configure size when using `xdg_decoration` in `kwin_wayland` -- On macOS, fix an issue that prevented the menu bar from showing in borderless fullscreen mode. -- On X11, EINTR while polling for events no longer causes a panic. Instead it will be treated as a spurious wakeup. +* Update `raw-window-handle` to `v0.4`. This is *not* a breaking change, we still implement `HasRawWindowHandle` from `v0.3`, see [rust-windowing/raw-window-handle#74](https://github.com/rust-windowing/raw-window-handle/pull/74). Note that you might have to run `cargo update -p raw-window-handle` after upgrading. +* On X11, bump `mio` to 0.8. +* On Android, fixed `WindowExtAndroid::config` initially returning an empty `Configuration`. +* On Android, fixed `Window::scale_factor` and `MonitorHandle::scale_factor` initially always returning 1.0. +* On X11, select an appropriate visual for transparency if is requested +* On Wayland and X11, fix diagonal window resize cursor orientation. +* On macOS, drop the event callback before exiting. +* On Android, implement `Window::request_redraw` +* **Breaking:** On Web, remove the `stdweb` backend. +* Added `Window::focus_window`to bring the window to the front and set input focus. +* On Wayland and X11, implement `is_maximized` method on `Window`. +* On Windows, prevent ghost window from showing up in the taskbar after either several hours of use or restarting `explorer.exe`. +* On macOS, fix issue where `ReceivedCharacter` was not being emitted during some key repeat events. +* On Wayland, load cursor icons `hand2` and `hand1` for `CursorIcon::Hand`. +* **Breaking:** On Wayland, Theme trait and its support types are dropped. +* On Wayland, bump `smithay-client-toolkit` to 0.15.1. +* On Wayland, implement `request_user_attention` with `xdg_activation_v1`. +* On X11, emit missing `WindowEvent::ScaleFactorChanged` when the only monitor gets reconnected. +* On X11, if RANDR based scale factor is higher than 20 reset it to 1 +* On Wayland, add an enabled-by-default feature called `wayland-dlopen` so users can opt out of using `dlopen` to load system libraries. +* **Breaking:** On Android, bump `ndk` and `ndk-glue` to 0.5. +* On Windows, increase wait timer resolution for more accurate timing when using `WaitUntil`. +* On macOS, fix native file dialogs hanging the event loop. +* On Wayland, implement a workaround for wrong configure size when using `xdg_decoration` in `kwin_wayland` +* On macOS, fix an issue that prevented the menu bar from showing in borderless fullscreen mode. +* On X11, EINTR while polling for events no longer causes a panic. Instead it will be treated as a spurious wakeup. # 0.25.0 (2021-05-15) -- **Breaking:** On macOS, replace `WindowBuilderExtMacOS::with_activation_policy` with `EventLoopExtMacOS::set_activation_policy` -- On macOS, wait with activating the application until the application has initialized. -- On macOS, fix creating new windows when the application has a main menu. -- On Windows, fix fractional deltas for mouse wheel device events. -- On macOS, fix segmentation fault after dropping the main window. -- On Android, `InputEvent::KeyEvent` is partially implemented providing the key scancode. -- Added `is_maximized` method to `Window`. -- On Windows, fix bug where clicking the decoration bar would make the cursor blink. -- On Windows, fix bug causing newly created windows to erroneously display the "wait" (spinning) cursor. -- On macOS, wake up the event loop immediately when a redraw is requested. -- On Windows, change the default window size (1024x768) to match the default on other desktop platforms (800x600). -- On Windows, fix bug causing mouse capture to not be released. -- On Windows, fix fullscreen not preserving minimized/maximized state. -- On Android, unimplemented events are marked as unhandled on the native event loop. -- On Windows, added `WindowBuilderExtWindows::with_menu` to set a custom menu at window creation time. -- On Android, bump `ndk` and `ndk-glue` to 0.3: use predefined constants for event `ident`. -- On macOS, fix objects captured by the event loop closure not being dropped on panic. -- On Windows, fixed `WindowEvent::ThemeChanged` not properly firing and fixed `Window::theme` returning the wrong theme. -- On Web, added support for `DeviceEvent::MouseMotion` to listen for relative mouse movements. -- Added `WindowBuilder::with_position` to allow setting the position of a `Window` on creation. Supported on Windows, macOS and X11. -- Added `Window::drag_window`. Implemented on Windows, macOS, X11 and Wayland. -- On X11, bump `mio` to 0.7. -- On Windows, added `WindowBuilderExtWindows::with_owner_window` to allow creating popup windows. -- On Windows, added `WindowExtWindows::set_enable` to allow creating modal popup windows. -- On macOS, emit `RedrawRequested` events immediately while the window is being resized. -- Implement `Default`, `Hash`, and `Eq` for `LogicalPosition`, `PhysicalPosition`, `LogicalSize`, and `PhysicalSize`. -- On macOS, initialize the Menu Bar with minimal defaults. (Can be prevented using `enable_default_menu_creation`) -- On macOS, change the default behavior for first click when the window was unfocused. Now the window becomes focused and then emits a `MouseInput` event on a "first mouse click". -- Implement mint (math interoperability standard types) conversions (under feature flag `mint`). +* **Breaking:** On macOS, replace `WindowBuilderExtMacOS::with_activation_policy` with `EventLoopExtMacOS::set_activation_policy` +* On macOS, wait with activating the application until the application has initialized. +* On macOS, fix creating new windows when the application has a main menu. +* On Windows, fix fractional deltas for mouse wheel device events. +* On macOS, fix segmentation fault after dropping the main window. +* On Android, `InputEvent::KeyEvent` is partially implemented providing the key scancode. +* Added `is_maximized` method to `Window`. +* On Windows, fix bug where clicking the decoration bar would make the cursor blink. +* On Windows, fix bug causing newly created windows to erroneously display the "wait" (spinning) cursor. +* On macOS, wake up the event loop immediately when a redraw is requested. +* On Windows, change the default window size (1024x768) to match the default on other desktop platforms (800x600). +* On Windows, fix bug causing mouse capture to not be released. +* On Windows, fix fullscreen not preserving minimized/maximized state. +* On Android, unimplemented events are marked as unhandled on the native event loop. +* On Windows, added `WindowBuilderExtWindows::with_menu` to set a custom menu at window creation time. +* On Android, bump `ndk` and `ndk-glue` to 0.3: use predefined constants for event `ident`. +* On macOS, fix objects captured by the event loop closure not being dropped on panic. +* On Windows, fixed `WindowEvent::ThemeChanged` not properly firing and fixed `Window::theme` returning the wrong theme. +* On Web, added support for `DeviceEvent::MouseMotion` to listen for relative mouse movements. +* Added `WindowBuilder::with_position` to allow setting the position of a `Window` on creation. Supported on Windows, macOS and X11. +* Added `Window::drag_window`. Implemented on Windows, macOS, X11 and Wayland. +* On X11, bump `mio` to 0.7. +* On Windows, added `WindowBuilderExtWindows::with_owner_window` to allow creating popup windows. +* On Windows, added `WindowExtWindows::set_enable` to allow creating modal popup windows. +* On macOS, emit `RedrawRequested` events immediately while the window is being resized. +* Implement `Default`, `Hash`, and `Eq` for `LogicalPosition`, `PhysicalPosition`, `LogicalSize`, and `PhysicalSize`. +* On macOS, initialize the Menu Bar with minimal defaults. (Can be prevented using `enable_default_menu_creation`) +* On macOS, change the default behavior for first click when the window was unfocused. Now the window becomes focused and then emits a `MouseInput` event on a "first mouse click". +* Implement mint (math interoperability standard types) conversions (under feature flag `mint`). # 0.24.0 (2020-12-09) -- On Windows, fix applications not exiting gracefully due to thread_event_target_callback accessing corrupted memory. -- On Windows, implement `Window::set_ime_position`. -- **Breaking:** On Windows, Renamed `WindowBuilderExtWindows`'s `is_dark_mode` to `theme`. -- **Breaking:** On Windows, renamed `WindowBuilderExtWindows::is_dark_mode` to `theme`. -- On Windows, add `WindowBuilderExtWindows::with_theme` to set a preferred theme. -- On Windows, fix bug causing message boxes to appear delayed. -- On Android, calling `WindowEvent::Focused` now works properly instead of always returning false. -- On Windows, fix Alt-Tab behaviour by removing borderless fullscreen "always on top" flag. -- On Windows, fix bug preventing windows with transparency enabled from having fully-opaque regions. -- **Breaking:** On Windows, include prefix byte in scancodes. -- On Wayland, fix window not being resizeable when using `WindowBuilder::with_min_inner_size`. -- On Unix, fix cross-compiling to wasm32 without enabling X11 or Wayland. -- On Windows, fix use-after-free crash during window destruction. -- On Web, fix `WindowEvent::ReceivedCharacter` never being sent on key input. -- On macOS, fix compilation when targeting aarch64. -- On X11, fix `Window::request_redraw` not waking the event loop. -- On Wayland, the keypad arrow keys are now recognized. -- **Breaking** Rename `desktop::EventLoopExtDesktop` to `run_return::EventLoopExtRunReturn`. -- Added `request_user_attention` method to `Window`. -- **Breaking:** On macOS, removed `WindowExt::request_user_attention`, use `Window::request_user_attention`. -- **Breaking:** On X11, removed `WindowExt::set_urgent`, use `Window::request_user_attention`. -- On Wayland, default font size in CSD increased from 11 to 17. -- On Windows, fix bug causing message boxes to appear delayed. -- On Android, support multi-touch. -- On Wayland, extra mouse buttons are not dropped anymore. -- **Breaking**: `MouseButton::Other` now uses `u16`. +* On Windows, fix applications not exiting gracefully due to thread_event_target_callback accessing corrupted memory. +* On Windows, implement `Window::set_ime_position`. +* **Breaking:** On Windows, Renamed `WindowBuilderExtWindows`'s `is_dark_mode` to `theme`. +* **Breaking:** On Windows, renamed `WindowBuilderExtWindows::is_dark_mode` to `theme`. +* On Windows, add `WindowBuilderExtWindows::with_theme` to set a preferred theme. +* On Windows, fix bug causing message boxes to appear delayed. +* On Android, calling `WindowEvent::Focused` now works properly instead of always returning false. +* On Windows, fix Alt-Tab behaviour by removing borderless fullscreen "always on top" flag. +* On Windows, fix bug preventing windows with transparency enabled from having fully-opaque regions. +* **Breaking:** On Windows, include prefix byte in scancodes. +* On Wayland, fix window not being resizeable when using `WindowBuilder::with_min_inner_size`. +* On Unix, fix cross-compiling to wasm32 without enabling X11 or Wayland. +* On Windows, fix use-after-free crash during window destruction. +* On Web, fix `WindowEvent::ReceivedCharacter` never being sent on key input. +* On macOS, fix compilation when targeting aarch64. +* On X11, fix `Window::request_redraw` not waking the event loop. +* On Wayland, the keypad arrow keys are now recognized. +* **Breaking** Rename `desktop::EventLoopExtDesktop` to `run_return::EventLoopExtRunReturn`. +* Added `request_user_attention` method to `Window`. +* **Breaking:** On macOS, removed `WindowExt::request_user_attention`, use `Window::request_user_attention`. +* **Breaking:** On X11, removed `WindowExt::set_urgent`, use `Window::request_user_attention`. +* On Wayland, default font size in CSD increased from 11 to 17. +* On Windows, fix bug causing message boxes to appear delayed. +* On Android, support multi-touch. +* On Wayland, extra mouse buttons are not dropped anymore. +* **Breaking**: `MouseButton::Other` now uses `u16`. # 0.23.0 (2020-10-02) -- On iOS, fixed support for the "Debug View Heirarchy" feature in Xcode. -- On all platforms, `available_monitors` and `primary_monitor` are now on `EventLoopWindowTarget` rather than `EventLoop` to list monitors event in the event loop. -- On Unix, X11 and Wayland are now optional features (enabled by default) -- On X11, fix deadlock when calling `set_fullscreen_inner`. -- On Web, prevent the webpage from scrolling when the user is focused on a winit canvas -- On Web, calling `window.set_cursor_icon` no longer breaks HiDPI scaling -- On Windows, drag and drop is now optional (enabled by default) and can be disabled with `WindowBuilderExtWindows::with_drag_and_drop(false)`. -- On Wayland, fix deadlock when calling to `set_inner_size` from a callback. -- On macOS, add `hide__other_applications` to `EventLoopWindowTarget` via existing `EventLoopWindowTargetExtMacOS` trait. `hide_other_applications` will hide other applications by calling `-[NSApplication hideOtherApplications: nil]`. -- On android added support for `run_return`. -- On MacOS, Fixed fullscreen and dialog support for `run_return`. -- On Windows, fix bug where we'd try to emit `MainEventsCleared` events during nested win32 event loops. -- On Web, use mouse events if pointer events aren't supported. This affects Safari. -- On Windows, `set_ime_position` is now a no-op instead of a runtime crash. -- On Android, `set_fullscreen` is now a no-op instead of a runtime crash. -- On iOS and Android, `set_inner_size` is now a no-op instead of a runtime crash. -- On Android, fix `ControlFlow::Poll` not polling the Android event queue. -- On macOS, add `NSWindow.hasShadow` support. -- On Web, fix vertical mouse wheel scrolling being inverted. -- On Web, implement mouse capturing for click-dragging out of the canvas. -- On Web, fix `ControlFlow::Exit` not properly handled. -- On Web (web-sys only), send `WindowEvent::ScaleFactorChanged` event when `window.devicePixelRatio` is changed. -- **Breaking:** On Web, `set_cursor_position` and `set_cursor_grab` will now always return an error. -- **Breaking:** `PixelDelta` scroll events now return a `PhysicalPosition`. -- On NetBSD, fixed crash due to incorrect detection of the main thread. -- **Breaking:** On X11, `-` key is mapped to the `Minus` virtual key code, instead of `Subtract`. -- On macOS, fix inverted horizontal scroll. -- **Breaking:** `current_monitor` now returns `Option`. -- **Breaking:** `primary_monitor` now returns `Option`. -- On macOS, updated core-* dependencies and cocoa. -- Bump `parking_lot` to 0.11 -- On Android, bump `ndk`, `ndk-sys` and `ndk-glue` to 0.2. Checkout the new ndk-glue main proc attribute. -- On iOS, fixed starting the app in landscape where the view still had portrait dimensions. -- Deprecate the stdweb backend, to be removed in a future release -- **Breaking:** Prefixed virtual key codes `Add`, `Multiply`, `Divide`, `Decimal`, and `Subtract` with `Numpad`. -- Added `Asterisk` and `Plus` virtual key codes. -- On Web (web-sys only), the `Event::LoopDestroyed` event is correctly emitted when leaving the page. -- On Web, the `WindowEvent::Destroyed` event now gets emitted when a `Window` is dropped. -- On Web (web-sys only), the event listeners are now removed when a `Window` is dropped or when the event loop is destroyed. -- On Web, the event handler closure passed to `EventLoop::run` now gets dropped after the event loop is destroyed. -- **Breaking:** On Web, the canvas element associated to a `Window` is no longer removed from the DOM when the `Window` is dropped. -- On Web, `WindowEvent::Resized` is now emitted when `Window::set_inner_size` is called. -- **Breaking:** `Fullscreen` enum now uses `Borderless(Option)` instead of `Borderless(MonitorHandle)` to allow picking the current monitor. -- On MacOS, fix `WindowEvent::Moved` ignoring the scale factor. -- On Wayland, add missing virtual keycodes. -- On Wayland, implement proper `set_cursor_grab`. -- On Wayland, the cursor will use similar icons if the requested one isn't available. -- On Wayland, right clicking on client side decorations will request application menu. -- On Wayland, fix tracking of window size after state changes. -- On Wayland, fix client side decorations not being hidden properly in fullscreen. -- On Wayland, fix incorrect size event when entering fullscreen with client side decorations. -- On Wayland, fix `resizable` attribute not being applied properly on startup. -- On Wayland, fix disabled repeat rate not being handled. -- On Wayland, fix decoration buttons not working after tty switch. -- On Wayland, fix scaling not being applied on output re-enable. -- On Wayland, fix crash when `XCURSOR_SIZE` is `0`. -- On Wayland, fix pointer getting created in some cases without pointer capability. -- On Wayland, on kwin, fix space between window and decorations on startup. -- **Breaking:** On Wayland, `Theme` trait was reworked. -- On Wayland, disable maximize button for non-resizable window. -- On Wayland, added support for `set_ime_position`. -- On Wayland, fix crash on startup since GNOME 3.37.90. -- On X11, fix incorrect modifiers state on startup. +* On iOS, fixed support for the "Debug View Heirarchy" feature in Xcode. +* On all platforms, `available_monitors` and `primary_monitor` are now on `EventLoopWindowTarget` rather than `EventLoop` to list monitors event in the event loop. +* On Unix, X11 and Wayland are now optional features (enabled by default) +* On X11, fix deadlock when calling `set_fullscreen_inner`. +* On Web, prevent the webpage from scrolling when the user is focused on a winit canvas +* On Web, calling `window.set_cursor_icon` no longer breaks HiDPI scaling +* On Windows, drag and drop is now optional (enabled by default) and can be disabled with `WindowBuilderExtWindows::with_drag_and_drop(false)`. +* On Wayland, fix deadlock when calling to `set_inner_size` from a callback. +* On macOS, add `hide__other_applications` to `EventLoopWindowTarget` via existing `EventLoopWindowTargetExtMacOS` trait. `hide_other_applications` will hide other applications by calling `-[NSApplication hideOtherApplications: nil]`. +* On android added support for `run_return`. +* On MacOS, Fixed fullscreen and dialog support for `run_return`. +* On Windows, fix bug where we'd try to emit `MainEventsCleared` events during nested win32 event loops. +* On Web, use mouse events if pointer events aren't supported. This affects Safari. +* On Windows, `set_ime_position` is now a no-op instead of a runtime crash. +* On Android, `set_fullscreen` is now a no-op instead of a runtime crash. +* On iOS and Android, `set_inner_size` is now a no-op instead of a runtime crash. +* On Android, fix `ControlFlow::Poll` not polling the Android event queue. +* On macOS, add `NSWindow.hasShadow` support. +* On Web, fix vertical mouse wheel scrolling being inverted. +* On Web, implement mouse capturing for click-dragging out of the canvas. +* On Web, fix `ControlFlow::Exit` not properly handled. +* On Web (web-sys only), send `WindowEvent::ScaleFactorChanged` event when `window.devicePixelRatio` is changed. +* **Breaking:** On Web, `set_cursor_position` and `set_cursor_grab` will now always return an error. +* **Breaking:** `PixelDelta` scroll events now return a `PhysicalPosition`. +* On NetBSD, fixed crash due to incorrect detection of the main thread. +* **Breaking:** On X11, `-` key is mapped to the `Minus` virtual key code, instead of `Subtract`. +* On macOS, fix inverted horizontal scroll. +* **Breaking:** `current_monitor` now returns `Option`. +* **Breaking:** `primary_monitor` now returns `Option`. +* On macOS, updated core-\* dependencies and cocoa. +* Bump `parking_lot` to 0.11 +* On Android, bump `ndk`, `ndk-sys` and `ndk-glue` to 0.2. Checkout the new ndk-glue main proc attribute. +* On iOS, fixed starting the app in landscape where the view still had portrait dimensions. +* Deprecate the stdweb backend, to be removed in a future release +* **Breaking:** Prefixed virtual key codes `Add`, `Multiply`, `Divide`, `Decimal`, and `Subtract` with `Numpad`. +* Added `Asterisk` and `Plus` virtual key codes. +* On Web (web-sys only), the `Event::LoopDestroyed` event is correctly emitted when leaving the page. +* On Web, the `WindowEvent::Destroyed` event now gets emitted when a `Window` is dropped. +* On Web (web-sys only), the event listeners are now removed when a `Window` is dropped or when the event loop is destroyed. +* On Web, the event handler closure passed to `EventLoop::run` now gets dropped after the event loop is destroyed. +* **Breaking:** On Web, the canvas element associated to a `Window` is no longer removed from the DOM when the `Window` is dropped. +* On Web, `WindowEvent::Resized` is now emitted when `Window::set_inner_size` is called. +* **Breaking:** `Fullscreen` enum now uses `Borderless(Option)` instead of `Borderless(MonitorHandle)` to allow picking the current monitor. +* On MacOS, fix `WindowEvent::Moved` ignoring the scale factor. +* On Wayland, add missing virtual keycodes. +* On Wayland, implement proper `set_cursor_grab`. +* On Wayland, the cursor will use similar icons if the requested one isn't available. +* On Wayland, right clicking on client side decorations will request application menu. +* On Wayland, fix tracking of window size after state changes. +* On Wayland, fix client side decorations not being hidden properly in fullscreen. +* On Wayland, fix incorrect size event when entering fullscreen with client side decorations. +* On Wayland, fix `resizable` attribute not being applied properly on startup. +* On Wayland, fix disabled repeat rate not being handled. +* On Wayland, fix decoration buttons not working after tty switch. +* On Wayland, fix scaling not being applied on output re-enable. +* On Wayland, fix crash when `XCURSOR_SIZE` is `0`. +* On Wayland, fix pointer getting created in some cases without pointer capability. +* On Wayland, on kwin, fix space between window and decorations on startup. +* **Breaking:** On Wayland, `Theme` trait was reworked. +* On Wayland, disable maximize button for non-resizable window. +* On Wayland, added support for `set_ime_position`. +* On Wayland, fix crash on startup since GNOME 3.37.90. +* On X11, fix incorrect modifiers state on startup. # 0.22.2 (2020-05-16) -- Added Clone implementation for 'static events. -- On Windows, fix window intermittently hanging when `ControlFlow` was set to `Poll`. -- On Windows, fix `WindowBuilder::with_maximized` being ignored. -- On Android, minimal platform support. -- On iOS, touch positions are now properly converted to physical pixels. -- On macOS, updated core-* dependencies and cocoa +* Added Clone implementation for 'static events. +* On Windows, fix window intermittently hanging when `ControlFlow` was set to `Poll`. +* On Windows, fix `WindowBuilder::with_maximized` being ignored. +* On Android, minimal platform support. +* On iOS, touch positions are now properly converted to physical pixels. +* On macOS, updated core-\* dependencies and cocoa # 0.22.1 (2020-04-16) -- On X11, fix `ResumeTimeReached` being fired too early. -- On Web, replaced zero timeout for `ControlFlow::Poll` with `requestAnimationFrame` -- On Web, fix a possible panic during event handling -- On macOS, fix `EventLoopProxy` leaking memory for every instance. +* On X11, fix `ResumeTimeReached` being fired too early. +* On Web, replaced zero timeout for `ControlFlow::Poll` with `requestAnimationFrame` +* On Web, fix a possible panic during event handling +* On macOS, fix `EventLoopProxy` leaking memory for every instance. # 0.22.0 (2020-03-09) -- On Windows, fix minor timing issue in wait_until_time_or_msg -- On Windows, rework handling of request_redraw() to address panics. -- On macOS, fix `set_simple_screen` to remember frame excluding title bar. -- On Wayland, fix coordinates in touch events when scale factor isn't 1. -- On Wayland, fix color from `close_button_icon_color` not applying. -- Ignore locale if unsupported by X11 backend -- On Wayland, Add HiDPI cursor support -- On Web, add the ability to query "Light" or "Dark" system theme send `ThemeChanged` on change. -- Fix `Event::to_static` returning `None` for user events. -- On Wayland, Hide CSD for fullscreen windows. -- On Windows, ignore spurious mouse move messages. -- **Breaking:** Move `ModifiersChanged` variant from `DeviceEvent` to `WindowEvent`. -- On Windows, add `IconExtWindows` trait which exposes creating an `Icon` from an external file or embedded resource -- Add `BadIcon::OsError` variant for when OS icon functionality fails -- On Windows, fix crash at startup on systems that do not properly support Windows' Dark Mode -- Revert On macOS, fix not sending ReceivedCharacter event for specific keys combinations. -- on macOS, fix incorrect ReceivedCharacter events for some key combinations. -- **Breaking:** Use `i32` instead of `u32` for position type in `WindowEvent::Moved`. -- On macOS, a mouse motion event is now generated before every mouse click. +* On Windows, fix minor timing issue in wait_until_time_or_msg +* On Windows, rework handling of request_redraw() to address panics. +* On macOS, fix `set_simple_screen` to remember frame excluding title bar. +* On Wayland, fix coordinates in touch events when scale factor isn't 1. +* On Wayland, fix color from `close_button_icon_color` not applying. +* Ignore locale if unsupported by X11 backend +* On Wayland, Add HiDPI cursor support +* On Web, add the ability to query "Light" or "Dark" system theme send `ThemeChanged` on change. +* Fix `Event::to_static` returning `None` for user events. +* On Wayland, Hide CSD for fullscreen windows. +* On Windows, ignore spurious mouse move messages. +* **Breaking:** Move `ModifiersChanged` variant from `DeviceEvent` to `WindowEvent`. +* On Windows, add `IconExtWindows` trait which exposes creating an `Icon` from an external file or embedded resource +* Add `BadIcon::OsError` variant for when OS icon functionality fails +* On Windows, fix crash at startup on systems that do not properly support Windows' Dark Mode +* Revert On macOS, fix not sending ReceivedCharacter event for specific keys combinations. +* on macOS, fix incorrect ReceivedCharacter events for some key combinations. +* **Breaking:** Use `i32` instead of `u32` for position type in `WindowEvent::Moved`. +* On macOS, a mouse motion event is now generated before every mouse click. # 0.21.0 (2020-02-04) -- On Windows, fixed "error: linking with `link.exe` failed: exit code: 1120" error on older versions of windows. -- On macOS, fix set_minimized(true) works only with decorations. -- On macOS, add `hide_application` to `EventLoopWindowTarget` via a new `EventLoopWindowTargetExtMacOS` trait. `hide_application` will hide the entire application by calling `-[NSApplication hide: nil]`. -- On macOS, fix not sending ReceivedCharacter event for specific keys combinations. -- On macOS, fix `CursorMoved` event reporting the cursor position using logical coordinates. -- On macOS, fix issue where unbundled applications would sometimes open without being focused. -- On macOS, fix `run_return` does not return unless it receives a message. -- On Windows, fix bug where `RedrawRequested` would only get emitted every other iteration of the event loop. -- On X11, fix deadlock on window state when handling certain window events. -- `WindowBuilder` now implements `Default`. -- **Breaking:** `WindowEvent::CursorMoved` changed to `f64` units, preserving high-precision data supplied by most backends -- On Wayland, fix coordinates in mouse events when scale factor isn't 1 -- On Web, add the ability to provide a custom canvas -- **Breaking:** On Wayland, the `WaylandTheme` struct has been replaced with a `Theme` trait, allowing for extra configuration +* On Windows, fixed "error: linking with `link.exe` failed: exit code: 1120" error on older versions of windows. +* On macOS, fix set_minimized(true) works only with decorations. +* On macOS, add `hide_application` to `EventLoopWindowTarget` via a new `EventLoopWindowTargetExtMacOS` trait. `hide_application` will hide the entire application by calling `-[NSApplication hide: nil]`. +* On macOS, fix not sending ReceivedCharacter event for specific keys combinations. +* On macOS, fix `CursorMoved` event reporting the cursor position using logical coordinates. +* On macOS, fix issue where unbundled applications would sometimes open without being focused. +* On macOS, fix `run_return` does not return unless it receives a message. +* On Windows, fix bug where `RedrawRequested` would only get emitted every other iteration of the event loop. +* On X11, fix deadlock on window state when handling certain window events. +* `WindowBuilder` now implements `Default`. +* **Breaking:** `WindowEvent::CursorMoved` changed to `f64` units, preserving high-precision data supplied by most backends +* On Wayland, fix coordinates in mouse events when scale factor isn't 1 +* On Web, add the ability to provide a custom canvas +* **Breaking:** On Wayland, the `WaylandTheme` struct has been replaced with a `Theme` trait, allowing for extra configuration # 0.20.0 (2020-01-05) -- On X11, fix `ModifiersChanged` emitting incorrect modifier change events -- **Breaking**: Overhaul how Winit handles DPI: - - Window functions and events now return `PhysicalSize` instead of `LogicalSize`. - - Functions that take `Size` or `Position` types can now take either `Logical` or `Physical` types. - - `hidpi_factor` has been renamed to `scale_factor`. - - `HiDpiFactorChanged` has been renamed to `ScaleFactorChanged`, and lets you control how the OS - resizes the window in response to the change. - - On X11, deprecate `WINIT_HIDPI_FACTOR` environment variable in favor of `WINIT_X11_SCALE_FACTOR`. - - `Size` and `Position` types are now generic over their exact pixel type. +* On X11, fix `ModifiersChanged` emitting incorrect modifier change events +* **Breaking**: Overhaul how Winit handles DPI: + * Window functions and events now return `PhysicalSize` instead of `LogicalSize`. + * Functions that take `Size` or `Position` types can now take either `Logical` or `Physical` types. + * `hidpi_factor` has been renamed to `scale_factor`. + * `HiDpiFactorChanged` has been renamed to `ScaleFactorChanged`, and lets you control how the OS + resizes the window in response to the change. + * On X11, deprecate `WINIT_HIDPI_FACTOR` environment variable in favor of `WINIT_X11_SCALE_FACTOR`. + * `Size` and `Position` types are now generic over their exact pixel type. # 0.20.0 Alpha 6 (2020-01-03) -- On macOS, fix `set_cursor_visible` hides cursor outside of window. -- On macOS, fix `CursorEntered` and `CursorLeft` events fired at old window size. -- On macOS, fix error when `set_fullscreen` is called during fullscreen transition. -- On all platforms except mobile and WASM, implement `Window::set_minimized`. -- On X11, fix `CursorEntered` event being generated for non-winit windows. -- On macOS, fix crash when starting maximized without decorations. -- On macOS, fix application not terminating on `run_return`. -- On Wayland, fix cursor icon updates on window borders when using CSD. -- On Wayland, under mutter(GNOME Wayland), fix CSD being behind the status bar, when starting window in maximized mode. -- On Windows, theme the title bar according to whether the system theme is "Light" or "Dark". -- Added `WindowEvent::ThemeChanged` variant to handle changes to the system theme. Currently only implemented on Windows. -- **Breaking**: Changes to the `RedrawRequested` event (#1041): - - `RedrawRequested` has been moved from `WindowEvent` to `Event`. - - `EventsCleared` has been renamed to `MainEventsCleared`. - - `RedrawRequested` is now issued only after `MainEventsCleared`. - - `RedrawEventsCleared` is issued after each set of `RedrawRequested` events. -- Implement synthetic window focus key events on Windows. -- **Breaking**: Change `ModifiersState` to a `bitflags` struct. -- On Windows, implement `VirtualKeyCode` translation for `LWin` and `RWin`. -- On Windows, fix closing the last opened window causing `DeviceEvent`s to stop getting emitted. -- On Windows, fix `Window::set_visible` not setting internal flags correctly. This resulted in some weird behavior. -- Add `DeviceEvent::ModifiersChanged`. - - Deprecate `modifiers` fields in other events in favor of `ModifiersChanged`. -- On X11, `WINIT_HIDPI_FACTOR` now dominates `Xft.dpi` when picking DPI factor for output. -- On X11, add special value `randr` for `WINIT_HIDPI_FACTOR` to make winit use self computed DPI factor instead of the one from `Xft.dpi`. +* On macOS, fix `set_cursor_visible` hides cursor outside of window. +* On macOS, fix `CursorEntered` and `CursorLeft` events fired at old window size. +* On macOS, fix error when `set_fullscreen` is called during fullscreen transition. +* On all platforms except mobile and WASM, implement `Window::set_minimized`. +* On X11, fix `CursorEntered` event being generated for non-winit windows. +* On macOS, fix crash when starting maximized without decorations. +* On macOS, fix application not terminating on `run_return`. +* On Wayland, fix cursor icon updates on window borders when using CSD. +* On Wayland, under mutter(GNOME Wayland), fix CSD being behind the status bar, when starting window in maximized mode. +* On Windows, theme the title bar according to whether the system theme is "Light" or "Dark". +* Added `WindowEvent::ThemeChanged` variant to handle changes to the system theme. Currently only implemented on Windows. +* **Breaking**: Changes to the `RedrawRequested` event (#1041): + * `RedrawRequested` has been moved from `WindowEvent` to `Event`. + * `EventsCleared` has been renamed to `MainEventsCleared`. + * `RedrawRequested` is now issued only after `MainEventsCleared`. + * `RedrawEventsCleared` is issued after each set of `RedrawRequested` events. +* Implement synthetic window focus key events on Windows. +* **Breaking**: Change `ModifiersState` to a `bitflags` struct. +* On Windows, implement `VirtualKeyCode` translation for `LWin` and `RWin`. +* On Windows, fix closing the last opened window causing `DeviceEvent`s to stop getting emitted. +* On Windows, fix `Window::set_visible` not setting internal flags correctly. This resulted in some weird behavior. +* Add `DeviceEvent::ModifiersChanged`. + * Deprecate `modifiers` fields in other events in favor of `ModifiersChanged`. +* On X11, `WINIT_HIDPI_FACTOR` now dominates `Xft.dpi` when picking DPI factor for output. +* On X11, add special value `randr` for `WINIT_HIDPI_FACTOR` to make winit use self computed DPI factor instead of the one from `Xft.dpi`. # 0.20.0 Alpha 5 (2019-12-09) -- On macOS, fix application termination on `ControlFlow::Exit` -- On Windows, fix missing `ReceivedCharacter` events when Alt is held. -- On macOS, stop emitting private corporate characters in `ReceivedCharacter` events. -- On X11, fix misreporting DPI factor at startup. -- On X11, fix events not being reported when using `run_return`. -- On X11, fix key modifiers being incorrectly reported. -- On X11, fix window creation hanging when another window is fullscreen. -- On Windows, fix focusing unfocused windows when switching from fullscreen to windowed. -- On X11, fix reporting incorrect DPI factor when waking from suspend. -- Change `EventLoopClosed` to contain the original event. -- **Breaking**: Add `is_synthetic` field to `WindowEvent` variant `KeyboardInput`, - indicating that the event is generated by winit. -- On X11, generate synthetic key events for keys held when a window gains or loses focus. -- On X11, issue a `CursorMoved` event when a `Touch` event occurs, - as X11 implicitly moves the cursor for such events. +* On macOS, fix application termination on `ControlFlow::Exit` +* On Windows, fix missing `ReceivedCharacter` events when Alt is held. +* On macOS, stop emitting private corporate characters in `ReceivedCharacter` events. +* On X11, fix misreporting DPI factor at startup. +* On X11, fix events not being reported when using `run_return`. +* On X11, fix key modifiers being incorrectly reported. +* On X11, fix window creation hanging when another window is fullscreen. +* On Windows, fix focusing unfocused windows when switching from fullscreen to windowed. +* On X11, fix reporting incorrect DPI factor when waking from suspend. +* Change `EventLoopClosed` to contain the original event. +* **Breaking**: Add `is_synthetic` field to `WindowEvent` variant `KeyboardInput`, + indicating that the event is generated by winit. +* On X11, generate synthetic key events for keys held when a window gains or loses focus. +* On X11, issue a `CursorMoved` event when a `Touch` event occurs, + as X11 implicitly moves the cursor for such events. # 0.20.0 Alpha 4 (2019-10-18) -- Add web support via the 'stdweb' or 'web-sys' features -- On Windows, implemented function to get HINSTANCE -- On macOS, implement `run_return`. -- On iOS, fix inverted parameter in `set_prefers_home_indicator_hidden`. -- On X11, performance is improved when rapidly calling `Window::set_cursor_icon`. -- On iOS, fix improper `msg_send` usage that was UB and/or would break if `!` is stabilized. -- On Windows, unset `maximized` when manually changing the window's position or size. -- On Windows, add touch pressure information for touch events. -- On macOS, differentiate between `CursorIcon::Grab` and `CursorIcon::Grabbing`. -- On Wayland, fix event processing sometimes stalling when using OpenGL with vsync. -- Officially remove the Emscripten backend. -- On Windows, fix handling of surrogate pairs when dispatching `ReceivedCharacter`. -- On macOS 10.15, fix freeze upon exiting exclusive fullscreen mode. -- On iOS, fix panic upon closing the app. -- On X11, allow setting mulitple `XWindowType`s. -- On iOS, fix null window on initial `HiDpiFactorChanged` event. -- On Windows, fix fullscreen window shrinking upon getting restored to a normal window. -- On macOS, fix events not being emitted during modal loops, such as when windows are being resized - by the user. -- On Windows, fix hovering the mouse over the active window creating an endless stream of CursorMoved events. -- Always dispatch a `RedrawRequested` event after creating a new window. -- On X11, return dummy monitor data to avoid panicking when no monitors exist. -- On X11, prevent stealing input focus when creating a new window. - Only steal input focus when entering fullscreen mode. -- On Wayland, fixed DeviceEvents for relative mouse movement is not always produced -- On Wayland, add support for set_cursor_visible and set_cursor_grab. -- On Wayland, fixed DeviceEvents for relative mouse movement is not always produced. -- Removed `derivative` crate dependency. -- On Wayland, add support for set_cursor_icon. -- Use `impl Iterator` instead of `AvailableMonitorsIter` consistently. -- On macOS, fix fullscreen state being updated after entering fullscreen instead of before, - resulting in `Window::fullscreen` returning the old state in `Resized` events instead of - reflecting the new fullscreen state -- On X11, fix use-after-free during window creation -- On Windows, disable monitor change keyboard shortcut while in exclusive fullscreen. -- On Windows, ensure that changing a borderless fullscreen window's monitor via keyboard shortcuts keeps the window fullscreen on the new monitor. -- Prevent `EventLoop::new` and `EventLoop::with_user_event` from getting called outside the main thread. - - This is because some platforms cannot run the event loop outside the main thread. Preventing this - reduces the potential for cross-platform compatibility gotchyas. -- On Windows and Linux X11/Wayland, add platform-specific functions for creating an `EventLoop` outside the main thread. -- On Wayland, drop resize events identical to the current window size. -- On Windows, fix window rectangle not getting set correctly on high-DPI systems. +* Add web support via the 'stdweb' or 'web-sys' features +* On Windows, implemented function to get HINSTANCE +* On macOS, implement `run_return`. +* On iOS, fix inverted parameter in `set_prefers_home_indicator_hidden`. +* On X11, performance is improved when rapidly calling `Window::set_cursor_icon`. +* On iOS, fix improper `msg_send` usage that was UB and/or would break if `!` is stabilized. +* On Windows, unset `maximized` when manually changing the window's position or size. +* On Windows, add touch pressure information for touch events. +* On macOS, differentiate between `CursorIcon::Grab` and `CursorIcon::Grabbing`. +* On Wayland, fix event processing sometimes stalling when using OpenGL with vsync. +* Officially remove the Emscripten backend. +* On Windows, fix handling of surrogate pairs when dispatching `ReceivedCharacter`. +* On macOS 10.15, fix freeze upon exiting exclusive fullscreen mode. +* On iOS, fix panic upon closing the app. +* On X11, allow setting mulitple `XWindowType`s. +* On iOS, fix null window on initial `HiDpiFactorChanged` event. +* On Windows, fix fullscreen window shrinking upon getting restored to a normal window. +* On macOS, fix events not being emitted during modal loops, such as when windows are being resized + by the user. +* On Windows, fix hovering the mouse over the active window creating an endless stream of CursorMoved events. +* Always dispatch a `RedrawRequested` event after creating a new window. +* On X11, return dummy monitor data to avoid panicking when no monitors exist. +* On X11, prevent stealing input focus when creating a new window. + Only steal input focus when entering fullscreen mode. +* On Wayland, fixed DeviceEvents for relative mouse movement is not always produced +* On Wayland, add support for set_cursor_visible and set_cursor_grab. +* On Wayland, fixed DeviceEvents for relative mouse movement is not always produced. +* Removed `derivative` crate dependency. +* On Wayland, add support for set_cursor_icon. +* Use `impl Iterator` instead of `AvailableMonitorsIter` consistently. +* On macOS, fix fullscreen state being updated after entering fullscreen instead of before, + resulting in `Window::fullscreen` returning the old state in `Resized` events instead of + reflecting the new fullscreen state +* On X11, fix use-after-free during window creation +* On Windows, disable monitor change keyboard shortcut while in exclusive fullscreen. +* On Windows, ensure that changing a borderless fullscreen window's monitor via keyboard shortcuts keeps the window fullscreen on the new monitor. +* Prevent `EventLoop::new` and `EventLoop::with_user_event` from getting called outside the main thread. + * This is because some platforms cannot run the event loop outside the main thread. Preventing this + reduces the potential for cross-platform compatibility gotchyas. +* On Windows and Linux X11/Wayland, add platform-specific functions for creating an `EventLoop` outside the main thread. +* On Wayland, drop resize events identical to the current window size. +* On Windows, fix window rectangle not getting set correctly on high-DPI systems. # 0.20.0 Alpha 3 (2019-08-14) -- On macOS, drop the run closure on exit. -- On Windows, location of `WindowEvent::Touch` are window client coordinates instead of screen coordinates. -- On X11, fix delayed events after window redraw. -- On macOS, add `WindowBuilderExt::with_disallow_hidpi` to have the option to turn off best resolution openGL surface. -- On Windows, screen saver won't start if the window is in fullscreen mode. -- Change all occurrences of the `new_user_event` method to `with_user_event`. -- On macOS, the dock and the menu bar are now hidden in fullscreen mode. -- `Window::set_fullscreen` now takes `Option` where `Fullscreen` - consists of `Fullscreen::Exclusive(VideoMode)` and - `Fullscreen::Borderless(MonitorHandle)` variants. - - Adds support for exclusive fullscreen mode. -- On iOS, add support for hiding the home indicator. -- On iOS, add support for deferring system gestures. -- On iOS, fix a crash that occurred while acquiring a monitor's name. -- On iOS, fix armv7-apple-ios compile target. -- Removed the `T: Clone` requirement from the `Clone` impl of `EventLoopProxy`. -- On iOS, disable overscan compensation for external displays (removes black - bars surrounding the image). -- On Linux, the functions `is_wayland`, `is_x11`, `xlib_xconnection` and `wayland_display` have been moved to a new `EventLoopWindowTargetExtUnix` trait. -- On iOS, add `set_prefers_status_bar_hidden` extension function instead of - hijacking `set_decorations` for this purpose. -- On macOS and iOS, corrected the auto trait impls of `EventLoopProxy`. -- On iOS, add touch pressure information for touch events. -- Implement `raw_window_handle::HasRawWindowHandle` for `Window` type on all supported platforms. -- On macOS, fix the signature of `-[NSView drawRect:]`. -- On iOS, fix the behavior of `ControlFlow::Poll`. It wasn't polling if that was the only mode ever used by the application. -- On iOS, fix DPI sent out by views on creation was `0.0` - now it gives a reasonable number. -- On iOS, RedrawRequested now works for gl/metal backed views. -- On iOS, RedrawRequested is generally ordered after EventsCleared. +* On macOS, drop the run closure on exit. +* On Windows, location of `WindowEvent::Touch` are window client coordinates instead of screen coordinates. +* On X11, fix delayed events after window redraw. +* On macOS, add `WindowBuilderExt::with_disallow_hidpi` to have the option to turn off best resolution openGL surface. +* On Windows, screen saver won't start if the window is in fullscreen mode. +* Change all occurrences of the `new_user_event` method to `with_user_event`. +* On macOS, the dock and the menu bar are now hidden in fullscreen mode. +* `Window::set_fullscreen` now takes `Option` where `Fullscreen` + consists of `Fullscreen::Exclusive(VideoMode)` and + `Fullscreen::Borderless(MonitorHandle)` variants. + * Adds support for exclusive fullscreen mode. +* On iOS, add support for hiding the home indicator. +* On iOS, add support for deferring system gestures. +* On iOS, fix a crash that occurred while acquiring a monitor's name. +* On iOS, fix armv7-apple-ios compile target. +* Removed the `T: Clone` requirement from the `Clone` impl of `EventLoopProxy`. +* On iOS, disable overscan compensation for external displays (removes black + bars surrounding the image). +* On Linux, the functions `is_wayland`, `is_x11`, `xlib_xconnection` and `wayland_display` have been moved to a new `EventLoopWindowTargetExtUnix` trait. +* On iOS, add `set_prefers_status_bar_hidden` extension function instead of + hijacking `set_decorations` for this purpose. +* On macOS and iOS, corrected the auto trait impls of `EventLoopProxy`. +* On iOS, add touch pressure information for touch events. +* Implement `raw_window_handle::HasRawWindowHandle` for `Window` type on all supported platforms. +* On macOS, fix the signature of `-[NSView drawRect:]`. +* On iOS, fix the behavior of `ControlFlow::Poll`. It wasn't polling if that was the only mode ever used by the application. +* On iOS, fix DPI sent out by views on creation was `0.0` - now it gives a reasonable number. +* On iOS, RedrawRequested now works for gl/metal backed views. +* On iOS, RedrawRequested is generally ordered after EventsCleared. # 0.20.0 Alpha 2 (2019-07-09) -- On X11, non-resizable windows now have maximize explicitly disabled. -- On Windows, support paths longer than MAX_PATH (260 characters) in `WindowEvent::DroppedFile` -and `WindowEvent::HoveredFile`. -- On Mac, implement `DeviceEvent::Button`. -- Change `Event::Suspended(true / false)` to `Event::Suspended` and `Event::Resumed`. -- On X11, fix sanity check which checks that a monitor's reported width and height (in millimeters) are non-zero when calculating the DPI factor. -- Revert the use of invisible surfaces in Wayland, which introduced graphical glitches with OpenGL (#835) -- On X11, implement `_NET_WM_PING` to allow desktop environment to kill unresponsive programs. -- On Windows, when a window is initially invisible, it won't take focus from the existing visible windows. -- On Windows, fix multiple calls to `request_redraw` during `EventsCleared` sending multiple `RedrawRequested events.` -- On Windows, fix edge case where `RedrawRequested` could be dispatched before input events in event loop iteration. -- On Windows, fix timing issue that could cause events to be improperly dispatched after `RedrawRequested` but before `EventsCleared`. -- On macOS, drop unused Metal dependency. -- On Windows, fix the trail effect happening on transparent decorated windows. Borderless (or un-decorated) windows were not affected. -- On Windows, fix `with_maximized` not properly setting window size to entire window. -- On macOS, change `WindowExtMacOS::request_user_attention()` to take an `enum` instead of a `bool`. +* On X11, non-resizable windows now have maximize explicitly disabled. +* On Windows, support paths longer than MAX_PATH (260 characters) in `WindowEvent::DroppedFile` + and `WindowEvent::HoveredFile`. +* On Mac, implement `DeviceEvent::Button`. +* Change `Event::Suspended(true / false)` to `Event::Suspended` and `Event::Resumed`. +* On X11, fix sanity check which checks that a monitor's reported width and height (in millimeters) are non-zero when calculating the DPI factor. +* Revert the use of invisible surfaces in Wayland, which introduced graphical glitches with OpenGL (#835) +* On X11, implement `_NET_WM_PING` to allow desktop environment to kill unresponsive programs. +* On Windows, when a window is initially invisible, it won't take focus from the existing visible windows. +* On Windows, fix multiple calls to `request_redraw` during `EventsCleared` sending multiple `RedrawRequested events.` +* On Windows, fix edge case where `RedrawRequested` could be dispatched before input events in event loop iteration. +* On Windows, fix timing issue that could cause events to be improperly dispatched after `RedrawRequested` but before `EventsCleared`. +* On macOS, drop unused Metal dependency. +* On Windows, fix the trail effect happening on transparent decorated windows. Borderless (or un-decorated) windows were not affected. +* On Windows, fix `with_maximized` not properly setting window size to entire window. +* On macOS, change `WindowExtMacOS::request_user_attention()` to take an `enum` instead of a `bool`. # 0.20.0 Alpha 1 (2019-06-21) -- Changes below are considered **breaking**. -- Change all occurrences of `EventsLoop` to `EventLoop`. -- Previously flat API is now exposed through `event`, `event_loop`, `monitor`, and `window` modules. -- `os` module changes: - - Renamed to `platform`. - - All traits now have platform-specific suffixes. - - Exposes new `desktop` module on Windows, Mac, and Linux. -- Changes to event loop types: - - `EventLoopProxy::wakeup` has been removed in favor of `send_event`. - - **Major:** New `run` method drives winit event loop. - - Returns `!` to ensure API behaves identically across all supported platforms. - - This allows `emscripten` implementation to work without lying about the API. - - `ControlFlow`'s variants have been replaced with `Wait`, `WaitUntil(Instant)`, `Poll`, and `Exit`. - - Is read after `EventsCleared` is processed. - - `Wait` waits until new events are available. - - `WaitUntil` waits until either new events are available or the provided time has been reached. - - `Poll` instantly resumes the event loop. - - `Exit` aborts the event loop. - - Takes a closure that implements `'static + FnMut(Event, &EventLoop, &mut ControlFlow)`. - - `&EventLoop` is provided to allow new `Window`s to be created. - - **Major:** `platform::desktop` module exposes `EventLoopExtDesktop` trait with `run_return` method. - - Behaves identically to `run`, but returns control flow to the calling context and can take non-`'static` closures. - - `EventLoop`'s `poll_events` and `run_forever` methods have been removed in favor of `run` and `run_return`. -- Changes to events: - - Remove `Event::Awakened` in favor of `Event::UserEvent(T)`. - - Can be sent with `EventLoopProxy::send_event`. - - Rename `WindowEvent::Refresh` to `WindowEvent::RedrawRequested`. - - `RedrawRequested` can be sent by the user with the `Window::request_redraw` method. - - `EventLoop`, `EventLoopProxy`, and `Event` are now generic over `T`, for use in `UserEvent`. - - **Major:** Add `NewEvents(StartCause)`, `EventsCleared`, and `LoopDestroyed` variants to `Event`. - - `NewEvents` is emitted when new events are ready to be processed by event loop. - - `StartCause` describes why new events are available, with `ResumeTimeReached`, `Poll`, `WaitCancelled`, and `Init` (sent once at start of loop). - - `EventsCleared` is emitted when all available events have been processed. - - Can be used to perform logic that depends on all events being processed (e.g. an iteration of a game loop). - - `LoopDestroyed` is emitted when the `run` or `run_return` method is about to exit. -- Rename `MonitorId` to `MonitorHandle`. -- Removed `serde` implementations from `ControlFlow`. -- Rename several functions to improve both internal consistency and compliance with Rust API guidelines. -- Remove `WindowBuilder::multitouch` field, since it was only implemented on a few platforms. Multitouch is always enabled now. -- **Breaking:** On macOS, change `ns` identifiers to use snake_case for consistency with iOS's `ui` identifiers. -- Add `MonitorHandle::video_modes` method for retrieving supported video modes for the given monitor. -- On Wayland, the window now exists even if nothing has been drawn. -- On Windows, fix initial dimensions of a fullscreen window. -- On Windows, Fix transparent borderless windows rendering wrong. +* Changes below are considered **breaking**. +* Change all occurrences of `EventsLoop` to `EventLoop`. +* Previously flat API is now exposed through `event`, `event_loop`, `monitor`, and `window` modules. +* `os` module changes: + * Renamed to `platform`. + * All traits now have platform-specific suffixes. + * Exposes new `desktop` module on Windows, Mac, and Linux. +* Changes to event loop types: + * `EventLoopProxy::wakeup` has been removed in favor of `send_event`. + * **Major:** New `run` method drives winit event loop. + * Returns `!` to ensure API behaves identically across all supported platforms. + * This allows `emscripten` implementation to work without lying about the API. + * `ControlFlow`'s variants have been replaced with `Wait`, `WaitUntil(Instant)`, `Poll`, and `Exit`. + * Is read after `EventsCleared` is processed. + * `Wait` waits until new events are available. + * `WaitUntil` waits until either new events are available or the provided time has been reached. + * `Poll` instantly resumes the event loop. + * `Exit` aborts the event loop. + * Takes a closure that implements `'static + FnMut(Event, &EventLoop, &mut ControlFlow)`. + * `&EventLoop` is provided to allow new `Window`s to be created. + * **Major:** `platform::desktop` module exposes `EventLoopExtDesktop` trait with `run_return` method. + * Behaves identically to `run`, but returns control flow to the calling context and can take non-`'static` closures. + * `EventLoop`'s `poll_events` and `run_forever` methods have been removed in favor of `run` and `run_return`. +* Changes to events: + * Remove `Event::Awakened` in favor of `Event::UserEvent(T)`. + * Can be sent with `EventLoopProxy::send_event`. + * Rename `WindowEvent::Refresh` to `WindowEvent::RedrawRequested`. + * `RedrawRequested` can be sent by the user with the `Window::request_redraw` method. + * `EventLoop`, `EventLoopProxy`, and `Event` are now generic over `T`, for use in `UserEvent`. + * **Major:** Add `NewEvents(StartCause)`, `EventsCleared`, and `LoopDestroyed` variants to `Event`. + * `NewEvents` is emitted when new events are ready to be processed by event loop. + * `StartCause` describes why new events are available, with `ResumeTimeReached`, `Poll`, `WaitCancelled`, and `Init` (sent once at start of loop). + * `EventsCleared` is emitted when all available events have been processed. + * Can be used to perform logic that depends on all events being processed (e.g. an iteration of a game loop). + * `LoopDestroyed` is emitted when the `run` or `run_return` method is about to exit. +* Rename `MonitorId` to `MonitorHandle`. +* Removed `serde` implementations from `ControlFlow`. +* Rename several functions to improve both internal consistency and compliance with Rust API guidelines. +* Remove `WindowBuilder::multitouch` field, since it was only implemented on a few platforms. Multitouch is always enabled now. +* **Breaking:** On macOS, change `ns` identifiers to use snake_case for consistency with iOS's `ui` identifiers. +* Add `MonitorHandle::video_modes` method for retrieving supported video modes for the given monitor. +* On Wayland, the window now exists even if nothing has been drawn. +* On Windows, fix initial dimensions of a fullscreen window. +* On Windows, Fix transparent borderless windows rendering wrong. # Version 0.19.1 (2019-04-08) -- On Wayland, added a `get_wayland_display` function to `EventsLoopExt`. -- On Windows, fix `CursorMoved(0, 0)` getting dispatched on window focus. -- On macOS, fix command key event left and right reverse. -- On FreeBSD, NetBSD, and OpenBSD, fix build of X11 backend. -- On Linux, the numpad's add, subtract and divide keys are now mapped to the `Add`, `Subtract` and `Divide` virtual key codes -- On macOS, the numpad's subtract key has been added to the `Subtract` mapping -- On Wayland, the numpad's home, end, page up and page down keys are now mapped to the `Home`, `End`, `PageUp` and `PageDown` virtual key codes -- On Windows, fix icon not showing up in corner of window. -- On X11, change DPI scaling factor behavior. First, winit tries to read it from "Xft.dpi" XResource, and uses DPI calculation from xrandr dimensions as fallback behavior. +* On Wayland, added a `get_wayland_display` function to `EventsLoopExt`. +* On Windows, fix `CursorMoved(0, 0)` getting dispatched on window focus. +* On macOS, fix command key event left and right reverse. +* On FreeBSD, NetBSD, and OpenBSD, fix build of X11 backend. +* On Linux, the numpad's add, subtract and divide keys are now mapped to the `Add`, `Subtract` and `Divide` virtual key codes +* On macOS, the numpad's subtract key has been added to the `Subtract` mapping +* On Wayland, the numpad's home, end, page up and page down keys are now mapped to the `Home`, `End`, `PageUp` and `PageDown` virtual key codes +* On Windows, fix icon not showing up in corner of window. +* On X11, change DPI scaling factor behavior. First, winit tries to read it from "Xft.dpi" XResource, and uses DPI calculation from xrandr dimensions as fallback behavior. # Version 0.19.0 (2019-03-06) -- On X11, we will use the faster `XRRGetScreenResourcesCurrent` function instead of `XRRGetScreenResources` when available. -- On macOS, fix keycodes being incorrect when using a non-US keyboard layout. -- On Wayland, fix `with_title()` not setting the windows title -- On Wayland, add `set_wayland_theme()` to control client decoration color theme -- Added serde serialization to `os::unix::XWindowType`. -- **Breaking:** Remove the `icon_loading` feature and the associated `image` dependency. -- On X11, make event loop thread safe by replacing XNextEvent with select(2) and XCheckIfEvent -- On Windows, fix malformed function pointer typecast that could invoke undefined behavior. -- Refactored Windows state/flag-setting code. -- On Windows, hiding the cursor no longer hides the cursor for all Winit windows - just the one `hide_cursor` was called on. -- On Windows, cursor grabs used to get perpetually canceled when the grabbing window lost focus. Now, cursor grabs automatically get re-initialized when the window regains focus and the mouse moves over the client area. -- On Windows, only vertical mouse wheel events were handled. Now, horizontal mouse wheel events are also handled. -- On Windows, ignore the AltGr key when populating the `ModifersState` type. +* On X11, we will use the faster `XRRGetScreenResourcesCurrent` function instead of `XRRGetScreenResources` when available. +* On macOS, fix keycodes being incorrect when using a non-US keyboard layout. +* On Wayland, fix `with_title()` not setting the windows title +* On Wayland, add `set_wayland_theme()` to control client decoration color theme +* Added serde serialization to `os::unix::XWindowType`. +* **Breaking:** Remove the `icon_loading` feature and the associated `image` dependency. +* On X11, make event loop thread safe by replacing XNextEvent with select(2) and XCheckIfEvent +* On Windows, fix malformed function pointer typecast that could invoke undefined behavior. +* Refactored Windows state/flag-setting code. +* On Windows, hiding the cursor no longer hides the cursor for all Winit windows - just the one `hide_cursor` was called on. +* On Windows, cursor grabs used to get perpetually canceled when the grabbing window lost focus. Now, cursor grabs automatically get re-initialized when the window regains focus and the mouse moves over the client area. +* On Windows, only vertical mouse wheel events were handled. Now, horizontal mouse wheel events are also handled. +* On Windows, ignore the AltGr key when populating the `ModifersState` type. # Version 0.18.1 (2018-12-30) -- On macOS, fix `Yen` (JIS) so applications receive the event. -- On X11 with a tiling WM, fixed high CPU usage when moving windows across monitors. -- On X11, fixed panic caused by dropping the window before running the event loop. -- on macOS, added `WindowExt::set_simple_fullscreen` which does not require a separate space -- Introduce `WindowBuilderExt::with_app_id` to allow setting the application ID on Wayland. -- On Windows, catch panics in event loop child thread and forward them to the parent thread. This prevents an invocation of undefined behavior due to unwinding into foreign code. -- On Windows, fix issue where resizing or moving window combined with grabbing the cursor would freeze program. -- On Windows, fix issue where resizing or moving window would eat `Awakened` events. -- On Windows, exiting fullscreen after entering fullscreen with disabled decorations no longer shrinks window. -- On X11, fixed a segfault when using virtual monitors with XRandR. -- Derive `Ord` and `PartialOrd` for `VirtualKeyCode` enum. -- On Windows, fix issue where hovering or dropping a non file item would create a panic. -- On Wayland, fix resizing and DPI calculation when a `wl_output` is removed without sending a `leave` event to the `wl_surface`, such as disconnecting a monitor from a laptop. -- On Wayland, DPI calculation is handled by smithay-client-toolkit. -- On X11, `WindowBuilder::with_min_dimensions` and `WindowBuilder::with_max_dimensions` now correctly account for DPI. -- Added support for generating dummy `DeviceId`s and `WindowId`s to better support unit testing. -- On macOS, fixed unsoundness in drag-and-drop that could result in drops being rejected. -- On macOS, implemented `WindowEvent::Refresh`. -- On macOS, all `MouseCursor` variants are now implemented and the cursor will no longer reset after unfocusing. -- Removed minimum supported Rust version guarantee. +* On macOS, fix `Yen` (JIS) so applications receive the event. +* On X11 with a tiling WM, fixed high CPU usage when moving windows across monitors. +* On X11, fixed panic caused by dropping the window before running the event loop. +* on macOS, added `WindowExt::set_simple_fullscreen` which does not require a separate space +* Introduce `WindowBuilderExt::with_app_id` to allow setting the application ID on Wayland. +* On Windows, catch panics in event loop child thread and forward them to the parent thread. This prevents an invocation of undefined behavior due to unwinding into foreign code. +* On Windows, fix issue where resizing or moving window combined with grabbing the cursor would freeze program. +* On Windows, fix issue where resizing or moving window would eat `Awakened` events. +* On Windows, exiting fullscreen after entering fullscreen with disabled decorations no longer shrinks window. +* On X11, fixed a segfault when using virtual monitors with XRandR. +* Derive `Ord` and `PartialOrd` for `VirtualKeyCode` enum. +* On Windows, fix issue where hovering or dropping a non file item would create a panic. +* On Wayland, fix resizing and DPI calculation when a `wl_output` is removed without sending a `leave` event to the `wl_surface`, such as disconnecting a monitor from a laptop. +* On Wayland, DPI calculation is handled by smithay-client-toolkit. +* On X11, `WindowBuilder::with_min_dimensions` and `WindowBuilder::with_max_dimensions` now correctly account for DPI. +* Added support for generating dummy `DeviceId`s and `WindowId`s to better support unit testing. +* On macOS, fixed unsoundness in drag-and-drop that could result in drops being rejected. +* On macOS, implemented `WindowEvent::Refresh`. +* On macOS, all `MouseCursor` variants are now implemented and the cursor will no longer reset after unfocusing. +* Removed minimum supported Rust version guarantee. # Version 0.18.0 (2018-11-07) -- **Breaking:** `image` crate upgraded to 0.20. This is exposed as part of the `icon_loading` API. -- On Wayland, pointer events will now provide the current modifiers state. -- On Wayland, titles will now be displayed in the window header decoration. -- On Wayland, key repetition is now ended when keyboard loses focus. -- On Wayland, windows will now use more stylish and modern client side decorations. -- On Wayland, windows will use server-side decorations when available. -- **Breaking:** Added support for F16-F24 keys (variants were added to the `VirtualKeyCode` enum). -- Fixed graphical glitches when resizing on Wayland. -- On Windows, fix freezes when performing certain actions after a window resize has been triggered. Reintroduces some visual artifacts when resizing. -- Updated window manager hints under X11 to v1.5 of [Extended Window Manager Hints](https://specifications.freedesktop.org/wm-spec/wm-spec-1.5.html#idm140200472629520). -- Added `WindowBuilderExt::with_gtk_theme_variant` to X11-specific `WindowBuilder` functions. -- Fixed UTF8 handling bug in X11 `set_title` function. -- On Windows, `Window::set_cursor` now applies immediately instead of requiring specific events to occur first. -- On Windows, the `HoveredFile` and `HoveredFileCancelled` events are now implemented. -- On Windows, fix `Window::set_maximized`. -- On Windows 10, fix transparency (#260). -- On macOS, fix modifiers during key repeat. -- Implemented the `Debug` trait for `Window`, `EventsLoop`, `EventsLoopProxy` and `WindowBuilder`. -- On X11, now a `Resized` event will always be generated after a DPI change to ensure the window's logical size is consistent with the new DPI. -- Added further clarifications to the DPI docs. -- On Linux, if neither X11 nor Wayland manage to initialize, the corresponding panic now consists of a single line only. -- Add optional `serde` feature with implementations of `Serialize`/`Deserialize` for DPI types and various event types. -- Add `PartialEq`, `Eq`, and `Hash` implementations on public types that could have them but were missing them. -- On X11, drag-and-drop receiving an unsupported drop type can no longer cause the WM to freeze. -- Fix issue whereby the OpenGL context would not appear at startup on macOS Mojave (#1069). -- **Breaking:** Removed `From` impl from `ActivationPolicy` on macOS. -- On macOS, the application can request the user's attention with `WindowExt::request_user_attention`. +* **Breaking:** `image` crate upgraded to 0.20. This is exposed as part of the `icon_loading` API. +* On Wayland, pointer events will now provide the current modifiers state. +* On Wayland, titles will now be displayed in the window header decoration. +* On Wayland, key repetition is now ended when keyboard loses focus. +* On Wayland, windows will now use more stylish and modern client side decorations. +* On Wayland, windows will use server-side decorations when available. +* **Breaking:** Added support for F16-F24 keys (variants were added to the `VirtualKeyCode` enum). +* Fixed graphical glitches when resizing on Wayland. +* On Windows, fix freezes when performing certain actions after a window resize has been triggered. Reintroduces some visual artifacts when resizing. +* Updated window manager hints under X11 to v1.5 of [Extended Window Manager Hints](https://specifications.freedesktop.org/wm-spec/wm-spec-1.5.html#idm140200472629520). +* Added `WindowBuilderExt::with_gtk_theme_variant` to X11-specific `WindowBuilder` functions. +* Fixed UTF8 handling bug in X11 `set_title` function. +* On Windows, `Window::set_cursor` now applies immediately instead of requiring specific events to occur first. +* On Windows, the `HoveredFile` and `HoveredFileCancelled` events are now implemented. +* On Windows, fix `Window::set_maximized`. +* On Windows 10, fix transparency (#260). +* On macOS, fix modifiers during key repeat. +* Implemented the `Debug` trait for `Window`, `EventsLoop`, `EventsLoopProxy` and `WindowBuilder`. +* On X11, now a `Resized` event will always be generated after a DPI change to ensure the window's logical size is consistent with the new DPI. +* Added further clarifications to the DPI docs. +* On Linux, if neither X11 nor Wayland manage to initialize, the corresponding panic now consists of a single line only. +* Add optional `serde` feature with implementations of `Serialize`/`Deserialize` for DPI types and various event types. +* Add `PartialEq`, `Eq`, and `Hash` implementations on public types that could have them but were missing them. +* On X11, drag-and-drop receiving an unsupported drop type can no longer cause the WM to freeze. +* Fix issue whereby the OpenGL context would not appear at startup on macOS Mojave (#1069). +* **Breaking:** Removed `From` impl from `ActivationPolicy` on macOS. +* On macOS, the application can request the user's attention with `WindowExt::request_user_attention`. # Version 0.17.2 (2018-08-19) -- On macOS, fix `` so applications receive the event. -- On macOS, fix `` so applications receive the event. -- On Wayland, key press events will now be repeated. +* On macOS, fix `` so applications receive the event. +* On macOS, fix `` so applications receive the event. +* On Wayland, key press events will now be repeated. # Version 0.17.1 (2018-08-05) -- On X11, prevent a compilation failure in release mode for versions of Rust greater than or equal to 1.30. -- Fixed deadlock that broke fullscreen mode on Windows. +* On X11, prevent a compilation failure in release mode for versions of Rust greater than or equal to 1.30. +* Fixed deadlock that broke fullscreen mode on Windows. # Version 0.17.0 (2018-08-02) -- Cocoa and core-graphics updates. -- Fixed thread-safety issues in several `Window` functions on Windows. -- On MacOS, the key state for modifiers key events is now properly set. -- On iOS, the view is now set correctly. This makes it possible to render things (instead of being stuck on a black screen), and touch events work again. -- Added NetBSD support. -- **Breaking:** On iOS, `UIView` is now the default root view. `WindowBuilderExt::with_root_view_class` can be used to set the root view objective-c class to `GLKView` (OpenGLES) or `MTKView` (Metal/MoltenVK). -- On iOS, the `UIApplication` is not started until `Window::new` is called. -- Fixed thread unsafety with cursor hiding on macOS. -- On iOS, fixed the size of the `JmpBuf` type used for `setjmp`/`longjmp` calls. Previously this was a buffer overflow on most architectures. -- On Windows, use cached window DPI instead of repeatedly querying the system. This fixes sporadic crashes on Windows 7. +* Cocoa and core-graphics updates. +* Fixed thread-safety issues in several `Window` functions on Windows. +* On MacOS, the key state for modifiers key events is now properly set. +* On iOS, the view is now set correctly. This makes it possible to render things (instead of being stuck on a black screen), and touch events work again. +* Added NetBSD support. +* **Breaking:** On iOS, `UIView` is now the default root view. `WindowBuilderExt::with_root_view_class` can be used to set the root view objective-c class to `GLKView` (OpenGLES) or `MTKView` (Metal/MoltenVK). +* On iOS, the `UIApplication` is not started until `Window::new` is called. +* Fixed thread unsafety with cursor hiding on macOS. +* On iOS, fixed the size of the `JmpBuf` type used for `setjmp`/`longjmp` calls. Previously this was a buffer overflow on most architectures. +* On Windows, use cached window DPI instead of repeatedly querying the system. This fixes sporadic crashes on Windows 7. # Version 0.16.2 (2018-07-07) -- On Windows, non-resizable windows now have the maximization button disabled. This is consistent with behavior on macOS and popular X11 WMs. -- Corrected incorrect `unreachable!` usage when guessing the DPI factor with no detected monitors. +* On Windows, non-resizable windows now have the maximization button disabled. This is consistent with behavior on macOS and popular X11 WMs. +* Corrected incorrect `unreachable!` usage when guessing the DPI factor with no detected monitors. # Version 0.16.1 (2018-07-02) -- Added logging through `log`. Logging will become more extensive over time. -- On X11 and Windows, the window's DPI factor is guessed before creating the window. This _greatly_ cuts back on unsightly auto-resizing that would occur immediately after window creation. -- Fixed X11 backend compilation for environments where `c_char` is unsigned. +* Added logging through `log`. Logging will become more extensive over time. +* On X11 and Windows, the window's DPI factor is guessed before creating the window. This *greatly* cuts back on unsightly auto-resizing that would occur immediately after window creation. +* Fixed X11 backend compilation for environments where `c_char` is unsigned. # Version 0.16.0 (2018-06-25) -- Windows additionally has `WindowBuilderExt::with_no_redirection_bitmap`. -- **Breaking:** Removed `VirtualKeyCode::LMenu` and `VirtualKeyCode::RMenu`; Windows now generates `VirtualKeyCode::LAlt` and `VirtualKeyCode::RAlt` instead. -- On X11, exiting fullscreen no longer leaves the window in the monitor's top left corner. -- **Breaking:** `Window::hidpi_factor` has been renamed to `Window::get_hidpi_factor` for better consistency. `WindowEvent::HiDPIFactorChanged` has been renamed to `WindowEvent::HiDpiFactorChanged`. DPI factors are always represented as `f64` instead of `f32` now. -- The Windows backend is now DPI aware. `WindowEvent::HiDpiFactorChanged` is implemented, and `MonitorId::get_hidpi_factor` and `Window::hidpi_factor` return accurate values. -- Implemented `WindowEvent::HiDpiFactorChanged` on X11. -- On macOS, `Window::set_cursor_position` is now relative to the client area. -- On macOS, setting the maximum and minimum dimensions now applies to the client area dimensions rather than to the window dimensions. -- On iOS, `MonitorId::get_dimensions` has been implemented and both `MonitorId::get_hidpi_factor` and `Window::get_hidpi_factor` return accurate values. -- On Emscripten, `MonitorId::get_hidpi_factor` now returns the same value as `Window::get_hidpi_factor` (it previously would always return 1.0). -- **Breaking:** The entire API for sizes, positions, etc. has changed. In the majority of cases, winit produces and consumes positions and sizes as `LogicalPosition` and `LogicalSize`, respectively. The notable exception is `MonitorId` methods, which deal in `PhysicalPosition` and `PhysicalSize`. See the documentation for specifics and explanations of the types. Additionally, winit automatically conserves logical size when the DPI factor changes. -- **Breaking:** All deprecated methods have been removed. For `Window::platform_display` and `Window::platform_window`, switch to the appropriate platform-specific `WindowExt` methods. For `Window::get_inner_size_points` and `Window::get_inner_size_pixels`, use the `LogicalSize` returned by `Window::get_inner_size` and convert as needed. -- HiDPI support for Wayland. -- `EventsLoop::get_available_monitors` and `EventsLoop::get_primary_monitor` now have identical counterparts on `Window`, so this information can be acquired without an `EventsLoop` borrow. -- `AvailableMonitorsIter` now implements `Debug`. -- Fixed quirk on macOS where certain keys would generate characters at twice the normal rate when held down. -- On X11, all event loops now share the same `XConnection`. -- **Breaking:** `Window::set_cursor_state` and `CursorState` enum removed in favor of the more composable `Window::grab_cursor` and `Window::hide_cursor`. As a result, grabbing the cursor no longer automatically hides it; you must call both methods to retain the old behavior on Windows and macOS. `Cursor::NoneCursor` has been removed, as it's no longer useful. -- **Breaking:** `Window::set_cursor_position` now returns `Result<(), String>`, thus allowing for `Box` conversion via `?`. +* Windows additionally has `WindowBuilderExt::with_no_redirection_bitmap`. +* **Breaking:** Removed `VirtualKeyCode::LMenu` and `VirtualKeyCode::RMenu`; Windows now generates `VirtualKeyCode::LAlt` and `VirtualKeyCode::RAlt` instead. +* On X11, exiting fullscreen no longer leaves the window in the monitor's top left corner. +* **Breaking:** `Window::hidpi_factor` has been renamed to `Window::get_hidpi_factor` for better consistency. `WindowEvent::HiDPIFactorChanged` has been renamed to `WindowEvent::HiDpiFactorChanged`. DPI factors are always represented as `f64` instead of `f32` now. +* The Windows backend is now DPI aware. `WindowEvent::HiDpiFactorChanged` is implemented, and `MonitorId::get_hidpi_factor` and `Window::hidpi_factor` return accurate values. +* Implemented `WindowEvent::HiDpiFactorChanged` on X11. +* On macOS, `Window::set_cursor_position` is now relative to the client area. +* On macOS, setting the maximum and minimum dimensions now applies to the client area dimensions rather than to the window dimensions. +* On iOS, `MonitorId::get_dimensions` has been implemented and both `MonitorId::get_hidpi_factor` and `Window::get_hidpi_factor` return accurate values. +* On Emscripten, `MonitorId::get_hidpi_factor` now returns the same value as `Window::get_hidpi_factor` (it previously would always return 1.0). +* **Breaking:** The entire API for sizes, positions, etc. has changed. In the majority of cases, winit produces and consumes positions and sizes as `LogicalPosition` and `LogicalSize`, respectively. The notable exception is `MonitorId` methods, which deal in `PhysicalPosition` and `PhysicalSize`. See the documentation for specifics and explanations of the types. Additionally, winit automatically conserves logical size when the DPI factor changes. +* **Breaking:** All deprecated methods have been removed. For `Window::platform_display` and `Window::platform_window`, switch to the appropriate platform-specific `WindowExt` methods. For `Window::get_inner_size_points` and `Window::get_inner_size_pixels`, use the `LogicalSize` returned by `Window::get_inner_size` and convert as needed. +* HiDPI support for Wayland. +* `EventsLoop::get_available_monitors` and `EventsLoop::get_primary_monitor` now have identical counterparts on `Window`, so this information can be acquired without an `EventsLoop` borrow. +* `AvailableMonitorsIter` now implements `Debug`. +* Fixed quirk on macOS where certain keys would generate characters at twice the normal rate when held down. +* On X11, all event loops now share the same `XConnection`. +* **Breaking:** `Window::set_cursor_state` and `CursorState` enum removed in favor of the more composable `Window::grab_cursor` and `Window::hide_cursor`. As a result, grabbing the cursor no longer automatically hides it; you must call both methods to retain the old behavior on Windows and macOS. `Cursor::NoneCursor` has been removed, as it's no longer useful. +* **Breaking:** `Window::set_cursor_position` now returns `Result<(), String>`, thus allowing for `Box` conversion via `?`. # Version 0.15.1 (2018-06-13) -- On X11, the `Moved` event is no longer sent when the window is resized without changing position. -- `MouseCursor` and `CursorState` now implement `Default`. -- `WindowBuilder::with_resizable` implemented for Windows, X11, Wayland, and macOS. -- `Window::set_resizable` implemented for Windows, X11, Wayland, and macOS. -- On X11, if the monitor's width or height in millimeters is reported as 0, the DPI is now 1.0 instead of +inf. -- On X11, the environment variable `WINIT_HIDPI_FACTOR` has been added for overriding DPI factor. -- On X11, enabling transparency no longer causes the window contents to flicker when resizing. -- On X11, `with_override_redirect` now actually enables override redirect. -- macOS now generates `VirtualKeyCode::LAlt` and `VirtualKeyCode::RAlt` instead of `None` for both. -- On macOS, `VirtualKeyCode::RWin` and `VirtualKeyCode::LWin` are no longer switched. -- On macOS, windows without decorations can once again be resized. -- Fixed race conditions when creating an `EventsLoop` on X11, most commonly manifesting as "[xcb] Unknown sequence number while processing queue". -- On macOS, `CursorMoved` and `MouseInput` events are only generated if they occurs within the window's client area. -- On macOS, resizing the window no longer generates a spurious `MouseInput` event. +* On X11, the `Moved` event is no longer sent when the window is resized without changing position. +* `MouseCursor` and `CursorState` now implement `Default`. +* `WindowBuilder::with_resizable` implemented for Windows, X11, Wayland, and macOS. +* `Window::set_resizable` implemented for Windows, X11, Wayland, and macOS. +* On X11, if the monitor's width or height in millimeters is reported as 0, the DPI is now 1.0 instead of +inf. +* On X11, the environment variable `WINIT_HIDPI_FACTOR` has been added for overriding DPI factor. +* On X11, enabling transparency no longer causes the window contents to flicker when resizing. +* On X11, `with_override_redirect` now actually enables override redirect. +* macOS now generates `VirtualKeyCode::LAlt` and `VirtualKeyCode::RAlt` instead of `None` for both. +* On macOS, `VirtualKeyCode::RWin` and `VirtualKeyCode::LWin` are no longer switched. +* On macOS, windows without decorations can once again be resized. +* Fixed race conditions when creating an `EventsLoop` on X11, most commonly manifesting as "\[xcb] Unknown sequence number while processing queue". +* On macOS, `CursorMoved` and `MouseInput` events are only generated if they occurs within the window's client area. +* On macOS, resizing the window no longer generates a spurious `MouseInput` event. # Version 0.15.0 (2018-05-22) -- `Icon::to_cardinals` is no longer public, since it was never supposed to be. -- Wayland: improve diagnostics if initialization fails -- Fix some system event key doesn't work when focused, do not block keyevent forward to system on macOS -- On X11, the scroll wheel position is now correctly reset on i3 and other WMs that have the same quirk. -- On X11, `Window::get_current_monitor` now reliably returns the correct monitor. -- On X11, `Window::hidpi_factor` returns values from XRandR rather than the inaccurate values previously queried from the core protocol. -- On X11, the primary monitor is detected correctly even when using versions of XRandR less than 1.5. -- `MonitorId` now implements `Debug`. -- Fixed bug on macOS where using `with_decorations(false)` would cause `set_decorations(true)` to produce a transparent titlebar with no title. -- Implemented `MonitorId::get_position` on macOS. -- On macOS, `Window::get_current_monitor` now returns accurate values. -- Added `WindowBuilderExt::with_resize_increments` to macOS. -- **Breaking:** On X11, `WindowBuilderExt::with_resize_increments` and `WindowBuilderExt::with_base_size` now take `u32` values rather than `i32`. -- macOS keyboard handling has been overhauled, allowing for the use of dead keys, IME, etc. Right modifier keys are also no longer reported as being left. -- Added the `Window::set_ime_spot(x: i32, y: i32)` method, which is implemented on X11 and macOS. -- **Breaking**: `os::unix::WindowExt::send_xim_spot(x: i16, y: i16)` no longer exists. Switch to the new `Window::set_ime_spot(x: i32, y: i32)`, which has equivalent functionality. -- Fixed detection of `Pause` and `Scroll` keys on Windows. -- On Windows, alt-tabbing while the cursor is grabbed no longer makes it impossible to re-grab the cursor. -- On Windows, using `CursorState::Hide` when the cursor is grabbed now ungrabs the cursor first. -- Implemented `MouseCursor::NoneCursor` on Windows. -- Added `WindowBuilder::with_always_on_top` and `Window::set_always_on_top`. Implemented on Windows, macOS, and X11. -- On X11, `WindowBuilderExt` now has `with_class`, `with_override_redirect`, and `with_x11_window_type` to allow for more control over window creation. `WindowExt` additionally has `set_urgent`. -- More hints are set by default on X11, including `_NET_WM_PID` and `WM_CLIENT_MACHINE`. Note that prior to this, the `WM_CLASS` hint was automatically set to whatever value was passed to `with_title`. It's now set to the executable name to better conform to expectations and the specification; if this is undesirable, you must explicitly use `WindowBuilderExt::with_class`. +* `Icon::to_cardinals` is no longer public, since it was never supposed to be. +* Wayland: improve diagnostics if initialization fails +* Fix some system event key doesn't work when focused, do not block keyevent forward to system on macOS +* On X11, the scroll wheel position is now correctly reset on i3 and other WMs that have the same quirk. +* On X11, `Window::get_current_monitor` now reliably returns the correct monitor. +* On X11, `Window::hidpi_factor` returns values from XRandR rather than the inaccurate values previously queried from the core protocol. +* On X11, the primary monitor is detected correctly even when using versions of XRandR less than 1.5. +* `MonitorId` now implements `Debug`. +* Fixed bug on macOS where using `with_decorations(false)` would cause `set_decorations(true)` to produce a transparent titlebar with no title. +* Implemented `MonitorId::get_position` on macOS. +* On macOS, `Window::get_current_monitor` now returns accurate values. +* Added `WindowBuilderExt::with_resize_increments` to macOS. +* **Breaking:** On X11, `WindowBuilderExt::with_resize_increments` and `WindowBuilderExt::with_base_size` now take `u32` values rather than `i32`. +* macOS keyboard handling has been overhauled, allowing for the use of dead keys, IME, etc. Right modifier keys are also no longer reported as being left. +* Added the `Window::set_ime_spot(x: i32, y: i32)` method, which is implemented on X11 and macOS. +* **Breaking**: `os::unix::WindowExt::send_xim_spot(x: i16, y: i16)` no longer exists. Switch to the new `Window::set_ime_spot(x: i32, y: i32)`, which has equivalent functionality. +* Fixed detection of `Pause` and `Scroll` keys on Windows. +* On Windows, alt-tabbing while the cursor is grabbed no longer makes it impossible to re-grab the cursor. +* On Windows, using `CursorState::Hide` when the cursor is grabbed now ungrabs the cursor first. +* Implemented `MouseCursor::NoneCursor` on Windows. +* Added `WindowBuilder::with_always_on_top` and `Window::set_always_on_top`. Implemented on Windows, macOS, and X11. +* On X11, `WindowBuilderExt` now has `with_class`, `with_override_redirect`, and `with_x11_window_type` to allow for more control over window creation. `WindowExt` additionally has `set_urgent`. +* More hints are set by default on X11, including `_NET_WM_PID` and `WM_CLIENT_MACHINE`. Note that prior to this, the `WM_CLASS` hint was automatically set to whatever value was passed to `with_title`. It's now set to the executable name to better conform to expectations and the specification; if this is undesirable, you must explicitly use `WindowBuilderExt::with_class`. # Version 0.14.0 (2018-05-09) -- Created the `Copy`, `Paste` and `Cut` `VirtualKeyCode`s and added support for them on X11 and Wayland -- Fix `.with_decorations(false)` in macOS -- On Mac, `NSWindow` and supporting objects might be alive long after they were `closed` which resulted in apps consuming more heap then needed. Mainly it was affecting multi window applications. Not expecting any user visible change of behaviour after the fix. -- Fix regression of Window platform extensions for macOS where `NSFullSizeContentViewWindowMask` was not being correctly applied to `.fullsize_content_view`. -- Corrected `get_position` on Windows to be relative to the screen rather than to the taskbar. -- Corrected `Moved` event on Windows to use position values equivalent to those returned by `get_position`. It previously supplied client area positions instead of window positions, and would additionally interpret negative values as being very large (around `u16::MAX`). -- Implemented `Moved` event on macOS. -- On X11, the `Moved` event correctly use window positions rather than client area positions. Additionally, a stray `Moved` that unconditionally accompanied `Resized` with the client area position relative to the parent has been eliminated; `Moved` is still received alongside `Resized`, but now only once and always correctly. -- On Windows, implemented all variants of `DeviceEvent` other than `Text`. Mouse `DeviceEvent`s are now received even if the window isn't in the foreground. -- `DeviceId` on Windows is no longer a unit struct, and now contains a `u32`. For `WindowEvent`s, this will always be 0, but on `DeviceEvent`s it will be the handle to that device. `DeviceIdExt::get_persistent_identifier` can be used to acquire a unique identifier for that device that persists across replugs/reboots/etc. -- Corrected `run_forever` on X11 to stop discarding `Awakened` events. -- Various safety and correctness improvements to the X11 backend internals. -- Fixed memory leak on X11 every time the mouse entered the window. -- On X11, drag and drop now works reliably in release mode. -- Added `WindowBuilderExt::with_resize_increments` and `WindowBuilderExt::with_base_size` to X11, allowing for more optional hints to be set. -- Rework of the wayland backend, migrating it to use [Smithay's Client Toolkit](https://github.com/Smithay/client-toolkit). -- Added `WindowBuilder::with_window_icon` and `Window::set_window_icon`, finally making it possible to set the window icon on Windows and X11. The `icon_loading` feature can be enabled to allow for icons to be easily loaded; see example program `window_icon.rs` for usage. -- Windows additionally has `WindowBuilderExt::with_taskbar_icon` and `WindowExt::set_taskbar_icon`. -- On Windows, fix panic when trying to call `set_fullscreen(None)` on a window that has not been fullscreened prior. +* Created the `Copy`, `Paste` and `Cut` `VirtualKeyCode`s and added support for them on X11 and Wayland +* Fix `.with_decorations(false)` in macOS +* On Mac, `NSWindow` and supporting objects might be alive long after they were `closed` which resulted in apps consuming more heap then needed. Mainly it was affecting multi window applications. Not expecting any user visible change of behaviour after the fix. +* Fix regression of Window platform extensions for macOS where `NSFullSizeContentViewWindowMask` was not being correctly applied to `.fullsize_content_view`. +* Corrected `get_position` on Windows to be relative to the screen rather than to the taskbar. +* Corrected `Moved` event on Windows to use position values equivalent to those returned by `get_position`. It previously supplied client area positions instead of window positions, and would additionally interpret negative values as being very large (around `u16::MAX`). +* Implemented `Moved` event on macOS. +* On X11, the `Moved` event correctly use window positions rather than client area positions. Additionally, a stray `Moved` that unconditionally accompanied `Resized` with the client area position relative to the parent has been eliminated; `Moved` is still received alongside `Resized`, but now only once and always correctly. +* On Windows, implemented all variants of `DeviceEvent` other than `Text`. Mouse `DeviceEvent`s are now received even if the window isn't in the foreground. +* `DeviceId` on Windows is no longer a unit struct, and now contains a `u32`. For `WindowEvent`s, this will always be 0, but on `DeviceEvent`s it will be the handle to that device. `DeviceIdExt::get_persistent_identifier` can be used to acquire a unique identifier for that device that persists across replugs/reboots/etc. +* Corrected `run_forever` on X11 to stop discarding `Awakened` events. +* Various safety and correctness improvements to the X11 backend internals. +* Fixed memory leak on X11 every time the mouse entered the window. +* On X11, drag and drop now works reliably in release mode. +* Added `WindowBuilderExt::with_resize_increments` and `WindowBuilderExt::with_base_size` to X11, allowing for more optional hints to be set. +* Rework of the wayland backend, migrating it to use [Smithay's Client Toolkit](https://github.com/Smithay/client-toolkit). +* Added `WindowBuilder::with_window_icon` and `Window::set_window_icon`, finally making it possible to set the window icon on Windows and X11. The `icon_loading` feature can be enabled to allow for icons to be easily loaded; see example program `window_icon.rs` for usage. +* Windows additionally has `WindowBuilderExt::with_taskbar_icon` and `WindowExt::set_taskbar_icon`. +* On Windows, fix panic when trying to call `set_fullscreen(None)` on a window that has not been fullscreened prior. # Version 0.13.1 (2018-04-26) -- Ensure necessary `x11-dl` version is used. +* Ensure necessary `x11-dl` version is used. # Version 0.13.0 (2018-04-25) -- Implement `WindowBuilder::with_maximized`, `Window::set_fullscreen`, `Window::set_maximized` and `Window::set_decorations` for MacOS. -- Implement `WindowBuilder::with_maximized`, `Window::set_fullscreen`, `Window::set_maximized` and `Window::set_decorations` for Windows. -- On Windows, `WindowBuilder::with_fullscreen` no longer changing monitor display resolution. -- Overhauled X11 window geometry calculations. `get_position` and `set_position` are more universally accurate across different window managers, and `get_outer_size` actually works now. -- Fixed SIGSEGV/SIGILL crashes on macOS caused by stabilization of the `!` (never) type. -- Implement `WindowEvent::HiDPIFactorChanged` for macOS -- On X11, input methods now work completely out of the box, no longer requiring application developers to manually call `setlocale`. Additionally, when input methods are started, stopped, or restarted on the server end, it's correctly handled. -- Implemented `Refresh` event on Windows. -- Properly calculate the minimum and maximum window size on Windows, including window decorations. -- Map more `MouseCursor` variants to cursor icons on Windows. -- Corrected `get_position` on macOS to return outer frame position, not content area position. -- Corrected `set_position` on macOS to set outer frame position, not content area position. -- Added `get_inner_position` method to `Window`, which gets the position of the window's client area. This is implemented on all applicable platforms (all desktop platforms other than Wayland, where this isn't possible). -- **Breaking:** the `Closed` event has been replaced by `CloseRequested` and `Destroyed`. To migrate, you typically just need to replace all usages of `Closed` with `CloseRequested`; see example programs for more info. The exception is iOS, where `Closed` must be replaced by `Destroyed`. +* Implement `WindowBuilder::with_maximized`, `Window::set_fullscreen`, `Window::set_maximized` and `Window::set_decorations` for MacOS. +* Implement `WindowBuilder::with_maximized`, `Window::set_fullscreen`, `Window::set_maximized` and `Window::set_decorations` for Windows. +* On Windows, `WindowBuilder::with_fullscreen` no longer changing monitor display resolution. +* Overhauled X11 window geometry calculations. `get_position` and `set_position` are more universally accurate across different window managers, and `get_outer_size` actually works now. +* Fixed SIGSEGV/SIGILL crashes on macOS caused by stabilization of the `!` (never) type. +* Implement `WindowEvent::HiDPIFactorChanged` for macOS +* On X11, input methods now work completely out of the box, no longer requiring application developers to manually call `setlocale`. Additionally, when input methods are started, stopped, or restarted on the server end, it's correctly handled. +* Implemented `Refresh` event on Windows. +* Properly calculate the minimum and maximum window size on Windows, including window decorations. +* Map more `MouseCursor` variants to cursor icons on Windows. +* Corrected `get_position` on macOS to return outer frame position, not content area position. +* Corrected `set_position` on macOS to set outer frame position, not content area position. +* Added `get_inner_position` method to `Window`, which gets the position of the window's client area. This is implemented on all applicable platforms (all desktop platforms other than Wayland, where this isn't possible). +* **Breaking:** the `Closed` event has been replaced by `CloseRequested` and `Destroyed`. To migrate, you typically just need to replace all usages of `Closed` with `CloseRequested`; see example programs for more info. The exception is iOS, where `Closed` must be replaced by `Destroyed`. # Version 0.12.0 (2018-04-06) -- Added subclass to macos windows so they can be made resizable even with no decorations. -- Dead keys now work properly on X11, no longer resulting in a panic. -- On X11, input method creation first tries to use the value from the user's `XMODIFIERS` environment variable, so application developers should no longer need to manually call `XSetLocaleModifiers`. If that fails, fallbacks are tried, which should prevent input method initialization from ever outright failing. -- Fixed thread safety issues with input methods on X11. -- Add support for `Touch` for win32 backend. -- Fixed `Window::get_inner_size` and friends to return the size in pixels instead of points when using HIDPI displays on OSX. +* Added subclass to macos windows so they can be made resizable even with no decorations. +* Dead keys now work properly on X11, no longer resulting in a panic. +* On X11, input method creation first tries to use the value from the user's `XMODIFIERS` environment variable, so application developers should no longer need to manually call `XSetLocaleModifiers`. If that fails, fallbacks are tried, which should prevent input method initialization from ever outright failing. +* Fixed thread safety issues with input methods on X11. +* Add support for `Touch` for win32 backend. +* Fixed `Window::get_inner_size` and friends to return the size in pixels instead of points when using HIDPI displays on OSX. # Version 0.11.3 (2018-03-28) -- Added `set_min_dimensions` and `set_max_dimensions` methods to `Window`, and implemented on Windows, X11, Wayland, and OSX. -- On X11, dropping a `Window` actually closes it now, and clicking the window's × button (or otherwise having the WM signal to close it) will result in the window closing. -- Added `WindowBuilderExt` methods for macos: `with_titlebar_transparent`, - `with_title_hidden`, `with_titlebar_buttons_hidden`, - `with_fullsize_content_view`. -- Mapped X11 numpad keycodes (arrows, Home, End, PageUp, PageDown, Insert and Delete) to corresponding virtual keycodes +* Added `set_min_dimensions` and `set_max_dimensions` methods to `Window`, and implemented on Windows, X11, Wayland, and OSX. +* On X11, dropping a `Window` actually closes it now, and clicking the window's × button (or otherwise having the WM signal to close it) will result in the window closing. +* Added `WindowBuilderExt` methods for macos: `with_titlebar_transparent`, + `with_title_hidden`, `with_titlebar_buttons_hidden`, + `with_fullsize_content_view`. +* Mapped X11 numpad keycodes (arrows, Home, End, PageUp, PageDown, Insert and Delete) to corresponding virtual keycodes # Version 0.11.2 (2018-03-06) -- Impl `Hash`, `PartialEq`, and `Eq` for `events::ModifiersState`. -- Implement `MonitorId::get_hidpi_factor` for MacOS. -- Added method `os::macos::MonitorIdExt::get_nsscreen() -> *mut c_void` that gets a `NSScreen` object matching the monitor ID. -- Send `Awakened` event on Android when event loop is woken up. +* Impl `Hash`, `PartialEq`, and `Eq` for `events::ModifiersState`. +* Implement `MonitorId::get_hidpi_factor` for MacOS. +* Added method `os::macos::MonitorIdExt::get_nsscreen() -> *mut c_void` that gets a `NSScreen` object matching the monitor ID. +* Send `Awakened` event on Android when event loop is woken up. # Version 0.11.1 (2018-02-19) -- Fixed windows not receiving mouse events when click-dragging the mouse outside the client area of a window, on Windows platforms. -- Added method `os::android::EventsLoopExt:set_suspend_callback(Option ()>>)` that allows glutin to register a callback when a suspend event happens +* Fixed windows not receiving mouse events when click-dragging the mouse outside the client area of a window, on Windows platforms. +* Added method `os::android::EventsLoopExt:set_suspend_callback(Option ()>>)` that allows glutin to register a callback when a suspend event happens # Version 0.11.0 (2018-02-09) -- Implement `MonitorId::get_dimensions` for Android. -- Added method `os::macos::WindowBuilderExt::with_movable_by_window_background(bool)` that allows to move a window without a titlebar - `with_decorations(false)` -- Implement `Window::set_fullscreen`, `Window::set_maximized` and `Window::set_decorations` for Wayland. -- Added `Caret` as VirtualKeyCode and support OSX ^-Key with german input. +* Implement `MonitorId::get_dimensions` for Android. +* Added method `os::macos::WindowBuilderExt::with_movable_by_window_background(bool)` that allows to move a window without a titlebar - `with_decorations(false)` +* Implement `Window::set_fullscreen`, `Window::set_maximized` and `Window::set_decorations` for Wayland. +* Added `Caret` as VirtualKeyCode and support OSX ^-Key with german input. # Version 0.10.1 (2018-02-05) -_Yanked_ +*Yanked* # Version 0.10.0 (2017-12-27) -- Add support for `Touch` for emscripten backend. -- Added support for `DroppedFile`, `HoveredFile`, and `HoveredFileCancelled` to X11 backend. -- **Breaking:** `unix::WindowExt` no longer returns pointers for things that aren't actually pointers; `get_xlib_window` now returns `Option` and `get_xlib_screen_id` returns `Option`. Additionally, methods that previously returned `libc::c_void` have been changed to return `std::os::raw::c_void`, which are not interchangeable types, so users wanting the former will need to explicitly cast. -- Added `set_decorations` method to `Window` to allow decorations to be toggled after the window is built. Presently only implemented on X11. -- Raised the minimum supported version of Rust to 1.20 on MacOS due to usage of associated constants in new versions of cocoa and core-graphics. -- Added `modifiers` field to `MouseInput`, `MouseWheel`, and `CursorMoved` events to track the modifiers state (`ModifiersState`). -- Fixed the emscripten backend to return the size of the canvas instead of the size of the window. +* Add support for `Touch` for emscripten backend. +* Added support for `DroppedFile`, `HoveredFile`, and `HoveredFileCancelled` to X11 backend. +* **Breaking:** `unix::WindowExt` no longer returns pointers for things that aren't actually pointers; `get_xlib_window` now returns `Option` and `get_xlib_screen_id` returns `Option`. Additionally, methods that previously returned `libc::c_void` have been changed to return `std::os::raw::c_void`, which are not interchangeable types, so users wanting the former will need to explicitly cast. +* Added `set_decorations` method to `Window` to allow decorations to be toggled after the window is built. Presently only implemented on X11. +* Raised the minimum supported version of Rust to 1.20 on MacOS due to usage of associated constants in new versions of cocoa and core-graphics. +* Added `modifiers` field to `MouseInput`, `MouseWheel`, and `CursorMoved` events to track the modifiers state (`ModifiersState`). +* Fixed the emscripten backend to return the size of the canvas instead of the size of the window. # Version 0.9.0 (2017-12-01) -- Added event `WindowEvent::HiDPIFactorChanged`. -- Added method `MonitorId::get_hidpi_factor`. -- Deprecated `get_inner_size_pixels` and `get_inner_size_points` methods of `Window` in favor of -`get_inner_size`. -- **Breaking:** `EventsLoop` is `!Send` and `!Sync` because of platform-dependant constraints, - but `Window`, `WindowId`, `DeviceId` and `MonitorId` guaranteed to be `Send`. -- `MonitorId::get_position` now returns `(i32, i32)` instead of `(u32, u32)`. -- Rewrite of the wayland backend to use wayland-client-0.11 -- Support for dead keys on wayland for keyboard utf8 input -- Monitor enumeration on Windows is now implemented using `EnumDisplayMonitors` instead of -`EnumDisplayDevices`. This changes the value returned by `MonitorId::get_name()`. -- On Windows added `MonitorIdExt::hmonitor` method -- Impl `Clone` for `EventsLoopProxy` -- `EventsLoop::get_primary_monitor()` on X11 will fallback to any available monitor if no primary is found -- Support for touch event on wayland -- `WindowEvent`s `MouseMoved`, `MouseEntered`, and `MouseLeft` have been renamed to -`CursorMoved`, `CursorEntered`, and `CursorLeft`. -- New `DeviceEvent`s added, `MouseMotion` and `MouseWheel`. -- Send `CursorMoved` event after `CursorEntered` and `Focused` events. -- Add support for `ModifiersState`, `MouseMove`, `MouseInput`, `MouseMotion` for emscripten backend. +* Added event `WindowEvent::HiDPIFactorChanged`. +* Added method `MonitorId::get_hidpi_factor`. +* Deprecated `get_inner_size_pixels` and `get_inner_size_points` methods of `Window` in favor of + `get_inner_size`. +* **Breaking:** `EventsLoop` is `!Send` and `!Sync` because of platform-dependant constraints, + but `Window`, `WindowId`, `DeviceId` and `MonitorId` guaranteed to be `Send`. +* `MonitorId::get_position` now returns `(i32, i32)` instead of `(u32, u32)`. +* Rewrite of the wayland backend to use wayland-client-0.11 +* Support for dead keys on wayland for keyboard utf8 input +* Monitor enumeration on Windows is now implemented using `EnumDisplayMonitors` instead of + `EnumDisplayDevices`. This changes the value returned by `MonitorId::get_name()`. +* On Windows added `MonitorIdExt::hmonitor` method +* Impl `Clone` for `EventsLoopProxy` +* `EventsLoop::get_primary_monitor()` on X11 will fallback to any available monitor if no primary is found +* Support for touch event on wayland +* `WindowEvent`s `MouseMoved`, `MouseEntered`, and `MouseLeft` have been renamed to + `CursorMoved`, `CursorEntered`, and `CursorLeft`. +* New `DeviceEvent`s added, `MouseMotion` and `MouseWheel`. +* Send `CursorMoved` event after `CursorEntered` and `Focused` events. +* Add support for `ModifiersState`, `MouseMove`, `MouseInput`, `MouseMotion` for emscripten backend. # Version 0.8.3 (2017-10-11) -- Fixed issue of calls to `set_inner_size` blocking on Windows. -- Mapped `ISO_Left_Tab` to `VirtualKeyCode::Tab` to make the key work with modifiers -- Fixed the X11 backed on 32bit targets +* Fixed issue of calls to `set_inner_size` blocking on Windows. +* Mapped `ISO_Left_Tab` to `VirtualKeyCode::Tab` to make the key work with modifiers +* Fixed the X11 backed on 32bit targets # Version 0.8.2 (2017-09-28) -- Uniformize keyboard scancode values accross Wayland and X11 (#297). -- Internal rework of the wayland event loop -- Added method `os::linux::WindowExt::is_ready` +* Uniformize keyboard scancode values accross Wayland and X11 (#297). +* Internal rework of the wayland event loop +* Added method `os::linux::WindowExt::is_ready` # Version 0.8.1 (2017-09-22) -- Added various methods to `os::linux::EventsLoopExt`, plus some hidden items necessary to make - glutin work. +* Added various methods to `os::linux::EventsLoopExt`, plus some hidden items necessary to make + glutin work. # Version 0.8.0 (2017-09-21) -- Added `Window::set_maximized`, `WindowAttributes::maximized` and `WindowBuilder::with_maximized`. -- Added `Window::set_fullscreen`. -- Changed `with_fullscreen` to take a `Option` instead of a `MonitorId`. -- Removed `MonitorId::get_native_identifer()` in favor of platform-specific traits in the `os` - module. -- Changed `get_available_monitors()` and `get_primary_monitor()` to be methods of `EventsLoop` - instead of stand-alone methods. -- Changed `EventsLoop` to be tied to a specific X11 or Wayland connection. -- Added a `os::linux::EventsLoopExt` trait that makes it possible to configure the connection. -- Fixed the emscripten code, which now compiles. -- Changed the X11 fullscreen code to use `xrandr` instead of `xxf86vm`. -- Fixed the Wayland backend to produce `Refresh` event after window creation. -- Changed the `Suspended` event to be outside of `WindowEvent`. -- Fixed the X11 backend sometimes reporting the wrong virtual key (#273). +* Added `Window::set_maximized`, `WindowAttributes::maximized` and `WindowBuilder::with_maximized`. +* Added `Window::set_fullscreen`. +* Changed `with_fullscreen` to take a `Option` instead of a `MonitorId`. +* Removed `MonitorId::get_native_identifer()` in favor of platform-specific traits in the `os` + module. +* Changed `get_available_monitors()` and `get_primary_monitor()` to be methods of `EventsLoop` + instead of stand-alone methods. +* Changed `EventsLoop` to be tied to a specific X11 or Wayland connection. +* Added a `os::linux::EventsLoopExt` trait that makes it possible to configure the connection. +* Fixed the emscripten code, which now compiles. +* Changed the X11 fullscreen code to use `xrandr` instead of `xxf86vm`. +* Fixed the Wayland backend to produce `Refresh` event after window creation. +* Changed the `Suspended` event to be outside of `WindowEvent`. +* Fixed the X11 backend sometimes reporting the wrong virtual key (#273). From 2d8d2a7a2628a778be6d8dbe5250effeffa6cf87 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Thu, 28 Apr 2022 22:00:27 -0400 Subject: [PATCH 003/151] Update feature matrix --- FEATURES.md | 319 ++++++++++++++++++++++++++++------------------------ 1 file changed, 175 insertions(+), 144 deletions(-) diff --git a/FEATURES.md b/FEATURES.md index 15aacb6b6b..e247b539af 100644 --- a/FEATURES.md +++ b/FEATURES.md @@ -2,30 +2,32 @@ Winit aims to expose an interface that abstracts over window creation and input handling, and can be used to create both games and applications. It supports the main graphical platforms: -- Desktop - - Windows - - macOS - - Unix - - via X11 - - via Wayland -- Mobile - - iOS - - Android -- Web - - via WASM + +* Desktop + * Windows + * macOS + * Unix + * via X11 + * via Wayland + * via DRM +* Mobile + * iOS + * Android +* Web + * via WASM Most platforms expose capabilities that cannot be meaningfully transposed onto others. Winit does not aim to support every single feature of every platform, but rather to abstract over the common features available everywhere. In this context, APIs exposed in winit can be split into different "support tiers": -- **Core:** Features that are essential to providing a well-formed abstraction over each platform's - windowing and input APIs. -- **Platform:** Platform-specific features that can't be meaningfully exposed through a common API and - cannot be implemented outside of Winit without exposing a significant amount of Winit's internals - or interfering with Winit's abstractions. -- **Usability:** Features that are not strictly essential to Winit's functionality, but provide meaningful - usability improvements and cannot be reasonably implemented in an external crate. These are - generally optional and exposed through Cargo features. +* **Core:** Features that are essential to providing a well-formed abstraction over each platform's + windowing and input APIs. +* **Platform:** Platform-specific features that can't be meaningfully exposed through a common API and + cannot be implemented outside of Winit without exposing a significant amount of Winit's internals + or interfering with Winit's abstractions. +* **Usability:** Features that are not strictly essential to Winit's functionality, but provide meaningful + usability improvements and cannot be reasonably implemented in an external crate. These are + generally optional and exposed through Cargo features. Core features are taken care of by the core Winit maintainers. Platform features are not. When a platform feature is submitted, the submitter is considered the expert in the @@ -42,6 +44,7 @@ be released and the library will enter maintenance mode. For the most part, new be added past this point. New platform features may be accepted and exposed through point releases. ### Tier upgrades + Some platform features could in theory be exposed across multiple platforms, but have not gone through the implementation work necessary to function on all platforms. When one of these features gets implemented across all platforms, a PR can be opened to upgrade the feature to a core feature. @@ -54,188 +57,216 @@ exposed through the core, cross-platform API. If your PR makes notable changes to Winit's features, please update this section as follows: -- If your PR adds a new feature, add a brief description to the relevant section. If the feature is a core - feature, add a row to the feature matrix and describe what platforms the feature has been implemented on. +* If your PR adds a new feature, add a brief description to the relevant section. If the feature is a core + feature, add a row to the feature matrix and describe what platforms the feature has been implemented on. -- If your PR begins a new API rework, add a row to the `Pending API Reworks` table. If the PR implements the - API rework on all relevant platforms, please move it to the `Completed API Reworks` table. +* If your PR begins a new API rework, add a row to the `Pending API Reworks` table. If the PR implements the + API rework on all relevant platforms, please move it to the `Completed API Reworks` table. -- If your PR implements an already-existing feature on a new platform, either mark the feature as *completed*, - or mark it as *mostly completed* and link to an issue describing the problems with the implementation. +* If your PR implements an already-existing feature on a new platform, either mark the feature as *completed*, + or mark it as *mostly completed* and link to an issue describing the problems with the implementation. ## Core ### Windowing -- **Window initialization**: Winit allows the creation of a window -- **Providing pointer to init OpenGL**: Winit provides the necessary pointers to initialize a working opengl context -- **Providing pointer to init Vulkan**: Same as OpenGL but for Vulkan -- **Window decorations**: The windows created by winit are properly decorated, and the decorations can - be deactivated -- **Window decorations toggle**: Decorations can be turned on or off after window creation -- **Window resizing**: The windows created by winit can be resized and generate the appropriate events - when they are. The application can precisely control its window size if desired. -- **Window resize increments**: When the window gets resized, the application can choose to snap the window's - size to specific values. -- **Window transparency**: Winit allows the creation of windows with a transparent background. -- **Window maximization**: The windows created by winit can be maximized upon creation. -- **Window maximization toggle**: The windows created by winit can be maximized and unmaximized after - creation. -- **Window minimization**: The windows created by winit can be minimized after creation. -- **Fullscreen**: The windows created by winit can be put into fullscreen mode. -- **Fullscreen toggle**: The windows created by winit can be switched to and from fullscreen after - creation. -- **Exclusive fullscreen**: Winit allows changing the video mode of the monitor - for fullscreen windows, and if applicable, captures the monitor for exclusive - use by this application. -- **HiDPI support**: Winit assists developers in appropriately scaling HiDPI content. -- **Popup / modal windows**: Windows can be created relative to the client area of other windows, and parent - windows can be disabled in favor of popup windows. This feature also guarantees that popup windows - get drawn above their owner. +* **Window initialization**: Winit allows the creation of a window +* **Providing pointer to init OpenGL**: Winit provides the necessary pointers to initialize a working opengl context +* **Providing pointer to init Vulkan**: Same as OpenGL but for Vulkan +* **Window decorations**: The windows created by winit are properly decorated, and the decorations can + be deactivated +* **Window decorations toggle**: Decorations can be turned on or off after window creation +* **Window resizing**: The windows created by winit can be resized and generate the appropriate events + when they are. The application can precisely control its window size if desired. +* **Window resize increments**: When the window gets resized, the application can choose to snap the window's + size to specific values. +* **Window transparency**: Winit allows the creation of windows with a transparent background. +* **Window maximization**: The windows created by winit can be maximized upon creation. +* **Window maximization toggle**: The windows created by winit can be maximized and unmaximized after + creation. +* **Window minimization**: The windows created by winit can be minimized after creation. +* **Fullscreen**: The windows created by winit can be put into fullscreen mode. +* **Fullscreen toggle**: The windows created by winit can be switched to and from fullscreen after + creation. +* **Exclusive fullscreen**: Winit allows changing the video mode of the monitor + for fullscreen windows, and if applicable, captures the monitor for exclusive + use by this application. +* **HiDPI support**: Winit assists developers in appropriately scaling HiDPI content. +* **Popup / modal windows**: Windows can be created relative to the client area of other windows, and parent + windows can be disabled in favor of popup windows. This feature also guarantees that popup windows + get drawn above their owner. ### System Information -- **Monitor list**: Retrieve the list of monitors and their metadata, including which one is primary. -- **Video mode query**: Monitors can be queried for their supported fullscreen video modes (consisting of resolution, refresh rate, and bit depth). + +* **Monitor list**: Retrieve the list of monitors and their metadata, including which one is primary. +* **Video mode query**: Monitors can be queried for their supported fullscreen video modes (consisting of resolution, refresh rate, and bit depth). ### Input Handling -- **Mouse events**: Generating mouse events associated with pointer motion, click, and scrolling events. -- **Mouse set location**: Forcibly changing the location of the pointer. -- **Cursor grab**: Locking the cursor so it cannot exit the client area of a window. -- **Cursor icon**: Changing the cursor icon, or hiding the cursor. -- **Cursor hittest**: Handle or ignore mouse events for a window. -- **Touch events**: Single-touch events. -- **Touch pressure**: Touch events contain information about the amount of force being applied. -- **Multitouch**: Multi-touch events, including cancellation of a gesture. -- **Keyboard events**: Properly processing keyboard events using the user-specified keymap and - translating keypresses into UTF-8 characters, handling dead keys and IMEs. -- **Drag & Drop**: Dragging content into winit, detecting when content enters, drops, or if the drop is cancelled. -- **Raw Device Events**: Capturing input from input devices without any OS filtering. -- **Gamepad/Joystick events**: Capturing input from gamepads and joysticks. -- **Device movement events**: Capturing input from the device gyroscope and accelerometer. + +* **Mouse events**: Generating mouse events associated with pointer motion, click, and scrolling events. +* **Mouse set location**: Forcibly changing the location of the pointer. +* **Cursor grab**: Locking the cursor so it cannot exit the client area of a window. +* **Cursor icon**: Changing the cursor icon, or hiding the cursor. +* **Cursor hittest**: Handle or ignore mouse events for a window. +* **Touch events**: Single-touch events. +* **Touch pressure**: Touch events contain information about the amount of force being applied. +* **Multitouch**: Multi-touch events, including cancellation of a gesture. +* **Keyboard events**: Properly processing keyboard events using the user-specified keymap and + translating keypresses into UTF-8 characters, handling dead keys and IMEs. +* **Drag & Drop**: Dragging content into winit, detecting when content enters, drops, or if the drop is cancelled. +* **Raw Device Events**: Capturing input from input devices without any OS filtering. +* **Gamepad/Joystick events**: Capturing input from gamepads and joysticks. +* **Device movement events**: Capturing input from the device gyroscope and accelerometer. ## Platform + ### Windows -* Setting the taskbar icon -* Setting the parent window -* Setting a menu bar -* `WS_EX_NOREDIRECTIONBITMAP` support -* Theme the title bar according to Windows 10 Dark Mode setting or set a preferred theme + +* Setting the taskbar icon +* Setting the parent window +* Setting a menu bar +* `WS_EX_NOREDIRECTIONBITMAP` support +* Theme the title bar according to Windows 10 Dark Mode setting or set a preferred theme ### macOS -* Window activation policy -* Window movable by background -* Transparent titlebar -* Hidden titlebar -* Hidden titlebar buttons -* Full-size content view + +* Window activation policy +* Window movable by background +* Transparent titlebar +* Hidden titlebar +* Hidden titlebar buttons +* Full-size content view ### Unix -* Window urgency -* X11 Window Class -* X11 Override Redirect Flag -* GTK Theme Variant -* Base window size + +* Window urgency +* X11 Window Class +* X11 Override Redirect Flag +* GTK Theme Variant +* Base window size ### iOS -* `winit` has a minimum OS requirement of iOS 8 -* Get the `UIWindow` object pointer -* Get the `UIViewController` object pointer -* Get the `UIView` object pointer -* Get the `UIScreen` object pointer -* Setting the `UIView` hidpi factor -* Valid orientations -* Home indicator visibility -* Status bar visibility -* Deferrring system gestures -* Support for custom `UIView` derived class -* Getting the device idiom -* Getting the preferred video mode + +* `winit` has a minimum OS requirement of iOS 8 +* Get the `UIWindow` object pointer +* Get the `UIViewController` object pointer +* Get the `UIView` object pointer +* Get the `UIScreen` object pointer +* Setting the `UIView` hidpi factor +* Valid orientations +* Home indicator visibility +* Status bar visibility +* Deferrring system gestures +* Support for custom `UIView` derived class +* Getting the device idiom +* Getting the preferred video mode ### Web -* Get if systems preferred color scheme is "dark" + +* Get if systems preferred color scheme is "dark" ## Usability -* `serde`: Enables serialization/deserialization of certain types with Serde. (Maintainer: @Osspial) + +* `serde`: Enables serialization/deserialization of certain types with Serde. (Maintainer: @Osspial) ## Compatibility Matrix Legend: -- ✔️: Works as intended -- ▢: Mostly works but some bugs are known -- ❌: Missing feature or large bugs making it unusable -- **N/A**: Not applicable for this platform -- ❓: Unknown status +* ✔️: Works as intended +* ▢: Mostly works but some bugs are known +* ❌: Missing feature or large bugs making it unusable +* **N/A**: Not applicable for this platform +* ❓: Unknown status ### Windowing -|Feature |Windows|MacOS |Linux x11 |Linux Wayland |Android|iOS |WASM | -|-------------------------------- | ----- | ---- | ------- | ----------- | ----- | ----- | -------- | -|Window initialization |✔️ |✔️ |▢[#5] |✔️ |▢[#33]|▢[#33] |✔️ | -|Providing pointer to init OpenGL |✔️ |✔️ |✔️ |✔️ |✔️ |✔️ |**N/A**| -|Providing pointer to init Vulkan |✔️ |✔️ |✔️ |✔️ |✔️ |❓ |**N/A**| -|Window decorations |✔️ |✔️ |✔️ |▢[#306] |**N/A**|**N/A**|**N/A**| -|Window decorations toggle |✔️ |✔️ |✔️ |✔️ |**N/A**|**N/A**|**N/A**| -|Window resizing |✔️ |▢[#219]|✔️ |▢[#306] |**N/A**|**N/A**|✔️ | -|Window resize increments |❌ |❌ |❌ |❌ |❌ |❌ |**N/A**| -|Window transparency |✔️ |✔️ |✔️ |✔️ |**N/A**|**N/A**|N/A | -|Window maximization |✔️ |✔️ |✔️ |✔️ |**N/A**|**N/A**|**N/A**| -|Window maximization toggle |✔️ |✔️ |✔️ |✔️ |**N/A**|**N/A**|**N/A**| -|Window minimization |✔️ |✔️ |✔️ |✔️ |**N/A**|**N/A**|**N/A**| -|Fullscreen |✔️ |✔️ |✔️ |✔️ |**N/A**|✔️ |✔️ | -|Fullscreen toggle |✔️ |✔️ |✔️ |✔️ |**N/A**|✔️ |✔️ | -|Exclusive fullscreen |✔️ |✔️ |✔️ |**N/A** |❌ |✔️ |**N/A**| -|HiDPI support |✔️ |✔️ |✔️ |✔️ |▢[#721]|✔️ |✔️ | -|Popup windows |❌ |❌ |❌ |❌ |❌ |❌ |**N/A**| + +|Feature |Windows|MacOS |Linux x11 |Linux Wayland |Linux DRM |Android|iOS |WASM | +|-------------------------------- | ----- | ---- | ------- | ----------- | ----- | ----- | ----- | -------- | +|Window initialization |✔️ |✔️ |▢[#5] |✔️ |✔️ |▢[#33]|▢[#33] |✔️ | +|Providing pointer to init OpenGL |✔️ |✔️ |✔️ |✔️ | |✔️ |✔️ |**N/A**| +|Providing pointer to init Vulkan |✔️ |✔️ |✔️ |✔️ | |✔️ |❓ |**N/A**| +|Window decorations |✔️ |✔️ |✔️ |▢[#306] |**N/A** |**N/A**|**N/A**|**N/A**| +|Window decorations toggle |✔️ |✔️ |✔️ |✔️ |**N/A** |**N/A**|**N/A**|**N/A**| +|Window resizing |✔️ |▢[#219]|✔️ |▢[#306] |**N/A** |**N/A**|**N/A**|✔️ | +|Window resize increments |❌ |❌ |❌ |❌ |**N/A** |❌ |❌ |**N/A**| +|Window transparency |✔️ |✔️ |✔️ |✔️ |**N/A** |**N/A**|**N/A**|N/A | +|Window maximization |✔️ |✔️ |✔️ |✔️ |**N/A** |**N/A**|**N/A**|**N/A**| +|Window maximization toggle |✔️ |✔️ |✔️ |✔️ |**N/A** |**N/A**|**N/A**|**N/A**| +|Window minimization |✔️ |✔️ |✔️ |✔️ |**N/A** |**N/A**|**N/A**|**N/A**| +|Fullscreen |✔️ |✔️ |✔️ |✔️ |**N/A** |**N/A**|✔️ |✔️ | +|Fullscreen toggle |✔️ |✔️ |✔️ |✔️ |**N/A** |**N/A**|✔️ |✔️ | +|Exclusive fullscreen |✔️ |✔️ |✔️ |**N/A** |✔️ |❌ |✔️ |**N/A**| +|HiDPI support |✔️ |✔️ |✔️ |✔️ |❌ |▢[#721]|✔️ |✔️ | +|Popup windows |❌ |❌ |❌ |❌ |❌ |❌ |❌ |**N/A**| ### System information -|Feature |Windows|MacOS |Linux x11|Linux Wayland|Android|iOS |WASM | -|---------------- | ----- | ---- | ------- | ----------- | ----- | ------- | -------- | -|Monitor list |✔️ |✔️ |✔️ |✔️ |**N/A**|✔️ |**N/A**| -|Video mode query |✔️ |✔️ |✔️ |✔️ |❌ |✔️ |**N/A**| + +|Feature |Windows|MacOS |Linux x11|Linux Wayland|Linux DRM|Android|iOS |WASM | +|---------------- | ----- | ---- | ------- | ----------- | ----- | ---- | ------- | -------- | +|Monitor list |✔️ |✔️ |✔️ |✔️ |✔️ |**N/A**|✔️ |**N/A**| +|Video mode query |✔️ |✔️ |✔️ |✔️ |✔️ |❌ |✔️ |**N/A**| ### Input handling -|Feature |Windows |MacOS |Linux x11|Linux Wayland|Android|iOS |WASM | + +|Feature |Windows |MacOS |Linux x11|Linux Wayland|Linux DRM|Android|iOS |WASM | |----------------------- | ----- | ---- | ------- | ----------- | ----- | ----- | -------- | -|Mouse events |✔️ |▢[#63] |✔️ |✔️ |**N/A**|**N/A**|✔️ | -|Mouse set location |✔️ |✔️ |✔️ |❓ |**N/A**|**N/A**|**N/A**| -|Cursor grab |✔️ |▢[#165] |▢[#242] |✔️ |**N/A**|**N/A**|✔️ | -|Cursor icon |✔️ |✔️ |✔️ |✔️ |**N/A**|**N/A**|✔️ | -|Cursor hittest |✔️ |✔️ |❌ |✔️ |**N/A**|**N/A**|❌ | -|Touch events |✔️ |❌ |✔️ |✔️ |✔️ |✔️ |❌ | -|Touch pressure |✔️ |❌ |❌ |❌ |❌ |✔️ |❌ | -|Multitouch |✔️ |❌ |✔️ |✔️ |✔️ |✔️ |❌ | -|Keyboard events |✔️ |✔️ |✔️ |✔️ |❓ |❌ |✔️ | -|Drag & Drop |▢[#720] |▢[#720] |▢[#720] |❌[#306] |**N/A**|**N/A**|❓ | -|Raw Device Events |▢[#750] |▢[#750] |▢[#750] |❌ |❌ |❌ |❓ | -|Gamepad/Joystick events |❌[#804] |❌ |❌ |❌ |❌ |❌ |❓ | -|Device movement events |❓ |❓ |❓ |❓ |❌ |❌ |❓ | -|Drag window with cursor |✔️ |✔️ |✔️ |✔️ |**N/A**|**N/A**|**N/A** | +|Mouse events |✔️ |▢[#63] |✔️ |✔️ |✔️ |**N/A**|**N/A**|✔️ | +|Mouse set location |✔️ |✔️ |✔️ |❓ |✔️ |**N/A**|**N/A**|**N/A**| +|Cursor grab |✔️ |▢[#165] |▢[#242] |✔️ |**N/A** |**N/A**|**N/A**|✔️ | +|Cursor icon |✔️ |✔️ |✔️ |✔️ |❌ |**N/A**|**N/A**|✔️ | +|Cursor hittest |✔️ |✔️ |❌ |✔️ |❌ |**N/A**|**N/A**|❌ | +|Touch events |✔️ |❌ |✔️ |✔️ |✔️ |✔️ |✔️ |❌ | +|Touch pressure |✔️ |❌ |❌ |❌ |✔️ |❌ |✔️ |❌ | +|Multitouch |✔️ |❌ |✔️ |✔️ |✔️ |✔️ |✔️ |❌ | +|Keyboard events |✔️ |✔️ |✔️ |✔️ |✔️ |❓ |❌ |✔️ | +|Drag & Drop |▢[#720] |▢[#720] |▢[#720] |❌[#306] |**N/A** |**N/A**|**N/A**|❓ | +|Raw Device Events |▢[#750] |▢[#750] |▢[#750] |❌ |✔️ |❌ |❌ |❓ | +|Gamepad/Joystick events |❌[#804] |❌ |❌ |❌ |❌ |❌ |❌ |❓ | +|Device movement events |❓ |❓ |❓ |❓ |❌ |❌ |❌ |❓ | +|Drag window with cursor |✔️ |✔️ |✔️ |✔️ |**N/A** |**N/A**|**N/A**|**N/A** | ### Pending API Reworks + Changes in the API that have been agreed upon but aren't implemented across all platforms. -|Feature |Windows|MacOS |Linux x11|Linux Wayland|Android|iOS |WASM | -|------------------------------ | ----- | ---- | ------- | ----------- | ----- | ----- | -------- | -|New API for HiDPI ([#315] [#319]) |✔️ |✔️ |✔️ |✔️ |▢[#721]|✔️ |❓ | -|Event Loop 2.0 ([#459]) |✔️ |✔️ |❌ |✔️ |❌ |✔️ |❓ | -|Keyboard Input ([#812]) |❌ |❌ |❌ |❌ |❌ |❌ |❓ | +|Feature |Windows|MacOS |Linux x11|Linux Wayland|Linux DRM|Android|iOS |WASM | +|------------------------------ | ----- | ---- | ------- | ----------- | ----- | ----- | ----- | -------- | +|New API for HiDPI ([#315] [#319]) |✔️ |✔️ |✔️ |✔️ |❌ |▢[#721]|✔️ |❓ | +|Event Loop 2.0 ([#459]) |✔️ |✔️ |❌ |✔️ |❌ |❌ |✔️ |❓ | +|Keyboard Input ([#812]) |❌ |❌ |❌ |❌ |❌ |❌ |❌ |❓ | ### Completed API Reworks + |Feature |Windows|MacOS |Linux x11|Linux Wayland|Android|iOS |WASM | |------------------------------ | ----- | ---- | ------- | ----------- | ----- | ----- | -------- | [#165]: https://github.com/rust-windowing/winit/issues/165 + [#219]: https://github.com/rust-windowing/winit/issues/219 + [#242]: https://github.com/rust-windowing/winit/issues/242 + [#306]: https://github.com/rust-windowing/winit/issues/306 + [#315]: https://github.com/rust-windowing/winit/issues/315 + [#319]: https://github.com/rust-windowing/winit/issues/319 + [#33]: https://github.com/rust-windowing/winit/issues/33 + [#459]: https://github.com/rust-windowing/winit/issues/459 + [#5]: https://github.com/rust-windowing/winit/issues/5 + [#63]: https://github.com/rust-windowing/winit/issues/63 + [#720]: https://github.com/rust-windowing/winit/issues/720 + [#721]: https://github.com/rust-windowing/winit/issues/721 + [#750]: https://github.com/rust-windowing/winit/issues/750 + [#804]: https://github.com/rust-windowing/winit/issues/804 + [#812]: https://github.com/rust-windowing/winit/issues/812 From e7ce9d174f5f5a9a7d7cac63c14d87aa36f1c171 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Thu, 28 Apr 2022 22:21:52 -0400 Subject: [PATCH 004/151] Fix stupid warning --- src/platform_impl/linux/drm/event_loop.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index 7513447879..ff54a3d183 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -1,5 +1,4 @@ use std::{ - cell::RefCell, collections::VecDeque, marker::PhantomData, os::unix::prelude::{AsRawFd, FromRawFd, IntoRawFd, OpenOptionsExt, RawFd}, From 1cb284e17f3371fa9d20748abe0d163da53008a0 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Thu, 28 Apr 2022 23:26:12 -0400 Subject: [PATCH 005/151] Fix formatting --- CHANGELOG.md | 1312 +++++++++++++++++++++++++------------------------- Cargo.toml | 160 +++--- FEATURES.md | 172 +++---- 3 files changed, 829 insertions(+), 815 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ec5f2fe5c1..dd65bc40e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,788 +8,788 @@ And please only add new entries to the top of this list, right below the `# Unre # Unreleased -* On Linux kmsdrm support is being worked on -* On macOS, Windows, and Wayland, add `set_cursor_hittest` to let the window ignore mouse events. -* On Windows, added `WindowExtWindows::set_skip_taskbar` and `WindowBuilderExtWindows::with_skip_taskbar`. -* On Windows, added `EventLoopBuilderExtWindows::with_msg_hook`. -* On Windows, remove internally unique DC per window. -* On macOS, remove the need to call `set_ime_position` after moving the window. -* Added `Window::is_visible`. -* Added `Window::is_resizable`. -* Added `Window::is_decorated`. -* On X11, fix for repeated event loop iteration when `ControlFlow` was `Wait` -* On X11, fix scale factor calculation when the only monitor is reconnected -* On Wayland, report unaccelerated mouse deltas in `DeviceEvent::MouseMotion`. -* **Breaking:** Bump `ndk` version to 0.6, ndk-sys to `v0.3`, `ndk-glue` to `0.6`. -* Remove no longer needed `WINIT_LINK_COLORSYNC` environment variable. -* **Breaking:** Rename the `Exit` variant of `ControlFlow` to `ExitWithCode`, which holds a value to control the exit code after running. Add an `Exit` constant which aliases to `ExitWithCode(0)` instead to avoid major breakage. This shouldn't affect most existing programs. -* Add `EventLoopBuilder`, which allows you to create and tweak the settings of an event loop before creating it. -* Deprecated `EventLoop::with_user_event`; use `EventLoopBuilder::with_user_event` instead. -* **Breaking:** Replaced `EventLoopExtMacOS` with `EventLoopBuilderExtMacOS` (which also has renamed methods). -* **Breaking:** Replaced `EventLoopExtWindows` with `EventLoopBuilderExtWindows` (which also has renamed methods). -* **Breaking:** Replaced `EventLoopExtUnix` with `EventLoopBuilderExtUnix` (which also has renamed methods). -* **Breaking:** The platform specific extensions for Windows `winit::platform::windows` have changed. All `HANDLE`-like types e.g. `HWND` and `HMENU` were converted from winapi types or `*mut c_void` to `isize`. This was done to be consistent with the type definitions in windows-sys and to not expose internal dependencies. -* The internal bindings to the [Windows API](https://docs.microsoft.com/en-us/windows/) were changed from the unofficial [winapi](https://github.com/retep998/winapi-rs) bindings to the official Microsoft [windows-sys](https://github.com/microsoft/windows-rs) bindings. -* On Wayland, fix resize and scale factor changes not being propagated properly. -* On Wayland, fix polling during consecutive `EventLoop::run_return` invocations. -* On Windows, fix race issue creating fullscreen windows with `WindowBuilder::with_fullscreen` -* On Android, `virtual_keycode` for `KeyboardInput` events is now filled in where a suitable match is found. -* Added helper methods on `ControlFlow` to set its value. -* On Wayland, fix `TouchPhase::Ended` always reporting the location of the first touch down, unless the compositor - sent a cancel or frame event. -* On iOS, send `RedrawEventsCleared` even if there are no redraw events, consistent with other platforms. -* **Breaking:** Replaced `Window::with_app_id` and `Window::with_class` with `Window::with_name` on `WindowBuilderExtUnix`. -* On Wayland and X11, fix window not resizing with `Window::set_inner_size` after calling `Window:set_resizable(false)`. +- On Linux, initial support has been added for a kmsdrm backend +- On macOS, Windows, and Wayland, add `set_cursor_hittest` to let the window ignore mouse events. +- On Windows, added `WindowExtWindows::set_skip_taskbar` and `WindowBuilderExtWindows::with_skip_taskbar`. +- On Windows, added `EventLoopBuilderExtWindows::with_msg_hook`. +- On Windows, remove internally unique DC per window. +- On macOS, remove the need to call `set_ime_position` after moving the window. +- Added `Window::is_visible`. +- Added `Window::is_resizable`. +- Added `Window::is_decorated`. +- On X11, fix for repeated event loop iteration when `ControlFlow` was `Wait` +- On X11, fix scale factor calculation when the only monitor is reconnected +- On Wayland, report unaccelerated mouse deltas in `DeviceEvent::MouseMotion`. +- **Breaking:** Bump `ndk` version to 0.6, ndk-sys to `v0.3`, `ndk-glue` to `0.6`. +- Remove no longer needed `WINIT_LINK_COLORSYNC` environment variable. +- **Breaking:** Rename the `Exit` variant of `ControlFlow` to `ExitWithCode`, which holds a value to control the exit code after running. Add an `Exit` constant which aliases to `ExitWithCode(0)` instead to avoid major breakage. This shouldn't affect most existing programs. +- Add `EventLoopBuilder`, which allows you to create and tweak the settings of an event loop before creating it. +- Deprecated `EventLoop::with_user_event`; use `EventLoopBuilder::with_user_event` instead. +- **Breaking:** Replaced `EventLoopExtMacOS` with `EventLoopBuilderExtMacOS` (which also has renamed methods). +- **Breaking:** Replaced `EventLoopExtWindows` with `EventLoopBuilderExtWindows` (which also has renamed methods). +- **Breaking:** Replaced `EventLoopExtUnix` with `EventLoopBuilderExtUnix` (which also has renamed methods). +- **Breaking:** The platform specific extensions for Windows `winit::platform::windows` have changed. All `HANDLE`-like types e.g. `HWND` and `HMENU` were converted from winapi types or `*mut c_void` to `isize`. This was done to be consistent with the type definitions in windows-sys and to not expose internal dependencies. +- The internal bindings to the [Windows API](https://docs.microsoft.com/en-us/windows/) were changed from the unofficial [winapi](https://github.com/retep998/winapi-rs) bindings to the official Microsoft [windows-sys](https://github.com/microsoft/windows-rs) bindings. +- On Wayland, fix resize and scale factor changes not being propagated properly. +- On Wayland, fix polling during consecutive `EventLoop::run_return` invocations. +- On Windows, fix race issue creating fullscreen windows with `WindowBuilder::with_fullscreen` +- On Android, `virtual_keycode` for `KeyboardInput` events is now filled in where a suitable match is found. +- Added helper methods on `ControlFlow` to set its value. +- On Wayland, fix `TouchPhase::Ended` always reporting the location of the first touch down, unless the compositor + sent a cancel or frame event. +- On iOS, send `RedrawEventsCleared` even if there are no redraw events, consistent with other platforms. +- **Breaking:** Replaced `Window::with_app_id` and `Window::with_class` with `Window::with_name` on `WindowBuilderExtUnix`. +- On Wayland and X11, fix window not resizing with `Window::set_inner_size` after calling `Window:set_resizable(false)`. # 0.26.1 (2022-01-05) -* Fix linking to the `ColorSync` framework on macOS 10.7, and in newer Rust versions. -* On Web, implement cursor grabbing through the pointer lock API. -* On X11, add mappings for numpad comma, numpad enter, numlock and pause. -* On macOS, fix Pinyin IME input by reverting a change that intended to improve IME. -* On Windows, fix a crash with transparent windows on Windows 11. -* **Breaking:**: Reverse horizontal scrolling sign in `MouseScrollDelta` to match the direction of vertical scrolling. A positive X value now means moving the content to the right. The meaning of vertical scrolling stays the same: a positive Y value means moving the content down. +- Fix linking to the `ColorSync` framework on macOS 10.7, and in newer Rust versions. +- On Web, implement cursor grabbing through the pointer lock API. +- On X11, add mappings for numpad comma, numpad enter, numlock and pause. +- On macOS, fix Pinyin IME input by reverting a change that intended to improve IME. +- On Windows, fix a crash with transparent windows on Windows 11. +- **Breaking:**: Reverse horizontal scrolling sign in `MouseScrollDelta` to match the direction of vertical scrolling. A positive X value now means moving the content to the right. The meaning of vertical scrolling stays the same: a positive Y value means moving the content down. # 0.26.0 (2021-12-01) -* Update `raw-window-handle` to `v0.4`. This is *not* a breaking change, we still implement `HasRawWindowHandle` from `v0.3`, see [rust-windowing/raw-window-handle#74](https://github.com/rust-windowing/raw-window-handle/pull/74). Note that you might have to run `cargo update -p raw-window-handle` after upgrading. -* On X11, bump `mio` to 0.8. -* On Android, fixed `WindowExtAndroid::config` initially returning an empty `Configuration`. -* On Android, fixed `Window::scale_factor` and `MonitorHandle::scale_factor` initially always returning 1.0. -* On X11, select an appropriate visual for transparency if is requested -* On Wayland and X11, fix diagonal window resize cursor orientation. -* On macOS, drop the event callback before exiting. -* On Android, implement `Window::request_redraw` -* **Breaking:** On Web, remove the `stdweb` backend. -* Added `Window::focus_window`to bring the window to the front and set input focus. -* On Wayland and X11, implement `is_maximized` method on `Window`. -* On Windows, prevent ghost window from showing up in the taskbar after either several hours of use or restarting `explorer.exe`. -* On macOS, fix issue where `ReceivedCharacter` was not being emitted during some key repeat events. -* On Wayland, load cursor icons `hand2` and `hand1` for `CursorIcon::Hand`. -* **Breaking:** On Wayland, Theme trait and its support types are dropped. -* On Wayland, bump `smithay-client-toolkit` to 0.15.1. -* On Wayland, implement `request_user_attention` with `xdg_activation_v1`. -* On X11, emit missing `WindowEvent::ScaleFactorChanged` when the only monitor gets reconnected. -* On X11, if RANDR based scale factor is higher than 20 reset it to 1 -* On Wayland, add an enabled-by-default feature called `wayland-dlopen` so users can opt out of using `dlopen` to load system libraries. -* **Breaking:** On Android, bump `ndk` and `ndk-glue` to 0.5. -* On Windows, increase wait timer resolution for more accurate timing when using `WaitUntil`. -* On macOS, fix native file dialogs hanging the event loop. -* On Wayland, implement a workaround for wrong configure size when using `xdg_decoration` in `kwin_wayland` -* On macOS, fix an issue that prevented the menu bar from showing in borderless fullscreen mode. -* On X11, EINTR while polling for events no longer causes a panic. Instead it will be treated as a spurious wakeup. +- Update `raw-window-handle` to `v0.4`. This is _not_ a breaking change, we still implement `HasRawWindowHandle` from `v0.3`, see [rust-windowing/raw-window-handle#74](https://github.com/rust-windowing/raw-window-handle/pull/74). Note that you might have to run `cargo update -p raw-window-handle` after upgrading. +- On X11, bump `mio` to 0.8. +- On Android, fixed `WindowExtAndroid::config` initially returning an empty `Configuration`. +- On Android, fixed `Window::scale_factor` and `MonitorHandle::scale_factor` initially always returning 1.0. +- On X11, select an appropriate visual for transparency if is requested +- On Wayland and X11, fix diagonal window resize cursor orientation. +- On macOS, drop the event callback before exiting. +- On Android, implement `Window::request_redraw` +- **Breaking:** On Web, remove the `stdweb` backend. +- Added `Window::focus_window`to bring the window to the front and set input focus. +- On Wayland and X11, implement `is_maximized` method on `Window`. +- On Windows, prevent ghost window from showing up in the taskbar after either several hours of use or restarting `explorer.exe`. +- On macOS, fix issue where `ReceivedCharacter` was not being emitted during some key repeat events. +- On Wayland, load cursor icons `hand2` and `hand1` for `CursorIcon::Hand`. +- **Breaking:** On Wayland, Theme trait and its support types are dropped. +- On Wayland, bump `smithay-client-toolkit` to 0.15.1. +- On Wayland, implement `request_user_attention` with `xdg_activation_v1`. +- On X11, emit missing `WindowEvent::ScaleFactorChanged` when the only monitor gets reconnected. +- On X11, if RANDR based scale factor is higher than 20 reset it to 1 +- On Wayland, add an enabled-by-default feature called `wayland-dlopen` so users can opt out of using `dlopen` to load system libraries. +- **Breaking:** On Android, bump `ndk` and `ndk-glue` to 0.5. +- On Windows, increase wait timer resolution for more accurate timing when using `WaitUntil`. +- On macOS, fix native file dialogs hanging the event loop. +- On Wayland, implement a workaround for wrong configure size when using `xdg_decoration` in `kwin_wayland` +- On macOS, fix an issue that prevented the menu bar from showing in borderless fullscreen mode. +- On X11, EINTR while polling for events no longer causes a panic. Instead it will be treated as a spurious wakeup. # 0.25.0 (2021-05-15) -* **Breaking:** On macOS, replace `WindowBuilderExtMacOS::with_activation_policy` with `EventLoopExtMacOS::set_activation_policy` -* On macOS, wait with activating the application until the application has initialized. -* On macOS, fix creating new windows when the application has a main menu. -* On Windows, fix fractional deltas for mouse wheel device events. -* On macOS, fix segmentation fault after dropping the main window. -* On Android, `InputEvent::KeyEvent` is partially implemented providing the key scancode. -* Added `is_maximized` method to `Window`. -* On Windows, fix bug where clicking the decoration bar would make the cursor blink. -* On Windows, fix bug causing newly created windows to erroneously display the "wait" (spinning) cursor. -* On macOS, wake up the event loop immediately when a redraw is requested. -* On Windows, change the default window size (1024x768) to match the default on other desktop platforms (800x600). -* On Windows, fix bug causing mouse capture to not be released. -* On Windows, fix fullscreen not preserving minimized/maximized state. -* On Android, unimplemented events are marked as unhandled on the native event loop. -* On Windows, added `WindowBuilderExtWindows::with_menu` to set a custom menu at window creation time. -* On Android, bump `ndk` and `ndk-glue` to 0.3: use predefined constants for event `ident`. -* On macOS, fix objects captured by the event loop closure not being dropped on panic. -* On Windows, fixed `WindowEvent::ThemeChanged` not properly firing and fixed `Window::theme` returning the wrong theme. -* On Web, added support for `DeviceEvent::MouseMotion` to listen for relative mouse movements. -* Added `WindowBuilder::with_position` to allow setting the position of a `Window` on creation. Supported on Windows, macOS and X11. -* Added `Window::drag_window`. Implemented on Windows, macOS, X11 and Wayland. -* On X11, bump `mio` to 0.7. -* On Windows, added `WindowBuilderExtWindows::with_owner_window` to allow creating popup windows. -* On Windows, added `WindowExtWindows::set_enable` to allow creating modal popup windows. -* On macOS, emit `RedrawRequested` events immediately while the window is being resized. -* Implement `Default`, `Hash`, and `Eq` for `LogicalPosition`, `PhysicalPosition`, `LogicalSize`, and `PhysicalSize`. -* On macOS, initialize the Menu Bar with minimal defaults. (Can be prevented using `enable_default_menu_creation`) -* On macOS, change the default behavior for first click when the window was unfocused. Now the window becomes focused and then emits a `MouseInput` event on a "first mouse click". -* Implement mint (math interoperability standard types) conversions (under feature flag `mint`). +- **Breaking:** On macOS, replace `WindowBuilderExtMacOS::with_activation_policy` with `EventLoopExtMacOS::set_activation_policy` +- On macOS, wait with activating the application until the application has initialized. +- On macOS, fix creating new windows when the application has a main menu. +- On Windows, fix fractional deltas for mouse wheel device events. +- On macOS, fix segmentation fault after dropping the main window. +- On Android, `InputEvent::KeyEvent` is partially implemented providing the key scancode. +- Added `is_maximized` method to `Window`. +- On Windows, fix bug where clicking the decoration bar would make the cursor blink. +- On Windows, fix bug causing newly created windows to erroneously display the "wait" (spinning) cursor. +- On macOS, wake up the event loop immediately when a redraw is requested. +- On Windows, change the default window size (1024x768) to match the default on other desktop platforms (800x600). +- On Windows, fix bug causing mouse capture to not be released. +- On Windows, fix fullscreen not preserving minimized/maximized state. +- On Android, unimplemented events are marked as unhandled on the native event loop. +- On Windows, added `WindowBuilderExtWindows::with_menu` to set a custom menu at window creation time. +- On Android, bump `ndk` and `ndk-glue` to 0.3: use predefined constants for event `ident`. +- On macOS, fix objects captured by the event loop closure not being dropped on panic. +- On Windows, fixed `WindowEvent::ThemeChanged` not properly firing and fixed `Window::theme` returning the wrong theme. +- On Web, added support for `DeviceEvent::MouseMotion` to listen for relative mouse movements. +- Added `WindowBuilder::with_position` to allow setting the position of a `Window` on creation. Supported on Windows, macOS and X11. +- Added `Window::drag_window`. Implemented on Windows, macOS, X11 and Wayland. +- On X11, bump `mio` to 0.7. +- On Windows, added `WindowBuilderExtWindows::with_owner_window` to allow creating popup windows. +- On Windows, added `WindowExtWindows::set_enable` to allow creating modal popup windows. +- On macOS, emit `RedrawRequested` events immediately while the window is being resized. +- Implement `Default`, `Hash`, and `Eq` for `LogicalPosition`, `PhysicalPosition`, `LogicalSize`, and `PhysicalSize`. +- On macOS, initialize the Menu Bar with minimal defaults. (Can be prevented using `enable_default_menu_creation`) +- On macOS, change the default behavior for first click when the window was unfocused. Now the window becomes focused and then emits a `MouseInput` event on a "first mouse click". +- Implement mint (math interoperability standard types) conversions (under feature flag `mint`). # 0.24.0 (2020-12-09) -* On Windows, fix applications not exiting gracefully due to thread_event_target_callback accessing corrupted memory. -* On Windows, implement `Window::set_ime_position`. -* **Breaking:** On Windows, Renamed `WindowBuilderExtWindows`'s `is_dark_mode` to `theme`. -* **Breaking:** On Windows, renamed `WindowBuilderExtWindows::is_dark_mode` to `theme`. -* On Windows, add `WindowBuilderExtWindows::with_theme` to set a preferred theme. -* On Windows, fix bug causing message boxes to appear delayed. -* On Android, calling `WindowEvent::Focused` now works properly instead of always returning false. -* On Windows, fix Alt-Tab behaviour by removing borderless fullscreen "always on top" flag. -* On Windows, fix bug preventing windows with transparency enabled from having fully-opaque regions. -* **Breaking:** On Windows, include prefix byte in scancodes. -* On Wayland, fix window not being resizeable when using `WindowBuilder::with_min_inner_size`. -* On Unix, fix cross-compiling to wasm32 without enabling X11 or Wayland. -* On Windows, fix use-after-free crash during window destruction. -* On Web, fix `WindowEvent::ReceivedCharacter` never being sent on key input. -* On macOS, fix compilation when targeting aarch64. -* On X11, fix `Window::request_redraw` not waking the event loop. -* On Wayland, the keypad arrow keys are now recognized. -* **Breaking** Rename `desktop::EventLoopExtDesktop` to `run_return::EventLoopExtRunReturn`. -* Added `request_user_attention` method to `Window`. -* **Breaking:** On macOS, removed `WindowExt::request_user_attention`, use `Window::request_user_attention`. -* **Breaking:** On X11, removed `WindowExt::set_urgent`, use `Window::request_user_attention`. -* On Wayland, default font size in CSD increased from 11 to 17. -* On Windows, fix bug causing message boxes to appear delayed. -* On Android, support multi-touch. -* On Wayland, extra mouse buttons are not dropped anymore. -* **Breaking**: `MouseButton::Other` now uses `u16`. +- On Windows, fix applications not exiting gracefully due to thread_event_target_callback accessing corrupted memory. +- On Windows, implement `Window::set_ime_position`. +- **Breaking:** On Windows, Renamed `WindowBuilderExtWindows`'s `is_dark_mode` to `theme`. +- **Breaking:** On Windows, renamed `WindowBuilderExtWindows::is_dark_mode` to `theme`. +- On Windows, add `WindowBuilderExtWindows::with_theme` to set a preferred theme. +- On Windows, fix bug causing message boxes to appear delayed. +- On Android, calling `WindowEvent::Focused` now works properly instead of always returning false. +- On Windows, fix Alt-Tab behaviour by removing borderless fullscreen "always on top" flag. +- On Windows, fix bug preventing windows with transparency enabled from having fully-opaque regions. +- **Breaking:** On Windows, include prefix byte in scancodes. +- On Wayland, fix window not being resizeable when using `WindowBuilder::with_min_inner_size`. +- On Unix, fix cross-compiling to wasm32 without enabling X11 or Wayland. +- On Windows, fix use-after-free crash during window destruction. +- On Web, fix `WindowEvent::ReceivedCharacter` never being sent on key input. +- On macOS, fix compilation when targeting aarch64. +- On X11, fix `Window::request_redraw` not waking the event loop. +- On Wayland, the keypad arrow keys are now recognized. +- **Breaking** Rename `desktop::EventLoopExtDesktop` to `run_return::EventLoopExtRunReturn`. +- Added `request_user_attention` method to `Window`. +- **Breaking:** On macOS, removed `WindowExt::request_user_attention`, use `Window::request_user_attention`. +- **Breaking:** On X11, removed `WindowExt::set_urgent`, use `Window::request_user_attention`. +- On Wayland, default font size in CSD increased from 11 to 17. +- On Windows, fix bug causing message boxes to appear delayed. +- On Android, support multi-touch. +- On Wayland, extra mouse buttons are not dropped anymore. +- **Breaking**: `MouseButton::Other` now uses `u16`. # 0.23.0 (2020-10-02) -* On iOS, fixed support for the "Debug View Heirarchy" feature in Xcode. -* On all platforms, `available_monitors` and `primary_monitor` are now on `EventLoopWindowTarget` rather than `EventLoop` to list monitors event in the event loop. -* On Unix, X11 and Wayland are now optional features (enabled by default) -* On X11, fix deadlock when calling `set_fullscreen_inner`. -* On Web, prevent the webpage from scrolling when the user is focused on a winit canvas -* On Web, calling `window.set_cursor_icon` no longer breaks HiDPI scaling -* On Windows, drag and drop is now optional (enabled by default) and can be disabled with `WindowBuilderExtWindows::with_drag_and_drop(false)`. -* On Wayland, fix deadlock when calling to `set_inner_size` from a callback. -* On macOS, add `hide__other_applications` to `EventLoopWindowTarget` via existing `EventLoopWindowTargetExtMacOS` trait. `hide_other_applications` will hide other applications by calling `-[NSApplication hideOtherApplications: nil]`. -* On android added support for `run_return`. -* On MacOS, Fixed fullscreen and dialog support for `run_return`. -* On Windows, fix bug where we'd try to emit `MainEventsCleared` events during nested win32 event loops. -* On Web, use mouse events if pointer events aren't supported. This affects Safari. -* On Windows, `set_ime_position` is now a no-op instead of a runtime crash. -* On Android, `set_fullscreen` is now a no-op instead of a runtime crash. -* On iOS and Android, `set_inner_size` is now a no-op instead of a runtime crash. -* On Android, fix `ControlFlow::Poll` not polling the Android event queue. -* On macOS, add `NSWindow.hasShadow` support. -* On Web, fix vertical mouse wheel scrolling being inverted. -* On Web, implement mouse capturing for click-dragging out of the canvas. -* On Web, fix `ControlFlow::Exit` not properly handled. -* On Web (web-sys only), send `WindowEvent::ScaleFactorChanged` event when `window.devicePixelRatio` is changed. -* **Breaking:** On Web, `set_cursor_position` and `set_cursor_grab` will now always return an error. -* **Breaking:** `PixelDelta` scroll events now return a `PhysicalPosition`. -* On NetBSD, fixed crash due to incorrect detection of the main thread. -* **Breaking:** On X11, `-` key is mapped to the `Minus` virtual key code, instead of `Subtract`. -* On macOS, fix inverted horizontal scroll. -* **Breaking:** `current_monitor` now returns `Option`. -* **Breaking:** `primary_monitor` now returns `Option`. -* On macOS, updated core-\* dependencies and cocoa. -* Bump `parking_lot` to 0.11 -* On Android, bump `ndk`, `ndk-sys` and `ndk-glue` to 0.2. Checkout the new ndk-glue main proc attribute. -* On iOS, fixed starting the app in landscape where the view still had portrait dimensions. -* Deprecate the stdweb backend, to be removed in a future release -* **Breaking:** Prefixed virtual key codes `Add`, `Multiply`, `Divide`, `Decimal`, and `Subtract` with `Numpad`. -* Added `Asterisk` and `Plus` virtual key codes. -* On Web (web-sys only), the `Event::LoopDestroyed` event is correctly emitted when leaving the page. -* On Web, the `WindowEvent::Destroyed` event now gets emitted when a `Window` is dropped. -* On Web (web-sys only), the event listeners are now removed when a `Window` is dropped or when the event loop is destroyed. -* On Web, the event handler closure passed to `EventLoop::run` now gets dropped after the event loop is destroyed. -* **Breaking:** On Web, the canvas element associated to a `Window` is no longer removed from the DOM when the `Window` is dropped. -* On Web, `WindowEvent::Resized` is now emitted when `Window::set_inner_size` is called. -* **Breaking:** `Fullscreen` enum now uses `Borderless(Option)` instead of `Borderless(MonitorHandle)` to allow picking the current monitor. -* On MacOS, fix `WindowEvent::Moved` ignoring the scale factor. -* On Wayland, add missing virtual keycodes. -* On Wayland, implement proper `set_cursor_grab`. -* On Wayland, the cursor will use similar icons if the requested one isn't available. -* On Wayland, right clicking on client side decorations will request application menu. -* On Wayland, fix tracking of window size after state changes. -* On Wayland, fix client side decorations not being hidden properly in fullscreen. -* On Wayland, fix incorrect size event when entering fullscreen with client side decorations. -* On Wayland, fix `resizable` attribute not being applied properly on startup. -* On Wayland, fix disabled repeat rate not being handled. -* On Wayland, fix decoration buttons not working after tty switch. -* On Wayland, fix scaling not being applied on output re-enable. -* On Wayland, fix crash when `XCURSOR_SIZE` is `0`. -* On Wayland, fix pointer getting created in some cases without pointer capability. -* On Wayland, on kwin, fix space between window and decorations on startup. -* **Breaking:** On Wayland, `Theme` trait was reworked. -* On Wayland, disable maximize button for non-resizable window. -* On Wayland, added support for `set_ime_position`. -* On Wayland, fix crash on startup since GNOME 3.37.90. -* On X11, fix incorrect modifiers state on startup. +- On iOS, fixed support for the "Debug View Heirarchy" feature in Xcode. +- On all platforms, `available_monitors` and `primary_monitor` are now on `EventLoopWindowTarget` rather than `EventLoop` to list monitors event in the event loop. +- On Unix, X11 and Wayland are now optional features (enabled by default) +- On X11, fix deadlock when calling `set_fullscreen_inner`. +- On Web, prevent the webpage from scrolling when the user is focused on a winit canvas +- On Web, calling `window.set_cursor_icon` no longer breaks HiDPI scaling +- On Windows, drag and drop is now optional (enabled by default) and can be disabled with `WindowBuilderExtWindows::with_drag_and_drop(false)`. +- On Wayland, fix deadlock when calling to `set_inner_size` from a callback. +- On macOS, add `hide__other_applications` to `EventLoopWindowTarget` via existing `EventLoopWindowTargetExtMacOS` trait. `hide_other_applications` will hide other applications by calling `-[NSApplication hideOtherApplications: nil]`. +- On android added support for `run_return`. +- On MacOS, Fixed fullscreen and dialog support for `run_return`. +- On Windows, fix bug where we'd try to emit `MainEventsCleared` events during nested win32 event loops. +- On Web, use mouse events if pointer events aren't supported. This affects Safari. +- On Windows, `set_ime_position` is now a no-op instead of a runtime crash. +- On Android, `set_fullscreen` is now a no-op instead of a runtime crash. +- On iOS and Android, `set_inner_size` is now a no-op instead of a runtime crash. +- On Android, fix `ControlFlow::Poll` not polling the Android event queue. +- On macOS, add `NSWindow.hasShadow` support. +- On Web, fix vertical mouse wheel scrolling being inverted. +- On Web, implement mouse capturing for click-dragging out of the canvas. +- On Web, fix `ControlFlow::Exit` not properly handled. +- On Web (web-sys only), send `WindowEvent::ScaleFactorChanged` event when `window.devicePixelRatio` is changed. +- **Breaking:** On Web, `set_cursor_position` and `set_cursor_grab` will now always return an error. +- **Breaking:** `PixelDelta` scroll events now return a `PhysicalPosition`. +- On NetBSD, fixed crash due to incorrect detection of the main thread. +- **Breaking:** On X11, `-` key is mapped to the `Minus` virtual key code, instead of `Subtract`. +- On macOS, fix inverted horizontal scroll. +- **Breaking:** `current_monitor` now returns `Option`. +- **Breaking:** `primary_monitor` now returns `Option`. +- On macOS, updated core-* dependencies and cocoa. +- Bump `parking_lot` to 0.11 +- On Android, bump `ndk`, `ndk-sys` and `ndk-glue` to 0.2. Checkout the new ndk-glue main proc attribute. +- On iOS, fixed starting the app in landscape where the view still had portrait dimensions. +- Deprecate the stdweb backend, to be removed in a future release +- **Breaking:** Prefixed virtual key codes `Add`, `Multiply`, `Divide`, `Decimal`, and `Subtract` with `Numpad`. +- Added `Asterisk` and `Plus` virtual key codes. +- On Web (web-sys only), the `Event::LoopDestroyed` event is correctly emitted when leaving the page. +- On Web, the `WindowEvent::Destroyed` event now gets emitted when a `Window` is dropped. +- On Web (web-sys only), the event listeners are now removed when a `Window` is dropped or when the event loop is destroyed. +- On Web, the event handler closure passed to `EventLoop::run` now gets dropped after the event loop is destroyed. +- **Breaking:** On Web, the canvas element associated to a `Window` is no longer removed from the DOM when the `Window` is dropped. +- On Web, `WindowEvent::Resized` is now emitted when `Window::set_inner_size` is called. +- **Breaking:** `Fullscreen` enum now uses `Borderless(Option)` instead of `Borderless(MonitorHandle)` to allow picking the current monitor. +- On MacOS, fix `WindowEvent::Moved` ignoring the scale factor. +- On Wayland, add missing virtual keycodes. +- On Wayland, implement proper `set_cursor_grab`. +- On Wayland, the cursor will use similar icons if the requested one isn't available. +- On Wayland, right clicking on client side decorations will request application menu. +- On Wayland, fix tracking of window size after state changes. +- On Wayland, fix client side decorations not being hidden properly in fullscreen. +- On Wayland, fix incorrect size event when entering fullscreen with client side decorations. +- On Wayland, fix `resizable` attribute not being applied properly on startup. +- On Wayland, fix disabled repeat rate not being handled. +- On Wayland, fix decoration buttons not working after tty switch. +- On Wayland, fix scaling not being applied on output re-enable. +- On Wayland, fix crash when `XCURSOR_SIZE` is `0`. +- On Wayland, fix pointer getting created in some cases without pointer capability. +- On Wayland, on kwin, fix space between window and decorations on startup. +- **Breaking:** On Wayland, `Theme` trait was reworked. +- On Wayland, disable maximize button for non-resizable window. +- On Wayland, added support for `set_ime_position`. +- On Wayland, fix crash on startup since GNOME 3.37.90. +- On X11, fix incorrect modifiers state on startup. # 0.22.2 (2020-05-16) -* Added Clone implementation for 'static events. -* On Windows, fix window intermittently hanging when `ControlFlow` was set to `Poll`. -* On Windows, fix `WindowBuilder::with_maximized` being ignored. -* On Android, minimal platform support. -* On iOS, touch positions are now properly converted to physical pixels. -* On macOS, updated core-\* dependencies and cocoa +- Added Clone implementation for 'static events. +- On Windows, fix window intermittently hanging when `ControlFlow` was set to `Poll`. +- On Windows, fix `WindowBuilder::with_maximized` being ignored. +- On Android, minimal platform support. +- On iOS, touch positions are now properly converted to physical pixels. +- On macOS, updated core-* dependencies and cocoa # 0.22.1 (2020-04-16) -* On X11, fix `ResumeTimeReached` being fired too early. -* On Web, replaced zero timeout for `ControlFlow::Poll` with `requestAnimationFrame` -* On Web, fix a possible panic during event handling -* On macOS, fix `EventLoopProxy` leaking memory for every instance. +- On X11, fix `ResumeTimeReached` being fired too early. +- On Web, replaced zero timeout for `ControlFlow::Poll` with `requestAnimationFrame` +- On Web, fix a possible panic during event handling +- On macOS, fix `EventLoopProxy` leaking memory for every instance. # 0.22.0 (2020-03-09) -* On Windows, fix minor timing issue in wait_until_time_or_msg -* On Windows, rework handling of request_redraw() to address panics. -* On macOS, fix `set_simple_screen` to remember frame excluding title bar. -* On Wayland, fix coordinates in touch events when scale factor isn't 1. -* On Wayland, fix color from `close_button_icon_color` not applying. -* Ignore locale if unsupported by X11 backend -* On Wayland, Add HiDPI cursor support -* On Web, add the ability to query "Light" or "Dark" system theme send `ThemeChanged` on change. -* Fix `Event::to_static` returning `None` for user events. -* On Wayland, Hide CSD for fullscreen windows. -* On Windows, ignore spurious mouse move messages. -* **Breaking:** Move `ModifiersChanged` variant from `DeviceEvent` to `WindowEvent`. -* On Windows, add `IconExtWindows` trait which exposes creating an `Icon` from an external file or embedded resource -* Add `BadIcon::OsError` variant for when OS icon functionality fails -* On Windows, fix crash at startup on systems that do not properly support Windows' Dark Mode -* Revert On macOS, fix not sending ReceivedCharacter event for specific keys combinations. -* on macOS, fix incorrect ReceivedCharacter events for some key combinations. -* **Breaking:** Use `i32` instead of `u32` for position type in `WindowEvent::Moved`. -* On macOS, a mouse motion event is now generated before every mouse click. +- On Windows, fix minor timing issue in wait_until_time_or_msg +- On Windows, rework handling of request_redraw() to address panics. +- On macOS, fix `set_simple_screen` to remember frame excluding title bar. +- On Wayland, fix coordinates in touch events when scale factor isn't 1. +- On Wayland, fix color from `close_button_icon_color` not applying. +- Ignore locale if unsupported by X11 backend +- On Wayland, Add HiDPI cursor support +- On Web, add the ability to query "Light" or "Dark" system theme send `ThemeChanged` on change. +- Fix `Event::to_static` returning `None` for user events. +- On Wayland, Hide CSD for fullscreen windows. +- On Windows, ignore spurious mouse move messages. +- **Breaking:** Move `ModifiersChanged` variant from `DeviceEvent` to `WindowEvent`. +- On Windows, add `IconExtWindows` trait which exposes creating an `Icon` from an external file or embedded resource +- Add `BadIcon::OsError` variant for when OS icon functionality fails +- On Windows, fix crash at startup on systems that do not properly support Windows' Dark Mode +- Revert On macOS, fix not sending ReceivedCharacter event for specific keys combinations. +- on macOS, fix incorrect ReceivedCharacter events for some key combinations. +- **Breaking:** Use `i32` instead of `u32` for position type in `WindowEvent::Moved`. +- On macOS, a mouse motion event is now generated before every mouse click. # 0.21.0 (2020-02-04) -* On Windows, fixed "error: linking with `link.exe` failed: exit code: 1120" error on older versions of windows. -* On macOS, fix set_minimized(true) works only with decorations. -* On macOS, add `hide_application` to `EventLoopWindowTarget` via a new `EventLoopWindowTargetExtMacOS` trait. `hide_application` will hide the entire application by calling `-[NSApplication hide: nil]`. -* On macOS, fix not sending ReceivedCharacter event for specific keys combinations. -* On macOS, fix `CursorMoved` event reporting the cursor position using logical coordinates. -* On macOS, fix issue where unbundled applications would sometimes open without being focused. -* On macOS, fix `run_return` does not return unless it receives a message. -* On Windows, fix bug where `RedrawRequested` would only get emitted every other iteration of the event loop. -* On X11, fix deadlock on window state when handling certain window events. -* `WindowBuilder` now implements `Default`. -* **Breaking:** `WindowEvent::CursorMoved` changed to `f64` units, preserving high-precision data supplied by most backends -* On Wayland, fix coordinates in mouse events when scale factor isn't 1 -* On Web, add the ability to provide a custom canvas -* **Breaking:** On Wayland, the `WaylandTheme` struct has been replaced with a `Theme` trait, allowing for extra configuration +- On Windows, fixed "error: linking with `link.exe` failed: exit code: 1120" error on older versions of windows. +- On macOS, fix set_minimized(true) works only with decorations. +- On macOS, add `hide_application` to `EventLoopWindowTarget` via a new `EventLoopWindowTargetExtMacOS` trait. `hide_application` will hide the entire application by calling `-[NSApplication hide: nil]`. +- On macOS, fix not sending ReceivedCharacter event for specific keys combinations. +- On macOS, fix `CursorMoved` event reporting the cursor position using logical coordinates. +- On macOS, fix issue where unbundled applications would sometimes open without being focused. +- On macOS, fix `run_return` does not return unless it receives a message. +- On Windows, fix bug where `RedrawRequested` would only get emitted every other iteration of the event loop. +- On X11, fix deadlock on window state when handling certain window events. +- `WindowBuilder` now implements `Default`. +- **Breaking:** `WindowEvent::CursorMoved` changed to `f64` units, preserving high-precision data supplied by most backends +- On Wayland, fix coordinates in mouse events when scale factor isn't 1 +- On Web, add the ability to provide a custom canvas +- **Breaking:** On Wayland, the `WaylandTheme` struct has been replaced with a `Theme` trait, allowing for extra configuration # 0.20.0 (2020-01-05) -* On X11, fix `ModifiersChanged` emitting incorrect modifier change events -* **Breaking**: Overhaul how Winit handles DPI: - * Window functions and events now return `PhysicalSize` instead of `LogicalSize`. - * Functions that take `Size` or `Position` types can now take either `Logical` or `Physical` types. - * `hidpi_factor` has been renamed to `scale_factor`. - * `HiDpiFactorChanged` has been renamed to `ScaleFactorChanged`, and lets you control how the OS - resizes the window in response to the change. - * On X11, deprecate `WINIT_HIDPI_FACTOR` environment variable in favor of `WINIT_X11_SCALE_FACTOR`. - * `Size` and `Position` types are now generic over their exact pixel type. +- On X11, fix `ModifiersChanged` emitting incorrect modifier change events +- **Breaking**: Overhaul how Winit handles DPI: + - Window functions and events now return `PhysicalSize` instead of `LogicalSize`. + - Functions that take `Size` or `Position` types can now take either `Logical` or `Physical` types. + - `hidpi_factor` has been renamed to `scale_factor`. + - `HiDpiFactorChanged` has been renamed to `ScaleFactorChanged`, and lets you control how the OS + resizes the window in response to the change. + - On X11, deprecate `WINIT_HIDPI_FACTOR` environment variable in favor of `WINIT_X11_SCALE_FACTOR`. + - `Size` and `Position` types are now generic over their exact pixel type. # 0.20.0 Alpha 6 (2020-01-03) -* On macOS, fix `set_cursor_visible` hides cursor outside of window. -* On macOS, fix `CursorEntered` and `CursorLeft` events fired at old window size. -* On macOS, fix error when `set_fullscreen` is called during fullscreen transition. -* On all platforms except mobile and WASM, implement `Window::set_minimized`. -* On X11, fix `CursorEntered` event being generated for non-winit windows. -* On macOS, fix crash when starting maximized without decorations. -* On macOS, fix application not terminating on `run_return`. -* On Wayland, fix cursor icon updates on window borders when using CSD. -* On Wayland, under mutter(GNOME Wayland), fix CSD being behind the status bar, when starting window in maximized mode. -* On Windows, theme the title bar according to whether the system theme is "Light" or "Dark". -* Added `WindowEvent::ThemeChanged` variant to handle changes to the system theme. Currently only implemented on Windows. -* **Breaking**: Changes to the `RedrawRequested` event (#1041): - * `RedrawRequested` has been moved from `WindowEvent` to `Event`. - * `EventsCleared` has been renamed to `MainEventsCleared`. - * `RedrawRequested` is now issued only after `MainEventsCleared`. - * `RedrawEventsCleared` is issued after each set of `RedrawRequested` events. -* Implement synthetic window focus key events on Windows. -* **Breaking**: Change `ModifiersState` to a `bitflags` struct. -* On Windows, implement `VirtualKeyCode` translation for `LWin` and `RWin`. -* On Windows, fix closing the last opened window causing `DeviceEvent`s to stop getting emitted. -* On Windows, fix `Window::set_visible` not setting internal flags correctly. This resulted in some weird behavior. -* Add `DeviceEvent::ModifiersChanged`. - * Deprecate `modifiers` fields in other events in favor of `ModifiersChanged`. -* On X11, `WINIT_HIDPI_FACTOR` now dominates `Xft.dpi` when picking DPI factor for output. -* On X11, add special value `randr` for `WINIT_HIDPI_FACTOR` to make winit use self computed DPI factor instead of the one from `Xft.dpi`. +- On macOS, fix `set_cursor_visible` hides cursor outside of window. +- On macOS, fix `CursorEntered` and `CursorLeft` events fired at old window size. +- On macOS, fix error when `set_fullscreen` is called during fullscreen transition. +- On all platforms except mobile and WASM, implement `Window::set_minimized`. +- On X11, fix `CursorEntered` event being generated for non-winit windows. +- On macOS, fix crash when starting maximized without decorations. +- On macOS, fix application not terminating on `run_return`. +- On Wayland, fix cursor icon updates on window borders when using CSD. +- On Wayland, under mutter(GNOME Wayland), fix CSD being behind the status bar, when starting window in maximized mode. +- On Windows, theme the title bar according to whether the system theme is "Light" or "Dark". +- Added `WindowEvent::ThemeChanged` variant to handle changes to the system theme. Currently only implemented on Windows. +- **Breaking**: Changes to the `RedrawRequested` event (#1041): + - `RedrawRequested` has been moved from `WindowEvent` to `Event`. + - `EventsCleared` has been renamed to `MainEventsCleared`. + - `RedrawRequested` is now issued only after `MainEventsCleared`. + - `RedrawEventsCleared` is issued after each set of `RedrawRequested` events. +- Implement synthetic window focus key events on Windows. +- **Breaking**: Change `ModifiersState` to a `bitflags` struct. +- On Windows, implement `VirtualKeyCode` translation for `LWin` and `RWin`. +- On Windows, fix closing the last opened window causing `DeviceEvent`s to stop getting emitted. +- On Windows, fix `Window::set_visible` not setting internal flags correctly. This resulted in some weird behavior. +- Add `DeviceEvent::ModifiersChanged`. + - Deprecate `modifiers` fields in other events in favor of `ModifiersChanged`. +- On X11, `WINIT_HIDPI_FACTOR` now dominates `Xft.dpi` when picking DPI factor for output. +- On X11, add special value `randr` for `WINIT_HIDPI_FACTOR` to make winit use self computed DPI factor instead of the one from `Xft.dpi`. # 0.20.0 Alpha 5 (2019-12-09) -* On macOS, fix application termination on `ControlFlow::Exit` -* On Windows, fix missing `ReceivedCharacter` events when Alt is held. -* On macOS, stop emitting private corporate characters in `ReceivedCharacter` events. -* On X11, fix misreporting DPI factor at startup. -* On X11, fix events not being reported when using `run_return`. -* On X11, fix key modifiers being incorrectly reported. -* On X11, fix window creation hanging when another window is fullscreen. -* On Windows, fix focusing unfocused windows when switching from fullscreen to windowed. -* On X11, fix reporting incorrect DPI factor when waking from suspend. -* Change `EventLoopClosed` to contain the original event. -* **Breaking**: Add `is_synthetic` field to `WindowEvent` variant `KeyboardInput`, - indicating that the event is generated by winit. -* On X11, generate synthetic key events for keys held when a window gains or loses focus. -* On X11, issue a `CursorMoved` event when a `Touch` event occurs, - as X11 implicitly moves the cursor for such events. +- On macOS, fix application termination on `ControlFlow::Exit` +- On Windows, fix missing `ReceivedCharacter` events when Alt is held. +- On macOS, stop emitting private corporate characters in `ReceivedCharacter` events. +- On X11, fix misreporting DPI factor at startup. +- On X11, fix events not being reported when using `run_return`. +- On X11, fix key modifiers being incorrectly reported. +- On X11, fix window creation hanging when another window is fullscreen. +- On Windows, fix focusing unfocused windows when switching from fullscreen to windowed. +- On X11, fix reporting incorrect DPI factor when waking from suspend. +- Change `EventLoopClosed` to contain the original event. +- **Breaking**: Add `is_synthetic` field to `WindowEvent` variant `KeyboardInput`, + indicating that the event is generated by winit. +- On X11, generate synthetic key events for keys held when a window gains or loses focus. +- On X11, issue a `CursorMoved` event when a `Touch` event occurs, + as X11 implicitly moves the cursor for such events. # 0.20.0 Alpha 4 (2019-10-18) -* Add web support via the 'stdweb' or 'web-sys' features -* On Windows, implemented function to get HINSTANCE -* On macOS, implement `run_return`. -* On iOS, fix inverted parameter in `set_prefers_home_indicator_hidden`. -* On X11, performance is improved when rapidly calling `Window::set_cursor_icon`. -* On iOS, fix improper `msg_send` usage that was UB and/or would break if `!` is stabilized. -* On Windows, unset `maximized` when manually changing the window's position or size. -* On Windows, add touch pressure information for touch events. -* On macOS, differentiate between `CursorIcon::Grab` and `CursorIcon::Grabbing`. -* On Wayland, fix event processing sometimes stalling when using OpenGL with vsync. -* Officially remove the Emscripten backend. -* On Windows, fix handling of surrogate pairs when dispatching `ReceivedCharacter`. -* On macOS 10.15, fix freeze upon exiting exclusive fullscreen mode. -* On iOS, fix panic upon closing the app. -* On X11, allow setting mulitple `XWindowType`s. -* On iOS, fix null window on initial `HiDpiFactorChanged` event. -* On Windows, fix fullscreen window shrinking upon getting restored to a normal window. -* On macOS, fix events not being emitted during modal loops, such as when windows are being resized - by the user. -* On Windows, fix hovering the mouse over the active window creating an endless stream of CursorMoved events. -* Always dispatch a `RedrawRequested` event after creating a new window. -* On X11, return dummy monitor data to avoid panicking when no monitors exist. -* On X11, prevent stealing input focus when creating a new window. - Only steal input focus when entering fullscreen mode. -* On Wayland, fixed DeviceEvents for relative mouse movement is not always produced -* On Wayland, add support for set_cursor_visible and set_cursor_grab. -* On Wayland, fixed DeviceEvents for relative mouse movement is not always produced. -* Removed `derivative` crate dependency. -* On Wayland, add support for set_cursor_icon. -* Use `impl Iterator` instead of `AvailableMonitorsIter` consistently. -* On macOS, fix fullscreen state being updated after entering fullscreen instead of before, - resulting in `Window::fullscreen` returning the old state in `Resized` events instead of - reflecting the new fullscreen state -* On X11, fix use-after-free during window creation -* On Windows, disable monitor change keyboard shortcut while in exclusive fullscreen. -* On Windows, ensure that changing a borderless fullscreen window's monitor via keyboard shortcuts keeps the window fullscreen on the new monitor. -* Prevent `EventLoop::new` and `EventLoop::with_user_event` from getting called outside the main thread. - * This is because some platforms cannot run the event loop outside the main thread. Preventing this - reduces the potential for cross-platform compatibility gotchyas. -* On Windows and Linux X11/Wayland, add platform-specific functions for creating an `EventLoop` outside the main thread. -* On Wayland, drop resize events identical to the current window size. -* On Windows, fix window rectangle not getting set correctly on high-DPI systems. +- Add web support via the 'stdweb' or 'web-sys' features +- On Windows, implemented function to get HINSTANCE +- On macOS, implement `run_return`. +- On iOS, fix inverted parameter in `set_prefers_home_indicator_hidden`. +- On X11, performance is improved when rapidly calling `Window::set_cursor_icon`. +- On iOS, fix improper `msg_send` usage that was UB and/or would break if `!` is stabilized. +- On Windows, unset `maximized` when manually changing the window's position or size. +- On Windows, add touch pressure information for touch events. +- On macOS, differentiate between `CursorIcon::Grab` and `CursorIcon::Grabbing`. +- On Wayland, fix event processing sometimes stalling when using OpenGL with vsync. +- Officially remove the Emscripten backend. +- On Windows, fix handling of surrogate pairs when dispatching `ReceivedCharacter`. +- On macOS 10.15, fix freeze upon exiting exclusive fullscreen mode. +- On iOS, fix panic upon closing the app. +- On X11, allow setting mulitple `XWindowType`s. +- On iOS, fix null window on initial `HiDpiFactorChanged` event. +- On Windows, fix fullscreen window shrinking upon getting restored to a normal window. +- On macOS, fix events not being emitted during modal loops, such as when windows are being resized + by the user. +- On Windows, fix hovering the mouse over the active window creating an endless stream of CursorMoved events. +- Always dispatch a `RedrawRequested` event after creating a new window. +- On X11, return dummy monitor data to avoid panicking when no monitors exist. +- On X11, prevent stealing input focus when creating a new window. + Only steal input focus when entering fullscreen mode. +- On Wayland, fixed DeviceEvents for relative mouse movement is not always produced +- On Wayland, add support for set_cursor_visible and set_cursor_grab. +- On Wayland, fixed DeviceEvents for relative mouse movement is not always produced. +- Removed `derivative` crate dependency. +- On Wayland, add support for set_cursor_icon. +- Use `impl Iterator` instead of `AvailableMonitorsIter` consistently. +- On macOS, fix fullscreen state being updated after entering fullscreen instead of before, + resulting in `Window::fullscreen` returning the old state in `Resized` events instead of + reflecting the new fullscreen state +- On X11, fix use-after-free during window creation +- On Windows, disable monitor change keyboard shortcut while in exclusive fullscreen. +- On Windows, ensure that changing a borderless fullscreen window's monitor via keyboard shortcuts keeps the window fullscreen on the new monitor. +- Prevent `EventLoop::new` and `EventLoop::with_user_event` from getting called outside the main thread. + - This is because some platforms cannot run the event loop outside the main thread. Preventing this + reduces the potential for cross-platform compatibility gotchyas. +- On Windows and Linux X11/Wayland, add platform-specific functions for creating an `EventLoop` outside the main thread. +- On Wayland, drop resize events identical to the current window size. +- On Windows, fix window rectangle not getting set correctly on high-DPI systems. # 0.20.0 Alpha 3 (2019-08-14) -* On macOS, drop the run closure on exit. -* On Windows, location of `WindowEvent::Touch` are window client coordinates instead of screen coordinates. -* On X11, fix delayed events after window redraw. -* On macOS, add `WindowBuilderExt::with_disallow_hidpi` to have the option to turn off best resolution openGL surface. -* On Windows, screen saver won't start if the window is in fullscreen mode. -* Change all occurrences of the `new_user_event` method to `with_user_event`. -* On macOS, the dock and the menu bar are now hidden in fullscreen mode. -* `Window::set_fullscreen` now takes `Option` where `Fullscreen` - consists of `Fullscreen::Exclusive(VideoMode)` and - `Fullscreen::Borderless(MonitorHandle)` variants. - * Adds support for exclusive fullscreen mode. -* On iOS, add support for hiding the home indicator. -* On iOS, add support for deferring system gestures. -* On iOS, fix a crash that occurred while acquiring a monitor's name. -* On iOS, fix armv7-apple-ios compile target. -* Removed the `T: Clone` requirement from the `Clone` impl of `EventLoopProxy`. -* On iOS, disable overscan compensation for external displays (removes black - bars surrounding the image). -* On Linux, the functions `is_wayland`, `is_x11`, `xlib_xconnection` and `wayland_display` have been moved to a new `EventLoopWindowTargetExtUnix` trait. -* On iOS, add `set_prefers_status_bar_hidden` extension function instead of - hijacking `set_decorations` for this purpose. -* On macOS and iOS, corrected the auto trait impls of `EventLoopProxy`. -* On iOS, add touch pressure information for touch events. -* Implement `raw_window_handle::HasRawWindowHandle` for `Window` type on all supported platforms. -* On macOS, fix the signature of `-[NSView drawRect:]`. -* On iOS, fix the behavior of `ControlFlow::Poll`. It wasn't polling if that was the only mode ever used by the application. -* On iOS, fix DPI sent out by views on creation was `0.0` - now it gives a reasonable number. -* On iOS, RedrawRequested now works for gl/metal backed views. -* On iOS, RedrawRequested is generally ordered after EventsCleared. +- On macOS, drop the run closure on exit. +- On Windows, location of `WindowEvent::Touch` are window client coordinates instead of screen coordinates. +- On X11, fix delayed events after window redraw. +- On macOS, add `WindowBuilderExt::with_disallow_hidpi` to have the option to turn off best resolution openGL surface. +- On Windows, screen saver won't start if the window is in fullscreen mode. +- Change all occurrences of the `new_user_event` method to `with_user_event`. +- On macOS, the dock and the menu bar are now hidden in fullscreen mode. +- `Window::set_fullscreen` now takes `Option` where `Fullscreen` + consists of `Fullscreen::Exclusive(VideoMode)` and + `Fullscreen::Borderless(MonitorHandle)` variants. + - Adds support for exclusive fullscreen mode. +- On iOS, add support for hiding the home indicator. +- On iOS, add support for deferring system gestures. +- On iOS, fix a crash that occurred while acquiring a monitor's name. +- On iOS, fix armv7-apple-ios compile target. +- Removed the `T: Clone` requirement from the `Clone` impl of `EventLoopProxy`. +- On iOS, disable overscan compensation for external displays (removes black + bars surrounding the image). +- On Linux, the functions `is_wayland`, `is_x11`, `xlib_xconnection` and `wayland_display` have been moved to a new `EventLoopWindowTargetExtUnix` trait. +- On iOS, add `set_prefers_status_bar_hidden` extension function instead of + hijacking `set_decorations` for this purpose. +- On macOS and iOS, corrected the auto trait impls of `EventLoopProxy`. +- On iOS, add touch pressure information for touch events. +- Implement `raw_window_handle::HasRawWindowHandle` for `Window` type on all supported platforms. +- On macOS, fix the signature of `-[NSView drawRect:]`. +- On iOS, fix the behavior of `ControlFlow::Poll`. It wasn't polling if that was the only mode ever used by the application. +- On iOS, fix DPI sent out by views on creation was `0.0` - now it gives a reasonable number. +- On iOS, RedrawRequested now works for gl/metal backed views. +- On iOS, RedrawRequested is generally ordered after EventsCleared. # 0.20.0 Alpha 2 (2019-07-09) -* On X11, non-resizable windows now have maximize explicitly disabled. -* On Windows, support paths longer than MAX_PATH (260 characters) in `WindowEvent::DroppedFile` - and `WindowEvent::HoveredFile`. -* On Mac, implement `DeviceEvent::Button`. -* Change `Event::Suspended(true / false)` to `Event::Suspended` and `Event::Resumed`. -* On X11, fix sanity check which checks that a monitor's reported width and height (in millimeters) are non-zero when calculating the DPI factor. -* Revert the use of invisible surfaces in Wayland, which introduced graphical glitches with OpenGL (#835) -* On X11, implement `_NET_WM_PING` to allow desktop environment to kill unresponsive programs. -* On Windows, when a window is initially invisible, it won't take focus from the existing visible windows. -* On Windows, fix multiple calls to `request_redraw` during `EventsCleared` sending multiple `RedrawRequested events.` -* On Windows, fix edge case where `RedrawRequested` could be dispatched before input events in event loop iteration. -* On Windows, fix timing issue that could cause events to be improperly dispatched after `RedrawRequested` but before `EventsCleared`. -* On macOS, drop unused Metal dependency. -* On Windows, fix the trail effect happening on transparent decorated windows. Borderless (or un-decorated) windows were not affected. -* On Windows, fix `with_maximized` not properly setting window size to entire window. -* On macOS, change `WindowExtMacOS::request_user_attention()` to take an `enum` instead of a `bool`. +- On X11, non-resizable windows now have maximize explicitly disabled. +- On Windows, support paths longer than MAX_PATH (260 characters) in `WindowEvent::DroppedFile` +and `WindowEvent::HoveredFile`. +- On Mac, implement `DeviceEvent::Button`. +- Change `Event::Suspended(true / false)` to `Event::Suspended` and `Event::Resumed`. +- On X11, fix sanity check which checks that a monitor's reported width and height (in millimeters) are non-zero when calculating the DPI factor. +- Revert the use of invisible surfaces in Wayland, which introduced graphical glitches with OpenGL (#835) +- On X11, implement `_NET_WM_PING` to allow desktop environment to kill unresponsive programs. +- On Windows, when a window is initially invisible, it won't take focus from the existing visible windows. +- On Windows, fix multiple calls to `request_redraw` during `EventsCleared` sending multiple `RedrawRequested events.` +- On Windows, fix edge case where `RedrawRequested` could be dispatched before input events in event loop iteration. +- On Windows, fix timing issue that could cause events to be improperly dispatched after `RedrawRequested` but before `EventsCleared`. +- On macOS, drop unused Metal dependency. +- On Windows, fix the trail effect happening on transparent decorated windows. Borderless (or un-decorated) windows were not affected. +- On Windows, fix `with_maximized` not properly setting window size to entire window. +- On macOS, change `WindowExtMacOS::request_user_attention()` to take an `enum` instead of a `bool`. # 0.20.0 Alpha 1 (2019-06-21) -* Changes below are considered **breaking**. -* Change all occurrences of `EventsLoop` to `EventLoop`. -* Previously flat API is now exposed through `event`, `event_loop`, `monitor`, and `window` modules. -* `os` module changes: - * Renamed to `platform`. - * All traits now have platform-specific suffixes. - * Exposes new `desktop` module on Windows, Mac, and Linux. -* Changes to event loop types: - * `EventLoopProxy::wakeup` has been removed in favor of `send_event`. - * **Major:** New `run` method drives winit event loop. - * Returns `!` to ensure API behaves identically across all supported platforms. - * This allows `emscripten` implementation to work without lying about the API. - * `ControlFlow`'s variants have been replaced with `Wait`, `WaitUntil(Instant)`, `Poll`, and `Exit`. - * Is read after `EventsCleared` is processed. - * `Wait` waits until new events are available. - * `WaitUntil` waits until either new events are available or the provided time has been reached. - * `Poll` instantly resumes the event loop. - * `Exit` aborts the event loop. - * Takes a closure that implements `'static + FnMut(Event, &EventLoop, &mut ControlFlow)`. - * `&EventLoop` is provided to allow new `Window`s to be created. - * **Major:** `platform::desktop` module exposes `EventLoopExtDesktop` trait with `run_return` method. - * Behaves identically to `run`, but returns control flow to the calling context and can take non-`'static` closures. - * `EventLoop`'s `poll_events` and `run_forever` methods have been removed in favor of `run` and `run_return`. -* Changes to events: - * Remove `Event::Awakened` in favor of `Event::UserEvent(T)`. - * Can be sent with `EventLoopProxy::send_event`. - * Rename `WindowEvent::Refresh` to `WindowEvent::RedrawRequested`. - * `RedrawRequested` can be sent by the user with the `Window::request_redraw` method. - * `EventLoop`, `EventLoopProxy`, and `Event` are now generic over `T`, for use in `UserEvent`. - * **Major:** Add `NewEvents(StartCause)`, `EventsCleared`, and `LoopDestroyed` variants to `Event`. - * `NewEvents` is emitted when new events are ready to be processed by event loop. - * `StartCause` describes why new events are available, with `ResumeTimeReached`, `Poll`, `WaitCancelled`, and `Init` (sent once at start of loop). - * `EventsCleared` is emitted when all available events have been processed. - * Can be used to perform logic that depends on all events being processed (e.g. an iteration of a game loop). - * `LoopDestroyed` is emitted when the `run` or `run_return` method is about to exit. -* Rename `MonitorId` to `MonitorHandle`. -* Removed `serde` implementations from `ControlFlow`. -* Rename several functions to improve both internal consistency and compliance with Rust API guidelines. -* Remove `WindowBuilder::multitouch` field, since it was only implemented on a few platforms. Multitouch is always enabled now. -* **Breaking:** On macOS, change `ns` identifiers to use snake_case for consistency with iOS's `ui` identifiers. -* Add `MonitorHandle::video_modes` method for retrieving supported video modes for the given monitor. -* On Wayland, the window now exists even if nothing has been drawn. -* On Windows, fix initial dimensions of a fullscreen window. -* On Windows, Fix transparent borderless windows rendering wrong. +- Changes below are considered **breaking**. +- Change all occurrences of `EventsLoop` to `EventLoop`. +- Previously flat API is now exposed through `event`, `event_loop`, `monitor`, and `window` modules. +- `os` module changes: + - Renamed to `platform`. + - All traits now have platform-specific suffixes. + - Exposes new `desktop` module on Windows, Mac, and Linux. +- Changes to event loop types: + - `EventLoopProxy::wakeup` has been removed in favor of `send_event`. + - **Major:** New `run` method drives winit event loop. + - Returns `!` to ensure API behaves identically across all supported platforms. + - This allows `emscripten` implementation to work without lying about the API. + - `ControlFlow`'s variants have been replaced with `Wait`, `WaitUntil(Instant)`, `Poll`, and `Exit`. + - Is read after `EventsCleared` is processed. + - `Wait` waits until new events are available. + - `WaitUntil` waits until either new events are available or the provided time has been reached. + - `Poll` instantly resumes the event loop. + - `Exit` aborts the event loop. + - Takes a closure that implements `'static + FnMut(Event, &EventLoop, &mut ControlFlow)`. + - `&EventLoop` is provided to allow new `Window`s to be created. + - **Major:** `platform::desktop` module exposes `EventLoopExtDesktop` trait with `run_return` method. + - Behaves identically to `run`, but returns control flow to the calling context and can take non-`'static` closures. + - `EventLoop`'s `poll_events` and `run_forever` methods have been removed in favor of `run` and `run_return`. +- Changes to events: + - Remove `Event::Awakened` in favor of `Event::UserEvent(T)`. + - Can be sent with `EventLoopProxy::send_event`. + - Rename `WindowEvent::Refresh` to `WindowEvent::RedrawRequested`. + - `RedrawRequested` can be sent by the user with the `Window::request_redraw` method. + - `EventLoop`, `EventLoopProxy`, and `Event` are now generic over `T`, for use in `UserEvent`. + - **Major:** Add `NewEvents(StartCause)`, `EventsCleared`, and `LoopDestroyed` variants to `Event`. + - `NewEvents` is emitted when new events are ready to be processed by event loop. + - `StartCause` describes why new events are available, with `ResumeTimeReached`, `Poll`, `WaitCancelled`, and `Init` (sent once at start of loop). + - `EventsCleared` is emitted when all available events have been processed. + - Can be used to perform logic that depends on all events being processed (e.g. an iteration of a game loop). + - `LoopDestroyed` is emitted when the `run` or `run_return` method is about to exit. +- Rename `MonitorId` to `MonitorHandle`. +- Removed `serde` implementations from `ControlFlow`. +- Rename several functions to improve both internal consistency and compliance with Rust API guidelines. +- Remove `WindowBuilder::multitouch` field, since it was only implemented on a few platforms. Multitouch is always enabled now. +- **Breaking:** On macOS, change `ns` identifiers to use snake_case for consistency with iOS's `ui` identifiers. +- Add `MonitorHandle::video_modes` method for retrieving supported video modes for the given monitor. +- On Wayland, the window now exists even if nothing has been drawn. +- On Windows, fix initial dimensions of a fullscreen window. +- On Windows, Fix transparent borderless windows rendering wrong. # Version 0.19.1 (2019-04-08) -* On Wayland, added a `get_wayland_display` function to `EventsLoopExt`. -* On Windows, fix `CursorMoved(0, 0)` getting dispatched on window focus. -* On macOS, fix command key event left and right reverse. -* On FreeBSD, NetBSD, and OpenBSD, fix build of X11 backend. -* On Linux, the numpad's add, subtract and divide keys are now mapped to the `Add`, `Subtract` and `Divide` virtual key codes -* On macOS, the numpad's subtract key has been added to the `Subtract` mapping -* On Wayland, the numpad's home, end, page up and page down keys are now mapped to the `Home`, `End`, `PageUp` and `PageDown` virtual key codes -* On Windows, fix icon not showing up in corner of window. -* On X11, change DPI scaling factor behavior. First, winit tries to read it from "Xft.dpi" XResource, and uses DPI calculation from xrandr dimensions as fallback behavior. +- On Wayland, added a `get_wayland_display` function to `EventsLoopExt`. +- On Windows, fix `CursorMoved(0, 0)` getting dispatched on window focus. +- On macOS, fix command key event left and right reverse. +- On FreeBSD, NetBSD, and OpenBSD, fix build of X11 backend. +- On Linux, the numpad's add, subtract and divide keys are now mapped to the `Add`, `Subtract` and `Divide` virtual key codes +- On macOS, the numpad's subtract key has been added to the `Subtract` mapping +- On Wayland, the numpad's home, end, page up and page down keys are now mapped to the `Home`, `End`, `PageUp` and `PageDown` virtual key codes +- On Windows, fix icon not showing up in corner of window. +- On X11, change DPI scaling factor behavior. First, winit tries to read it from "Xft.dpi" XResource, and uses DPI calculation from xrandr dimensions as fallback behavior. # Version 0.19.0 (2019-03-06) -* On X11, we will use the faster `XRRGetScreenResourcesCurrent` function instead of `XRRGetScreenResources` when available. -* On macOS, fix keycodes being incorrect when using a non-US keyboard layout. -* On Wayland, fix `with_title()` not setting the windows title -* On Wayland, add `set_wayland_theme()` to control client decoration color theme -* Added serde serialization to `os::unix::XWindowType`. -* **Breaking:** Remove the `icon_loading` feature and the associated `image` dependency. -* On X11, make event loop thread safe by replacing XNextEvent with select(2) and XCheckIfEvent -* On Windows, fix malformed function pointer typecast that could invoke undefined behavior. -* Refactored Windows state/flag-setting code. -* On Windows, hiding the cursor no longer hides the cursor for all Winit windows - just the one `hide_cursor` was called on. -* On Windows, cursor grabs used to get perpetually canceled when the grabbing window lost focus. Now, cursor grabs automatically get re-initialized when the window regains focus and the mouse moves over the client area. -* On Windows, only vertical mouse wheel events were handled. Now, horizontal mouse wheel events are also handled. -* On Windows, ignore the AltGr key when populating the `ModifersState` type. +- On X11, we will use the faster `XRRGetScreenResourcesCurrent` function instead of `XRRGetScreenResources` when available. +- On macOS, fix keycodes being incorrect when using a non-US keyboard layout. +- On Wayland, fix `with_title()` not setting the windows title +- On Wayland, add `set_wayland_theme()` to control client decoration color theme +- Added serde serialization to `os::unix::XWindowType`. +- **Breaking:** Remove the `icon_loading` feature and the associated `image` dependency. +- On X11, make event loop thread safe by replacing XNextEvent with select(2) and XCheckIfEvent +- On Windows, fix malformed function pointer typecast that could invoke undefined behavior. +- Refactored Windows state/flag-setting code. +- On Windows, hiding the cursor no longer hides the cursor for all Winit windows - just the one `hide_cursor` was called on. +- On Windows, cursor grabs used to get perpetually canceled when the grabbing window lost focus. Now, cursor grabs automatically get re-initialized when the window regains focus and the mouse moves over the client area. +- On Windows, only vertical mouse wheel events were handled. Now, horizontal mouse wheel events are also handled. +- On Windows, ignore the AltGr key when populating the `ModifersState` type. # Version 0.18.1 (2018-12-30) -* On macOS, fix `Yen` (JIS) so applications receive the event. -* On X11 with a tiling WM, fixed high CPU usage when moving windows across monitors. -* On X11, fixed panic caused by dropping the window before running the event loop. -* on macOS, added `WindowExt::set_simple_fullscreen` which does not require a separate space -* Introduce `WindowBuilderExt::with_app_id` to allow setting the application ID on Wayland. -* On Windows, catch panics in event loop child thread and forward them to the parent thread. This prevents an invocation of undefined behavior due to unwinding into foreign code. -* On Windows, fix issue where resizing or moving window combined with grabbing the cursor would freeze program. -* On Windows, fix issue where resizing or moving window would eat `Awakened` events. -* On Windows, exiting fullscreen after entering fullscreen with disabled decorations no longer shrinks window. -* On X11, fixed a segfault when using virtual monitors with XRandR. -* Derive `Ord` and `PartialOrd` for `VirtualKeyCode` enum. -* On Windows, fix issue where hovering or dropping a non file item would create a panic. -* On Wayland, fix resizing and DPI calculation when a `wl_output` is removed without sending a `leave` event to the `wl_surface`, such as disconnecting a monitor from a laptop. -* On Wayland, DPI calculation is handled by smithay-client-toolkit. -* On X11, `WindowBuilder::with_min_dimensions` and `WindowBuilder::with_max_dimensions` now correctly account for DPI. -* Added support for generating dummy `DeviceId`s and `WindowId`s to better support unit testing. -* On macOS, fixed unsoundness in drag-and-drop that could result in drops being rejected. -* On macOS, implemented `WindowEvent::Refresh`. -* On macOS, all `MouseCursor` variants are now implemented and the cursor will no longer reset after unfocusing. -* Removed minimum supported Rust version guarantee. +- On macOS, fix `Yen` (JIS) so applications receive the event. +- On X11 with a tiling WM, fixed high CPU usage when moving windows across monitors. +- On X11, fixed panic caused by dropping the window before running the event loop. +- on macOS, added `WindowExt::set_simple_fullscreen` which does not require a separate space +- Introduce `WindowBuilderExt::with_app_id` to allow setting the application ID on Wayland. +- On Windows, catch panics in event loop child thread and forward them to the parent thread. This prevents an invocation of undefined behavior due to unwinding into foreign code. +- On Windows, fix issue where resizing or moving window combined with grabbing the cursor would freeze program. +- On Windows, fix issue where resizing or moving window would eat `Awakened` events. +- On Windows, exiting fullscreen after entering fullscreen with disabled decorations no longer shrinks window. +- On X11, fixed a segfault when using virtual monitors with XRandR. +- Derive `Ord` and `PartialOrd` for `VirtualKeyCode` enum. +- On Windows, fix issue where hovering or dropping a non file item would create a panic. +- On Wayland, fix resizing and DPI calculation when a `wl_output` is removed without sending a `leave` event to the `wl_surface`, such as disconnecting a monitor from a laptop. +- On Wayland, DPI calculation is handled by smithay-client-toolkit. +- On X11, `WindowBuilder::with_min_dimensions` and `WindowBuilder::with_max_dimensions` now correctly account for DPI. +- Added support for generating dummy `DeviceId`s and `WindowId`s to better support unit testing. +- On macOS, fixed unsoundness in drag-and-drop that could result in drops being rejected. +- On macOS, implemented `WindowEvent::Refresh`. +- On macOS, all `MouseCursor` variants are now implemented and the cursor will no longer reset after unfocusing. +- Removed minimum supported Rust version guarantee. # Version 0.18.0 (2018-11-07) -* **Breaking:** `image` crate upgraded to 0.20. This is exposed as part of the `icon_loading` API. -* On Wayland, pointer events will now provide the current modifiers state. -* On Wayland, titles will now be displayed in the window header decoration. -* On Wayland, key repetition is now ended when keyboard loses focus. -* On Wayland, windows will now use more stylish and modern client side decorations. -* On Wayland, windows will use server-side decorations when available. -* **Breaking:** Added support for F16-F24 keys (variants were added to the `VirtualKeyCode` enum). -* Fixed graphical glitches when resizing on Wayland. -* On Windows, fix freezes when performing certain actions after a window resize has been triggered. Reintroduces some visual artifacts when resizing. -* Updated window manager hints under X11 to v1.5 of [Extended Window Manager Hints](https://specifications.freedesktop.org/wm-spec/wm-spec-1.5.html#idm140200472629520). -* Added `WindowBuilderExt::with_gtk_theme_variant` to X11-specific `WindowBuilder` functions. -* Fixed UTF8 handling bug in X11 `set_title` function. -* On Windows, `Window::set_cursor` now applies immediately instead of requiring specific events to occur first. -* On Windows, the `HoveredFile` and `HoveredFileCancelled` events are now implemented. -* On Windows, fix `Window::set_maximized`. -* On Windows 10, fix transparency (#260). -* On macOS, fix modifiers during key repeat. -* Implemented the `Debug` trait for `Window`, `EventsLoop`, `EventsLoopProxy` and `WindowBuilder`. -* On X11, now a `Resized` event will always be generated after a DPI change to ensure the window's logical size is consistent with the new DPI. -* Added further clarifications to the DPI docs. -* On Linux, if neither X11 nor Wayland manage to initialize, the corresponding panic now consists of a single line only. -* Add optional `serde` feature with implementations of `Serialize`/`Deserialize` for DPI types and various event types. -* Add `PartialEq`, `Eq`, and `Hash` implementations on public types that could have them but were missing them. -* On X11, drag-and-drop receiving an unsupported drop type can no longer cause the WM to freeze. -* Fix issue whereby the OpenGL context would not appear at startup on macOS Mojave (#1069). -* **Breaking:** Removed `From` impl from `ActivationPolicy` on macOS. -* On macOS, the application can request the user's attention with `WindowExt::request_user_attention`. +- **Breaking:** `image` crate upgraded to 0.20. This is exposed as part of the `icon_loading` API. +- On Wayland, pointer events will now provide the current modifiers state. +- On Wayland, titles will now be displayed in the window header decoration. +- On Wayland, key repetition is now ended when keyboard loses focus. +- On Wayland, windows will now use more stylish and modern client side decorations. +- On Wayland, windows will use server-side decorations when available. +- **Breaking:** Added support for F16-F24 keys (variants were added to the `VirtualKeyCode` enum). +- Fixed graphical glitches when resizing on Wayland. +- On Windows, fix freezes when performing certain actions after a window resize has been triggered. Reintroduces some visual artifacts when resizing. +- Updated window manager hints under X11 to v1.5 of [Extended Window Manager Hints](https://specifications.freedesktop.org/wm-spec/wm-spec-1.5.html#idm140200472629520). +- Added `WindowBuilderExt::with_gtk_theme_variant` to X11-specific `WindowBuilder` functions. +- Fixed UTF8 handling bug in X11 `set_title` function. +- On Windows, `Window::set_cursor` now applies immediately instead of requiring specific events to occur first. +- On Windows, the `HoveredFile` and `HoveredFileCancelled` events are now implemented. +- On Windows, fix `Window::set_maximized`. +- On Windows 10, fix transparency (#260). +- On macOS, fix modifiers during key repeat. +- Implemented the `Debug` trait for `Window`, `EventsLoop`, `EventsLoopProxy` and `WindowBuilder`. +- On X11, now a `Resized` event will always be generated after a DPI change to ensure the window's logical size is consistent with the new DPI. +- Added further clarifications to the DPI docs. +- On Linux, if neither X11 nor Wayland manage to initialize, the corresponding panic now consists of a single line only. +- Add optional `serde` feature with implementations of `Serialize`/`Deserialize` for DPI types and various event types. +- Add `PartialEq`, `Eq`, and `Hash` implementations on public types that could have them but were missing them. +- On X11, drag-and-drop receiving an unsupported drop type can no longer cause the WM to freeze. +- Fix issue whereby the OpenGL context would not appear at startup on macOS Mojave (#1069). +- **Breaking:** Removed `From` impl from `ActivationPolicy` on macOS. +- On macOS, the application can request the user's attention with `WindowExt::request_user_attention`. # Version 0.17.2 (2018-08-19) -* On macOS, fix `` so applications receive the event. -* On macOS, fix `` so applications receive the event. -* On Wayland, key press events will now be repeated. +- On macOS, fix `` so applications receive the event. +- On macOS, fix `` so applications receive the event. +- On Wayland, key press events will now be repeated. # Version 0.17.1 (2018-08-05) -* On X11, prevent a compilation failure in release mode for versions of Rust greater than or equal to 1.30. -* Fixed deadlock that broke fullscreen mode on Windows. +- On X11, prevent a compilation failure in release mode for versions of Rust greater than or equal to 1.30. +- Fixed deadlock that broke fullscreen mode on Windows. # Version 0.17.0 (2018-08-02) -* Cocoa and core-graphics updates. -* Fixed thread-safety issues in several `Window` functions on Windows. -* On MacOS, the key state for modifiers key events is now properly set. -* On iOS, the view is now set correctly. This makes it possible to render things (instead of being stuck on a black screen), and touch events work again. -* Added NetBSD support. -* **Breaking:** On iOS, `UIView` is now the default root view. `WindowBuilderExt::with_root_view_class` can be used to set the root view objective-c class to `GLKView` (OpenGLES) or `MTKView` (Metal/MoltenVK). -* On iOS, the `UIApplication` is not started until `Window::new` is called. -* Fixed thread unsafety with cursor hiding on macOS. -* On iOS, fixed the size of the `JmpBuf` type used for `setjmp`/`longjmp` calls. Previously this was a buffer overflow on most architectures. -* On Windows, use cached window DPI instead of repeatedly querying the system. This fixes sporadic crashes on Windows 7. +- Cocoa and core-graphics updates. +- Fixed thread-safety issues in several `Window` functions on Windows. +- On MacOS, the key state for modifiers key events is now properly set. +- On iOS, the view is now set correctly. This makes it possible to render things (instead of being stuck on a black screen), and touch events work again. +- Added NetBSD support. +- **Breaking:** On iOS, `UIView` is now the default root view. `WindowBuilderExt::with_root_view_class` can be used to set the root view objective-c class to `GLKView` (OpenGLES) or `MTKView` (Metal/MoltenVK). +- On iOS, the `UIApplication` is not started until `Window::new` is called. +- Fixed thread unsafety with cursor hiding on macOS. +- On iOS, fixed the size of the `JmpBuf` type used for `setjmp`/`longjmp` calls. Previously this was a buffer overflow on most architectures. +- On Windows, use cached window DPI instead of repeatedly querying the system. This fixes sporadic crashes on Windows 7. # Version 0.16.2 (2018-07-07) -* On Windows, non-resizable windows now have the maximization button disabled. This is consistent with behavior on macOS and popular X11 WMs. -* Corrected incorrect `unreachable!` usage when guessing the DPI factor with no detected monitors. +- On Windows, non-resizable windows now have the maximization button disabled. This is consistent with behavior on macOS and popular X11 WMs. +- Corrected incorrect `unreachable!` usage when guessing the DPI factor with no detected monitors. # Version 0.16.1 (2018-07-02) -* Added logging through `log`. Logging will become more extensive over time. -* On X11 and Windows, the window's DPI factor is guessed before creating the window. This *greatly* cuts back on unsightly auto-resizing that would occur immediately after window creation. -* Fixed X11 backend compilation for environments where `c_char` is unsigned. +- Added logging through `log`. Logging will become more extensive over time. +- On X11 and Windows, the window's DPI factor is guessed before creating the window. This _greatly_ cuts back on unsightly auto-resizing that would occur immediately after window creation. +- Fixed X11 backend compilation for environments where `c_char` is unsigned. # Version 0.16.0 (2018-06-25) -* Windows additionally has `WindowBuilderExt::with_no_redirection_bitmap`. -* **Breaking:** Removed `VirtualKeyCode::LMenu` and `VirtualKeyCode::RMenu`; Windows now generates `VirtualKeyCode::LAlt` and `VirtualKeyCode::RAlt` instead. -* On X11, exiting fullscreen no longer leaves the window in the monitor's top left corner. -* **Breaking:** `Window::hidpi_factor` has been renamed to `Window::get_hidpi_factor` for better consistency. `WindowEvent::HiDPIFactorChanged` has been renamed to `WindowEvent::HiDpiFactorChanged`. DPI factors are always represented as `f64` instead of `f32` now. -* The Windows backend is now DPI aware. `WindowEvent::HiDpiFactorChanged` is implemented, and `MonitorId::get_hidpi_factor` and `Window::hidpi_factor` return accurate values. -* Implemented `WindowEvent::HiDpiFactorChanged` on X11. -* On macOS, `Window::set_cursor_position` is now relative to the client area. -* On macOS, setting the maximum and minimum dimensions now applies to the client area dimensions rather than to the window dimensions. -* On iOS, `MonitorId::get_dimensions` has been implemented and both `MonitorId::get_hidpi_factor` and `Window::get_hidpi_factor` return accurate values. -* On Emscripten, `MonitorId::get_hidpi_factor` now returns the same value as `Window::get_hidpi_factor` (it previously would always return 1.0). -* **Breaking:** The entire API for sizes, positions, etc. has changed. In the majority of cases, winit produces and consumes positions and sizes as `LogicalPosition` and `LogicalSize`, respectively. The notable exception is `MonitorId` methods, which deal in `PhysicalPosition` and `PhysicalSize`. See the documentation for specifics and explanations of the types. Additionally, winit automatically conserves logical size when the DPI factor changes. -* **Breaking:** All deprecated methods have been removed. For `Window::platform_display` and `Window::platform_window`, switch to the appropriate platform-specific `WindowExt` methods. For `Window::get_inner_size_points` and `Window::get_inner_size_pixels`, use the `LogicalSize` returned by `Window::get_inner_size` and convert as needed. -* HiDPI support for Wayland. -* `EventsLoop::get_available_monitors` and `EventsLoop::get_primary_monitor` now have identical counterparts on `Window`, so this information can be acquired without an `EventsLoop` borrow. -* `AvailableMonitorsIter` now implements `Debug`. -* Fixed quirk on macOS where certain keys would generate characters at twice the normal rate when held down. -* On X11, all event loops now share the same `XConnection`. -* **Breaking:** `Window::set_cursor_state` and `CursorState` enum removed in favor of the more composable `Window::grab_cursor` and `Window::hide_cursor`. As a result, grabbing the cursor no longer automatically hides it; you must call both methods to retain the old behavior on Windows and macOS. `Cursor::NoneCursor` has been removed, as it's no longer useful. -* **Breaking:** `Window::set_cursor_position` now returns `Result<(), String>`, thus allowing for `Box` conversion via `?`. +- Windows additionally has `WindowBuilderExt::with_no_redirection_bitmap`. +- **Breaking:** Removed `VirtualKeyCode::LMenu` and `VirtualKeyCode::RMenu`; Windows now generates `VirtualKeyCode::LAlt` and `VirtualKeyCode::RAlt` instead. +- On X11, exiting fullscreen no longer leaves the window in the monitor's top left corner. +- **Breaking:** `Window::hidpi_factor` has been renamed to `Window::get_hidpi_factor` for better consistency. `WindowEvent::HiDPIFactorChanged` has been renamed to `WindowEvent::HiDpiFactorChanged`. DPI factors are always represented as `f64` instead of `f32` now. +- The Windows backend is now DPI aware. `WindowEvent::HiDpiFactorChanged` is implemented, and `MonitorId::get_hidpi_factor` and `Window::hidpi_factor` return accurate values. +- Implemented `WindowEvent::HiDpiFactorChanged` on X11. +- On macOS, `Window::set_cursor_position` is now relative to the client area. +- On macOS, setting the maximum and minimum dimensions now applies to the client area dimensions rather than to the window dimensions. +- On iOS, `MonitorId::get_dimensions` has been implemented and both `MonitorId::get_hidpi_factor` and `Window::get_hidpi_factor` return accurate values. +- On Emscripten, `MonitorId::get_hidpi_factor` now returns the same value as `Window::get_hidpi_factor` (it previously would always return 1.0). +- **Breaking:** The entire API for sizes, positions, etc. has changed. In the majority of cases, winit produces and consumes positions and sizes as `LogicalPosition` and `LogicalSize`, respectively. The notable exception is `MonitorId` methods, which deal in `PhysicalPosition` and `PhysicalSize`. See the documentation for specifics and explanations of the types. Additionally, winit automatically conserves logical size when the DPI factor changes. +- **Breaking:** All deprecated methods have been removed. For `Window::platform_display` and `Window::platform_window`, switch to the appropriate platform-specific `WindowExt` methods. For `Window::get_inner_size_points` and `Window::get_inner_size_pixels`, use the `LogicalSize` returned by `Window::get_inner_size` and convert as needed. +- HiDPI support for Wayland. +- `EventsLoop::get_available_monitors` and `EventsLoop::get_primary_monitor` now have identical counterparts on `Window`, so this information can be acquired without an `EventsLoop` borrow. +- `AvailableMonitorsIter` now implements `Debug`. +- Fixed quirk on macOS where certain keys would generate characters at twice the normal rate when held down. +- On X11, all event loops now share the same `XConnection`. +- **Breaking:** `Window::set_cursor_state` and `CursorState` enum removed in favor of the more composable `Window::grab_cursor` and `Window::hide_cursor`. As a result, grabbing the cursor no longer automatically hides it; you must call both methods to retain the old behavior on Windows and macOS. `Cursor::NoneCursor` has been removed, as it's no longer useful. +- **Breaking:** `Window::set_cursor_position` now returns `Result<(), String>`, thus allowing for `Box` conversion via `?`. # Version 0.15.1 (2018-06-13) -* On X11, the `Moved` event is no longer sent when the window is resized without changing position. -* `MouseCursor` and `CursorState` now implement `Default`. -* `WindowBuilder::with_resizable` implemented for Windows, X11, Wayland, and macOS. -* `Window::set_resizable` implemented for Windows, X11, Wayland, and macOS. -* On X11, if the monitor's width or height in millimeters is reported as 0, the DPI is now 1.0 instead of +inf. -* On X11, the environment variable `WINIT_HIDPI_FACTOR` has been added for overriding DPI factor. -* On X11, enabling transparency no longer causes the window contents to flicker when resizing. -* On X11, `with_override_redirect` now actually enables override redirect. -* macOS now generates `VirtualKeyCode::LAlt` and `VirtualKeyCode::RAlt` instead of `None` for both. -* On macOS, `VirtualKeyCode::RWin` and `VirtualKeyCode::LWin` are no longer switched. -* On macOS, windows without decorations can once again be resized. -* Fixed race conditions when creating an `EventsLoop` on X11, most commonly manifesting as "\[xcb] Unknown sequence number while processing queue". -* On macOS, `CursorMoved` and `MouseInput` events are only generated if they occurs within the window's client area. -* On macOS, resizing the window no longer generates a spurious `MouseInput` event. +- On X11, the `Moved` event is no longer sent when the window is resized without changing position. +- `MouseCursor` and `CursorState` now implement `Default`. +- `WindowBuilder::with_resizable` implemented for Windows, X11, Wayland, and macOS. +- `Window::set_resizable` implemented for Windows, X11, Wayland, and macOS. +- On X11, if the monitor's width or height in millimeters is reported as 0, the DPI is now 1.0 instead of +inf. +- On X11, the environment variable `WINIT_HIDPI_FACTOR` has been added for overriding DPI factor. +- On X11, enabling transparency no longer causes the window contents to flicker when resizing. +- On X11, `with_override_redirect` now actually enables override redirect. +- macOS now generates `VirtualKeyCode::LAlt` and `VirtualKeyCode::RAlt` instead of `None` for both. +- On macOS, `VirtualKeyCode::RWin` and `VirtualKeyCode::LWin` are no longer switched. +- On macOS, windows without decorations can once again be resized. +- Fixed race conditions when creating an `EventsLoop` on X11, most commonly manifesting as "[xcb] Unknown sequence number while processing queue". +- On macOS, `CursorMoved` and `MouseInput` events are only generated if they occurs within the window's client area. +- On macOS, resizing the window no longer generates a spurious `MouseInput` event. # Version 0.15.0 (2018-05-22) -* `Icon::to_cardinals` is no longer public, since it was never supposed to be. -* Wayland: improve diagnostics if initialization fails -* Fix some system event key doesn't work when focused, do not block keyevent forward to system on macOS -* On X11, the scroll wheel position is now correctly reset on i3 and other WMs that have the same quirk. -* On X11, `Window::get_current_monitor` now reliably returns the correct monitor. -* On X11, `Window::hidpi_factor` returns values from XRandR rather than the inaccurate values previously queried from the core protocol. -* On X11, the primary monitor is detected correctly even when using versions of XRandR less than 1.5. -* `MonitorId` now implements `Debug`. -* Fixed bug on macOS where using `with_decorations(false)` would cause `set_decorations(true)` to produce a transparent titlebar with no title. -* Implemented `MonitorId::get_position` on macOS. -* On macOS, `Window::get_current_monitor` now returns accurate values. -* Added `WindowBuilderExt::with_resize_increments` to macOS. -* **Breaking:** On X11, `WindowBuilderExt::with_resize_increments` and `WindowBuilderExt::with_base_size` now take `u32` values rather than `i32`. -* macOS keyboard handling has been overhauled, allowing for the use of dead keys, IME, etc. Right modifier keys are also no longer reported as being left. -* Added the `Window::set_ime_spot(x: i32, y: i32)` method, which is implemented on X11 and macOS. -* **Breaking**: `os::unix::WindowExt::send_xim_spot(x: i16, y: i16)` no longer exists. Switch to the new `Window::set_ime_spot(x: i32, y: i32)`, which has equivalent functionality. -* Fixed detection of `Pause` and `Scroll` keys on Windows. -* On Windows, alt-tabbing while the cursor is grabbed no longer makes it impossible to re-grab the cursor. -* On Windows, using `CursorState::Hide` when the cursor is grabbed now ungrabs the cursor first. -* Implemented `MouseCursor::NoneCursor` on Windows. -* Added `WindowBuilder::with_always_on_top` and `Window::set_always_on_top`. Implemented on Windows, macOS, and X11. -* On X11, `WindowBuilderExt` now has `with_class`, `with_override_redirect`, and `with_x11_window_type` to allow for more control over window creation. `WindowExt` additionally has `set_urgent`. -* More hints are set by default on X11, including `_NET_WM_PID` and `WM_CLIENT_MACHINE`. Note that prior to this, the `WM_CLASS` hint was automatically set to whatever value was passed to `with_title`. It's now set to the executable name to better conform to expectations and the specification; if this is undesirable, you must explicitly use `WindowBuilderExt::with_class`. +- `Icon::to_cardinals` is no longer public, since it was never supposed to be. +- Wayland: improve diagnostics if initialization fails +- Fix some system event key doesn't work when focused, do not block keyevent forward to system on macOS +- On X11, the scroll wheel position is now correctly reset on i3 and other WMs that have the same quirk. +- On X11, `Window::get_current_monitor` now reliably returns the correct monitor. +- On X11, `Window::hidpi_factor` returns values from XRandR rather than the inaccurate values previously queried from the core protocol. +- On X11, the primary monitor is detected correctly even when using versions of XRandR less than 1.5. +- `MonitorId` now implements `Debug`. +- Fixed bug on macOS where using `with_decorations(false)` would cause `set_decorations(true)` to produce a transparent titlebar with no title. +- Implemented `MonitorId::get_position` on macOS. +- On macOS, `Window::get_current_monitor` now returns accurate values. +- Added `WindowBuilderExt::with_resize_increments` to macOS. +- **Breaking:** On X11, `WindowBuilderExt::with_resize_increments` and `WindowBuilderExt::with_base_size` now take `u32` values rather than `i32`. +- macOS keyboard handling has been overhauled, allowing for the use of dead keys, IME, etc. Right modifier keys are also no longer reported as being left. +- Added the `Window::set_ime_spot(x: i32, y: i32)` method, which is implemented on X11 and macOS. +- **Breaking**: `os::unix::WindowExt::send_xim_spot(x: i16, y: i16)` no longer exists. Switch to the new `Window::set_ime_spot(x: i32, y: i32)`, which has equivalent functionality. +- Fixed detection of `Pause` and `Scroll` keys on Windows. +- On Windows, alt-tabbing while the cursor is grabbed no longer makes it impossible to re-grab the cursor. +- On Windows, using `CursorState::Hide` when the cursor is grabbed now ungrabs the cursor first. +- Implemented `MouseCursor::NoneCursor` on Windows. +- Added `WindowBuilder::with_always_on_top` and `Window::set_always_on_top`. Implemented on Windows, macOS, and X11. +- On X11, `WindowBuilderExt` now has `with_class`, `with_override_redirect`, and `with_x11_window_type` to allow for more control over window creation. `WindowExt` additionally has `set_urgent`. +- More hints are set by default on X11, including `_NET_WM_PID` and `WM_CLIENT_MACHINE`. Note that prior to this, the `WM_CLASS` hint was automatically set to whatever value was passed to `with_title`. It's now set to the executable name to better conform to expectations and the specification; if this is undesirable, you must explicitly use `WindowBuilderExt::with_class`. # Version 0.14.0 (2018-05-09) -* Created the `Copy`, `Paste` and `Cut` `VirtualKeyCode`s and added support for them on X11 and Wayland -* Fix `.with_decorations(false)` in macOS -* On Mac, `NSWindow` and supporting objects might be alive long after they were `closed` which resulted in apps consuming more heap then needed. Mainly it was affecting multi window applications. Not expecting any user visible change of behaviour after the fix. -* Fix regression of Window platform extensions for macOS where `NSFullSizeContentViewWindowMask` was not being correctly applied to `.fullsize_content_view`. -* Corrected `get_position` on Windows to be relative to the screen rather than to the taskbar. -* Corrected `Moved` event on Windows to use position values equivalent to those returned by `get_position`. It previously supplied client area positions instead of window positions, and would additionally interpret negative values as being very large (around `u16::MAX`). -* Implemented `Moved` event on macOS. -* On X11, the `Moved` event correctly use window positions rather than client area positions. Additionally, a stray `Moved` that unconditionally accompanied `Resized` with the client area position relative to the parent has been eliminated; `Moved` is still received alongside `Resized`, but now only once and always correctly. -* On Windows, implemented all variants of `DeviceEvent` other than `Text`. Mouse `DeviceEvent`s are now received even if the window isn't in the foreground. -* `DeviceId` on Windows is no longer a unit struct, and now contains a `u32`. For `WindowEvent`s, this will always be 0, but on `DeviceEvent`s it will be the handle to that device. `DeviceIdExt::get_persistent_identifier` can be used to acquire a unique identifier for that device that persists across replugs/reboots/etc. -* Corrected `run_forever` on X11 to stop discarding `Awakened` events. -* Various safety and correctness improvements to the X11 backend internals. -* Fixed memory leak on X11 every time the mouse entered the window. -* On X11, drag and drop now works reliably in release mode. -* Added `WindowBuilderExt::with_resize_increments` and `WindowBuilderExt::with_base_size` to X11, allowing for more optional hints to be set. -* Rework of the wayland backend, migrating it to use [Smithay's Client Toolkit](https://github.com/Smithay/client-toolkit). -* Added `WindowBuilder::with_window_icon` and `Window::set_window_icon`, finally making it possible to set the window icon on Windows and X11. The `icon_loading` feature can be enabled to allow for icons to be easily loaded; see example program `window_icon.rs` for usage. -* Windows additionally has `WindowBuilderExt::with_taskbar_icon` and `WindowExt::set_taskbar_icon`. -* On Windows, fix panic when trying to call `set_fullscreen(None)` on a window that has not been fullscreened prior. +- Created the `Copy`, `Paste` and `Cut` `VirtualKeyCode`s and added support for them on X11 and Wayland +- Fix `.with_decorations(false)` in macOS +- On Mac, `NSWindow` and supporting objects might be alive long after they were `closed` which resulted in apps consuming more heap then needed. Mainly it was affecting multi window applications. Not expecting any user visible change of behaviour after the fix. +- Fix regression of Window platform extensions for macOS where `NSFullSizeContentViewWindowMask` was not being correctly applied to `.fullsize_content_view`. +- Corrected `get_position` on Windows to be relative to the screen rather than to the taskbar. +- Corrected `Moved` event on Windows to use position values equivalent to those returned by `get_position`. It previously supplied client area positions instead of window positions, and would additionally interpret negative values as being very large (around `u16::MAX`). +- Implemented `Moved` event on macOS. +- On X11, the `Moved` event correctly use window positions rather than client area positions. Additionally, a stray `Moved` that unconditionally accompanied `Resized` with the client area position relative to the parent has been eliminated; `Moved` is still received alongside `Resized`, but now only once and always correctly. +- On Windows, implemented all variants of `DeviceEvent` other than `Text`. Mouse `DeviceEvent`s are now received even if the window isn't in the foreground. +- `DeviceId` on Windows is no longer a unit struct, and now contains a `u32`. For `WindowEvent`s, this will always be 0, but on `DeviceEvent`s it will be the handle to that device. `DeviceIdExt::get_persistent_identifier` can be used to acquire a unique identifier for that device that persists across replugs/reboots/etc. +- Corrected `run_forever` on X11 to stop discarding `Awakened` events. +- Various safety and correctness improvements to the X11 backend internals. +- Fixed memory leak on X11 every time the mouse entered the window. +- On X11, drag and drop now works reliably in release mode. +- Added `WindowBuilderExt::with_resize_increments` and `WindowBuilderExt::with_base_size` to X11, allowing for more optional hints to be set. +- Rework of the wayland backend, migrating it to use [Smithay's Client Toolkit](https://github.com/Smithay/client-toolkit). +- Added `WindowBuilder::with_window_icon` and `Window::set_window_icon`, finally making it possible to set the window icon on Windows and X11. The `icon_loading` feature can be enabled to allow for icons to be easily loaded; see example program `window_icon.rs` for usage. +- Windows additionally has `WindowBuilderExt::with_taskbar_icon` and `WindowExt::set_taskbar_icon`. +- On Windows, fix panic when trying to call `set_fullscreen(None)` on a window that has not been fullscreened prior. # Version 0.13.1 (2018-04-26) -* Ensure necessary `x11-dl` version is used. +- Ensure necessary `x11-dl` version is used. # Version 0.13.0 (2018-04-25) -* Implement `WindowBuilder::with_maximized`, `Window::set_fullscreen`, `Window::set_maximized` and `Window::set_decorations` for MacOS. -* Implement `WindowBuilder::with_maximized`, `Window::set_fullscreen`, `Window::set_maximized` and `Window::set_decorations` for Windows. -* On Windows, `WindowBuilder::with_fullscreen` no longer changing monitor display resolution. -* Overhauled X11 window geometry calculations. `get_position` and `set_position` are more universally accurate across different window managers, and `get_outer_size` actually works now. -* Fixed SIGSEGV/SIGILL crashes on macOS caused by stabilization of the `!` (never) type. -* Implement `WindowEvent::HiDPIFactorChanged` for macOS -* On X11, input methods now work completely out of the box, no longer requiring application developers to manually call `setlocale`. Additionally, when input methods are started, stopped, or restarted on the server end, it's correctly handled. -* Implemented `Refresh` event on Windows. -* Properly calculate the minimum and maximum window size on Windows, including window decorations. -* Map more `MouseCursor` variants to cursor icons on Windows. -* Corrected `get_position` on macOS to return outer frame position, not content area position. -* Corrected `set_position` on macOS to set outer frame position, not content area position. -* Added `get_inner_position` method to `Window`, which gets the position of the window's client area. This is implemented on all applicable platforms (all desktop platforms other than Wayland, where this isn't possible). -* **Breaking:** the `Closed` event has been replaced by `CloseRequested` and `Destroyed`. To migrate, you typically just need to replace all usages of `Closed` with `CloseRequested`; see example programs for more info. The exception is iOS, where `Closed` must be replaced by `Destroyed`. +- Implement `WindowBuilder::with_maximized`, `Window::set_fullscreen`, `Window::set_maximized` and `Window::set_decorations` for MacOS. +- Implement `WindowBuilder::with_maximized`, `Window::set_fullscreen`, `Window::set_maximized` and `Window::set_decorations` for Windows. +- On Windows, `WindowBuilder::with_fullscreen` no longer changing monitor display resolution. +- Overhauled X11 window geometry calculations. `get_position` and `set_position` are more universally accurate across different window managers, and `get_outer_size` actually works now. +- Fixed SIGSEGV/SIGILL crashes on macOS caused by stabilization of the `!` (never) type. +- Implement `WindowEvent::HiDPIFactorChanged` for macOS +- On X11, input methods now work completely out of the box, no longer requiring application developers to manually call `setlocale`. Additionally, when input methods are started, stopped, or restarted on the server end, it's correctly handled. +- Implemented `Refresh` event on Windows. +- Properly calculate the minimum and maximum window size on Windows, including window decorations. +- Map more `MouseCursor` variants to cursor icons on Windows. +- Corrected `get_position` on macOS to return outer frame position, not content area position. +- Corrected `set_position` on macOS to set outer frame position, not content area position. +- Added `get_inner_position` method to `Window`, which gets the position of the window's client area. This is implemented on all applicable platforms (all desktop platforms other than Wayland, where this isn't possible). +- **Breaking:** the `Closed` event has been replaced by `CloseRequested` and `Destroyed`. To migrate, you typically just need to replace all usages of `Closed` with `CloseRequested`; see example programs for more info. The exception is iOS, where `Closed` must be replaced by `Destroyed`. # Version 0.12.0 (2018-04-06) -* Added subclass to macos windows so they can be made resizable even with no decorations. -* Dead keys now work properly on X11, no longer resulting in a panic. -* On X11, input method creation first tries to use the value from the user's `XMODIFIERS` environment variable, so application developers should no longer need to manually call `XSetLocaleModifiers`. If that fails, fallbacks are tried, which should prevent input method initialization from ever outright failing. -* Fixed thread safety issues with input methods on X11. -* Add support for `Touch` for win32 backend. -* Fixed `Window::get_inner_size` and friends to return the size in pixels instead of points when using HIDPI displays on OSX. +- Added subclass to macos windows so they can be made resizable even with no decorations. +- Dead keys now work properly on X11, no longer resulting in a panic. +- On X11, input method creation first tries to use the value from the user's `XMODIFIERS` environment variable, so application developers should no longer need to manually call `XSetLocaleModifiers`. If that fails, fallbacks are tried, which should prevent input method initialization from ever outright failing. +- Fixed thread safety issues with input methods on X11. +- Add support for `Touch` for win32 backend. +- Fixed `Window::get_inner_size` and friends to return the size in pixels instead of points when using HIDPI displays on OSX. # Version 0.11.3 (2018-03-28) -* Added `set_min_dimensions` and `set_max_dimensions` methods to `Window`, and implemented on Windows, X11, Wayland, and OSX. -* On X11, dropping a `Window` actually closes it now, and clicking the window's × button (or otherwise having the WM signal to close it) will result in the window closing. -* Added `WindowBuilderExt` methods for macos: `with_titlebar_transparent`, - `with_title_hidden`, `with_titlebar_buttons_hidden`, - `with_fullsize_content_view`. -* Mapped X11 numpad keycodes (arrows, Home, End, PageUp, PageDown, Insert and Delete) to corresponding virtual keycodes +- Added `set_min_dimensions` and `set_max_dimensions` methods to `Window`, and implemented on Windows, X11, Wayland, and OSX. +- On X11, dropping a `Window` actually closes it now, and clicking the window's × button (or otherwise having the WM signal to close it) will result in the window closing. +- Added `WindowBuilderExt` methods for macos: `with_titlebar_transparent`, + `with_title_hidden`, `with_titlebar_buttons_hidden`, + `with_fullsize_content_view`. +- Mapped X11 numpad keycodes (arrows, Home, End, PageUp, PageDown, Insert and Delete) to corresponding virtual keycodes # Version 0.11.2 (2018-03-06) -* Impl `Hash`, `PartialEq`, and `Eq` for `events::ModifiersState`. -* Implement `MonitorId::get_hidpi_factor` for MacOS. -* Added method `os::macos::MonitorIdExt::get_nsscreen() -> *mut c_void` that gets a `NSScreen` object matching the monitor ID. -* Send `Awakened` event on Android when event loop is woken up. +- Impl `Hash`, `PartialEq`, and `Eq` for `events::ModifiersState`. +- Implement `MonitorId::get_hidpi_factor` for MacOS. +- Added method `os::macos::MonitorIdExt::get_nsscreen() -> *mut c_void` that gets a `NSScreen` object matching the monitor ID. +- Send `Awakened` event on Android when event loop is woken up. # Version 0.11.1 (2018-02-19) -* Fixed windows not receiving mouse events when click-dragging the mouse outside the client area of a window, on Windows platforms. -* Added method `os::android::EventsLoopExt:set_suspend_callback(Option ()>>)` that allows glutin to register a callback when a suspend event happens +- Fixed windows not receiving mouse events when click-dragging the mouse outside the client area of a window, on Windows platforms. +- Added method `os::android::EventsLoopExt:set_suspend_callback(Option ()>>)` that allows glutin to register a callback when a suspend event happens # Version 0.11.0 (2018-02-09) -* Implement `MonitorId::get_dimensions` for Android. -* Added method `os::macos::WindowBuilderExt::with_movable_by_window_background(bool)` that allows to move a window without a titlebar - `with_decorations(false)` -* Implement `Window::set_fullscreen`, `Window::set_maximized` and `Window::set_decorations` for Wayland. -* Added `Caret` as VirtualKeyCode and support OSX ^-Key with german input. +- Implement `MonitorId::get_dimensions` for Android. +- Added method `os::macos::WindowBuilderExt::with_movable_by_window_background(bool)` that allows to move a window without a titlebar - `with_decorations(false)` +- Implement `Window::set_fullscreen`, `Window::set_maximized` and `Window::set_decorations` for Wayland. +- Added `Caret` as VirtualKeyCode and support OSX ^-Key with german input. # Version 0.10.1 (2018-02-05) -*Yanked* +_Yanked_ # Version 0.10.0 (2017-12-27) -* Add support for `Touch` for emscripten backend. -* Added support for `DroppedFile`, `HoveredFile`, and `HoveredFileCancelled` to X11 backend. -* **Breaking:** `unix::WindowExt` no longer returns pointers for things that aren't actually pointers; `get_xlib_window` now returns `Option` and `get_xlib_screen_id` returns `Option`. Additionally, methods that previously returned `libc::c_void` have been changed to return `std::os::raw::c_void`, which are not interchangeable types, so users wanting the former will need to explicitly cast. -* Added `set_decorations` method to `Window` to allow decorations to be toggled after the window is built. Presently only implemented on X11. -* Raised the minimum supported version of Rust to 1.20 on MacOS due to usage of associated constants in new versions of cocoa and core-graphics. -* Added `modifiers` field to `MouseInput`, `MouseWheel`, and `CursorMoved` events to track the modifiers state (`ModifiersState`). -* Fixed the emscripten backend to return the size of the canvas instead of the size of the window. +- Add support for `Touch` for emscripten backend. +- Added support for `DroppedFile`, `HoveredFile`, and `HoveredFileCancelled` to X11 backend. +- **Breaking:** `unix::WindowExt` no longer returns pointers for things that aren't actually pointers; `get_xlib_window` now returns `Option` and `get_xlib_screen_id` returns `Option`. Additionally, methods that previously returned `libc::c_void` have been changed to return `std::os::raw::c_void`, which are not interchangeable types, so users wanting the former will need to explicitly cast. +- Added `set_decorations` method to `Window` to allow decorations to be toggled after the window is built. Presently only implemented on X11. +- Raised the minimum supported version of Rust to 1.20 on MacOS due to usage of associated constants in new versions of cocoa and core-graphics. +- Added `modifiers` field to `MouseInput`, `MouseWheel`, and `CursorMoved` events to track the modifiers state (`ModifiersState`). +- Fixed the emscripten backend to return the size of the canvas instead of the size of the window. # Version 0.9.0 (2017-12-01) -* Added event `WindowEvent::HiDPIFactorChanged`. -* Added method `MonitorId::get_hidpi_factor`. -* Deprecated `get_inner_size_pixels` and `get_inner_size_points` methods of `Window` in favor of - `get_inner_size`. -* **Breaking:** `EventsLoop` is `!Send` and `!Sync` because of platform-dependant constraints, - but `Window`, `WindowId`, `DeviceId` and `MonitorId` guaranteed to be `Send`. -* `MonitorId::get_position` now returns `(i32, i32)` instead of `(u32, u32)`. -* Rewrite of the wayland backend to use wayland-client-0.11 -* Support for dead keys on wayland for keyboard utf8 input -* Monitor enumeration on Windows is now implemented using `EnumDisplayMonitors` instead of - `EnumDisplayDevices`. This changes the value returned by `MonitorId::get_name()`. -* On Windows added `MonitorIdExt::hmonitor` method -* Impl `Clone` for `EventsLoopProxy` -* `EventsLoop::get_primary_monitor()` on X11 will fallback to any available monitor if no primary is found -* Support for touch event on wayland -* `WindowEvent`s `MouseMoved`, `MouseEntered`, and `MouseLeft` have been renamed to - `CursorMoved`, `CursorEntered`, and `CursorLeft`. -* New `DeviceEvent`s added, `MouseMotion` and `MouseWheel`. -* Send `CursorMoved` event after `CursorEntered` and `Focused` events. -* Add support for `ModifiersState`, `MouseMove`, `MouseInput`, `MouseMotion` for emscripten backend. +- Added event `WindowEvent::HiDPIFactorChanged`. +- Added method `MonitorId::get_hidpi_factor`. +- Deprecated `get_inner_size_pixels` and `get_inner_size_points` methods of `Window` in favor of +`get_inner_size`. +- **Breaking:** `EventsLoop` is `!Send` and `!Sync` because of platform-dependant constraints, + but `Window`, `WindowId`, `DeviceId` and `MonitorId` guaranteed to be `Send`. +- `MonitorId::get_position` now returns `(i32, i32)` instead of `(u32, u32)`. +- Rewrite of the wayland backend to use wayland-client-0.11 +- Support for dead keys on wayland for keyboard utf8 input +- Monitor enumeration on Windows is now implemented using `EnumDisplayMonitors` instead of +`EnumDisplayDevices`. This changes the value returned by `MonitorId::get_name()`. +- On Windows added `MonitorIdExt::hmonitor` method +- Impl `Clone` for `EventsLoopProxy` +- `EventsLoop::get_primary_monitor()` on X11 will fallback to any available monitor if no primary is found +- Support for touch event on wayland +- `WindowEvent`s `MouseMoved`, `MouseEntered`, and `MouseLeft` have been renamed to +`CursorMoved`, `CursorEntered`, and `CursorLeft`. +- New `DeviceEvent`s added, `MouseMotion` and `MouseWheel`. +- Send `CursorMoved` event after `CursorEntered` and `Focused` events. +- Add support for `ModifiersState`, `MouseMove`, `MouseInput`, `MouseMotion` for emscripten backend. # Version 0.8.3 (2017-10-11) -* Fixed issue of calls to `set_inner_size` blocking on Windows. -* Mapped `ISO_Left_Tab` to `VirtualKeyCode::Tab` to make the key work with modifiers -* Fixed the X11 backed on 32bit targets +- Fixed issue of calls to `set_inner_size` blocking on Windows. +- Mapped `ISO_Left_Tab` to `VirtualKeyCode::Tab` to make the key work with modifiers +- Fixed the X11 backed on 32bit targets # Version 0.8.2 (2017-09-28) -* Uniformize keyboard scancode values accross Wayland and X11 (#297). -* Internal rework of the wayland event loop -* Added method `os::linux::WindowExt::is_ready` +- Uniformize keyboard scancode values accross Wayland and X11 (#297). +- Internal rework of the wayland event loop +- Added method `os::linux::WindowExt::is_ready` # Version 0.8.1 (2017-09-22) -* Added various methods to `os::linux::EventsLoopExt`, plus some hidden items necessary to make - glutin work. +- Added various methods to `os::linux::EventsLoopExt`, plus some hidden items necessary to make + glutin work. # Version 0.8.0 (2017-09-21) -* Added `Window::set_maximized`, `WindowAttributes::maximized` and `WindowBuilder::with_maximized`. -* Added `Window::set_fullscreen`. -* Changed `with_fullscreen` to take a `Option` instead of a `MonitorId`. -* Removed `MonitorId::get_native_identifer()` in favor of platform-specific traits in the `os` - module. -* Changed `get_available_monitors()` and `get_primary_monitor()` to be methods of `EventsLoop` - instead of stand-alone methods. -* Changed `EventsLoop` to be tied to a specific X11 or Wayland connection. -* Added a `os::linux::EventsLoopExt` trait that makes it possible to configure the connection. -* Fixed the emscripten code, which now compiles. -* Changed the X11 fullscreen code to use `xrandr` instead of `xxf86vm`. -* Fixed the Wayland backend to produce `Refresh` event after window creation. -* Changed the `Suspended` event to be outside of `WindowEvent`. -* Fixed the X11 backend sometimes reporting the wrong virtual key (#273). +- Added `Window::set_maximized`, `WindowAttributes::maximized` and `WindowBuilder::with_maximized`. +- Added `Window::set_fullscreen`. +- Changed `with_fullscreen` to take a `Option` instead of a `MonitorId`. +- Removed `MonitorId::get_native_identifer()` in favor of platform-specific traits in the `os` + module. +- Changed `get_available_monitors()` and `get_primary_monitor()` to be methods of `EventsLoop` + instead of stand-alone methods. +- Changed `EventsLoop` to be tied to a specific X11 or Wayland connection. +- Added a `os::linux::EventsLoopExt` trait that makes it possible to configure the connection. +- Fixed the emscripten code, which now compiles. +- Changed the X11 fullscreen code to use `xrandr` instead of `xxf86vm`. +- Fixed the Wayland backend to produce `Refresh` event after window creation. +- Changed the `Suspended` event to be outside of `WindowEvent`. +- Fixed the X11 backend sometimes reporting the wrong virtual key (#273). \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index cb4250f961..cc806f669b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,10 @@ [package] name = "winit" version = "0.26.1" -authors = ["The winit contributors", "Pierre Krieger "] +authors = [ + "The winit contributors", + "Pierre Krieger ", +] description = "Cross-platform window creation library." edition = "2021" keywords = ["windowing"] @@ -14,7 +17,14 @@ categories = ["gui"] [package.metadata.docs.rs] features = ["serde"] default-target = "x86_64-unknown-linux-gnu" -targets = ["i686-pc-windows-msvc", "x86_64-pc-windows-msvc", "i686-unknown-linux-gnu", "x86_64-unknown-linux-gnu", "x86_64-apple-darwin", "wasm32-unknown-unknown"] +targets = [ + "i686-pc-windows-msvc", + "x86_64-pc-windows-msvc", + "i686-unknown-linux-gnu", + "x86_64-unknown-linux-gnu", + "x86_64-apple-darwin", + "wasm32-unknown-unknown", +] [features] default = ["x11", "wayland", "wayland-dlopen", "kmsdrm"] @@ -62,79 +72,83 @@ parking_lot = "0.12" [target.'cfg(target_os = "windows")'.dependencies.windows-sys] version = "0.33" features = [ - "Win32_Devices_HumanInterfaceDevice", - "Win32_Foundation", - "Win32_Globalization", - "Win32_Graphics_Dwm", - "Win32_Graphics_Gdi", - "Win32_Media", - "Win32_System_Com_StructuredStorage", - "Win32_System_Com", - "Win32_System_LibraryLoader", - "Win32_System_Ole", - "Win32_System_SystemInformation", - "Win32_System_SystemServices", - "Win32_System_Threading", - "Win32_System_WindowsProgramming", - "Win32_UI_Accessibility", - "Win32_UI_Controls", - "Win32_UI_HiDpi", - "Win32_UI_Input_Ime", - "Win32_UI_Input_KeyboardAndMouse", - "Win32_UI_Input_Pointer", - "Win32_UI_Input_Touch", - "Win32_UI_Shell", - "Win32_UI_TextServices", - "Win32_UI_WindowsAndMessaging", - ] + "Win32_Devices_HumanInterfaceDevice", + "Win32_Foundation", + "Win32_Globalization", + "Win32_Graphics_Dwm", + "Win32_Graphics_Gdi", + "Win32_Media", + "Win32_System_Com_StructuredStorage", + "Win32_System_Com", + "Win32_System_LibraryLoader", + "Win32_System_Ole", + "Win32_System_SystemInformation", + "Win32_System_SystemServices", + "Win32_System_Threading", + "Win32_System_WindowsProgramming", + "Win32_UI_Accessibility", + "Win32_UI_Controls", + "Win32_UI_HiDpi", + "Win32_UI_Input_Ime", + "Win32_UI_Input_KeyboardAndMouse", + "Win32_UI_Input_Pointer", + "Win32_UI_Input_Touch", + "Win32_UI_Shell", + "Win32_UI_TextServices", + "Win32_UI_WindowsAndMessaging", +] - [target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))'.dependencies] - wayland-client = { version = "0.29", default_features = false, features = ["use_system_lib"], optional = true } - wayland-protocols = { version = "0.29", features = [ "staging_protocols"], optional = true } - calloop = { version = "0.9.3", optional = true } - sctk = { package = "smithay-client-toolkit", version = "0.15.4", default_features = false, features = ["calloop"], optional = true } - mio = { version = "0.8", features = ["os-ext"], optional = true } - x11-dl = { version = "2.18.5", optional = true } - percent-encoding = { version = "2.0", optional = true } - parking_lot = { version = "0.12.0", optional = true } - libc = "0.2.64" - drm = { version = "0.6.2", optional = true } - gbm = { version = "0.8.0", optional = true } - input = { version = "0.7.1", optional = true } +[target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))'.dependencies] +wayland-client = { version = "0.29", default_features = false, features = [ + "use_system_lib", +], optional = true } +wayland-protocols = { version = "0.29", features = [ + "staging_protocols", +], optional = true } +calloop = { version = "0.9.3", optional = true } +sctk = { package = "smithay-client-toolkit", version = "0.15.4", default_features = false, features = [ + "calloop", +], optional = true } +mio = { version = "0.8", features = ["os-ext"], optional = true } +x11-dl = { version = "2.18.5", optional = true } +percent-encoding = { version = "2.0", optional = true } +parking_lot = { version = "0.12.0", optional = true } +libc = "0.2.64" +drm = { version = "0.6.2", optional = true } +gbm = { version = "0.8.0", optional = true } +input = { version = "0.7.1", optional = true } - [target.'cfg(target_arch = "wasm32")'.dependencies.web_sys] - package = "web-sys" - version = "0.3.22" - features = [ - 'console', - "AddEventListenerOptions", - 'CssStyleDeclaration', - 'BeforeUnloadEvent', - 'Document', - 'DomRect', - 'Element', - 'Event', - 'EventTarget', - 'FocusEvent', - 'HtmlCanvasElement', - 'HtmlElement', - 'KeyboardEvent', - 'MediaQueryList', - 'MediaQueryListEvent', - 'MouseEvent', - 'Node', - 'PointerEvent', - 'Window', - 'WheelEvent' - ] +[target.'cfg(target_arch = "wasm32")'.dependencies.web_sys] +package = "web-sys" +version = "0.3.22" +features = [ + 'console', + "AddEventListenerOptions", + 'CssStyleDeclaration', + 'BeforeUnloadEvent', + 'Document', + 'DomRect', + 'Element', + 'Event', + 'EventTarget', + 'FocusEvent', + 'HtmlCanvasElement', + 'HtmlElement', + 'KeyboardEvent', + 'MediaQueryList', + 'MediaQueryListEvent', + 'MouseEvent', + 'Node', + 'PointerEvent', + 'Window', + 'WheelEvent', +] - [target.'cfg(target_arch = "wasm32")'.dependencies.wasm-bindgen] - version = "0.2.45" +[target.'cfg(target_arch = "wasm32")'.dependencies.wasm-bindgen] +version = "0.2.45" - [target.'cfg(target_arch = "wasm32")'.dev-dependencies] - console_log = "0.2" +[target.'cfg(target_arch = "wasm32")'.dev-dependencies] +console_log = "0.2" - [workspace] - members = [ - "run-wasm", - ] +[workspace] +members = ["run-wasm"] diff --git a/FEATURES.md b/FEATURES.md index e247b539af..e9a6c54a08 100644 --- a/FEATURES.md +++ b/FEATURES.md @@ -3,29 +3,29 @@ Winit aims to expose an interface that abstracts over window creation and input handling, and can be used to create both games and applications. It supports the main graphical platforms: -* Desktop - * Windows - * macOS - * Unix - * via X11 - * via Wayland - * via DRM -* Mobile - * iOS - * Android -* Web - * via WASM +- Desktop + - Windows + - macOS + - Unix + - via X11 + - via Wayland + - via DRM +- Mobile + - iOS + - Android +- Web + - via WASM Most platforms expose capabilities that cannot be meaningfully transposed onto others. Winit does not aim to support every single feature of every platform, but rather to abstract over the common features available everywhere. In this context, APIs exposed in winit can be split into different "support tiers": -* **Core:** Features that are essential to providing a well-formed abstraction over each platform's +- **Core:** Features that are essential to providing a well-formed abstraction over each platform's windowing and input APIs. -* **Platform:** Platform-specific features that can't be meaningfully exposed through a common API and +- **Platform:** Platform-specific features that can't be meaningfully exposed through a common API and cannot be implemented outside of Winit without exposing a significant amount of Winit's internals or interfering with Winit's abstractions. -* **Usability:** Features that are not strictly essential to Winit's functionality, but provide meaningful +- **Usability:** Features that are not strictly essential to Winit's functionality, but provide meaningful usability improvements and cannot be reasonably implemented in an external crate. These are generally optional and exposed through Cargo features. @@ -47,7 +47,7 @@ be added past this point. New platform features may be accepted and exposed thro Some platform features could in theory be exposed across multiple platforms, but have not gone through the implementation work necessary to function on all platforms. When one of these features -gets implemented across all platforms, a PR can be opened to upgrade the feature to a core feature. +gets implemented across all platforms, a PR can be opened to upgrade the feature to a core f*eature. If that gets accepted, the platform-specific functions gets deprecated and become permanently exposed through the core, cross-platform API. @@ -57,127 +57,127 @@ exposed through the core, cross-platform API. If your PR makes notable changes to Winit's features, please update this section as follows: -* If your PR adds a new feature, add a brief description to the relevant section. If the feature is a core +- If your PR adds a new feature, add a brief description to the relevant section. If the feature is a core feature, add a row to the feature matrix and describe what platforms the feature has been implemented on. -* If your PR begins a new API rework, add a row to the `Pending API Reworks` table. If the PR implements the +- If your PR begins a new API rework, add a row to the `Pending API Reworks` table. If the PR implements the API rework on all relevant platforms, please move it to the `Completed API Reworks` table. -* If your PR implements an already-existing feature on a new platform, either mark the feature as *completed*, +- If your PR implements an already-existing feature on a new platform, either mark the feature as *completed*, or mark it as *mostly completed* and link to an issue describing the problems with the implementation. ## Core ### Windowing -* **Window initialization**: Winit allows the creation of a window -* **Providing pointer to init OpenGL**: Winit provides the necessary pointers to initialize a working opengl context -* **Providing pointer to init Vulkan**: Same as OpenGL but for Vulkan -* **Window decorations**: The windows created by winit are properly decorated, and the decorations can +- **Window initialization**: Winit allows the creation of a window +- **Providing pointer to init OpenGL**: Winit provides the necessary pointers to initialize a working opengl context +- **Providing pointer to init Vulkan**: Same as OpenGL but for Vulkan +- **Window decorations**: The windows created by winit are properly decorated, and the decorations can be deactivated -* **Window decorations toggle**: Decorations can be turned on or off after window creation -* **Window resizing**: The windows created by winit can be resized and generate the appropriate events +- **Window decorations toggle**: Decorations can be turned on or off after window creation +- **Window resizing**: The windows created by winit can be resized and generate the appropriate events when they are. The application can precisely control its window size if desired. -* **Window resize increments**: When the window gets resized, the application can choose to snap the window's +- **Window resize increments**: When the window gets resized, the application can choose to snap the window's size to specific values. -* **Window transparency**: Winit allows the creation of windows with a transparent background. -* **Window maximization**: The windows created by winit can be maximized upon creation. -* **Window maximization toggle**: The windows created by winit can be maximized and unmaximized after +- **Window transparency**: Winit allows the creation of windows with a transparent background. +- **Window maximization**: The windows created by winit can be maximized upon creation. +- **Window maximization toggle**: The windows created by winit can be maximized and unmaximized after creation. -* **Window minimization**: The windows created by winit can be minimized after creation. -* **Fullscreen**: The windows created by winit can be put into fullscreen mode. -* **Fullscreen toggle**: The windows created by winit can be switched to and from fullscreen after +- **Window minimization**: The windows created by winit can be minimized after creation. +- **Fullscreen**: The windows created by winit can be put into fullscreen mode. +- **Fullscreen toggle**: The windows created by winit can be switched to and from fullscreen after creation. -* **Exclusive fullscreen**: Winit allows changing the video mode of the monitor +- **Exclusive fullscreen**: Winit allows changing the video mode of the monitor for fullscreen windows, and if applicable, captures the monitor for exclusive use by this application. -* **HiDPI support**: Winit assists developers in appropriately scaling HiDPI content. -* **Popup / modal windows**: Windows can be created relative to the client area of other windows, and parent +- **HiDPI support**: Winit assists developers in appropriately scaling HiDPI content. +- **Popup / modal windows**: Windows can be created relative to the client area of other windows, and parent windows can be disabled in favor of popup windows. This feature also guarantees that popup windows get drawn above their owner. ### System Information -* **Monitor list**: Retrieve the list of monitors and their metadata, including which one is primary. -* **Video mode query**: Monitors can be queried for their supported fullscreen video modes (consisting of resolution, refresh rate, and bit depth). +- **Monitor list**: Retrieve the list of monitors and their metadata, including which one is primary. +- **Video mode query**: Monitors can be queried for their supported fullscreen video modes (consisting of resolution, refresh rate, and bit depth). ### Input Handling -* **Mouse events**: Generating mouse events associated with pointer motion, click, and scrolling events. -* **Mouse set location**: Forcibly changing the location of the pointer. -* **Cursor grab**: Locking the cursor so it cannot exit the client area of a window. -* **Cursor icon**: Changing the cursor icon, or hiding the cursor. -* **Cursor hittest**: Handle or ignore mouse events for a window. -* **Touch events**: Single-touch events. -* **Touch pressure**: Touch events contain information about the amount of force being applied. -* **Multitouch**: Multi-touch events, including cancellation of a gesture. -* **Keyboard events**: Properly processing keyboard events using the user-specified keymap and +- **Mouse events**: Generating mouse events associated with pointer motion, click, and scrolling events. +- **Mouse set location**: Forcibly changing the location of the pointer. +- **Cursor grab**: Locking the cursor so it cannot exit the client area of a window. +- **Cursor icon**: Changing the cursor icon, or hiding the cursor. +- **Cursor hittest**: Handle or ignore mouse events for a window. +- **Touch events**: Single-touch events. +- **Touch pressure**: Touch events contain information about the amount of force being applied. +- **Multitouch**: Multi-touch events, including cancellation of a gesture. +- **Keyboard events**: Properly processing keyboard events using the user-specified keymap and translating keypresses into UTF-8 characters, handling dead keys and IMEs. -* **Drag & Drop**: Dragging content into winit, detecting when content enters, drops, or if the drop is cancelled. -* **Raw Device Events**: Capturing input from input devices without any OS filtering. -* **Gamepad/Joystick events**: Capturing input from gamepads and joysticks. -* **Device movement events**: Capturing input from the device gyroscope and accelerometer. +- **Drag & Drop**: Dragging content into winit, detecting when content enters, drops, or if the drop is cancelled. +- **Raw Device Events**: Capturing input from input devices without any OS filtering. +- **Gamepad/Joystick events**: Capturing input from gamepads and joysticks. +- **Device movement events**: Capturing input from the device gyroscope and accelerometer. ## Platform ### Windows -* Setting the taskbar icon -* Setting the parent window -* Setting a menu bar -* `WS_EX_NOREDIRECTIONBITMAP` support -* Theme the title bar according to Windows 10 Dark Mode setting or set a preferred theme +- Setting the taskbar icon +- Setting the parent window +- Setting a menu bar +- `WS_EX_NOREDIRECTIONBITMAP` support +- Theme the title bar according to Windows 10 Dark Mode setting or set a preferred theme ### macOS -* Window activation policy -* Window movable by background -* Transparent titlebar -* Hidden titlebar -* Hidden titlebar buttons -* Full-size content view +- Window activation policy +- Window movable by background +- Transparent titlebar +- Hidden titlebar +- Hidden titlebar buttons +- Full-size content view ### Unix -* Window urgency -* X11 Window Class -* X11 Override Redirect Flag -* GTK Theme Variant -* Base window size +- Window urgency +- X11 Window Class +- X11 Override Redirect Flag +- GTK Theme Variant +- Base window size ### iOS -* `winit` has a minimum OS requirement of iOS 8 -* Get the `UIWindow` object pointer -* Get the `UIViewController` object pointer -* Get the `UIView` object pointer -* Get the `UIScreen` object pointer -* Setting the `UIView` hidpi factor -* Valid orientations -* Home indicator visibility -* Status bar visibility -* Deferrring system gestures -* Support for custom `UIView` derived class -* Getting the device idiom -* Getting the preferred video mode +- `winit` has a minimum OS requirement of iOS 8 +- Get the `UIWindow` object pointer +- Get the `UIViewController` object pointer +- Get the `UIView` object pointer +- Get the `UIScreen` object pointer +- Setting the `UIView` hidpi factor +- Valid orientations +- Home indicator visibility +- Status bar visibility +- Deferrring system gestures +- Support for custom `UIView` derived class +- Getting the device idiom +- Getting the preferred video mode ### Web -* Get if systems preferred color scheme is "dark" +- Get if systems preferred color scheme is "dark" ## Usability -* `serde`: Enables serialization/deserialization of certain types with Serde. (Maintainer: @Osspial) +- `serde`: Enables serialization/deserialization of certain types with Serde. (Maintainer: @Osspial) ## Compatibility Matrix Legend: -* ✔️: Works as intended -* ▢: Mostly works but some bugs are known -* ❌: Missing feature or large bugs making it unusable -* **N/A**: Not applicable for this platform -* ❓: Unknown status +- ✔️: Works as intended +- ▢: Mostly works but some bugs are known +- ❌: Missing feature or large bugs making it unusable +- **N/A**: Not applicable for this platform +- ❓: Unknown status ### Windowing From 664cbe9c13156151a3d23420abdb4436187a19b1 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Fri, 29 Apr 2022 00:13:47 -0400 Subject: [PATCH 006/151] Access to more pointers for future glutin creation in kmsdrm --- src/platform/unix.rs | 32 +++++++ src/platform_impl/linux/drm/event_loop.rs | 11 +++ src/platform_impl/linux/drm/window.rs | 101 ++++++++-------------- 3 files changed, 80 insertions(+), 64 deletions(-) diff --git a/src/platform/unix.rs b/src/platform/unix.rs index 2b0173990e..7a721670f7 100644 --- a/src/platform/unix.rs +++ b/src/platform/unix.rs @@ -74,6 +74,18 @@ pub trait EventLoopWindowTargetExtUnix { >, >, >; + + /// Returns the current crtc of the gbm device + /// + /// Returns `None` if the `EventLoop` doesn't use kmsdrm (if it uses wayland for example). + #[cfg(feature = "kmsdrm")] + fn gbm_crtc(&self) -> Option<&drm::control::crtc::Info>; + + /// Returns the current connector of the gbm device + /// + /// Returns `None` if the `EventLoop` doesn't use kmsdrm (if it uses wayland for example). + #[cfg(feature = "kmsdrm")] + fn gbm_connector(&self) -> Option<&drm::control::connector::Info>; } impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { @@ -140,6 +152,26 @@ impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { _ => None, } } + + #[inline] + #[cfg(feature = "kmsdrm")] + fn gbm_crtc(&self) -> Option<&drm::control::crtc::Info> { + match self.p { + crate::platform_impl::EventLoopWindowTarget::Drm(ref window) => Some(&window.crtc), + #[cfg(any(feature = "x11", feature = "wayland"))] + _ => None, + } + } + + #[inline] + #[cfg(feature = "kmsdrm")] + fn gbm_connector(&self) -> Option<&drm::control::connector::Info> { + match self.p { + crate::platform_impl::EventLoopWindowTarget::Drm(ref window) => Some(&window.connector), + #[cfg(any(feature = "x11", feature = "wayland"))] + _ => None, + } + } } /// Additional methods on [`EventLoopBuilder`] that are specific to Unix. diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index ff54a3d183..b29e4e96c9 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -571,6 +571,9 @@ pub struct EventLoopWindowTarget { /// gbm Connector pub connector: drm::control::connector::Info, + /// gbm crtc + pub crtc: drm::control::crtc::Info, + /// Event loop handle. pub event_loop_handle: calloop::LoopHandle<'static, EventSink>, @@ -664,6 +667,13 @@ impl EventLoop { .iter() .flat_map(|con| gbm.get_connector(*con)) .collect(); + let crtcinfo: Vec = res + .crtcs() + .iter() + .flat_map(|crtc| gbm.get_crtc(*crtc)) + .collect(); + + let crtc = crtcinfo.get(0).expect("No crtcs found"); // Filter each connector until we find one that's connected. let con = coninfo @@ -734,6 +744,7 @@ impl EventLoop { let window_target = crate::event_loop::EventLoopWindowTarget { p: crate::platform_impl::EventLoopWindowTarget::Drm(EventLoopWindowTarget { connector: con.clone(), + crtc: crtc.clone(), event_loop_handle: handle, event_sink, event_loop_awakener, diff --git a/src/platform_impl/linux/drm/window.rs b/src/platform_impl/linux/drm/window.rs index a748627912..4f239c8fc2 100644 --- a/src/platform_impl/linux/drm/window.rs +++ b/src/platform_impl/linux/drm/window.rs @@ -31,62 +31,31 @@ impl Window { crate::platform_impl::OsError::DrmMisc("Failed to acquire gbm lock"), ) })?; - let res = gbm.resource_handles().map_err(|_| { - crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc("Could not get resource handles"), - ) - })?; - let coninfo: Vec = res - .connectors() - .iter() - .flat_map(|con| gbm.get_connector(*con)) - .collect(); - - // Filter each connector until we find one that's connected. - let con = coninfo - .iter() - .find(|&i| i.state() == drm::control::connector::State::Connected) + let &mode = event_loop_window_target + .connector + .modes() + .get(0) .ok_or_else(|| { crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::DrmMisc("No connected connectors"), + crate::platform_impl::OsError::DrmMisc("No modes found on connector"), ) })?; - let crtcinfo: Vec = res - .crtcs() - .iter() - .flat_map(|crtc| gbm.get_crtc(*crtc)) - .collect(); - - let crtc = crtcinfo.get(0).ok_or_else(|| { - crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc("No crtcs found"), - ) - })?; - let &mode = con.modes().get(0).ok_or_else(|| { - crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc("No modes found on connector"), - ) - })?; let mut atomic_req = atomic::AtomicModeReq::new(); atomic_req.add_property( - con.handle(), - find_prop_id(&gbm, con.handle(), "CRTC_ID").ok_or_else(|| { - crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc("Could not get CRTC_ID"), - ) - })?, - property::Value::CRTC(Some(crtc.handle())), + event_loop_window_target.connector.handle(), + find_prop_id(&gbm, event_loop_window_target.connector.handle(), "CRTC_ID").ok_or_else( + || { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Could not get CRTC_ID"), + ) + }, + )?, + property::Value::CRTC(Some(event_loop_window_target.crtc.handle())), ); let blob = gbm.create_property_blob(&mode).map_err(|_| { crate::error::OsError::new( @@ -96,25 +65,29 @@ impl Window { ) })?; atomic_req.add_property( - crtc.handle(), - find_prop_id(&gbm, crtc.handle(), "MODE_ID").ok_or_else(|| { - crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc("Could not get MODE_ID"), - ) - })?, + event_loop_window_target.crtc.handle(), + find_prop_id(&gbm, event_loop_window_target.crtc.handle(), "MODE_ID").ok_or_else( + || { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Could not get MODE_ID"), + ) + }, + )?, blob, ); atomic_req.add_property( - crtc.handle(), - find_prop_id(&gbm, crtc.handle(), "ACTIVE").ok_or_else(|| { - crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc("Could not get ACTIVE"), - ) - })?, + event_loop_window_target.crtc.handle(), + find_prop_id(&gbm, event_loop_window_target.crtc.handle(), "ACTIVE").ok_or_else( + || { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Could not get ACTIVE"), + ) + }, + )?, property::Value::Boolean(true), ); @@ -129,7 +102,7 @@ impl Window { Ok(Self( mode, - con.clone(), + event_loop_window_target.connector.clone(), event_loop_window_target.event_loop_awakener.clone(), )) } From 7439d332c9dda9d3e403f6d6905e48b1483d1b6e Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Fri, 29 Apr 2022 00:23:36 -0400 Subject: [PATCH 007/151] Add kmsdrm to README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 88e44f80f8..ec5fee5141 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,7 @@ Winit provides the following features, which can be enabled in your `Cargo.toml` * `serde`: Enables serialization/deserialization of certain types with [Serde](https://crates.io/crates/serde). * `x11` (enabled by default): On Unix platform, compiles with the X11 backend * `wayland` (enabled by default): On Unix platform, compiles with the Wayland backend +* `kmsdrm` (enabled by default): On Unix platform, compiles with the kmsdrm backend * `mint`: Enables mint (math interoperability standard types) conversions. ### Platform-specific usage From d9ebd7d473b38f78d4e5c07816fe2da86bf3dadd Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Fri, 29 Apr 2022 00:35:53 -0400 Subject: [PATCH 008/151] Fix formatting --- FEATURES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FEATURES.md b/FEATURES.md index e9a6c54a08..4a72f18df4 100644 --- a/FEATURES.md +++ b/FEATURES.md @@ -210,7 +210,7 @@ Legend: ### Input handling |Feature |Windows |MacOS |Linux x11|Linux Wayland|Linux DRM|Android|iOS |WASM | -|----------------------- | ----- | ---- | ------- | ----------- | ----- | ----- | -------- | +|----------------------- | ----- | ---- | ------- | ----------- | ----- | ----- | -------- | ------- | |Mouse events |✔️ |▢[#63] |✔️ |✔️ |✔️ |**N/A**|**N/A**|✔️ | |Mouse set location |✔️ |✔️ |✔️ |❓ |✔️ |**N/A**|**N/A**|**N/A**| |Cursor grab |✔️ |▢[#165] |▢[#242] |✔️ |**N/A** |**N/A**|**N/A**|✔️ | From 9c26d721eee2a9a582f5c8d603e61295b19c21eb Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Fri, 29 Apr 2022 08:38:20 -0400 Subject: [PATCH 009/151] Annotations on potentially expensive swap just in case --- src/platform_impl/linux/drm/event_loop.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index b29e4e96c9..3c50476b59 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -878,7 +878,10 @@ impl EventLoop { // to create a window in one of those callbacks. self.with_window_target(|window_target| { let state = &mut window_target.event_sink.window_events; - std::mem::swap(&mut event_sink_back_buffer, state) + std::mem::swap::>>( + &mut event_sink_back_buffer, + state, + ); }); // Handle pending window events. From f14691a7180c99c6809086874b2e56ee68901491 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Fri, 29 Apr 2022 08:50:43 -0400 Subject: [PATCH 010/151] EventSink can just be a type annotation --- src/platform_impl/linux/drm/event_loop.rs | 26 +++++++---------------- 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index 3c50476b59..2508c56999 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -556,16 +556,7 @@ impl EventSource for LibinputInputBackend { /// An event loop's sink to deliver events from the Wayland event callbacks /// to the winit's user. -#[derive(Default)] -pub struct EventSink { - pub window_events: Vec>, -} - -impl EventSink { - pub fn new() -> Self { - Default::default() - } -} +type EventSink = Vec>; pub struct EventLoopWindowTarget { /// gbm Connector @@ -718,12 +709,11 @@ impl EventLoop { .insert_source( event_loop_awakener_source, move |_event, _metadata, data| { - data.window_events - .push(crate::event::Event::RedrawRequested( - crate::window::WindowId(crate::platform_impl::WindowId::Drm( - super::WindowId, - )), - )); + data.push(crate::event::Event::RedrawRequested( + crate::window::WindowId(crate::platform_impl::WindowId::Drm( + super::WindowId, + )), + )); }, ) .unwrap(); @@ -735,7 +725,7 @@ impl EventLoop { calloop::Dispatcher::new( input_backend, move |event, _metadata, data: &mut EventSink| { - data.window_events.push(event); + data.push(event); }, ); @@ -877,7 +867,7 @@ impl EventLoop { // we're doing callback to the user, since we can double borrow if the user decides // to create a window in one of those callbacks. self.with_window_target(|window_target| { - let state = &mut window_target.event_sink.window_events; + let state = &mut window_target.event_sink; std::mem::swap::>>( &mut event_sink_back_buffer, state, From e03d0fe0395bdcd4872a1abe78981416a2fe3ada Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Fri, 29 Apr 2022 10:20:01 -0400 Subject: [PATCH 011/151] Better error handling --- src/platform_impl/linux/drm/event_loop.rs | 50 ++++++++++++++++++----- src/platform_impl/linux/drm/mod.rs | 6 +-- src/platform_impl/linux/mod.rs | 15 ++++--- 3 files changed, 53 insertions(+), 18 deletions(-) diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index 2508c56999..45a6e5dda8 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -633,7 +633,7 @@ pub(crate) fn find_prop_id( } impl EventLoop { - pub fn new() -> Result, ()> { + pub fn new() -> Result, crate::error::OsError> { match GBM_DEVICE.lock().as_ref() { Ok(gbm) => { drm::Device::set_client_capability( @@ -641,18 +641,32 @@ impl EventLoop { drm::ClientCapability::UniversalPlanes, true, ) - .expect("kmsdrm device does not support universal planes"); + .or(Err(crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc( + "kmsdrm device does not support universal planes", + ), + )))?; drm::Device::set_client_capability( gbm.as_ref(), drm::ClientCapability::Atomic, true, ) - .expect("kmsdrm device does not support atomic modesetting"); + .or(Err(crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc( + "kmsdrm device does not support atomic modesetting", + ), + )))?; // Load the information. - let res = gbm - .resource_handles() - .expect("Could not load normal resource ids."); + let res = gbm.resource_handles().or(Err(crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Could not load normal resource ids."), + )))?; let coninfo: Vec = res .connectors() .iter() @@ -664,16 +678,28 @@ impl EventLoop { .flat_map(|crtc| gbm.get_crtc(*crtc)) .collect(); - let crtc = crtcinfo.get(0).expect("No crtcs found"); + let crtc = crtcinfo.get(0).ok_or(crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("No crtcs found"), + ))?; // Filter each connector until we find one that's connected. let con = coninfo .iter() .find(|&i| i.state() == drm::control::connector::State::Connected) - .expect("No connected connectors"); + .ok_or(crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("No connected connectors"), + ))?; // Get the first (usually best) mode - let &mode = con.modes().get(0).expect("No modes found on connector"); + let &mode = con.modes().get(0).ok_or(crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("No modes found on connector"), + ))?; let (disp_width, disp_height) = mode.size(); @@ -750,7 +776,11 @@ impl EventLoop { window_target, }) } - Err(_) => Err(()), + Err(_) => Err(crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("gbm failed to initialize"), + )), } } diff --git a/src/platform_impl/linux/drm/mod.rs b/src/platform_impl/linux/drm/mod.rs index 782d5d30ac..9ea828df2f 100644 --- a/src/platform_impl/linux/drm/mod.rs +++ b/src/platform_impl/linux/drm/mod.rs @@ -30,14 +30,14 @@ impl ControlDevice for Card {} /// Simple helper methods for opening a `Card`. impl Card { - pub fn open(path: &str) -> Self { + pub fn open(path: &str) -> Result { let mut options = std::fs::OpenOptions::new(); options.read(true); options.write(true); - Card(options.open(path).unwrap()) + Ok(Card(options.open(path)?)) } - pub fn open_global() -> Self { + pub fn open_global() -> Result { Self::open("/dev/dri/card0") } } diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index a2d65afe94..398543708b 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -165,9 +165,14 @@ impl std::ops::DerefMut for AssertSync { #[cfg(feature = "kmsdrm")] lazy_static! { pub static ref GBM_DEVICE: Mutex>, std::io::Error>>> = - Mutex::new(AssertSync( - gbm::Device::new(drm::Card::open_global()).map(Arc::new) - )); + match drm::Card::open_global() { + Ok(card) => { + Mutex::new(AssertSync(gbm::Device::new(card).map(Arc::new))) + } + Err(e) => { + Mutex::new(AssertSync(Err(e))) + } + }; } #[derive(Debug, Clone)] @@ -798,7 +803,7 @@ impl EventLoop { panic!( "Failed to initialize any backend! Wayland status: {:?} X11 status: {:?} DRM status: {:?}", wayland_err, x11_err, drm_err - ); + ); } #[cfg(feature = "wayland")] @@ -817,7 +822,7 @@ impl EventLoop { } #[cfg(feature = "kmsdrm")] - fn new_drm_any_thread() -> Result, ()> { + fn new_drm_any_thread() -> Result, RootOsError> { drm::EventLoop::new().map(EventLoop::Drm) } From e8cee9c4b1cdb456dc36dd06ef0bb9ec0dddf031 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Fri, 29 Apr 2022 10:46:45 -0400 Subject: [PATCH 012/151] Request redraw when event loop starts --- src/platform_impl/linux/drm/event_loop.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index 45a6e5dda8..13eb4de91e 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -814,6 +814,14 @@ impl EventLoop { &mut control_flow, ); + callback( + crate::event::Event::RedrawRequested(crate::window::WindowId( + crate::platform_impl::WindowId::Drm(super::WindowId), + )), + &self.window_target, + &mut control_flow, + ); + let exit_code = loop { match control_flow { ControlFlow::ExitWithCode(code) => break code, From aea7680af5b4e2bf0bc9a24d1bf9f1c948d1252c Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Fri, 29 Apr 2022 11:00:13 -0400 Subject: [PATCH 013/151] Make Card and AssertSync structs public for OpenGL context creation --- src/platform/unix.rs | 75 ++++++++++++++++++++--- src/platform_impl/linux/drm/event_loop.rs | 3 +- src/platform_impl/linux/drm/mod.rs | 33 ---------- src/platform_impl/linux/mod.rs | 30 ++------- 4 files changed, 72 insertions(+), 69 deletions(-) diff --git a/src/platform/unix.rs b/src/platform/unix.rs index 7a721670f7..a2a9a3226b 100644 --- a/src/platform/unix.rs +++ b/src/platform/unix.rs @@ -25,6 +25,9 @@ use crate::platform_impl::{ Window as LinuxWindow, }; +#[cfg(feature = "kmsdrm")] +use ::drm::{control::Device as ControlDevice, Device}; + // TODO: stupid hack so that glutin can do its work #[doc(hidden)] #[cfg(feature = "x11")] @@ -32,6 +35,64 @@ pub use crate::platform_impl::x11; #[cfg(feature = "x11")] pub use crate::platform_impl::{x11::util::WindowType as XWindowType, XNotSupported}; +#[cfg(feature = "kmsdrm")] +#[derive(Debug)] +/// A simple wrapper for a device node. +pub struct Card(std::fs::File); + +#[cfg(feature = "kmsdrm")] +/// Implementing `AsRawFd` is a prerequisite to implementing the traits found +/// in this crate. Here, we are just calling `as_raw_fd()` on the inner File. +impl std::os::unix::io::AsRawFd for Card { + fn as_raw_fd(&self) -> std::os::unix::io::RawFd { + self.0.as_raw_fd() + } +} + +#[cfg(feature = "kmsdrm")] +/// With `AsRawFd` implemented, we can now implement `drm::Device`. +impl Device for Card {} +#[cfg(feature = "kmsdrm")] +impl ControlDevice for Card {} + +#[cfg(feature = "kmsdrm")] +/// Simple helper methods for opening a `Card`. +impl Card { + pub fn open(path: &str) -> Result { + let mut options = std::fs::OpenOptions::new(); + options.read(true); + options.write(true); + Ok(Card(options.open(path)?)) + } + + pub fn open_global() -> Result { + Self::open("/dev/dri/card0") + } +} + +#[cfg(feature = "kmsdrm")] +#[repr(transparent)] +pub struct AssertSync(pub T); + +#[cfg(feature = "kmsdrm")] +unsafe impl Sync for AssertSync {} +#[cfg(feature = "kmsdrm")] +unsafe impl Send for AssertSync {} +#[cfg(feature = "kmsdrm")] +impl std::ops::Deref for AssertSync { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} +#[cfg(feature = "kmsdrm")] +impl std::ops::DerefMut for AssertSync { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + /// Additional methods on `EventLoopWindowTarget` that are specific to Unix. pub trait EventLoopWindowTargetExtUnix { /// True if the `EventLoopWindowTarget` uses Wayland. @@ -66,11 +127,8 @@ pub trait EventLoopWindowTargetExtUnix { &self, ) -> Option< &parking_lot::Mutex< - crate::platform_impl::AssertSync< - Result< - std::sync::Arc>, - std::io::Error, - >, + AssertSync< + Result>, std::io::Error>, >, >, >; @@ -136,11 +194,8 @@ impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { &self, ) -> Option< &parking_lot::Mutex< - crate::platform_impl::AssertSync< - Result< - std::sync::Arc>, - std::io::Error, - >, + AssertSync< + Result>, std::io::Error>, >, >, > { diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index 13eb4de91e..930c5d7a82 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -25,6 +25,7 @@ use crate::{ dpi::PhysicalPosition, event::{Force, KeyboardInput, ModifiersState, MouseScrollDelta, StartCause}, event_loop::{ControlFlow, EventLoopClosed}, + platform::unix::Card, platform_impl::{platform::sticky_exit_callback, GBM_DEVICE}, }; @@ -616,7 +617,7 @@ pub struct EventLoop { } pub(crate) fn find_prop_id( - card: &std::sync::Arc>, + card: &std::sync::Arc>, handle: T, name: &'static str, ) -> Option { diff --git a/src/platform_impl/linux/drm/mod.rs b/src/platform_impl/linux/drm/mod.rs index 9ea828df2f..86d300e46e 100644 --- a/src/platform_impl/linux/drm/mod.rs +++ b/src/platform_impl/linux/drm/mod.rs @@ -1,6 +1,3 @@ -use drm::control::Device as ControlDevice; -use drm::Device; - use crate::dpi::{PhysicalPosition, PhysicalSize}; pub mod event_loop; @@ -12,36 +9,6 @@ pub use event_loop::EventLoopProxy; pub use event_loop::EventLoopWindowTarget; pub use window::Window; -#[derive(Debug)] -/// A simple wrapper for a device node. -pub struct Card(std::fs::File); - -/// Implementing `AsRawFd` is a prerequisite to implementing the traits found -/// in this crate. Here, we are just calling `as_raw_fd()` on the inner File. -impl std::os::unix::io::AsRawFd for Card { - fn as_raw_fd(&self) -> std::os::unix::io::RawFd { - self.0.as_raw_fd() - } -} - -/// With `AsRawFd` implemented, we can now implement `drm::Device`. -impl Device for Card {} -impl ControlDevice for Card {} - -/// Simple helper methods for opening a `Card`. -impl Card { - pub fn open(path: &str) -> Result { - let mut options = std::fs::OpenOptions::new(); - options.read(true); - options.write(true); - Ok(Card(options.open(path)?)) - } - - pub fn open_global() -> Result { - Self::open("/dev/dri/card0") - } -} - #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct DeviceId; diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index 398543708b..df514a635d 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -37,6 +37,9 @@ use crate::{ window::{CursorIcon, Fullscreen, UserAttentionType, WindowAttributes}, }; +#[cfg(feature = "kmsdrm")] +use crate::platform::unix::{AssertSync, Card}; + pub(crate) use crate::icon::RgbaIcon as PlatformIcon; #[cfg(feature = "kmsdrm")] @@ -139,33 +142,10 @@ lazy_static! { Mutex::new(XConnection::new(Some(x_error_callback)).map(Arc::new)); } -#[cfg(feature = "kmsdrm")] -#[repr(transparent)] -pub struct AssertSync(pub T); - -#[cfg(feature = "kmsdrm")] -unsafe impl Sync for AssertSync {} -#[cfg(feature = "kmsdrm")] -unsafe impl Send for AssertSync {} -#[cfg(feature = "kmsdrm")] -impl std::ops::Deref for AssertSync { - type Target = T; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} -#[cfg(feature = "kmsdrm")] -impl std::ops::DerefMut for AssertSync { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } -} - #[cfg(feature = "kmsdrm")] lazy_static! { - pub static ref GBM_DEVICE: Mutex>, std::io::Error>>> = - match drm::Card::open_global() { + pub static ref GBM_DEVICE: Mutex>, std::io::Error>>> = + match Card::open_global() { Ok(card) => { Mutex::new(AssertSync(gbm::Device::new(card).map(Arc::new))) } From 28c70dc54478c52e3665763bcbab1ade9f257935 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Mon, 2 May 2022 21:19:55 -0400 Subject: [PATCH 014/151] Changes to support glutin --- src/platform/unix.rs | 29 ++++++++++++++++------- src/platform_impl/linux/drm/event_loop.rs | 29 ++++++++++++----------- src/platform_impl/linux/mod.rs | 4 ++-- 3 files changed, 38 insertions(+), 24 deletions(-) diff --git a/src/platform/unix.rs b/src/platform/unix.rs index a2a9a3226b..736c46f7ba 100644 --- a/src/platform/unix.rs +++ b/src/platform/unix.rs @@ -71,6 +71,7 @@ impl Card { } #[cfg(feature = "kmsdrm")] +#[derive(Debug)] #[repr(transparent)] pub struct AssertSync(pub T); @@ -126,10 +127,8 @@ pub trait EventLoopWindowTargetExtUnix { fn gbm_device( &self, ) -> Option< - &parking_lot::Mutex< - AssertSync< - Result>, std::io::Error>, - >, + &'static parking_lot::Mutex< + AssertSync, std::io::Error>>, >, >; @@ -144,6 +143,12 @@ pub trait EventLoopWindowTargetExtUnix { /// Returns `None` if the `EventLoop` doesn't use kmsdrm (if it uses wayland for example). #[cfg(feature = "kmsdrm")] fn gbm_connector(&self) -> Option<&drm::control::connector::Info>; + + /// Returns the current mode of the gbm device + /// + /// Returns `None` if the `EventLoop` doesn't use kmsdrm (if it uses wayland for example). + #[cfg(feature = "kmsdrm")] + fn gbm_mode(&self) -> Option; } impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { @@ -193,10 +198,8 @@ impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { fn gbm_device( &self, ) -> Option< - &parking_lot::Mutex< - AssertSync< - Result>, std::io::Error>, - >, + &'static parking_lot::Mutex< + AssertSync, std::io::Error>>, >, > { use crate::platform_impl::GBM_DEVICE; @@ -227,6 +230,16 @@ impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { _ => None, } } + + #[inline] + #[cfg(feature = "kmsdrm")] + fn gbm_mode(&self) -> Option { + match self.p { + crate::platform_impl::EventLoopWindowTarget::Drm(ref window) => Some(window.mode), + #[cfg(any(feature = "x11", feature = "wayland"))] + _ => None, + } + } } /// Additional methods on [`EventLoopBuilder`] that are specific to Unix. diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index 930c5d7a82..e4317a4148 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -566,6 +566,9 @@ pub struct EventLoopWindowTarget { /// gbm crtc pub crtc: drm::control::crtc::Info, + /// gbm mode + pub mode: drm::control::Mode, + /// Event loop handle. pub event_loop_handle: calloop::LoopHandle<'static, EventSink>, @@ -617,7 +620,7 @@ pub struct EventLoop { } pub(crate) fn find_prop_id( - card: &std::sync::Arc>, + card: &gbm::Device, handle: T, name: &'static str, ) -> Option { @@ -638,7 +641,7 @@ impl EventLoop { match GBM_DEVICE.lock().as_ref() { Ok(gbm) => { drm::Device::set_client_capability( - gbm.as_ref(), + gbm, drm::ClientCapability::UniversalPlanes, true, ) @@ -649,18 +652,15 @@ impl EventLoop { "kmsdrm device does not support universal planes", ), )))?; - drm::Device::set_client_capability( - gbm.as_ref(), - drm::ClientCapability::Atomic, - true, - ) - .or(Err(crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc( - "kmsdrm device does not support atomic modesetting", - ), - )))?; + drm::Device::set_client_capability(gbm, drm::ClientCapability::Atomic, true).or( + Err(crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc( + "kmsdrm device does not support atomic modesetting", + ), + )), + )?; // Load the information. let res = gbm.resource_handles().or(Err(crate::error::OsError::new( @@ -762,6 +762,7 @@ impl EventLoop { p: crate::platform_impl::EventLoopWindowTarget::Drm(EventLoopWindowTarget { connector: con.clone(), crtc: crtc.clone(), + mode, event_loop_handle: handle, event_sink, event_loop_awakener, diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index df514a635d..56e3d41f05 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -144,10 +144,10 @@ lazy_static! { #[cfg(feature = "kmsdrm")] lazy_static! { - pub static ref GBM_DEVICE: Mutex>, std::io::Error>>> = + pub static ref GBM_DEVICE: Mutex, std::io::Error>>> = match Card::open_global() { Ok(card) => { - Mutex::new(AssertSync(gbm::Device::new(card).map(Arc::new))) + Mutex::new(AssertSync(gbm::Device::new(card))) } Err(e) => { Mutex::new(AssertSync(Err(e))) From 889f71c10e0db1f73d3652f37c3a8f0d3904d789 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 3 May 2022 07:16:09 -0400 Subject: [PATCH 015/151] Fix formatting (again) --- Cargo.toml | 125 +++++----- FEATURES.md | 326 ++++++++++++-------------- src/platform_impl/linux/drm/window.rs | 14 +- src/platform_impl/linux/mod.rs | 2 +- 4 files changed, 217 insertions(+), 250 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index cc806f669b..08065a942d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,10 +1,7 @@ [package] name = "winit" version = "0.26.1" -authors = [ - "The winit contributors", - "Pierre Krieger ", -] +authors = ["The winit contributors", "Pierre Krieger "] description = "Cross-platform window creation library." edition = "2021" keywords = ["windowing"] @@ -17,29 +14,21 @@ categories = ["gui"] [package.metadata.docs.rs] features = ["serde"] default-target = "x86_64-unknown-linux-gnu" -targets = [ - "i686-pc-windows-msvc", - "x86_64-pc-windows-msvc", - "i686-unknown-linux-gnu", - "x86_64-unknown-linux-gnu", - "x86_64-apple-darwin", - "wasm32-unknown-unknown", -] +targets = ["i686-pc-windows-msvc", "x86_64-pc-windows-msvc", "i686-unknown-linux-gnu", "x86_64-unknown-linux-gnu", "x86_64-apple-darwin", "wasm32-unknown-unknown"] [features] default = ["x11", "wayland", "wayland-dlopen", "kmsdrm"] x11 = ["x11-dl", "mio", "percent-encoding", "parking_lot"] wayland = ["wayland-client", "wayland-protocols", "sctk", "calloop"] -kmsdrm = ["drm", "gbm", "input", "calloop"] wayland-dlopen = ["sctk/dlopen", "wayland-client/dlopen"] +kmsdrm = ["drm", "gbm", "input", "calloop"] [dependencies] instant = { version = "0.1", features = ["wasm-bindgen"] } lazy_static = "1" log = "0.4" serde = { version = "1", optional = true, features = ["serde_derive"] } -# raw-window-handle = "0.4.2" -raw-window-handle = "0.4.3" +raw-window-handle = "0.4.2" bitflags = "1" mint = { version = "0.5.6", optional = true } @@ -70,45 +59,39 @@ features = ["display_link"] parking_lot = "0.12" [target.'cfg(target_os = "windows")'.dependencies.windows-sys] -version = "0.33" +version = "0.36" features = [ - "Win32_Devices_HumanInterfaceDevice", - "Win32_Foundation", - "Win32_Globalization", - "Win32_Graphics_Dwm", - "Win32_Graphics_Gdi", - "Win32_Media", - "Win32_System_Com_StructuredStorage", - "Win32_System_Com", - "Win32_System_LibraryLoader", - "Win32_System_Ole", - "Win32_System_SystemInformation", - "Win32_System_SystemServices", - "Win32_System_Threading", - "Win32_System_WindowsProgramming", - "Win32_UI_Accessibility", - "Win32_UI_Controls", - "Win32_UI_HiDpi", - "Win32_UI_Input_Ime", - "Win32_UI_Input_KeyboardAndMouse", - "Win32_UI_Input_Pointer", - "Win32_UI_Input_Touch", - "Win32_UI_Shell", - "Win32_UI_TextServices", - "Win32_UI_WindowsAndMessaging", + "Win32_Devices_HumanInterfaceDevice", + "Win32_Foundation", + "Win32_Globalization", + "Win32_Graphics_Dwm", + "Win32_Graphics_Gdi", + "Win32_Media", + "Win32_System_Com_StructuredStorage", + "Win32_System_Com", + "Win32_System_LibraryLoader", + "Win32_System_Ole", + "Win32_System_SystemInformation", + "Win32_System_SystemServices", + "Win32_System_Threading", + "Win32_System_WindowsProgramming", + "Win32_UI_Accessibility", + "Win32_UI_Controls", + "Win32_UI_HiDpi", + "Win32_UI_Input_Ime", + "Win32_UI_Input_KeyboardAndMouse", + "Win32_UI_Input_Pointer", + "Win32_UI_Input_Touch", + "Win32_UI_Shell", + "Win32_UI_TextServices", + "Win32_UI_WindowsAndMessaging", ] [target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))'.dependencies] -wayland-client = { version = "0.29", default_features = false, features = [ - "use_system_lib", -], optional = true } -wayland-protocols = { version = "0.29", features = [ - "staging_protocols", -], optional = true } +wayland-client = { version = "0.29", default_features = false, features = ["use_system_lib"], optional = true } +wayland-protocols = { version = "0.29", features = [ "staging_protocols"], optional = true } +sctk = { package = "smithay-client-toolkit", version = "0.15.4", default_features = false, features = ["calloop"], optional = true } calloop = { version = "0.9.3", optional = true } -sctk = { package = "smithay-client-toolkit", version = "0.15.4", default_features = false, features = [ - "calloop", -], optional = true } mio = { version = "0.8", features = ["os-ext"], optional = true } x11-dl = { version = "2.18.5", optional = true } percent-encoding = { version = "2.0", optional = true } @@ -122,26 +105,26 @@ input = { version = "0.7.1", optional = true } package = "web-sys" version = "0.3.22" features = [ - 'console', - "AddEventListenerOptions", - 'CssStyleDeclaration', - 'BeforeUnloadEvent', - 'Document', - 'DomRect', - 'Element', - 'Event', - 'EventTarget', - 'FocusEvent', - 'HtmlCanvasElement', - 'HtmlElement', - 'KeyboardEvent', - 'MediaQueryList', - 'MediaQueryListEvent', - 'MouseEvent', - 'Node', - 'PointerEvent', - 'Window', - 'WheelEvent', + 'console', + "AddEventListenerOptions", + 'CssStyleDeclaration', + 'BeforeUnloadEvent', + 'Document', + 'DomRect', + 'Element', + 'Event', + 'EventTarget', + 'FocusEvent', + 'HtmlCanvasElement', + 'HtmlElement', + 'KeyboardEvent', + 'MediaQueryList', + 'MediaQueryListEvent', + 'MouseEvent', + 'Node', + 'PointerEvent', + 'Window', + 'WheelEvent' ] [target.'cfg(target_arch = "wasm32")'.dependencies.wasm-bindgen] @@ -151,4 +134,6 @@ version = "0.2.45" console_log = "0.2" [workspace] -members = ["run-wasm"] +members = [ + "run-wasm", +] \ No newline at end of file diff --git a/FEATURES.md b/FEATURES.md index 4a72f18df4..da622f093c 100644 --- a/FEATURES.md +++ b/FEATURES.md @@ -2,32 +2,31 @@ Winit aims to expose an interface that abstracts over window creation and input handling, and can be used to create both games and applications. It supports the main graphical platforms: - -- Desktop - - Windows - - macOS - - Unix - - via X11 - - via Wayland - - via DRM -- Mobile - - iOS - - Android -- Web - - via WASM +- Desktop + - Windows + - macOS + - Unix + - via X11 + - via Wayland + - via KMS/DRM +- Mobile + - iOS + - Android +- Web + - via WASM Most platforms expose capabilities that cannot be meaningfully transposed onto others. Winit does not aim to support every single feature of every platform, but rather to abstract over the common features available everywhere. In this context, APIs exposed in winit can be split into different "support tiers": -- **Core:** Features that are essential to providing a well-formed abstraction over each platform's - windowing and input APIs. -- **Platform:** Platform-specific features that can't be meaningfully exposed through a common API and - cannot be implemented outside of Winit without exposing a significant amount of Winit's internals - or interfering with Winit's abstractions. -- **Usability:** Features that are not strictly essential to Winit's functionality, but provide meaningful - usability improvements and cannot be reasonably implemented in an external crate. These are - generally optional and exposed through Cargo features. +- **Core:** Features that are essential to providing a well-formed abstraction over each platform's + windowing and input APIs. +- **Platform:** Platform-specific features that can't be meaningfully exposed through a common API and + cannot be implemented outside of Winit without exposing a significant amount of Winit's internals + or interfering with Winit's abstractions. +- **Usability:** Features that are not strictly essential to Winit's functionality, but provide meaningful + usability improvements and cannot be reasonably implemented in an external crate. These are + generally optional and exposed through Cargo features. Core features are taken care of by the core Winit maintainers. Platform features are not. When a platform feature is submitted, the submitter is considered the expert in the @@ -44,10 +43,9 @@ be released and the library will enter maintenance mode. For the most part, new be added past this point. New platform features may be accepted and exposed through point releases. ### Tier upgrades - Some platform features could in theory be exposed across multiple platforms, but have not gone through the implementation work necessary to function on all platforms. When one of these features -gets implemented across all platforms, a PR can be opened to upgrade the feature to a core f*eature. +gets implemented across all platforms, a PR can be opened to upgrade the feature to a core feature. If that gets accepted, the platform-specific functions gets deprecated and become permanently exposed through the core, cross-platform API. @@ -57,216 +55,188 @@ exposed through the core, cross-platform API. If your PR makes notable changes to Winit's features, please update this section as follows: -- If your PR adds a new feature, add a brief description to the relevant section. If the feature is a core - feature, add a row to the feature matrix and describe what platforms the feature has been implemented on. +- If your PR adds a new feature, add a brief description to the relevant section. If the feature is a core + feature, add a row to the feature matrix and describe what platforms the feature has been implemented on. -- If your PR begins a new API rework, add a row to the `Pending API Reworks` table. If the PR implements the - API rework on all relevant platforms, please move it to the `Completed API Reworks` table. +- If your PR begins a new API rework, add a row to the `Pending API Reworks` table. If the PR implements the + API rework on all relevant platforms, please move it to the `Completed API Reworks` table. -- If your PR implements an already-existing feature on a new platform, either mark the feature as *completed*, - or mark it as *mostly completed* and link to an issue describing the problems with the implementation. +- If your PR implements an already-existing feature on a new platform, either mark the feature as *completed*, + or mark it as *mostly completed* and link to an issue describing the problems with the implementation. ## Core ### Windowing +- **Window initialization**: Winit allows the creation of a window +- **Providing pointer to init OpenGL**: Winit provides the necessary pointers to initialize a working opengl context +- **Providing pointer to init Vulkan**: Same as OpenGL but for Vulkan +- **Window decorations**: The windows created by winit are properly decorated, and the decorations can + be deactivated +- **Window decorations toggle**: Decorations can be turned on or off after window creation +- **Window resizing**: The windows created by winit can be resized and generate the appropriate events + when they are. The application can precisely control its window size if desired. +- **Window resize increments**: When the window gets resized, the application can choose to snap the window's + size to specific values. +- **Window transparency**: Winit allows the creation of windows with a transparent background. +- **Window maximization**: The windows created by winit can be maximized upon creation. +- **Window maximization toggle**: The windows created by winit can be maximized and unmaximized after + creation. +- **Window minimization**: The windows created by winit can be minimized after creation. +- **Fullscreen**: The windows created by winit can be put into fullscreen mode. +- **Fullscreen toggle**: The windows created by winit can be switched to and from fullscreen after + creation. +- **Exclusive fullscreen**: Winit allows changing the video mode of the monitor + for fullscreen windows, and if applicable, captures the monitor for exclusive + use by this application. +- **HiDPI support**: Winit assists developers in appropriately scaling HiDPI content. +- **Popup / modal windows**: Windows can be created relative to the client area of other windows, and parent + windows can be disabled in favor of popup windows. This feature also guarantees that popup windows + get drawn above their owner. -- **Window initialization**: Winit allows the creation of a window -- **Providing pointer to init OpenGL**: Winit provides the necessary pointers to initialize a working opengl context -- **Providing pointer to init Vulkan**: Same as OpenGL but for Vulkan -- **Window decorations**: The windows created by winit are properly decorated, and the decorations can - be deactivated -- **Window decorations toggle**: Decorations can be turned on or off after window creation -- **Window resizing**: The windows created by winit can be resized and generate the appropriate events - when they are. The application can precisely control its window size if desired. -- **Window resize increments**: When the window gets resized, the application can choose to snap the window's - size to specific values. -- **Window transparency**: Winit allows the creation of windows with a transparent background. -- **Window maximization**: The windows created by winit can be maximized upon creation. -- **Window maximization toggle**: The windows created by winit can be maximized and unmaximized after - creation. -- **Window minimization**: The windows created by winit can be minimized after creation. -- **Fullscreen**: The windows created by winit can be put into fullscreen mode. -- **Fullscreen toggle**: The windows created by winit can be switched to and from fullscreen after - creation. -- **Exclusive fullscreen**: Winit allows changing the video mode of the monitor - for fullscreen windows, and if applicable, captures the monitor for exclusive - use by this application. -- **HiDPI support**: Winit assists developers in appropriately scaling HiDPI content. -- **Popup / modal windows**: Windows can be created relative to the client area of other windows, and parent - windows can be disabled in favor of popup windows. This feature also guarantees that popup windows - get drawn above their owner. ### System Information - -- **Monitor list**: Retrieve the list of monitors and their metadata, including which one is primary. -- **Video mode query**: Monitors can be queried for their supported fullscreen video modes (consisting of resolution, refresh rate, and bit depth). +- **Monitor list**: Retrieve the list of monitors and their metadata, including which one is primary. +- **Video mode query**: Monitors can be queried for their supported fullscreen video modes (consisting of resolution, refresh rate, and bit depth). ### Input Handling - -- **Mouse events**: Generating mouse events associated with pointer motion, click, and scrolling events. -- **Mouse set location**: Forcibly changing the location of the pointer. -- **Cursor grab**: Locking the cursor so it cannot exit the client area of a window. -- **Cursor icon**: Changing the cursor icon, or hiding the cursor. -- **Cursor hittest**: Handle or ignore mouse events for a window. -- **Touch events**: Single-touch events. -- **Touch pressure**: Touch events contain information about the amount of force being applied. -- **Multitouch**: Multi-touch events, including cancellation of a gesture. -- **Keyboard events**: Properly processing keyboard events using the user-specified keymap and - translating keypresses into UTF-8 characters, handling dead keys and IMEs. -- **Drag & Drop**: Dragging content into winit, detecting when content enters, drops, or if the drop is cancelled. -- **Raw Device Events**: Capturing input from input devices without any OS filtering. -- **Gamepad/Joystick events**: Capturing input from gamepads and joysticks. -- **Device movement events**: Capturing input from the device gyroscope and accelerometer. +- **Mouse events**: Generating mouse events associated with pointer motion, click, and scrolling events. +- **Mouse set location**: Forcibly changing the location of the pointer. +- **Cursor grab**: Locking the cursor so it cannot exit the client area of a window. +- **Cursor icon**: Changing the cursor icon, or hiding the cursor. +- **Cursor hittest**: Handle or ignore mouse events for a window. +- **Touch events**: Single-touch events. +- **Touch pressure**: Touch events contain information about the amount of force being applied. +- **Multitouch**: Multi-touch events, including cancellation of a gesture. +- **Keyboard events**: Properly processing keyboard events using the user-specified keymap and + translating keypresses into UTF-8 characters, handling dead keys and IMEs. +- **Drag & Drop**: Dragging content into winit, detecting when content enters, drops, or if the drop is cancelled. +- **Raw Device Events**: Capturing input from input devices without any OS filtering. +- **Gamepad/Joystick events**: Capturing input from gamepads and joysticks. +- **Device movement events**: Capturing input from the device gyroscope and accelerometer. ## Platform - ### Windows - -- Setting the taskbar icon -- Setting the parent window -- Setting a menu bar -- `WS_EX_NOREDIRECTIONBITMAP` support -- Theme the title bar according to Windows 10 Dark Mode setting or set a preferred theme +* Setting the taskbar icon +* Setting the parent window +* Setting a menu bar +* `WS_EX_NOREDIRECTIONBITMAP` support +* Theme the title bar according to Windows 10 Dark Mode setting or set a preferred theme ### macOS - -- Window activation policy -- Window movable by background -- Transparent titlebar -- Hidden titlebar -- Hidden titlebar buttons -- Full-size content view +* Window activation policy +* Window movable by background +* Transparent titlebar +* Hidden titlebar +* Hidden titlebar buttons +* Full-size content view ### Unix - -- Window urgency -- X11 Window Class -- X11 Override Redirect Flag -- GTK Theme Variant -- Base window size +* Window urgency +* X11 Window Class +* X11 Override Redirect Flag +* GTK Theme Variant +* Base window size ### iOS - -- `winit` has a minimum OS requirement of iOS 8 -- Get the `UIWindow` object pointer -- Get the `UIViewController` object pointer -- Get the `UIView` object pointer -- Get the `UIScreen` object pointer -- Setting the `UIView` hidpi factor -- Valid orientations -- Home indicator visibility -- Status bar visibility -- Deferrring system gestures -- Support for custom `UIView` derived class -- Getting the device idiom -- Getting the preferred video mode +* `winit` has a minimum OS requirement of iOS 8 +* Get the `UIWindow` object pointer +* Get the `UIViewController` object pointer +* Get the `UIView` object pointer +* Get the `UIScreen` object pointer +* Setting the `UIView` hidpi factor +* Valid orientations +* Home indicator visibility +* Status bar visibility +* Deferrring system gestures +* Support for custom `UIView` derived class +* Getting the device idiom +* Getting the preferred video mode ### Web - -- Get if systems preferred color scheme is "dark" +* Get if systems preferred color scheme is "dark" ## Usability - -- `serde`: Enables serialization/deserialization of certain types with Serde. (Maintainer: @Osspial) +* `serde`: Enables serialization/deserialization of certain types with Serde. (Maintainer: @Osspial) ## Compatibility Matrix Legend: -- ✔️: Works as intended -- ▢: Mostly works but some bugs are known -- ❌: Missing feature or large bugs making it unusable -- **N/A**: Not applicable for this platform -- ❓: Unknown status +- ✔️: Works as intended +- ▢: Mostly works but some bugs are known +- ❌: Missing feature or large bugs making it unusable +- **N/A**: Not applicable for this platform +- ❓: Unknown status ### Windowing - -|Feature |Windows|MacOS |Linux x11 |Linux Wayland |Linux DRM |Android|iOS |WASM | -|-------------------------------- | ----- | ---- | ------- | ----------- | ----- | ----- | ----- | -------- | -|Window initialization |✔️ |✔️ |▢[#5] |✔️ |✔️ |▢[#33]|▢[#33] |✔️ | -|Providing pointer to init OpenGL |✔️ |✔️ |✔️ |✔️ | |✔️ |✔️ |**N/A**| -|Providing pointer to init Vulkan |✔️ |✔️ |✔️ |✔️ | |✔️ |❓ |**N/A**| -|Window decorations |✔️ |✔️ |✔️ |▢[#306] |**N/A** |**N/A**|**N/A**|**N/A**| -|Window decorations toggle |✔️ |✔️ |✔️ |✔️ |**N/A** |**N/A**|**N/A**|**N/A**| -|Window resizing |✔️ |▢[#219]|✔️ |▢[#306] |**N/A** |**N/A**|**N/A**|✔️ | -|Window resize increments |❌ |❌ |❌ |❌ |**N/A** |❌ |❌ |**N/A**| -|Window transparency |✔️ |✔️ |✔️ |✔️ |**N/A** |**N/A**|**N/A**|N/A | -|Window maximization |✔️ |✔️ |✔️ |✔️ |**N/A** |**N/A**|**N/A**|**N/A**| -|Window maximization toggle |✔️ |✔️ |✔️ |✔️ |**N/A** |**N/A**|**N/A**|**N/A**| -|Window minimization |✔️ |✔️ |✔️ |✔️ |**N/A** |**N/A**|**N/A**|**N/A**| -|Fullscreen |✔️ |✔️ |✔️ |✔️ |**N/A** |**N/A**|✔️ |✔️ | -|Fullscreen toggle |✔️ |✔️ |✔️ |✔️ |**N/A** |**N/A**|✔️ |✔️ | -|Exclusive fullscreen |✔️ |✔️ |✔️ |**N/A** |✔️ |❌ |✔️ |**N/A**| -|HiDPI support |✔️ |✔️ |✔️ |✔️ |❌ |▢[#721]|✔️ |✔️ | -|Popup windows |❌ |❌ |❌ |❌ |❌ |❌ |❌ |**N/A**| +|Feature | Windows |MacOS |Linux x11 |Linux Wayland | Linux KMS/DRM | |Android |iOS |WASM | +| -------------------------------- | ------- | ------ | ---------- | ------------ | ------------ | ------- | ----- | -------- | +|Window initialization |✔️ |✔️ |▢[#5] |✔️ |✔️ |▢[#33] |▢[#33] |✔️ | +|Providing pointer to init OpenGL |✔️ |✔️ |✔️ |✔️ |✔️ |✔️ |✔️ |**N/A**| +|Providing pointer to init Vulkan |✔️ |✔️ |✔️ |✔️ |✔️ |✔️ |❓ |**N/A**| +|Window decorations |✔️ |✔️ |✔️ |▢[#306] |**N/A** |**N/A** |**N/A** |**N/A**| +|Window decorations toggle |✔️ |✔️ |✔️ |✔️ |**N/A** |**N/A** |**N/A** |**N/A**| +|Window resizing |✔️ |▢[#219]|✔️ |▢[#306] |**N/A** |**N/A** |**N/A** |✔️ | +|Window resize increments |❌ |❌ |❌ |❌ |❌ |❌ |❌ |**N/A**| +|Window transparency |✔️ |✔️ |✔️ |✔️ |**N/A** |**N/A** |**N/A** |N/A | +|Window maximization |✔️ |✔️ |✔️ |✔️ |**N/A** |**N/A** |**N/A** |**N/A**| +|Window maximization toggle |✔️ |✔️ |✔️ |✔️ |**N/A** |**N/A** |**N/A** |**N/A**| +|Window minimization |✔️ |✔️ |✔️ |✔️ |**N/A** |**N/A** |**N/A** |**N/A**| +|Fullscreen |✔️ |✔️ |✔️ |✔️ |**N/A** |**N/A** |✔️ |✔️ | +|Fullscreen toggle |✔️ |✔️ |✔️ |✔️ |**N/A** |**N/A** |✔️ |✔️ | +|Exclusive fullscreen |✔️ |✔️ |✔️ |**N/A** |✔️ |❌ |✔️ |**N/A**| +|HiDPI support |✔️ |✔️ |✔️ |✔️ |❌ |▢[#721] |✔️ |✔️ | +|Popup windows |❌ |❌ |❌ |❌ |❌ |❌ |❌ |**N/A**| ### System information - -|Feature |Windows|MacOS |Linux x11|Linux Wayland|Linux DRM|Android|iOS |WASM | -|---------------- | ----- | ---- | ------- | ----------- | ----- | ---- | ------- | -------- | -|Monitor list |✔️ |✔️ |✔️ |✔️ |✔️ |**N/A**|✔️ |**N/A**| -|Video mode query |✔️ |✔️ |✔️ |✔️ |✔️ |❌ |✔️ |**N/A**| +|Feature |Windows|MacOS |Linux x11|Linux Wayland|Linux KMS/DRM|Android|iOS |WASM | +|---------------- | ----- | ---- | ------- | ----------- | ----------- | ----- | ------- | -------- | +|Monitor list |✔️ |✔️ |✔️ |✔️ |✔️ |**N/A** |✔️ |**N/A**| +|Video mode query |✔️ |✔️ |✔️ |✔️ |✔️ |❌ |✔️ |**N/A**| ### Input handling - -|Feature |Windows |MacOS |Linux x11|Linux Wayland|Linux DRM|Android|iOS |WASM | -|----------------------- | ----- | ---- | ------- | ----------- | ----- | ----- | -------- | ------- | -|Mouse events |✔️ |▢[#63] |✔️ |✔️ |✔️ |**N/A**|**N/A**|✔️ | -|Mouse set location |✔️ |✔️ |✔️ |❓ |✔️ |**N/A**|**N/A**|**N/A**| -|Cursor grab |✔️ |▢[#165] |▢[#242] |✔️ |**N/A** |**N/A**|**N/A**|✔️ | -|Cursor icon |✔️ |✔️ |✔️ |✔️ |❌ |**N/A**|**N/A**|✔️ | -|Cursor hittest |✔️ |✔️ |❌ |✔️ |❌ |**N/A**|**N/A**|❌ | -|Touch events |✔️ |❌ |✔️ |✔️ |✔️ |✔️ |✔️ |❌ | -|Touch pressure |✔️ |❌ |❌ |❌ |✔️ |❌ |✔️ |❌ | -|Multitouch |✔️ |❌ |✔️ |✔️ |✔️ |✔️ |✔️ |❌ | -|Keyboard events |✔️ |✔️ |✔️ |✔️ |✔️ |❓ |❌ |✔️ | -|Drag & Drop |▢[#720] |▢[#720] |▢[#720] |❌[#306] |**N/A** |**N/A**|**N/A**|❓ | -|Raw Device Events |▢[#750] |▢[#750] |▢[#750] |❌ |✔️ |❌ |❌ |❓ | -|Gamepad/Joystick events |❌[#804] |❌ |❌ |❌ |❌ |❌ |❌ |❓ | -|Device movement events |❓ |❓ |❓ |❓ |❌ |❌ |❌ |❓ | -|Drag window with cursor |✔️ |✔️ |✔️ |✔️ |**N/A** |**N/A**|**N/A**|**N/A** | +|Feature |Windows |MacOS |Linux x11|Linux Wayland|Linux KMS/DRM|Android|iOS |WASM | +|----------------------- | ----- | ---- | ------- | ----------- | ----------- | ----- | ----- | -------- | +|Mouse events |✔️ |▢[#63] |✔️ |✔️ |✔️ |**N/A**|**N/A**|✔️ | +|Mouse set location |✔️ |✔️ |✔️ |❓ |✔️ |**N/A**|**N/A**|**N/A**| +|Cursor grab |✔️ |▢[#165] |▢[#242] |✔️ |✔️ |**N/A**|**N/A**|✔️ | +|Cursor icon |✔️ |✔️ |✔️ |✔️ |✔️ |**N/A**|**N/A**|✔️ | +|Cursor hittest |✔️ |✔️ |❌ |✔️ |❌ |**N/A**|**N/A**|❌ | +|Touch events |✔️ |❌ |✔️ |✔️ |✔️ |✔️ |✔️ |❌ | +|Touch pressure |✔️ |❌ |❌ |❌ |✔️ |❌ |✔️ |❌ | +|Multitouch |✔️ |❌ |✔️ |✔️ |✔️ |✔️ |✔️ |❌ | +|Keyboard events |✔️ |✔️ |✔️ |✔️ |✔️ |❓ |❌ |✔️ | +|Drag & Drop |▢[#720] |▢[#720] |▢[#720] |❌[#306] |**N/A |**N/A**|**N/A**|❓ | +|Raw Device Events |▢[#750] |▢[#750] |▢[#750] |❌ |✔️ |❌ |❌ |❓ | +|Gamepad/Joystick events |❌[#804] |❌ |❌ |❌ |❌ |❌ |❌ |❓ | +|Device movement events |❓ |❓ |❓ |❓ |❌ |❌ |❌ |❓ | +|Drag window with cursor |✔️ |✔️ |✔️ |✔️ |**N/A** |**N/A**|**N/A**|**N/A** | ### Pending API Reworks - Changes in the API that have been agreed upon but aren't implemented across all platforms. -|Feature |Windows|MacOS |Linux x11|Linux Wayland|Linux DRM|Android|iOS |WASM | -|------------------------------ | ----- | ---- | ------- | ----------- | ----- | ----- | ----- | -------- | -|New API for HiDPI ([#315] [#319]) |✔️ |✔️ |✔️ |✔️ |❌ |▢[#721]|✔️ |❓ | -|Event Loop 2.0 ([#459]) |✔️ |✔️ |❌ |✔️ |❌ |❌ |✔️ |❓ | -|Keyboard Input ([#812]) |❌ |❌ |❌ |❌ |❌ |❌ |❌ |❓ | +|Feature |Windows|MacOS |Linux x11|Linux Wayland|Linux KMS/DRM|Android|iOS |WASM | +|------------------------------ | ----- | ---- | ------- | ----------- | ----------- | ----- | ----- | -------- | +|New API for HiDPI ([#315] [#319]) |✔️ |✔️ |✔️ |✔️ |❌ |▢[#721]|✔️ |❓ | +|Event Loop 2.0 ([#459]) |✔️ |✔️ |❌ |✔️ |❌ |❌ |✔️ |❓ | +|Keyboard Input ([#812]) |❌ |❌ |❌ |❌ |❌ |❌ |❌ |❓ | ### Completed API Reworks - |Feature |Windows|MacOS |Linux x11|Linux Wayland|Android|iOS |WASM | |------------------------------ | ----- | ---- | ------- | ----------- | ----- | ----- | -------- | [#165]: https://github.com/rust-windowing/winit/issues/165 - [#219]: https://github.com/rust-windowing/winit/issues/219 - [#242]: https://github.com/rust-windowing/winit/issues/242 - [#306]: https://github.com/rust-windowing/winit/issues/306 - [#315]: https://github.com/rust-windowing/winit/issues/315 - [#319]: https://github.com/rust-windowing/winit/issues/319 - [#33]: https://github.com/rust-windowing/winit/issues/33 - [#459]: https://github.com/rust-windowing/winit/issues/459 - [#5]: https://github.com/rust-windowing/winit/issues/5 - [#63]: https://github.com/rust-windowing/winit/issues/63 - [#720]: https://github.com/rust-windowing/winit/issues/720 - [#721]: https://github.com/rust-windowing/winit/issues/721 - [#750]: https://github.com/rust-windowing/winit/issues/750 - [#804]: https://github.com/rust-windowing/winit/issues/804 - -[#812]: https://github.com/rust-windowing/winit/issues/812 +[#812]: https://github.com/rust-windowing/winit/issues/812 \ No newline at end of file diff --git a/src/platform_impl/linux/drm/window.rs b/src/platform_impl/linux/drm/window.rs index 4f239c8fc2..5d9e6ad584 100644 --- a/src/platform_impl/linux/drm/window.rs +++ b/src/platform_impl/linux/drm/window.rs @@ -1,6 +1,7 @@ -use std::collections::VecDeque; +use std::{collections::VecDeque, os::unix::prelude::AsRawFd}; use drm::control::{atomic, property, AtomicCommitFlags, Device}; +use gbm::AsRaw; use crate::{ dpi::{PhysicalPosition, PhysicalSize, Position, Size}, @@ -287,6 +288,17 @@ impl Window { } } + /* + #[inline] + pub fn raw_window_handle(&self) -> raw_window_handle::GbmHandle { + let mut rwh = raw_window_handle::GbmHandle::empty(); + let lock = GBM_DEVICE.lock(); + rwh.fd = lock.as_ref().unwrap().as_raw_fd(); + rwh.display = lock.as_ref().unwrap().as_raw() as *mut std::os::raw::c_void; + rwh + } + */ + #[inline] pub fn primary_monitor(&self) -> Option { Some(crate::monitor::MonitorHandle { diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index 56e3d41f05..d3f84faef2 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -633,7 +633,7 @@ impl Window { #[cfg(feature = "wayland")] Window::Wayland(ref window) => RawWindowHandle::Wayland(window.raw_window_handle()), #[cfg(feature = "kmsdrm")] - Window::Drm(_) => unimplemented!(), + Window::Drm(_) => unimplemented!(), //RawWindowHandle::Gbm(window.raw_window_handle()), } } } From 4b6412ba4df597c8711401b54cef0767caaf8b1a Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 3 May 2022 08:15:29 -0400 Subject: [PATCH 016/151] GBM is indeed thread safe --- src/platform/unix.rs | 13 +++---------- src/platform_impl/linux/drm/event_loop.rs | 4 ++-- src/platform_impl/linux/drm/window.rs | 10 ++++------ src/platform_impl/linux/mod.rs | 6 +++--- 4 files changed, 12 insertions(+), 21 deletions(-) diff --git a/src/platform/unix.rs b/src/platform/unix.rs index 736c46f7ba..bba90bd8a0 100644 --- a/src/platform/unix.rs +++ b/src/platform/unix.rs @@ -126,11 +126,7 @@ pub trait EventLoopWindowTargetExtUnix { #[cfg(feature = "kmsdrm")] fn gbm_device( &self, - ) -> Option< - &'static parking_lot::Mutex< - AssertSync, std::io::Error>>, - >, - >; + ) -> Option<&'static AssertSync, std::io::Error>>>; /// Returns the current crtc of the gbm device /// @@ -197,11 +193,8 @@ impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { #[cfg(feature = "kmsdrm")] fn gbm_device( &self, - ) -> Option< - &'static parking_lot::Mutex< - AssertSync, std::io::Error>>, - >, - > { + ) -> Option<&'static AssertSync, std::io::Error>>> + { use crate::platform_impl::GBM_DEVICE; match self.p { diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index e4317a4148..1b25c43c13 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -592,7 +592,7 @@ impl EventLoopWindowTarget { #[inline] pub fn available_monitors(&self) -> VecDeque { - if let Ok(gbm) = &**GBM_DEVICE.lock() { + if let Ok(gbm) = GBM_DEVICE.as_ref() { gbm.resource_handles() .unwrap() .connectors() @@ -638,7 +638,7 @@ pub(crate) fn find_prop_id( impl EventLoop { pub fn new() -> Result, crate::error::OsError> { - match GBM_DEVICE.lock().as_ref() { + match GBM_DEVICE.as_ref() { Ok(gbm) => { drm::Device::set_client_capability( gbm, diff --git a/src/platform_impl/linux/drm/window.rs b/src/platform_impl/linux/drm/window.rs index 5d9e6ad584..9bf89292b7 100644 --- a/src/platform_impl/linux/drm/window.rs +++ b/src/platform_impl/linux/drm/window.rs @@ -1,7 +1,6 @@ -use std::{collections::VecDeque, os::unix::prelude::AsRawFd}; +use std::collections::VecDeque; use drm::control::{atomic, property, AtomicCommitFlags, Device}; -use gbm::AsRaw; use crate::{ dpi::{PhysicalPosition, PhysicalSize, Position, Size}, @@ -24,12 +23,11 @@ impl Window { _attributes: crate::window::WindowAttributes, _platform_attributes: crate::platform_impl::PlatformSpecificWindowBuilderAttributes, ) -> Result { - let gbm = GBM_DEVICE.lock(); - let gbm = gbm.as_ref().map_err(|_| { + let gbm = GBM_DEVICE.as_ref().map_err(|_| { crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::DrmMisc("Failed to acquire gbm lock"), + crate::platform_impl::OsError::DrmMisc("GBM is not initialized"), ) })?; let &mode = event_loop_window_target @@ -276,7 +274,7 @@ impl Window { #[inline] pub fn available_monitors(&self) -> VecDeque { - if let Ok(gbm) = &**GBM_DEVICE.lock() { + if let Ok(gbm) = GBM_DEVICE.as_ref() { gbm.resource_handles() .unwrap() .connectors() diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index d3f84faef2..d54a7474a0 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -144,13 +144,13 @@ lazy_static! { #[cfg(feature = "kmsdrm")] lazy_static! { - pub static ref GBM_DEVICE: Mutex, std::io::Error>>> = + pub static ref GBM_DEVICE: AssertSync, std::io::Error>> = match Card::open_global() { Ok(card) => { - Mutex::new(AssertSync(gbm::Device::new(card))) + AssertSync(gbm::Device::new(card)) } Err(e) => { - Mutex::new(AssertSync(Err(e))) + AssertSync(Err(e)) } }; } From f92a16a4f4699e032a5f2b59a974e1fe6609f144 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 3 May 2022 08:18:08 -0400 Subject: [PATCH 017/151] Update libraries --- Cargo.toml | 58 +++++++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 08065a942d..9181c9dd53 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,30 +24,30 @@ wayland-dlopen = ["sctk/dlopen", "wayland-client/dlopen"] kmsdrm = ["drm", "gbm", "input", "calloop"] [dependencies] -instant = { version = "0.1", features = ["wasm-bindgen"] } -lazy_static = "1" -log = "0.4" -serde = { version = "1", optional = true, features = ["serde_derive"] } -raw-window-handle = "0.4.2" -bitflags = "1" -mint = { version = "0.5.6", optional = true } +instant = { version = "0.1.12", features = ["wasm-bindgen"] } +lazy_static = "1.4.0" +log = "0.4.17" +serde = { version = "1.0.137", optional = true, features = ["serde_derive"] } +raw-window-handle = "0.4.3" +bitflags = "1.3.2" +mint = { version = "0.5.9", optional = true } [dev-dependencies] -image = { version = "0.24.0", default-features = false, features = ["png"] } +image = { version = "0.24.2", default-features = false, features = ["png"] } simple_logger = "2.1.0" [target.'cfg(target_os = "android")'.dependencies] -ndk = "0.6" -ndk-sys = "0.3" -ndk-glue = "0.6" +ndk = "0.6.0" +ndk-sys = "0.3.0" +ndk-glue = "0.6.2" [target.'cfg(any(target_os = "ios", target_os = "macos"))'.dependencies] objc = "0.2.7" [target.'cfg(target_os = "macos")'.dependencies] -cocoa = "0.24" -core-foundation = "0.9" -core-graphics = "0.22" +cocoa = "0.24.0" +core-foundation = "0.9.3" +core-graphics = "0.22.3" dispatch = "0.2.0" [target.'cfg(target_os = "macos")'.dependencies.core-video-sys] @@ -56,10 +56,10 @@ default_features = false features = ["display_link"] [target.'cfg(target_os = "windows")'.dependencies] -parking_lot = "0.12" +parking_lot = "0.12.0" [target.'cfg(target_os = "windows")'.dependencies.windows-sys] -version = "0.36" +version = "0.36.1" features = [ "Win32_Devices_HumanInterfaceDevice", "Win32_Foundation", @@ -88,22 +88,25 @@ features = [ ] [target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))'.dependencies] -wayland-client = { version = "0.29", default_features = false, features = ["use_system_lib"], optional = true } -wayland-protocols = { version = "0.29", features = [ "staging_protocols"], optional = true } -sctk = { package = "smithay-client-toolkit", version = "0.15.4", default_features = false, features = ["calloop"], optional = true } +wayland-client = { version = "0.29.4", default_features = false, features = ["use_system_lib"], optional = true } +wayland-protocols = { version = "0.29.4", features = [ "staging_protocols"], optional = true } +sctk = { package = "smithay-client-toolkit", version = "0.15.4", default_features = false, features = ["calloop"], optional = true } calloop = { version = "0.9.3", optional = true } -mio = { version = "0.8", features = ["os-ext"], optional = true } -x11-dl = { version = "2.18.5", optional = true } -percent-encoding = { version = "2.0", optional = true } +mio = { version = "0.8.2", features = ["os-ext"], optional = true } +x11-dl = { version = "2.19.1", optional = true } +percent-encoding = { version = "2.1.0", optional = true } parking_lot = { version = "0.12.0", optional = true } -libc = "0.2.64" +libc = "0.2.125" drm = { version = "0.6.2", optional = true } gbm = { version = "0.8.0", optional = true } input = { version = "0.7.1", optional = true } +[target.'cfg(target_arch = "wasm32")'.dependencies] +wasm-bindgen= "0.2.80" + [target.'cfg(target_arch = "wasm32")'.dependencies.web_sys] package = "web-sys" -version = "0.3.22" +version = "0.3.57" features = [ 'console', "AddEventListenerOptions", @@ -127,13 +130,10 @@ features = [ 'WheelEvent' ] -[target.'cfg(target_arch = "wasm32")'.dependencies.wasm-bindgen] -version = "0.2.45" - [target.'cfg(target_arch = "wasm32")'.dev-dependencies] -console_log = "0.2" +console_log = "0.2.0" [workspace] members = [ "run-wasm", -] \ No newline at end of file +] From 3ad772404d6ad646392a9d452e8bdd093b36a7c6 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 3 May 2022 09:58:09 -0400 Subject: [PATCH 018/151] Fix formatting --- Cargo.toml | 2 +- src/platform_impl/linux/drm/window.rs | 10 ++++------ src/platform_impl/linux/mod.rs | 2 +- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9181c9dd53..32a34698eb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -136,4 +136,4 @@ console_log = "0.2.0" [workspace] members = [ "run-wasm", -] +] \ No newline at end of file diff --git a/src/platform_impl/linux/drm/window.rs b/src/platform_impl/linux/drm/window.rs index 9bf89292b7..1933f8019f 100644 --- a/src/platform_impl/linux/drm/window.rs +++ b/src/platform_impl/linux/drm/window.rs @@ -1,6 +1,7 @@ -use std::collections::VecDeque; +use std::{collections::VecDeque, os::unix::prelude::AsRawFd}; use drm::control::{atomic, property, AtomicCommitFlags, Device}; +use gbm::AsRaw; use crate::{ dpi::{PhysicalPosition, PhysicalSize, Position, Size}, @@ -286,16 +287,13 @@ impl Window { } } - /* #[inline] pub fn raw_window_handle(&self) -> raw_window_handle::GbmHandle { let mut rwh = raw_window_handle::GbmHandle::empty(); - let lock = GBM_DEVICE.lock(); - rwh.fd = lock.as_ref().unwrap().as_raw_fd(); - rwh.display = lock.as_ref().unwrap().as_raw() as *mut std::os::raw::c_void; + rwh.fd = GBM_DEVICE.as_ref().unwrap().as_raw_fd(); + rwh.display = GBM_DEVICE.as_ref().unwrap().as_raw() as *mut std::os::raw::c_void; rwh } - */ #[inline] pub fn primary_monitor(&self) -> Option { diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index d54a7474a0..63f6ad0157 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -633,7 +633,7 @@ impl Window { #[cfg(feature = "wayland")] Window::Wayland(ref window) => RawWindowHandle::Wayland(window.raw_window_handle()), #[cfg(feature = "kmsdrm")] - Window::Drm(_) => unimplemented!(), //RawWindowHandle::Gbm(window.raw_window_handle()), + Window::Drm(ref window) => RawWindowHandle::Gbm(window.raw_window_handle()), } } } From 84e6dea8c03aad8acbcc857ce2634f379cf21414 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 3 May 2022 10:12:30 -0400 Subject: [PATCH 019/151] Fix building issue --- Cargo.toml | 5 ++- src/platform/unix.rs | 43 +++++++++-------------- src/platform_impl/linux/drm/event_loop.rs | 32 ++++++++--------- src/platform_impl/linux/drm/window.rs | 24 ++++++------- src/platform_impl/linux/mod.rs | 11 ++---- 5 files changed, 47 insertions(+), 68 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 32a34698eb..854994ea6a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,14 +21,14 @@ default = ["x11", "wayland", "wayland-dlopen", "kmsdrm"] x11 = ["x11-dl", "mio", "percent-encoding", "parking_lot"] wayland = ["wayland-client", "wayland-protocols", "sctk", "calloop"] wayland-dlopen = ["sctk/dlopen", "wayland-client/dlopen"] -kmsdrm = ["drm", "gbm", "input", "calloop"] +kmsdrm = ["drm", "input", "calloop"] [dependencies] instant = { version = "0.1.12", features = ["wasm-bindgen"] } lazy_static = "1.4.0" log = "0.4.17" serde = { version = "1.0.137", optional = true, features = ["serde_derive"] } -raw-window-handle = "0.4.3" +raw-window-handle = { git = "https://github.com/StratusFearMe21/raw-window-handle" } bitflags = "1.3.2" mint = { version = "0.5.9", optional = true } @@ -98,7 +98,6 @@ percent-encoding = { version = "2.1.0", optional = true } parking_lot = { version = "0.12.0", optional = true } libc = "0.2.125" drm = { version = "0.6.2", optional = true } -gbm = { version = "0.8.0", optional = true } input = { version = "0.7.1", optional = true } [target.'cfg(target_arch = "wasm32")'.dependencies] diff --git a/src/platform/unix.rs b/src/platform/unix.rs index bba90bd8a0..8e5ab24bef 100644 --- a/src/platform/unix.rs +++ b/src/platform/unix.rs @@ -120,31 +120,31 @@ pub trait EventLoopWindowTargetExtUnix { #[cfg(feature = "wayland")] fn wayland_display(&self) -> Option<*mut raw::c_void>; - /// Returns the gbm device of the event loop's fd + /// Returns the drm device of the event loop's fd /// /// Returns `None` if the `EventLoop` doesn't use kmsdrm (if it uses wayland for example). #[cfg(feature = "kmsdrm")] - fn gbm_device( + fn drm_device( &self, - ) -> Option<&'static AssertSync, std::io::Error>>>; + ) -> Option<&'static AssertSync>>; - /// Returns the current crtc of the gbm device + /// Returns the current crtc of the drm device /// /// Returns `None` if the `EventLoop` doesn't use kmsdrm (if it uses wayland for example). #[cfg(feature = "kmsdrm")] - fn gbm_crtc(&self) -> Option<&drm::control::crtc::Info>; + fn drm_crtc(&self) -> Option<&drm::control::crtc::Info>; - /// Returns the current connector of the gbm device + /// Returns the current connector of the drm device /// /// Returns `None` if the `EventLoop` doesn't use kmsdrm (if it uses wayland for example). #[cfg(feature = "kmsdrm")] - fn gbm_connector(&self) -> Option<&drm::control::connector::Info>; + fn drm_connector(&self) -> Option<&drm::control::connector::Info>; - /// Returns the current mode of the gbm device + /// Returns the current mode of the drm device /// /// Returns `None` if the `EventLoop` doesn't use kmsdrm (if it uses wayland for example). #[cfg(feature = "kmsdrm")] - fn gbm_mode(&self) -> Option; + fn drm_mode(&self) -> Option; } impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { @@ -191,14 +191,13 @@ impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { #[inline] #[cfg(feature = "kmsdrm")] - fn gbm_device( + fn drm_device( &self, - ) -> Option<&'static AssertSync, std::io::Error>>> - { - use crate::platform_impl::GBM_DEVICE; + ) -> Option<&'static AssertSync>> { + use crate::platform_impl::DRM_DEVICE; match self.p { - crate::platform_impl::EventLoopWindowTarget::Drm(_) => Some(&*GBM_DEVICE), + crate::platform_impl::EventLoopWindowTarget::Drm(_) => Some(&*DRM_DEVICE), #[cfg(any(feature = "x11", feature = "wayland"))] _ => None, } @@ -206,7 +205,7 @@ impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { #[inline] #[cfg(feature = "kmsdrm")] - fn gbm_crtc(&self) -> Option<&drm::control::crtc::Info> { + fn drm_crtc(&self) -> Option<&drm::control::crtc::Info> { match self.p { crate::platform_impl::EventLoopWindowTarget::Drm(ref window) => Some(&window.crtc), #[cfg(any(feature = "x11", feature = "wayland"))] @@ -216,7 +215,7 @@ impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { #[inline] #[cfg(feature = "kmsdrm")] - fn gbm_connector(&self) -> Option<&drm::control::connector::Info> { + fn drm_connector(&self) -> Option<&drm::control::connector::Info> { match self.p { crate::platform_impl::EventLoopWindowTarget::Drm(ref window) => Some(&window.connector), #[cfg(any(feature = "x11", feature = "wayland"))] @@ -226,7 +225,7 @@ impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { #[inline] #[cfg(feature = "kmsdrm")] - fn gbm_mode(&self) -> Option { + fn drm_mode(&self) -> Option { match self.p { crate::platform_impl::EventLoopWindowTarget::Drm(ref window) => Some(window.mode), #[cfg(any(feature = "x11", feature = "wayland"))] @@ -332,16 +331,6 @@ pub trait WindowExtUnix { #[cfg(feature = "wayland")] fn wayland_display(&self) -> Option<*mut raw::c_void>; - /* - /// Returns the gbm device that is used by this window. - /// - /// Returns `None` if the window doesn't use kmsdrm (if it uses wayland for example). - /// - /// The pointer will become invalid when the glutin `Window` is destroyed. - #[cfg(feature = "kmsdrm")] - fn gbm_device(&self) -> Option<&gbm::Device>; - */ - /// Check if the window is ready for drawing /// /// It is a remnant of a previous implementation detail for the diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index 1b25c43c13..04e02d83be 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -26,7 +26,7 @@ use crate::{ event::{Force, KeyboardInput, ModifiersState, MouseScrollDelta, StartCause}, event_loop::{ControlFlow, EventLoopClosed}, platform::unix::Card, - platform_impl::{platform::sticky_exit_callback, GBM_DEVICE}, + platform_impl::{platform::sticky_exit_callback, DRM_DEVICE}, }; use super::input_to_vk::CHAR_MAPPINGS; @@ -560,13 +560,13 @@ impl EventSource for LibinputInputBackend { type EventSink = Vec>; pub struct EventLoopWindowTarget { - /// gbm Connector + /// drm Connector pub connector: drm::control::connector::Info, - /// gbm crtc + /// drm crtc pub crtc: drm::control::crtc::Info, - /// gbm mode + /// drm mode pub mode: drm::control::Mode, /// Event loop handle. @@ -592,12 +592,12 @@ impl EventLoopWindowTarget { #[inline] pub fn available_monitors(&self) -> VecDeque { - if let Ok(gbm) = GBM_DEVICE.as_ref() { - gbm.resource_handles() + if let Ok(drm) = DRM_DEVICE.as_ref() { + drm.resource_handles() .unwrap() .connectors() .iter() - .map(|f| super::MonitorHandle(gbm.get_connector(*f).unwrap())) + .map(|f| super::MonitorHandle(drm.get_connector(*f).unwrap())) .collect() } else { VecDeque::new() @@ -620,7 +620,7 @@ pub struct EventLoop { } pub(crate) fn find_prop_id( - card: &gbm::Device, + card: &Card, handle: T, name: &'static str, ) -> Option { @@ -638,10 +638,10 @@ pub(crate) fn find_prop_id( impl EventLoop { pub fn new() -> Result, crate::error::OsError> { - match GBM_DEVICE.as_ref() { - Ok(gbm) => { + match DRM_DEVICE.as_ref() { + Ok(drm) => { drm::Device::set_client_capability( - gbm, + drm, drm::ClientCapability::UniversalPlanes, true, ) @@ -652,7 +652,7 @@ impl EventLoop { "kmsdrm device does not support universal planes", ), )))?; - drm::Device::set_client_capability(gbm, drm::ClientCapability::Atomic, true).or( + drm::Device::set_client_capability(drm, drm::ClientCapability::Atomic, true).or( Err(crate::error::OsError::new( line!(), file!(), @@ -663,7 +663,7 @@ impl EventLoop { )?; // Load the information. - let res = gbm.resource_handles().or(Err(crate::error::OsError::new( + let res = drm.resource_handles().or(Err(crate::error::OsError::new( line!(), file!(), crate::platform_impl::OsError::DrmMisc("Could not load normal resource ids."), @@ -671,12 +671,12 @@ impl EventLoop { let coninfo: Vec = res .connectors() .iter() - .flat_map(|con| gbm.get_connector(*con)) + .flat_map(|con| drm.get_connector(*con)) .collect(); let crtcinfo: Vec = res .crtcs() .iter() - .flat_map(|crtc| gbm.get_crtc(*crtc)) + .flat_map(|crtc| drm.get_crtc(*crtc)) .collect(); let crtc = crtcinfo.get(0).ok_or(crate::error::OsError::new( @@ -781,7 +781,7 @@ impl EventLoop { Err(_) => Err(crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::DrmMisc("gbm failed to initialize"), + crate::platform_impl::OsError::DrmMisc("drm failed to initialize"), )), } } diff --git a/src/platform_impl/linux/drm/window.rs b/src/platform_impl/linux/drm/window.rs index 1933f8019f..6de397219f 100644 --- a/src/platform_impl/linux/drm/window.rs +++ b/src/platform_impl/linux/drm/window.rs @@ -1,12 +1,11 @@ use std::{collections::VecDeque, os::unix::prelude::AsRawFd}; use drm::control::{atomic, property, AtomicCommitFlags, Device}; -use gbm::AsRaw; use crate::{ dpi::{PhysicalPosition, PhysicalSize, Position, Size}, error::{ExternalError, NotSupportedError}, - platform_impl::GBM_DEVICE, + platform_impl::DRM_DEVICE, window::{CursorIcon, Fullscreen}, }; @@ -24,7 +23,7 @@ impl Window { _attributes: crate::window::WindowAttributes, _platform_attributes: crate::platform_impl::PlatformSpecificWindowBuilderAttributes, ) -> Result { - let gbm = GBM_DEVICE.as_ref().map_err(|_| { + let drm = DRM_DEVICE.as_ref().map_err(|_| { crate::error::OsError::new( line!(), file!(), @@ -46,7 +45,7 @@ impl Window { let mut atomic_req = atomic::AtomicModeReq::new(); atomic_req.add_property( event_loop_window_target.connector.handle(), - find_prop_id(&gbm, event_loop_window_target.connector.handle(), "CRTC_ID").ok_or_else( + find_prop_id(&drm, event_loop_window_target.connector.handle(), "CRTC_ID").ok_or_else( || { crate::error::OsError::new( line!(), @@ -57,7 +56,7 @@ impl Window { )?, property::Value::CRTC(Some(event_loop_window_target.crtc.handle())), ); - let blob = gbm.create_property_blob(&mode).map_err(|_| { + let blob = drm.create_property_blob(&mode).map_err(|_| { crate::error::OsError::new( line!(), file!(), @@ -66,7 +65,7 @@ impl Window { })?; atomic_req.add_property( event_loop_window_target.crtc.handle(), - find_prop_id(&gbm, event_loop_window_target.crtc.handle(), "MODE_ID").ok_or_else( + find_prop_id(&drm, event_loop_window_target.crtc.handle(), "MODE_ID").ok_or_else( || { crate::error::OsError::new( line!(), @@ -79,7 +78,7 @@ impl Window { ); atomic_req.add_property( event_loop_window_target.crtc.handle(), - find_prop_id(&gbm, event_loop_window_target.crtc.handle(), "ACTIVE").ok_or_else( + find_prop_id(&drm, event_loop_window_target.crtc.handle(), "ACTIVE").ok_or_else( || { crate::error::OsError::new( line!(), @@ -91,7 +90,7 @@ impl Window { property::Value::Boolean(true), ); - gbm.atomic_commit(AtomicCommitFlags::ALLOW_MODESET, atomic_req) + drm.atomic_commit(AtomicCommitFlags::ALLOW_MODESET, atomic_req) .map_err(|_| { crate::error::OsError::new( line!(), @@ -275,12 +274,12 @@ impl Window { #[inline] pub fn available_monitors(&self) -> VecDeque { - if let Ok(gbm) = GBM_DEVICE.as_ref() { - gbm.resource_handles() + if let Ok(drm) = DRM_DEVICE.as_ref() { + drm.resource_handles() .unwrap() .connectors() .iter() - .map(|f| super::MonitorHandle(gbm.get_connector(*f).unwrap())) + .map(|f| super::MonitorHandle(drm.get_connector(*f).unwrap())) .collect() } else { VecDeque::new() @@ -290,8 +289,7 @@ impl Window { #[inline] pub fn raw_window_handle(&self) -> raw_window_handle::GbmHandle { let mut rwh = raw_window_handle::GbmHandle::empty(); - rwh.fd = GBM_DEVICE.as_ref().unwrap().as_raw_fd(); - rwh.display = GBM_DEVICE.as_ref().unwrap().as_raw() as *mut std::os::raw::c_void; + rwh.fd = DRM_DEVICE.as_ref().unwrap().as_raw_fd(); rwh } diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index 63f6ad0157..2c92cc0326 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -144,15 +144,8 @@ lazy_static! { #[cfg(feature = "kmsdrm")] lazy_static! { - pub static ref GBM_DEVICE: AssertSync, std::io::Error>> = - match Card::open_global() { - Ok(card) => { - AssertSync(gbm::Device::new(card)) - } - Err(e) => { - AssertSync(Err(e)) - } - }; + pub static ref DRM_DEVICE: AssertSync> = + AssertSync(Card::open_global()); } #[derive(Debug, Clone)] From eefdba55ffa5b6cac70f5061e7f18f1e7604efb1 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 3 May 2022 10:32:01 -0400 Subject: [PATCH 020/151] Make Card Sync --- src/platform/unix.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/platform/unix.rs b/src/platform/unix.rs index 8e5ab24bef..2ff6463ada 100644 --- a/src/platform/unix.rs +++ b/src/platform/unix.rs @@ -36,9 +36,9 @@ pub use crate::platform_impl::x11; pub use crate::platform_impl::{x11::util::WindowType as XWindowType, XNotSupported}; #[cfg(feature = "kmsdrm")] -#[derive(Debug)] +#[derive(Debug, Clone)] /// A simple wrapper for a device node. -pub struct Card(std::fs::File); +pub struct Card(Arc); #[cfg(feature = "kmsdrm")] /// Implementing `AsRawFd` is a prerequisite to implementing the traits found @@ -62,7 +62,7 @@ impl Card { let mut options = std::fs::OpenOptions::new(); options.read(true); options.write(true); - Ok(Card(options.open(path)?)) + Ok(Card(Arc::new(options.open(path)?))) } pub fn open_global() -> Result { From 56f285e6c76741935ad37be2040f01b75b8b67f9 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 3 May 2022 10:38:57 -0400 Subject: [PATCH 021/151] Make Card Sync --- src/platform/unix.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/platform/unix.rs b/src/platform/unix.rs index 2ff6463ada..f069c4dfb5 100644 --- a/src/platform/unix.rs +++ b/src/platform/unix.rs @@ -75,6 +75,13 @@ impl Card { #[repr(transparent)] pub struct AssertSync(pub T); +#[cfg(feature = "kmsdrm")] +impl Clone for AssertSync { + fn clone(&self) -> Self { + Self(self.0.clone()) + } +} + #[cfg(feature = "kmsdrm")] unsafe impl Sync for AssertSync {} #[cfg(feature = "kmsdrm")] From b5b7824f7b7c266749630369194d080625cdefea Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 3 May 2022 10:48:46 -0400 Subject: [PATCH 022/151] Find preferred mode --- src/platform_impl/linux/drm/window.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/platform_impl/linux/drm/window.rs b/src/platform_impl/linux/drm/window.rs index 6de397219f..59359e8460 100644 --- a/src/platform_impl/linux/drm/window.rs +++ b/src/platform_impl/linux/drm/window.rs @@ -1,6 +1,6 @@ use std::{collections::VecDeque, os::unix::prelude::AsRawFd}; -use drm::control::{atomic, property, AtomicCommitFlags, Device}; +use drm::control::{atomic, property, AtomicCommitFlags, Device, ModeTypeFlags}; use crate::{ dpi::{PhysicalPosition, PhysicalSize, Position, Size}, @@ -33,7 +33,9 @@ impl Window { let &mode = event_loop_window_target .connector .modes() - .get(0) + .iter() + .find(|&&f| f.mode_type() == ModeTypeFlags::PREFERRED) + .or(event_loop_window_target.connector.modes().get(0)) .ok_or_else(|| { crate::error::OsError::new( line!(), From 3f16ac4ed3c231ae77095b1b7443ee06e4bd1775 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 3 May 2022 10:50:35 -0400 Subject: [PATCH 023/151] Oops, bitflags --- src/platform_impl/linux/drm/window.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform_impl/linux/drm/window.rs b/src/platform_impl/linux/drm/window.rs index 59359e8460..d9b790b6ec 100644 --- a/src/platform_impl/linux/drm/window.rs +++ b/src/platform_impl/linux/drm/window.rs @@ -34,7 +34,7 @@ impl Window { .connector .modes() .iter() - .find(|&&f| f.mode_type() == ModeTypeFlags::PREFERRED) + .find(|&&f| f.mode_type().contains(ModeTypeFlags::PREFERRED)) .or(event_loop_window_target.connector.modes().get(0)) .ok_or_else(|| { crate::error::OsError::new( From 364451b0e48a6c17633409e94b98f0ddbf587acd Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 3 May 2022 11:02:33 -0400 Subject: [PATCH 024/151] Fix naming --- src/platform_impl/linux/drm/window.rs | 4 ++-- src/platform_impl/linux/mod.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/platform_impl/linux/drm/window.rs b/src/platform_impl/linux/drm/window.rs index d9b790b6ec..08056030f3 100644 --- a/src/platform_impl/linux/drm/window.rs +++ b/src/platform_impl/linux/drm/window.rs @@ -289,8 +289,8 @@ impl Window { } #[inline] - pub fn raw_window_handle(&self) -> raw_window_handle::GbmHandle { - let mut rwh = raw_window_handle::GbmHandle::empty(); + pub fn raw_window_handle(&self) -> raw_window_handle::DrmHandle { + let mut rwh = raw_window_handle::DrmHandle::empty(); rwh.fd = DRM_DEVICE.as_ref().unwrap().as_raw_fd(); rwh } diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index 2c92cc0326..abdaec3326 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -626,7 +626,7 @@ impl Window { #[cfg(feature = "wayland")] Window::Wayland(ref window) => RawWindowHandle::Wayland(window.raw_window_handle()), #[cfg(feature = "kmsdrm")] - Window::Drm(ref window) => RawWindowHandle::Gbm(window.raw_window_handle()), + Window::Drm(ref window) => RawWindowHandle::Drm(window.raw_window_handle()), } } } From 2522bc79fc115a578fc445630fbfcb66165e0efd Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 3 May 2022 12:48:02 -0400 Subject: [PATCH 025/151] Mirror X.org connector behavior with drm --- src/platform/unix.rs | 42 +-- src/platform_impl/linux/drm/event_loop.rs | 304 +++++++++++----------- src/platform_impl/linux/drm/window.rs | 40 +-- src/platform_impl/linux/mod.rs | 6 +- 4 files changed, 184 insertions(+), 208 deletions(-) diff --git a/src/platform/unix.rs b/src/platform/unix.rs index f069c4dfb5..b4bba0fc94 100644 --- a/src/platform/unix.rs +++ b/src/platform/unix.rs @@ -36,9 +36,9 @@ pub use crate::platform_impl::x11; pub use crate::platform_impl::{x11::util::WindowType as XWindowType, XNotSupported}; #[cfg(feature = "kmsdrm")] -#[derive(Debug, Clone)] +#[derive(Debug)] /// A simple wrapper for a device node. -pub struct Card(Arc); +pub struct Card(std::fs::File); #[cfg(feature = "kmsdrm")] /// Implementing `AsRawFd` is a prerequisite to implementing the traits found @@ -62,7 +62,7 @@ impl Card { let mut options = std::fs::OpenOptions::new(); options.read(true); options.write(true); - Ok(Card(Arc::new(options.open(path)?))) + Ok(Card(options.open(path)?)) } pub fn open_global() -> Result { @@ -70,37 +70,6 @@ impl Card { } } -#[cfg(feature = "kmsdrm")] -#[derive(Debug)] -#[repr(transparent)] -pub struct AssertSync(pub T); - -#[cfg(feature = "kmsdrm")] -impl Clone for AssertSync { - fn clone(&self) -> Self { - Self(self.0.clone()) - } -} - -#[cfg(feature = "kmsdrm")] -unsafe impl Sync for AssertSync {} -#[cfg(feature = "kmsdrm")] -unsafe impl Send for AssertSync {} -#[cfg(feature = "kmsdrm")] -impl std::ops::Deref for AssertSync { - type Target = T; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} -#[cfg(feature = "kmsdrm")] -impl std::ops::DerefMut for AssertSync { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } -} - /// Additional methods on `EventLoopWindowTarget` that are specific to Unix. pub trait EventLoopWindowTargetExtUnix { /// True if the `EventLoopWindowTarget` uses Wayland. @@ -133,7 +102,7 @@ pub trait EventLoopWindowTargetExtUnix { #[cfg(feature = "kmsdrm")] fn drm_device( &self, - ) -> Option<&'static AssertSync>>; + ) -> Option<&'static parking_lot::Mutex, std::io::Error>>>; /// Returns the current crtc of the drm device /// @@ -200,7 +169,8 @@ impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { #[cfg(feature = "kmsdrm")] fn drm_device( &self, - ) -> Option<&'static AssertSync>> { + ) -> Option<&'static parking_lot::Mutex, std::io::Error>>> + { use crate::platform_impl::DRM_DEVICE; match self.p { diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index 04e02d83be..7500445912 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -569,6 +569,9 @@ pub struct EventLoopWindowTarget { /// drm mode pub mode: drm::control::Mode, + /// drm device + pub device: std::sync::Arc, + /// Event loop handle. pub event_loop_handle: calloop::LoopHandle<'static, EventSink>, @@ -592,16 +595,13 @@ impl EventLoopWindowTarget { #[inline] pub fn available_monitors(&self) -> VecDeque { - if let Ok(drm) = DRM_DEVICE.as_ref() { - drm.resource_handles() - .unwrap() - .connectors() - .iter() - .map(|f| super::MonitorHandle(drm.get_connector(*f).unwrap())) - .collect() - } else { - VecDeque::new() - } + self.device + .resource_handles() + .unwrap() + .connectors() + .iter() + .map(|f| super::MonitorHandle(self.device.get_connector(*f).unwrap())) + .collect() } } @@ -638,152 +638,154 @@ pub(crate) fn find_prop_id( impl EventLoop { pub fn new() -> Result, crate::error::OsError> { - match DRM_DEVICE.as_ref() { - Ok(drm) => { - drm::Device::set_client_capability( - drm, - drm::ClientCapability::UniversalPlanes, - true, - ) - .or(Err(crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc( - "kmsdrm device does not support universal planes", - ), - )))?; - drm::Device::set_client_capability(drm, drm::ClientCapability::Atomic, true).or( - Err(crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc( - "kmsdrm device does not support atomic modesetting", - ), - )), - )?; - - // Load the information. - let res = drm.resource_handles().or(Err(crate::error::OsError::new( + let drm = DRM_DEVICE + .lock() + .as_ref() + .map_err(|_| { + crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::DrmMisc("Could not load normal resource ids."), - )))?; - let coninfo: Vec = res - .connectors() - .iter() - .flat_map(|con| drm.get_connector(*con)) - .collect(); - let crtcinfo: Vec = res - .crtcs() - .iter() - .flat_map(|crtc| drm.get_crtc(*crtc)) - .collect(); - - let crtc = crtcinfo.get(0).ok_or(crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc("No crtcs found"), - ))?; - - // Filter each connector until we find one that's connected. - let con = coninfo - .iter() - .find(|&i| i.state() == drm::control::connector::State::Connected) - .ok_or(crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc("No connected connectors"), - ))?; - - // Get the first (usually best) mode - let &mode = con.modes().get(0).ok_or(crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc("No modes found on connector"), - ))?; - - let (disp_width, disp_height) = mode.size(); - - let mut input = input::Libinput::new_with_udev(Interface); - input.udev_assign_seat("seat0").unwrap(); - let event_loop: calloop::EventLoop<'static, EventSink> = - calloop::EventLoop::try_new().unwrap(); - - let handle = event_loop.handle(); - - // A source of user events. - let pending_user_events = std::rc::Rc::new(std::cell::RefCell::new(Vec::new())); - let pending_user_events_clone = pending_user_events.clone(); - let (user_events_sender, user_events_channel) = calloop::channel::channel(); - - // User events channel. - handle - .insert_source(user_events_channel, move |event, _, _| { - if let calloop::channel::Event::Msg(msg) = event { - pending_user_events_clone.borrow_mut().push(msg); - } - }) - .unwrap(); - - // An event's loop awakener to wake up for window events from winit's windows. - let (event_loop_awakener, event_loop_awakener_source) = - calloop::ping::make_ping().unwrap(); - - let event_sink = EventSink::new(); - - // Handler of window requests. - handle - .insert_source( - event_loop_awakener_source, - move |_event, _metadata, data| { - data.push(crate::event::Event::RedrawRequested( - crate::window::WindowId(crate::platform_impl::WindowId::Drm( - super::WindowId, - )), - )); - }, - ) - .unwrap(); - - let input_backend: LibinputInputBackend = - LibinputInputBackend::new(input, (disp_width.into(), disp_height.into())); - - let input_loop: calloop::Dispatcher<'static, LibinputInputBackend, EventSink> = - calloop::Dispatcher::new( - input_backend, - move |event, _metadata, data: &mut EventSink| { - data.push(event); - }, - ); - - handle.register_dispatcher(input_loop).unwrap(); - - let window_target = crate::event_loop::EventLoopWindowTarget { - p: crate::platform_impl::EventLoopWindowTarget::Drm(EventLoopWindowTarget { - connector: con.clone(), - crtc: crtc.clone(), - mode, - event_loop_handle: handle, - event_sink, - event_loop_awakener, - _marker: PhantomData, - }), - _marker: PhantomData, - }; - - Ok(EventLoop { - event_loop, - pending_user_events, - user_events_sender, - window_target, - }) - } - Err(_) => Err(crate::error::OsError::new( + crate::platform_impl::OsError::DrmMisc("KMS/DRM is not initialized"), + ) + })? + .clone(); + drm::Device::set_client_capability( + drm.as_ref(), + drm::ClientCapability::UniversalPlanes, + true, + ) + .or(Err(crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc( + "kmsdrm device does not support universal planes", + ), + )))?; + drm::Device::set_client_capability(drm.as_ref(), drm::ClientCapability::Atomic, true).or( + Err(crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::DrmMisc("drm failed to initialize"), + crate::platform_impl::OsError::DrmMisc( + "kmsdrm device does not support atomic modesetting", + ), )), - } + )?; + + // Load the information. + let res = drm.resource_handles().or(Err(crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Could not load normal resource ids."), + )))?; + let coninfo: Vec = res + .connectors() + .iter() + .flat_map(|con| drm.get_connector(*con)) + .collect(); + let crtcinfo: Vec = res + .crtcs() + .iter() + .flat_map(|crtc| drm.get_crtc(*crtc)) + .collect(); + + let crtc = crtcinfo.get(0).ok_or(crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("No crtcs found"), + ))?; + + // Filter each connector until we find one that's connected. + let con = coninfo + .iter() + .find(|&i| i.state() == drm::control::connector::State::Connected) + .ok_or(crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("No connected connectors"), + ))?; + + // Get the first (usually best) mode + let &mode = con.modes().get(0).ok_or(crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("No modes found on connector"), + ))?; + + let (disp_width, disp_height) = mode.size(); + + let mut input = input::Libinput::new_with_udev(Interface); + input.udev_assign_seat("seat0").unwrap(); + let event_loop: calloop::EventLoop<'static, EventSink> = + calloop::EventLoop::try_new().unwrap(); + + let handle = event_loop.handle(); + + // A source of user events. + let pending_user_events = std::rc::Rc::new(std::cell::RefCell::new(Vec::new())); + let pending_user_events_clone = pending_user_events.clone(); + let (user_events_sender, user_events_channel) = calloop::channel::channel(); + + // User events channel. + handle + .insert_source(user_events_channel, move |event, _, _| { + if let calloop::channel::Event::Msg(msg) = event { + pending_user_events_clone.borrow_mut().push(msg); + } + }) + .unwrap(); + + // An event's loop awakener to wake up for window events from winit's windows. + let (event_loop_awakener, event_loop_awakener_source) = calloop::ping::make_ping().unwrap(); + + let event_sink = EventSink::new(); + + // Handler of window requests. + handle + .insert_source( + event_loop_awakener_source, + move |_event, _metadata, data| { + data.push(crate::event::Event::RedrawRequested( + crate::window::WindowId(crate::platform_impl::WindowId::Drm( + super::WindowId, + )), + )); + }, + ) + .unwrap(); + + let input_backend: LibinputInputBackend = + LibinputInputBackend::new(input, (disp_width.into(), disp_height.into())); + + let input_loop: calloop::Dispatcher<'static, LibinputInputBackend, EventSink> = + calloop::Dispatcher::new( + input_backend, + move |event, _metadata, data: &mut EventSink| { + data.push(event); + }, + ); + + handle.register_dispatcher(input_loop).unwrap(); + + let window_target = crate::event_loop::EventLoopWindowTarget { + p: crate::platform_impl::EventLoopWindowTarget::Drm(EventLoopWindowTarget { + connector: con.clone(), + crtc: crtc.clone(), + device: drm, + mode, + event_loop_handle: handle, + event_sink, + event_loop_awakener, + _marker: PhantomData, + }), + _marker: PhantomData, + }; + + Ok(EventLoop { + event_loop, + pending_user_events, + user_events_sender, + window_target, + }) } pub fn run(mut self, callback: F) -> ! diff --git a/src/platform_impl/linux/drm/window.rs b/src/platform_impl/linux/drm/window.rs index 08056030f3..da19c2585c 100644 --- a/src/platform_impl/linux/drm/window.rs +++ b/src/platform_impl/linux/drm/window.rs @@ -5,6 +5,7 @@ use drm::control::{atomic, property, AtomicCommitFlags, Device, ModeTypeFlags}; use crate::{ dpi::{PhysicalPosition, PhysicalSize, Position, Size}, error::{ExternalError, NotSupportedError}, + platform::unix::Card, platform_impl::DRM_DEVICE, window::{CursorIcon, Fullscreen}, }; @@ -15,6 +16,7 @@ pub struct Window( drm::control::Mode, drm::control::connector::Info, calloop::ping::Ping, + std::sync::Arc, ); impl Window { @@ -23,13 +25,17 @@ impl Window { _attributes: crate::window::WindowAttributes, _platform_attributes: crate::platform_impl::PlatformSpecificWindowBuilderAttributes, ) -> Result { - let drm = DRM_DEVICE.as_ref().map_err(|_| { - crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc("GBM is not initialized"), - ) - })?; + let drm = DRM_DEVICE + .lock() + .as_ref() + .map_err(|_| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("GBM is not initialized"), + ) + })? + .clone(); let &mode = event_loop_window_target .connector .modes() @@ -105,6 +111,7 @@ impl Window { mode, event_loop_window_target.connector.clone(), event_loop_window_target.event_loop_awakener.clone(), + drm, )) } #[inline] @@ -276,22 +283,19 @@ impl Window { #[inline] pub fn available_monitors(&self) -> VecDeque { - if let Ok(drm) = DRM_DEVICE.as_ref() { - drm.resource_handles() - .unwrap() - .connectors() - .iter() - .map(|f| super::MonitorHandle(drm.get_connector(*f).unwrap())) - .collect() - } else { - VecDeque::new() - } + self.3 + .resource_handles() + .unwrap() + .connectors() + .iter() + .map(|f| super::MonitorHandle(self.3.get_connector(*f).unwrap())) + .collect() } #[inline] pub fn raw_window_handle(&self) -> raw_window_handle::DrmHandle { let mut rwh = raw_window_handle::DrmHandle::empty(); - rwh.fd = DRM_DEVICE.as_ref().unwrap().as_raw_fd(); + rwh.fd = self.3.as_raw_fd(); rwh } diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index abdaec3326..ea320b50c9 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -38,7 +38,7 @@ use crate::{ }; #[cfg(feature = "kmsdrm")] -use crate::platform::unix::{AssertSync, Card}; +use crate::platform::unix::Card; pub(crate) use crate::icon::RgbaIcon as PlatformIcon; @@ -144,8 +144,8 @@ lazy_static! { #[cfg(feature = "kmsdrm")] lazy_static! { - pub static ref DRM_DEVICE: AssertSync> = - AssertSync(Card::open_global()); + pub static ref DRM_DEVICE: Mutex, std::io::Error>> = + Mutex::new(Card::open_global().map(Arc::new)); } #[derive(Debug, Clone)] From 2bcc6023719552fde8e87078e77eb4720092144a Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 3 May 2022 13:04:49 -0400 Subject: [PATCH 026/151] Mirror X.org connector behavior with drm --- src/platform/unix.rs | 10 ++++----- src/platform_impl/linux/drm/event_loop.rs | 27 ++++++++++------------- src/platform_impl/linux/drm/window.rs | 2 +- src/platform_impl/linux/mod.rs | 4 ++-- 4 files changed, 20 insertions(+), 23 deletions(-) diff --git a/src/platform/unix.rs b/src/platform/unix.rs index b4bba0fc94..5f2bcce7bb 100644 --- a/src/platform/unix.rs +++ b/src/platform/unix.rs @@ -36,9 +36,9 @@ pub use crate::platform_impl::x11; pub use crate::platform_impl::{x11::util::WindowType as XWindowType, XNotSupported}; #[cfg(feature = "kmsdrm")] -#[derive(Debug)] +#[derive(Debug, Clone)] /// A simple wrapper for a device node. -pub struct Card(std::fs::File); +pub struct Card(Arc); #[cfg(feature = "kmsdrm")] /// Implementing `AsRawFd` is a prerequisite to implementing the traits found @@ -62,7 +62,7 @@ impl Card { let mut options = std::fs::OpenOptions::new(); options.read(true); options.write(true); - Ok(Card(options.open(path)?)) + Ok(Card(Arc::new(options.open(path)?))) } pub fn open_global() -> Result { @@ -102,7 +102,7 @@ pub trait EventLoopWindowTargetExtUnix { #[cfg(feature = "kmsdrm")] fn drm_device( &self, - ) -> Option<&'static parking_lot::Mutex, std::io::Error>>>; + ) -> Option<&'static parking_lot::Mutex>>; /// Returns the current crtc of the drm device /// @@ -169,7 +169,7 @@ impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { #[cfg(feature = "kmsdrm")] fn drm_device( &self, - ) -> Option<&'static parking_lot::Mutex, std::io::Error>>> + ) -> Option<&'static parking_lot::Mutex>> { use crate::platform_impl::DRM_DEVICE; diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index 7500445912..1d33814d73 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -570,7 +570,7 @@ pub struct EventLoopWindowTarget { pub mode: drm::control::Mode, /// drm device - pub device: std::sync::Arc, + pub device: Card, /// Event loop handle. pub event_loop_handle: calloop::LoopHandle<'static, EventSink>, @@ -649,27 +649,24 @@ impl EventLoop { ) })? .clone(); - drm::Device::set_client_capability( - drm.as_ref(), - drm::ClientCapability::UniversalPlanes, - true, - ) - .or(Err(crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc( - "kmsdrm device does not support universal planes", - ), - )))?; - drm::Device::set_client_capability(drm.as_ref(), drm::ClientCapability::Atomic, true).or( + drm::Device::set_client_capability(&drm, drm::ClientCapability::UniversalPlanes, true).or( Err(crate::error::OsError::new( line!(), file!(), crate::platform_impl::OsError::DrmMisc( - "kmsdrm device does not support atomic modesetting", + "kmsdrm device does not support universal planes", ), )), )?; + drm::Device::set_client_capability(&drm, drm::ClientCapability::Atomic, true).or(Err( + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc( + "kmsdrm device does not support atomic modesetting", + ), + ), + ))?; // Load the information. let res = drm.resource_handles().or(Err(crate::error::OsError::new( diff --git a/src/platform_impl/linux/drm/window.rs b/src/platform_impl/linux/drm/window.rs index da19c2585c..19ac278ab9 100644 --- a/src/platform_impl/linux/drm/window.rs +++ b/src/platform_impl/linux/drm/window.rs @@ -16,7 +16,7 @@ pub struct Window( drm::control::Mode, drm::control::connector::Info, calloop::ping::Ping, - std::sync::Arc, + Card, ); impl Window { diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index ea320b50c9..5696246c7f 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -144,8 +144,8 @@ lazy_static! { #[cfg(feature = "kmsdrm")] lazy_static! { - pub static ref DRM_DEVICE: Mutex, std::io::Error>> = - Mutex::new(Card::open_global().map(Arc::new)); + pub static ref DRM_DEVICE: Mutex> = + Mutex::new(Card::open_global()); } #[derive(Debug, Clone)] From b8ac6dbb229eb954d8bd8cd5960c1c997781fc18 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 3 May 2022 15:31:29 -0400 Subject: [PATCH 027/151] Proper seat management with libseat --- Cargo.toml | 5 +-- src/platform_impl/linux/drm/event_loop.rs | 40 ++++++++++++++--------- 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ec5ed4d3bd..d241a3fbaf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ default = ["x11", "wayland", "wayland-dlopen", "kmsdrm"] x11 = ["x11-dl", "mio", "percent-encoding", "parking_lot"] wayland = ["wayland-client", "wayland-protocols", "sctk", "calloop"] wayland-dlopen = ["sctk/dlopen", "wayland-client/dlopen"] -kmsdrm = ["drm", "input", "calloop"] +kmsdrm = ["drm", "input", "calloop", "libseat"] [dependencies] instant = { version = "0.1.12", features = ["wasm-bindgen"] } @@ -100,6 +100,7 @@ parking_lot = { version = "0.12.0", optional = true } libc = "0.2.125" drm = { version = "0.6.2", optional = true } input = { version = "0.7.1", optional = true } +libseat = { version = "0.1.4", optional = true } [target.'cfg(target_arch = "wasm32")'.dependencies] wasm-bindgen= "0.2.80" @@ -136,4 +137,4 @@ console_log = "0.2.0" [workspace] members = [ "run-wasm", -] \ No newline at end of file +] diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index 1d33814d73..c7c9879002 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -1,7 +1,7 @@ use std::{ - collections::VecDeque, + collections::{HashMap, VecDeque}, marker::PhantomData, - os::unix::prelude::{AsRawFd, FromRawFd, IntoRawFd, OpenOptionsExt, RawFd}, + os::unix::prelude::{AsRawFd, FromRawFd, RawFd}, path::Path, sync::mpsc::SendError, }; @@ -19,7 +19,6 @@ use input::{ LibinputInterface, }; use instant::{Duration, Instant}; -use libc::{O_RDONLY, O_RDWR, O_WRONLY}; use crate::{ dpi::PhysicalPosition, @@ -31,22 +30,23 @@ use crate::{ use super::input_to_vk::CHAR_MAPPINGS; -struct Interface; +struct Interface(libseat::Seat, HashMap); impl LibinputInterface for Interface { - fn open_restricted(&mut self, path: &Path, flags: i32) -> Result { - std::fs::OpenOptions::new() - .custom_flags(flags) - .read((flags & O_RDONLY != 0) | (flags & O_RDWR != 0)) - .write((flags & O_WRONLY != 0) | (flags & O_RDWR != 0)) - .open(path) - .map(|file| file.into_raw_fd()) - .map_err(|err| err.raw_os_error().unwrap()) + fn open_restricted(&mut self, path: &Path, _flags: i32) -> Result { + self.0 + .open_device(&path) + .map(|(id, file)| { + self.1.insert(file, id); + file + }) + .map_err(|err| err.into()) } fn close_restricted(&mut self, fd: RawFd) { - unsafe { - std::fs::File::from_raw_fd(fd); + if let Some(dev) = self.1.get(&fd).copied() { + self.0.close_device(dev).unwrap(); } + unsafe { std::fs::File::from_raw_fd(fd) }; } } @@ -710,8 +710,16 @@ impl EventLoop { let (disp_width, disp_height) = mode.size(); - let mut input = input::Libinput::new_with_udev(Interface); - input.udev_assign_seat("seat0").unwrap(); + let mut seat = libseat::Seat::open(|_, _| {}, None).map_err(|_| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Failed to open libseat"), + ) + })?; + seat.dispatch(0).unwrap(); + + let input = input::Libinput::new_with_udev(Interface(seat, HashMap::new())); let event_loop: calloop::EventLoop<'static, EventSink> = calloop::EventLoop::try_new().unwrap(); From 8d067aabb2a3bcd0a3cee44cdac56b8267786c79 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 3 May 2022 15:58:48 -0400 Subject: [PATCH 028/151] Fix seat management --- src/platform_impl/linux/drm/event_loop.rs | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index c7c9879002..cc70091aa0 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -710,16 +710,17 @@ impl EventLoop { let (disp_width, disp_height) = mode.size(); - let mut seat = libseat::Seat::open(|_, _| {}, None).map_err(|_| { - crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc("Failed to open libseat"), - ) - })?; - seat.dispatch(0).unwrap(); - - let input = input::Libinput::new_with_udev(Interface(seat, HashMap::new())); + let mut input = input::Libinput::new_with_udev(Interface( + libseat::Seat::open(|_, _| {}, None).map_err(|_| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Failed to open libseat"), + ) + })?, + HashMap::new(), + )); + input.udev_assign_seat("seat0").unwrap(); let event_loop: calloop::EventLoop<'static, EventSink> = calloop::EventLoop::try_new().unwrap(); From 6a8457dc4e2ef6e0c0d5d769d25ecb8771b31a47 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 3 May 2022 17:22:35 -0400 Subject: [PATCH 029/151] Add fallback method to close window --- src/platform_impl/linux/drm/event_loop.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index cc70091aa0..b203e20f86 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -517,8 +517,17 @@ impl EventSource for LibinputInputBackend { } callback(crate::event::Event::WindowEvent { window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), - event:crate::event::WindowEvent::ModifiersChanged(self.modifiers)}, &mut ()); + event: crate::event::WindowEvent::ModifiersChanged(self.modifiers)}, &mut ()); + } + 99 // SysRq + => { + if self.modifiers.is_empty() { + callback(crate::event::Event::WindowEvent { + window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), + event: crate::event::WindowEvent::CloseRequested + }, &mut ()); } + } k => { callback(crate::event::Event::WindowEvent { From dda06ff7128334ba733d8773537d4590bc8e80e3 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 3 May 2022 18:29:49 -0400 Subject: [PATCH 030/151] Pass drm plane to user --- src/platform/unix.rs | 16 ++ src/platform_impl/linux/drm/window.rs | 212 ++++++++++++++++++++------ 2 files changed, 182 insertions(+), 46 deletions(-) diff --git a/src/platform/unix.rs b/src/platform/unix.rs index 5f2bcce7bb..79548e9d6b 100644 --- a/src/platform/unix.rs +++ b/src/platform/unix.rs @@ -316,6 +316,12 @@ pub trait WindowExtUnix { /// Always return true. #[deprecated] fn is_ready(&self) -> bool; + + /// Return a handle to the `drm::control::plane::Handle` the is used by the window + /// + /// Returns `None` if the window doesn't use kmsdrm (if it uses xlib for example). + #[cfg(feature = "kmsdrm")] + fn drm_plane(&self) -> Option; } impl WindowExtUnix for Window { @@ -390,6 +396,16 @@ impl WindowExtUnix for Window { } } + #[inline] + #[cfg(feature = "kmsdrm")] + fn drm_plane(&self) -> Option { + match self.window { + LinuxWindow::Drm(ref w) => Some(w.drm_plane()), + #[cfg(any(feature = "x11", feature = "wayland"))] + _ => None, + } + } + #[inline] fn is_ready(&self) -> bool { true diff --git a/src/platform_impl/linux/drm/window.rs b/src/platform_impl/linux/drm/window.rs index 19ac278ab9..ebc1fac468 100644 --- a/src/platform_impl/linux/drm/window.rs +++ b/src/platform_impl/linux/drm/window.rs @@ -17,6 +17,8 @@ pub struct Window( drm::control::connector::Info, calloop::ping::Ping, Card, + drm::control::dumbbuffer::DumbBuffer, + drm::control::plane::Handle, ); impl Window { @@ -50,6 +52,99 @@ impl Window { ) })?; + let res = drm.resource_handles().or(Err(crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Could not load normal resource ids."), + )))?; + + let mut db = drm + .create_dumb_buffer((64, 64), drm::buffer::DrmFourcc::Xrgb8888, 32) + .or(Err(crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Could not create dumb buffer"), + )))?; + + { + let mut map = drm + .map_dumb_buffer(&mut db) + .expect("Could not map dumbbuffer"); + for b in map.as_mut() { + *b = 128; + } + } + + let fb = drm + .add_framebuffer(&db, 24, 32) + .or(Err(crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Could not create FB"), + )))?; + + let planes = drm.plane_handles().or(Err(crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Could not list planes"), + )))?; + let (better_planes, compatible_planes): ( + Vec, + Vec, + ) = planes + .planes() + .iter() + .filter(|&&plane| { + drm.get_plane(plane) + .map(|plane_info| { + let compatible_crtcs = res.filter_crtcs(plane_info.possible_crtcs()); + compatible_crtcs.contains(&event_loop_window_target.crtc.handle()) + }) + .unwrap_or(false) + }) + .partition(|&&plane| { + if let Ok(props) = drm.get_properties(plane) { + let (ids, vals) = props.as_props_and_values(); + for (&id, &val) in ids.iter().zip(vals.iter()) { + if let Ok(info) = drm.get_property(id) { + if info.name().to_str().map(|x| x == "type").unwrap_or(false) { + return val == (drm::control::PlaneType::Cursor as u32).into(); + } + } + } + } + false + }); + let plane = *better_planes.get(0).unwrap_or(&compatible_planes[0]); + let (p_better_planes, p_compatible_planes): ( + Vec, + Vec, + ) = compatible_planes + .iter() + .filter(|&&plane| { + drm.get_plane(plane) + .map(|plane_info| { + let compatible_crtcs = res.filter_crtcs(plane_info.possible_crtcs()); + compatible_crtcs.contains(&event_loop_window_target.crtc.handle()) + }) + .unwrap_or(false) + }) + .partition(|&&plane| { + if let Ok(props) = drm.get_properties(plane) { + let (ids, vals) = props.as_props_and_values(); + for (&id, &val) in ids.iter().zip(vals.iter()) { + if let Ok(info) = drm.get_property(id) { + if info.name().to_str().map(|x| x == "type").unwrap_or(false) { + return val == (drm::control::PlaneType::Primary as u32).into(); + } + } + } + } + false + }); + + let p_plane = *better_planes.get(0).unwrap_or(&compatible_planes[0]); + let mut atomic_req = atomic::AtomicModeReq::new(); atomic_req.add_property( event_loop_window_target.connector.handle(), @@ -97,6 +192,56 @@ impl Window { )?, property::Value::Boolean(true), ); + atomic_req.add_property( + plane, + find_prop_id(&drm, plane, "FB_ID").expect("Could not get FB_ID"), + property::Value::Framebuffer(Some(fb)), + ); + atomic_req.add_property( + plane, + find_prop_id(&drm, plane, "CRTC_ID").expect("Could not get CRTC_ID"), + property::Value::CRTC(Some(event_loop_window_target.crtc.handle())), + ); + atomic_req.add_property( + plane, + find_prop_id(&drm, plane, "SRC_X").expect("Could not get SRC_X"), + property::Value::UnsignedRange(0), + ); + atomic_req.add_property( + plane, + find_prop_id(&drm, plane, "SRC_Y").expect("Could not get SRC_Y"), + property::Value::UnsignedRange(0), + ); + atomic_req.add_property( + plane, + find_prop_id(&drm, plane, "SRC_W").expect("Could not get SRC_W"), + property::Value::UnsignedRange(64 << 16), + ); + atomic_req.add_property( + plane, + find_prop_id(&drm, plane, "SRC_H").expect("Could not get SRC_H"), + property::Value::UnsignedRange(64 << 16), + ); + atomic_req.add_property( + plane, + find_prop_id(&drm, plane, "CRTC_X").expect("Could not get CRTC_X"), + property::Value::SignedRange(0), + ); + atomic_req.add_property( + plane, + find_prop_id(&drm, plane, "CRTC_Y").expect("Could not get CRTC_Y"), + property::Value::SignedRange(0), + ); + atomic_req.add_property( + plane, + find_prop_id(&drm, plane, "CRTC_W").expect("Could not get CRTC_W"), + property::Value::UnsignedRange(mode.size().0 as u64), + ); + atomic_req.add_property( + plane, + find_prop_id(&drm, plane, "CRTC_H").expect("Could not get CRTC_H"), + property::Value::UnsignedRange(mode.size().1 as u64), + ); drm.atomic_commit(AtomicCommitFlags::ALLOW_MODESET, atomic_req) .map_err(|_| { @@ -112,6 +257,8 @@ impl Window { event_loop_window_target.connector.clone(), event_loop_window_target.event_loop_awakener.clone(), drm, + db, + plane, )) } #[inline] @@ -123,11 +270,7 @@ impl Window { pub fn set_title(&self, _title: &str) {} #[inline] - pub fn set_visible(&self, visible: bool) { - if !visible { - eprintln!("It is not possible to make a window not visible in kmsdrm mode"); - } - } + pub fn set_visible(&self, _visible: bool) {} #[inline] pub fn is_visible(&self) -> Option { @@ -145,9 +288,7 @@ impl Window { } #[inline] - pub fn set_outer_position(&self, _position: Position) { - eprintln!("The window cannot be moved in kmsdrm mode"); - } + pub fn set_outer_position(&self, _position: Position) {} #[inline] pub fn inner_size(&self) -> PhysicalSize { @@ -164,25 +305,16 @@ impl Window { pub fn set_inner_size(&self, _size: Size) { // It's technically possible to do this by changing video modes but that seems a little // restrictive - eprintln!("The window cannot be resized in kmsdrm mode"); } #[inline] - pub fn set_min_inner_size(&self, _dimensions: Option) { - eprintln!("The window cannot be resized in kmsdrm mode"); - } + pub fn set_min_inner_size(&self, _dimensions: Option) {} #[inline] - pub fn set_max_inner_size(&self, _dimensions: Option) { - // It's technically possible to do this by changing video modes but that seems a little - // restrictive - eprintln!("The window cannot be resized in kmsdrm mode"); - } + pub fn set_max_inner_size(&self, _dimensions: Option) {} #[inline] - pub fn set_resizable(&self, _resizable: bool) { - eprintln!("The window cannot be resized in kmsdrm mode"); - } + pub fn set_resizable(&self, _resizable: bool) {} #[inline] pub fn is_resizable(&self) -> bool { @@ -190,25 +322,19 @@ impl Window { } #[inline] - pub fn set_cursor_icon(&self, _cursor: CursorIcon) { - unimplemented!() - } + pub fn set_cursor_icon(&self, _cursor: CursorIcon) {} #[inline] pub fn set_cursor_grab(&self, _grab: bool) -> Result<(), ExternalError> { - eprintln!("The cursor is always grabbed in kmsdrm mode"); - Ok(()) + Err(ExternalError::NotSupported(NotSupportedError::new())) } #[inline] - pub fn set_cursor_visible(&self, _visible: bool) { - unimplemented!() - } + pub fn set_cursor_visible(&self, _visible: bool) {} #[inline] pub fn drag_window(&self) -> Result<(), ExternalError> { - eprintln!("The window cannot be dragged in kmsdrm mode"); - Ok(()) + Err(ExternalError::NotSupported(NotSupportedError::new())) } #[inline] @@ -227,9 +353,7 @@ impl Window { } #[inline] - pub fn set_maximized(&self, _maximized: bool) { - eprintln!("The window is always maximized in kmsdrm mode"); - } + pub fn set_maximized(&self, _maximized: bool) {} #[inline] pub fn is_maximized(&self) -> bool { @@ -237,10 +361,7 @@ impl Window { } #[inline] - pub fn set_minimized(&self, _minimized: bool) { - // By switching the crtc to the tty you can technically hide the "window". - eprintln!("The window cannot be minimized in kmsdrm mode"); - } + pub fn set_minimized(&self, _minimized: bool) {} #[inline] pub fn fullscreen(&self) -> Option { @@ -253,23 +374,17 @@ impl Window { } #[inline] - pub fn set_fullscreen(&self, _monitor: Option) { - eprintln!("The window is always in fullscreen in kmsdrm mode"); - } + pub fn set_fullscreen(&self, _monitor: Option) {} #[inline] - pub fn set_decorations(&self, _decorations: bool) { - eprintln!("The window cannot be decorated in kmsdrm mode"); - } + pub fn set_decorations(&self, _decorations: bool) {} pub fn is_decorated(&self) -> bool { false } #[inline] - pub fn set_ime_position(&self, _position: Position) { - eprintln!("The window cannot be moved in kmsdrm mode"); - } + pub fn set_ime_position(&self, _position: Position) {} #[inline] pub fn request_redraw(&self) { @@ -299,6 +414,11 @@ impl Window { rwh } + #[inline] + pub fn drm_plane(&self) -> drm::control::plane::Handle { + self.5 + } + #[inline] pub fn primary_monitor(&self) -> Option { Some(crate::monitor::MonitorHandle { From 85b2deec94e778a7133dba9b2212cd0ff16c2f9a Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 3 May 2022 19:02:02 -0400 Subject: [PATCH 031/151] Expose primary plane --- src/platform/unix.rs | 32 ++--- src/platform_impl/linux/drm/event_loop.rs | 98 +++++++++++++- src/platform_impl/linux/drm/window.rs | 154 +++++----------------- 3 files changed, 143 insertions(+), 141 deletions(-) diff --git a/src/platform/unix.rs b/src/platform/unix.rs index 79548e9d6b..708165cb03 100644 --- a/src/platform/unix.rs +++ b/src/platform/unix.rs @@ -121,6 +121,12 @@ pub trait EventLoopWindowTargetExtUnix { /// Returns `None` if the `EventLoop` doesn't use kmsdrm (if it uses wayland for example). #[cfg(feature = "kmsdrm")] fn drm_mode(&self) -> Option; + + /// Returns the primary plane of the drm device + /// + /// Returns `None` if the `EventLoop` doesn't use kmsdrm (if it uses wayland for example). + #[cfg(feature = "kmsdrm")] + fn drm_plane(&self) -> Option; } impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { @@ -209,6 +215,16 @@ impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { _ => None, } } + + #[inline] + #[cfg(feature = "kmsdrm")] + fn drm_plane(&self) -> Option { + match self.p { + crate::platform_impl::EventLoopWindowTarget::Drm(ref window) => Some(window.plane), + #[cfg(any(feature = "x11", feature = "wayland"))] + _ => None, + } + } } /// Additional methods on [`EventLoopBuilder`] that are specific to Unix. @@ -316,12 +332,6 @@ pub trait WindowExtUnix { /// Always return true. #[deprecated] fn is_ready(&self) -> bool; - - /// Return a handle to the `drm::control::plane::Handle` the is used by the window - /// - /// Returns `None` if the window doesn't use kmsdrm (if it uses xlib for example). - #[cfg(feature = "kmsdrm")] - fn drm_plane(&self) -> Option; } impl WindowExtUnix for Window { @@ -396,16 +406,6 @@ impl WindowExtUnix for Window { } } - #[inline] - #[cfg(feature = "kmsdrm")] - fn drm_plane(&self) -> Option { - match self.window { - LinuxWindow::Drm(ref w) => Some(w.drm_plane()), - #[cfg(any(feature = "x11", feature = "wayland"))] - _ => None, - } - } - #[inline] fn is_ready(&self) -> bool { true diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index b203e20f86..c35fafde9b 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -58,12 +58,19 @@ pub struct LibinputInputBackend { screen_size: (u32, u32), modifiers: ModifiersState, cursor_positon: PhysicalPosition, + cursor_plane: drm::control::plane::Handle, + cursor_buffer: drm::control::framebuffer::Handle, } impl LibinputInputBackend { /// Initialize a new [`LibinputInputBackend`] from a given already initialized /// [libinput context](libinput::Libinput). - pub fn new(context: input::Libinput, screen_size: (u32, u32)) -> Self { + pub fn new( + context: input::Libinput, + screen_size: (u32, u32), + cursor_plane: drm::control::plane::Handle, + cursor_buffer: drm::control::framebuffer::Handle, + ) -> Self { LibinputInputBackend { context, token: Token::invalid(), @@ -71,6 +78,8 @@ impl LibinputInputBackend { cursor_positon: PhysicalPosition::new(0.0, 0.0), modifiers: ModifiersState::empty(), screen_size, + cursor_buffer, + cursor_plane, } } } @@ -578,6 +587,12 @@ pub struct EventLoopWindowTarget { /// drm mode pub mode: drm::control::Mode, + /// drm plane + pub plane: drm::control::plane::Handle, + + /// drm dumbbuffer containing the cursor + pub cursor_buffer: drm::control::framebuffer::Handle, + /// drm device pub device: Card, @@ -717,6 +732,83 @@ impl EventLoop { crate::platform_impl::OsError::DrmMisc("No modes found on connector"), ))?; + let mut db = drm + .create_dumb_buffer((64, 64), drm::buffer::DrmFourcc::Xrgb8888, 32) + .or(Err(crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Could not create dumb buffer"), + )))?; + + { + let mut map = drm + .map_dumb_buffer(&mut db) + .expect("Could not map dumbbuffer"); + for b in map.as_mut() { + *b = 128; + } + } + + let fb = drm + .add_framebuffer(&db, 24, 32) + .or(Err(crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Could not create FB"), + )))?; + + let planes = drm.plane_handles().or(Err(crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Could not list planes"), + )))?; + let (better_planes, compatible_planes): ( + Vec, + Vec, + ) = planes + .planes() + .iter() + .filter(|&&plane| { + drm.get_plane(plane) + .map(|plane_info| { + let compatible_crtcs = res.filter_crtcs(plane_info.possible_crtcs()); + compatible_crtcs.contains(&crtc.handle()) + }) + .unwrap_or(false) + }) + .partition(|&&plane| { + if let Ok(props) = drm.get_properties(plane) { + let (ids, vals) = props.as_props_and_values(); + for (&id, &val) in ids.iter().zip(vals.iter()) { + if let Ok(info) = drm.get_property(id) { + if info.name().to_str().map(|x| x == "type").unwrap_or(false) { + return val == (drm::control::PlaneType::Cursor as u32).into(); + } + } + } + } + false + }); + let plane = *better_planes.get(0).unwrap_or(&compatible_planes[0]); + let (p_better_planes, p_compatible_planes): ( + Vec, + Vec, + ) = compatible_planes.iter().partition(|&&plane| { + if let Ok(props) = drm.get_properties(plane) { + let (ids, vals) = props.as_props_and_values(); + for (&id, &val) in ids.iter().zip(vals.iter()) { + if let Ok(info) = drm.get_property(id) { + if info.name().to_str().map(|x| x == "type").unwrap_or(false) { + return val == (drm::control::PlaneType::Primary as u32).into(); + } + } + } + } + false + }); + + let p_plane = *p_better_planes.get(0).unwrap_or(&p_compatible_planes[0]); + let (disp_width, disp_height) = mode.size(); let mut input = input::Libinput::new_with_udev(Interface( @@ -769,7 +861,7 @@ impl EventLoop { .unwrap(); let input_backend: LibinputInputBackend = - LibinputInputBackend::new(input, (disp_width.into(), disp_height.into())); + LibinputInputBackend::new(input, (disp_width.into(), disp_height.into()), plane, fb); let input_loop: calloop::Dispatcher<'static, LibinputInputBackend, EventSink> = calloop::Dispatcher::new( @@ -786,6 +878,8 @@ impl EventLoop { connector: con.clone(), crtc: crtc.clone(), device: drm, + plane: p_plane, + cursor_buffer: fb, mode, event_loop_handle: handle, event_sink, diff --git a/src/platform_impl/linux/drm/window.rs b/src/platform_impl/linux/drm/window.rs index ebc1fac468..f212d4358a 100644 --- a/src/platform_impl/linux/drm/window.rs +++ b/src/platform_impl/linux/drm/window.rs @@ -17,8 +17,6 @@ pub struct Window( drm::control::connector::Info, calloop::ping::Ping, Card, - drm::control::dumbbuffer::DumbBuffer, - drm::control::plane::Handle, ); impl Window { @@ -52,99 +50,6 @@ impl Window { ) })?; - let res = drm.resource_handles().or(Err(crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc("Could not load normal resource ids."), - )))?; - - let mut db = drm - .create_dumb_buffer((64, 64), drm::buffer::DrmFourcc::Xrgb8888, 32) - .or(Err(crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc("Could not create dumb buffer"), - )))?; - - { - let mut map = drm - .map_dumb_buffer(&mut db) - .expect("Could not map dumbbuffer"); - for b in map.as_mut() { - *b = 128; - } - } - - let fb = drm - .add_framebuffer(&db, 24, 32) - .or(Err(crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc("Could not create FB"), - )))?; - - let planes = drm.plane_handles().or(Err(crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc("Could not list planes"), - )))?; - let (better_planes, compatible_planes): ( - Vec, - Vec, - ) = planes - .planes() - .iter() - .filter(|&&plane| { - drm.get_plane(plane) - .map(|plane_info| { - let compatible_crtcs = res.filter_crtcs(plane_info.possible_crtcs()); - compatible_crtcs.contains(&event_loop_window_target.crtc.handle()) - }) - .unwrap_or(false) - }) - .partition(|&&plane| { - if let Ok(props) = drm.get_properties(plane) { - let (ids, vals) = props.as_props_and_values(); - for (&id, &val) in ids.iter().zip(vals.iter()) { - if let Ok(info) = drm.get_property(id) { - if info.name().to_str().map(|x| x == "type").unwrap_or(false) { - return val == (drm::control::PlaneType::Cursor as u32).into(); - } - } - } - } - false - }); - let plane = *better_planes.get(0).unwrap_or(&compatible_planes[0]); - let (p_better_planes, p_compatible_planes): ( - Vec, - Vec, - ) = compatible_planes - .iter() - .filter(|&&plane| { - drm.get_plane(plane) - .map(|plane_info| { - let compatible_crtcs = res.filter_crtcs(plane_info.possible_crtcs()); - compatible_crtcs.contains(&event_loop_window_target.crtc.handle()) - }) - .unwrap_or(false) - }) - .partition(|&&plane| { - if let Ok(props) = drm.get_properties(plane) { - let (ids, vals) = props.as_props_and_values(); - for (&id, &val) in ids.iter().zip(vals.iter()) { - if let Ok(info) = drm.get_property(id) { - if info.name().to_str().map(|x| x == "type").unwrap_or(false) { - return val == (drm::control::PlaneType::Primary as u32).into(); - } - } - } - } - false - }); - - let p_plane = *better_planes.get(0).unwrap_or(&compatible_planes[0]); - let mut atomic_req = atomic::AtomicModeReq::new(); atomic_req.add_property( event_loop_window_target.connector.handle(), @@ -193,53 +98,63 @@ impl Window { property::Value::Boolean(true), ); atomic_req.add_property( - plane, - find_prop_id(&drm, plane, "FB_ID").expect("Could not get FB_ID"), - property::Value::Framebuffer(Some(fb)), + event_loop_window_target.plane, + find_prop_id(&drm, event_loop_window_target.plane, "FB_ID") + .expect("Could not get FB_ID"), + property::Value::Framebuffer(Some(event_loop_window_target.cursor_buffer)), ); atomic_req.add_property( - plane, - find_prop_id(&drm, plane, "CRTC_ID").expect("Could not get CRTC_ID"), + event_loop_window_target.plane, + find_prop_id(&drm, event_loop_window_target.plane, "CRTC_ID") + .expect("Could not get CRTC_ID"), property::Value::CRTC(Some(event_loop_window_target.crtc.handle())), ); atomic_req.add_property( - plane, - find_prop_id(&drm, plane, "SRC_X").expect("Could not get SRC_X"), + event_loop_window_target.plane, + find_prop_id(&drm, event_loop_window_target.plane, "SRC_X") + .expect("Could not get SRC_X"), property::Value::UnsignedRange(0), ); atomic_req.add_property( - plane, - find_prop_id(&drm, plane, "SRC_Y").expect("Could not get SRC_Y"), + event_loop_window_target.plane, + find_prop_id(&drm, event_loop_window_target.plane, "SRC_Y") + .expect("Could not get SRC_Y"), property::Value::UnsignedRange(0), ); atomic_req.add_property( - plane, - find_prop_id(&drm, plane, "SRC_W").expect("Could not get SRC_W"), + event_loop_window_target.plane, + find_prop_id(&drm, event_loop_window_target.plane, "SRC_W") + .expect("Could not get SRC_W"), property::Value::UnsignedRange(64 << 16), ); atomic_req.add_property( - plane, - find_prop_id(&drm, plane, "SRC_H").expect("Could not get SRC_H"), + event_loop_window_target.plane, + find_prop_id(&drm, event_loop_window_target.plane, "SRC_H") + .expect("Could not get SRC_H"), property::Value::UnsignedRange(64 << 16), ); atomic_req.add_property( - plane, - find_prop_id(&drm, plane, "CRTC_X").expect("Could not get CRTC_X"), + event_loop_window_target.plane, + find_prop_id(&drm, event_loop_window_target.plane, "CRTC_X") + .expect("Could not get CRTC_X"), property::Value::SignedRange(0), ); atomic_req.add_property( - plane, - find_prop_id(&drm, plane, "CRTC_Y").expect("Could not get CRTC_Y"), + event_loop_window_target.plane, + find_prop_id(&drm, event_loop_window_target.plane, "CRTC_Y") + .expect("Could not get CRTC_Y"), property::Value::SignedRange(0), ); atomic_req.add_property( - plane, - find_prop_id(&drm, plane, "CRTC_W").expect("Could not get CRTC_W"), + event_loop_window_target.plane, + find_prop_id(&drm, event_loop_window_target.plane, "CRTC_W") + .expect("Could not get CRTC_W"), property::Value::UnsignedRange(mode.size().0 as u64), ); atomic_req.add_property( - plane, - find_prop_id(&drm, plane, "CRTC_H").expect("Could not get CRTC_H"), + event_loop_window_target.plane, + find_prop_id(&drm, event_loop_window_target.plane, "CRTC_H") + .expect("Could not get CRTC_H"), property::Value::UnsignedRange(mode.size().1 as u64), ); @@ -257,8 +172,6 @@ impl Window { event_loop_window_target.connector.clone(), event_loop_window_target.event_loop_awakener.clone(), drm, - db, - plane, )) } #[inline] @@ -414,11 +327,6 @@ impl Window { rwh } - #[inline] - pub fn drm_plane(&self) -> drm::control::plane::Handle { - self.5 - } - #[inline] pub fn primary_monitor(&self) -> Option { Some(crate::monitor::MonitorHandle { From f7185cc3d137f027c15a4f03267d102904aed046 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 3 May 2022 19:19:01 -0400 Subject: [PATCH 032/151] Attempt to fix modesetting --- src/platform_impl/linux/drm/window.rs | 35 +++++++++------------------ 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/src/platform_impl/linux/drm/window.rs b/src/platform_impl/linux/drm/window.rs index f212d4358a..88ca1366ce 100644 --- a/src/platform_impl/linux/drm/window.rs +++ b/src/platform_impl/linux/drm/window.rs @@ -36,19 +36,6 @@ impl Window { ) })? .clone(); - let &mode = event_loop_window_target - .connector - .modes() - .iter() - .find(|&&f| f.mode_type().contains(ModeTypeFlags::PREFERRED)) - .or(event_loop_window_target.connector.modes().get(0)) - .ok_or_else(|| { - crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc("No modes found on connector"), - ) - })?; let mut atomic_req = atomic::AtomicModeReq::new(); atomic_req.add_property( @@ -64,13 +51,15 @@ impl Window { )?, property::Value::CRTC(Some(event_loop_window_target.crtc.handle())), ); - let blob = drm.create_property_blob(&mode).map_err(|_| { - crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc("Failed to create blob"), - ) - })?; + let blob = drm + .create_property_blob(&event_loop_window_target.mode) + .map_err(|_| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Failed to create blob"), + ) + })?; atomic_req.add_property( event_loop_window_target.crtc.handle(), find_prop_id(&drm, event_loop_window_target.crtc.handle(), "MODE_ID").ok_or_else( @@ -149,13 +138,13 @@ impl Window { event_loop_window_target.plane, find_prop_id(&drm, event_loop_window_target.plane, "CRTC_W") .expect("Could not get CRTC_W"), - property::Value::UnsignedRange(mode.size().0 as u64), + property::Value::UnsignedRange(event_loop_window_target.mode.size().0 as u64), ); atomic_req.add_property( event_loop_window_target.plane, find_prop_id(&drm, event_loop_window_target.plane, "CRTC_H") .expect("Could not get CRTC_H"), - property::Value::UnsignedRange(mode.size().1 as u64), + property::Value::UnsignedRange(event_loop_window_target.mode.size().1 as u64), ); drm.atomic_commit(AtomicCommitFlags::ALLOW_MODESET, atomic_req) @@ -168,7 +157,7 @@ impl Window { })?; Ok(Self( - mode, + event_loop_window_target.mode.clone(), event_loop_window_target.connector.clone(), event_loop_window_target.event_loop_awakener.clone(), drm, From 465b9df8063a184299eee51755bf7169f6ef30e0 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 3 May 2022 19:26:43 -0400 Subject: [PATCH 033/151] Attempt to fix modesetting --- src/platform_impl/linux/drm/event_loop.rs | 42 +++++++++++++---------- src/platform_impl/linux/drm/window.rs | 8 +---- 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index c35fafde9b..275d2a682e 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -58,8 +58,8 @@ pub struct LibinputInputBackend { screen_size: (u32, u32), modifiers: ModifiersState, cursor_positon: PhysicalPosition, - cursor_plane: drm::control::plane::Handle, - cursor_buffer: drm::control::framebuffer::Handle, + // cursor_plane: drm::control::plane::Handle, + // cursor_buffer: drm::control::framebuffer::Handle, } impl LibinputInputBackend { @@ -68,8 +68,8 @@ impl LibinputInputBackend { pub fn new( context: input::Libinput, screen_size: (u32, u32), - cursor_plane: drm::control::plane::Handle, - cursor_buffer: drm::control::framebuffer::Handle, + // cursor_plane: drm::control::plane::Handle, + // cursor_buffer: drm::control::framebuffer::Handle, ) -> Self { LibinputInputBackend { context, @@ -78,8 +78,8 @@ impl LibinputInputBackend { cursor_positon: PhysicalPosition::new(0.0, 0.0), modifiers: ModifiersState::empty(), screen_size, - cursor_buffer, - cursor_plane, + // cursor_buffer, + // cursor_plane, } } } @@ -590,9 +590,8 @@ pub struct EventLoopWindowTarget { /// drm plane pub plane: drm::control::plane::Handle, - /// drm dumbbuffer containing the cursor - pub cursor_buffer: drm::control::framebuffer::Handle, - + // /// drm dumbbuffer containing the cursor + // pub cursor_buffer: drm::control::framebuffer::Handle, /// drm device pub device: Card, @@ -732,6 +731,13 @@ impl EventLoop { crate::platform_impl::OsError::DrmMisc("No modes found on connector"), ))?; + let planes = drm.plane_handles().or(Err(crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Could not list planes"), + )))?; + + /* let mut db = drm .create_dumb_buffer((64, 64), drm::buffer::DrmFourcc::Xrgb8888, 32) .or(Err(crate::error::OsError::new( @@ -757,12 +763,7 @@ impl EventLoop { crate::platform_impl::OsError::DrmMisc("Could not create FB"), )))?; - let planes = drm.plane_handles().or(Err(crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc("Could not list planes"), - )))?; - let (better_planes, compatible_planes): ( + let (better_planes, compatible_planes): ( Vec, Vec, ) = planes @@ -790,10 +791,11 @@ impl EventLoop { false }); let plane = *better_planes.get(0).unwrap_or(&compatible_planes[0]); + */ let (p_better_planes, p_compatible_planes): ( Vec, Vec, - ) = compatible_planes.iter().partition(|&&plane| { + ) = planes.planes().iter().partition(|&&plane| { if let Ok(props) = drm.get_properties(plane) { let (ids, vals) = props.as_props_and_values(); for (&id, &val) in ids.iter().zip(vals.iter()) { @@ -860,8 +862,10 @@ impl EventLoop { ) .unwrap(); - let input_backend: LibinputInputBackend = - LibinputInputBackend::new(input, (disp_width.into(), disp_height.into()), plane, fb); + let input_backend: LibinputInputBackend = LibinputInputBackend::new( + input, + (disp_width.into(), disp_height.into()), // plane, fb + ); let input_loop: calloop::Dispatcher<'static, LibinputInputBackend, EventSink> = calloop::Dispatcher::new( @@ -879,7 +883,7 @@ impl EventLoop { crtc: crtc.clone(), device: drm, plane: p_plane, - cursor_buffer: fb, + // cursor_buffer: fb, mode, event_loop_handle: handle, event_sink, diff --git a/src/platform_impl/linux/drm/window.rs b/src/platform_impl/linux/drm/window.rs index 88ca1366ce..d3fee1b478 100644 --- a/src/platform_impl/linux/drm/window.rs +++ b/src/platform_impl/linux/drm/window.rs @@ -1,6 +1,6 @@ use std::{collections::VecDeque, os::unix::prelude::AsRawFd}; -use drm::control::{atomic, property, AtomicCommitFlags, Device, ModeTypeFlags}; +use drm::control::{atomic, property, AtomicCommitFlags, Device}; use crate::{ dpi::{PhysicalPosition, PhysicalSize, Position, Size}, @@ -86,12 +86,6 @@ impl Window { )?, property::Value::Boolean(true), ); - atomic_req.add_property( - event_loop_window_target.plane, - find_prop_id(&drm, event_loop_window_target.plane, "FB_ID") - .expect("Could not get FB_ID"), - property::Value::Framebuffer(Some(event_loop_window_target.cursor_buffer)), - ); atomic_req.add_property( event_loop_window_target.plane, find_prop_id(&drm, event_loop_window_target.plane, "CRTC_ID") From d851d91d378f636c386d9c4ebdcd5a4b4ec193ec Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 3 May 2022 19:32:17 -0400 Subject: [PATCH 034/151] Attempt to fix modesetting --- src/platform_impl/linux/drm/window.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/platform_impl/linux/drm/window.rs b/src/platform_impl/linux/drm/window.rs index d3fee1b478..1a0d5b5e6f 100644 --- a/src/platform_impl/linux/drm/window.rs +++ b/src/platform_impl/linux/drm/window.rs @@ -86,6 +86,12 @@ impl Window { )?, property::Value::Boolean(true), ); + atomic_req.add_property( + event_loop_window_target.plane, + find_prop_id(&drm, event_loop_window_target.plane, "FB_ID") + .expect("Could not get FB_ID"), + property::Value::Framebuffer(None), + ); atomic_req.add_property( event_loop_window_target.plane, find_prop_id(&drm, event_loop_window_target.plane, "CRTC_ID") From fa697f9cf49c8a5a523da65b1630ce67134731c4 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 3 May 2022 19:38:30 -0400 Subject: [PATCH 035/151] Attempt to fix modesetting --- src/platform_impl/linux/drm/window.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/platform_impl/linux/drm/window.rs b/src/platform_impl/linux/drm/window.rs index 1a0d5b5e6f..d3fee1b478 100644 --- a/src/platform_impl/linux/drm/window.rs +++ b/src/platform_impl/linux/drm/window.rs @@ -86,12 +86,6 @@ impl Window { )?, property::Value::Boolean(true), ); - atomic_req.add_property( - event_loop_window_target.plane, - find_prop_id(&drm, event_loop_window_target.plane, "FB_ID") - .expect("Could not get FB_ID"), - property::Value::Framebuffer(None), - ); atomic_req.add_property( event_loop_window_target.plane, find_prop_id(&drm, event_loop_window_target.plane, "CRTC_ID") From ec97e9aa34c937e3af9e321f7a61d4cae8233b5d Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 3 May 2022 19:43:07 -0400 Subject: [PATCH 036/151] Attempt to fix modesetting --- src/platform_impl/linux/drm/window.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/platform_impl/linux/drm/window.rs b/src/platform_impl/linux/drm/window.rs index d3fee1b478..8d3712203a 100644 --- a/src/platform_impl/linux/drm/window.rs +++ b/src/platform_impl/linux/drm/window.rs @@ -108,13 +108,13 @@ impl Window { event_loop_window_target.plane, find_prop_id(&drm, event_loop_window_target.plane, "SRC_W") .expect("Could not get SRC_W"), - property::Value::UnsignedRange(64 << 16), + property::Value::UnsignedRange((event_loop_window_target.mode.size().0 as u64) << 16), ); atomic_req.add_property( event_loop_window_target.plane, find_prop_id(&drm, event_loop_window_target.plane, "SRC_H") .expect("Could not get SRC_H"), - property::Value::UnsignedRange(64 << 16), + property::Value::UnsignedRange((event_loop_window_target.mode.size().1 as u64) << 16), ); atomic_req.add_property( event_loop_window_target.plane, From 792fe86f49f357668f9b2bc42ad5e57d629bc90d Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 3 May 2022 19:50:00 -0400 Subject: [PATCH 037/151] Attempt to fix modesetting --- src/platform_impl/linux/drm/event_loop.rs | 44 ++++++++++++++--------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index 275d2a682e..cc05d41acf 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -707,13 +707,6 @@ impl EventLoop { .iter() .flat_map(|crtc| drm.get_crtc(*crtc)) .collect(); - - let crtc = crtcinfo.get(0).ok_or(crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc("No crtcs found"), - ))?; - // Filter each connector until we find one that's connected. let con = coninfo .iter() @@ -724,6 +717,12 @@ impl EventLoop { crate::platform_impl::OsError::DrmMisc("No connected connectors"), ))?; + let crtc = crtcinfo.get(0).ok_or(crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("No crtcs found"), + ))?; + // Get the first (usually best) mode let &mode = con.modes().get(0).ok_or(crate::error::OsError::new( line!(), @@ -795,19 +794,30 @@ impl EventLoop { let (p_better_planes, p_compatible_planes): ( Vec, Vec, - ) = planes.planes().iter().partition(|&&plane| { - if let Ok(props) = drm.get_properties(plane) { - let (ids, vals) = props.as_props_and_values(); - for (&id, &val) in ids.iter().zip(vals.iter()) { - if let Ok(info) = drm.get_property(id) { - if info.name().to_str().map(|x| x == "type").unwrap_or(false) { - return val == (drm::control::PlaneType::Primary as u32).into(); + ) = planes + .planes() + .iter() + .filter(|&&plane| { + drm.get_plane(plane) + .map(|plane_info| { + let compatible_crtcs = res.filter_crtcs(plane_info.possible_crtcs()); + compatible_crtcs.contains(&crtc.handle()) + }) + .unwrap_or(false) + }) + .partition(|&&plane| { + if let Ok(props) = drm.get_properties(plane) { + let (ids, vals) = props.as_props_and_values(); + for (&id, &val) in ids.iter().zip(vals.iter()) { + if let Ok(info) = drm.get_property(id) { + if info.name().to_str().map(|x| x == "type").unwrap_or(false) { + return val == (drm::control::PlaneType::Primary as u32).into(); + } } } } - } - false - }); + false + }); let p_plane = *p_better_planes.get(0).unwrap_or(&p_compatible_planes[0]); From 0840f02783377d26caf975c19311453e8d376a94 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 3 May 2022 20:57:29 -0400 Subject: [PATCH 038/151] Open drm through seat manager --- src/platform/unix.rs | 41 ++---- src/platform_impl/linux/drm/event_loop.rs | 54 +++++--- src/platform_impl/linux/drm/window.rs | 155 +++++++++++++--------- src/platform_impl/linux/mod.rs | 9 -- 4 files changed, 144 insertions(+), 115 deletions(-) diff --git a/src/platform/unix.rs b/src/platform/unix.rs index 708165cb03..20a2a753f3 100644 --- a/src/platform/unix.rs +++ b/src/platform/unix.rs @@ -6,7 +6,7 @@ target_os = "openbsd" ))] -use std::os::raw; +use std::os::{raw, unix::prelude::FromRawFd}; #[cfg(feature = "x11")] use std::{ptr, sync::Arc}; @@ -38,14 +38,21 @@ pub use crate::platform_impl::{x11::util::WindowType as XWindowType, XNotSupport #[cfg(feature = "kmsdrm")] #[derive(Debug, Clone)] /// A simple wrapper for a device node. -pub struct Card(Arc); +pub struct Card(pub(crate) Arc); #[cfg(feature = "kmsdrm")] /// Implementing `AsRawFd` is a prerequisite to implementing the traits found /// in this crate. Here, we are just calling `as_raw_fd()` on the inner File. impl std::os::unix::io::AsRawFd for Card { fn as_raw_fd(&self) -> std::os::unix::io::RawFd { - self.0.as_raw_fd() + *self.0 + } +} + +#[cfg(feature = "kmsdrm")] +impl Drop for Card { + fn drop(&mut self) { + unsafe { std::fs::File::from_raw_fd(*self.0) }; } } @@ -55,21 +62,6 @@ impl Device for Card {} #[cfg(feature = "kmsdrm")] impl ControlDevice for Card {} -#[cfg(feature = "kmsdrm")] -/// Simple helper methods for opening a `Card`. -impl Card { - pub fn open(path: &str) -> Result { - let mut options = std::fs::OpenOptions::new(); - options.read(true); - options.write(true); - Ok(Card(Arc::new(options.open(path)?))) - } - - pub fn open_global() -> Result { - Self::open("/dev/dri/card0") - } -} - /// Additional methods on `EventLoopWindowTarget` that are specific to Unix. pub trait EventLoopWindowTargetExtUnix { /// True if the `EventLoopWindowTarget` uses Wayland. @@ -100,9 +92,7 @@ pub trait EventLoopWindowTargetExtUnix { /// /// Returns `None` if the `EventLoop` doesn't use kmsdrm (if it uses wayland for example). #[cfg(feature = "kmsdrm")] - fn drm_device( - &self, - ) -> Option<&'static parking_lot::Mutex>>; + fn drm_device(&self) -> Option<&crate::platform::unix::Card>; /// Returns the current crtc of the drm device /// @@ -173,14 +163,9 @@ impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { #[inline] #[cfg(feature = "kmsdrm")] - fn drm_device( - &self, - ) -> Option<&'static parking_lot::Mutex>> - { - use crate::platform_impl::DRM_DEVICE; - + fn drm_device(&self) -> Option<&crate::platform::unix::Card> { match self.p { - crate::platform_impl::EventLoopWindowTarget::Drm(_) => Some(&*DRM_DEVICE), + crate::platform_impl::EventLoopWindowTarget::Drm(ref evlp) => Some(&evlp.device), #[cfg(any(feature = "x11", feature = "wayland"))] _ => None, } diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index cc05d41acf..a4a4c3533f 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -19,13 +19,14 @@ use input::{ LibinputInterface, }; use instant::{Duration, Instant}; +use parking_lot::{Condvar, Mutex}; use crate::{ dpi::PhysicalPosition, event::{Force, KeyboardInput, ModifiersState, MouseScrollDelta, StartCause}, event_loop::{ControlFlow, EventLoopClosed}, platform::unix::Card, - platform_impl::{platform::sticky_exit_callback, DRM_DEVICE}, + platform_impl::platform::sticky_exit_callback, }; use super::input_to_vk::CHAR_MAPPINGS; @@ -661,17 +662,45 @@ pub(crate) fn find_prop_id( impl EventLoop { pub fn new() -> Result, crate::error::OsError> { - let drm = DRM_DEVICE - .lock() - .as_ref() + let mut seat = { + let seat_active = std::sync::Arc::new((Mutex::new(false), Condvar::new())); + let callback_seat_active = std::sync::Arc::clone(&seat_active); + let s = libseat::Seat::open( + move |_, event| { + let (lock, cvar) = &*callback_seat_active; + let mut started = lock.lock(); + if let libseat::SeatEvent::Enable = event { + *started = true; + cvar.notify_one(); + } + }, + None, + ) .map_err(|_| { crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::DrmMisc("KMS/DRM is not initialized"), + crate::platform_impl::OsError::DrmMisc("Failed to open libseat"), ) - })? - .clone(); + })?; + let (lock, cvar) = &*seat_active; + let mut started = lock.lock(); + while !*started { + cvar.wait(&mut started); + } + s + }; + let dev = seat.open_device(&"/dev/dri/card0").map_err(|_| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Failed to initialize DRM"), + ) + })?; + let drm = Card(std::sync::Arc::new(dev.1)); + let mut input = input::Libinput::new_with_udev(Interface(seat, HashMap::new())); + input.udev_assign_seat("seat0").unwrap(); + drm::Device::set_client_capability(&drm, drm::ClientCapability::UniversalPlanes, true).or( Err(crate::error::OsError::new( line!(), @@ -823,17 +852,6 @@ impl EventLoop { let (disp_width, disp_height) = mode.size(); - let mut input = input::Libinput::new_with_udev(Interface( - libseat::Seat::open(|_, _| {}, None).map_err(|_| { - crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc("Failed to open libseat"), - ) - })?, - HashMap::new(), - )); - input.udev_assign_seat("seat0").unwrap(); let event_loop: calloop::EventLoop<'static, EventSink> = calloop::EventLoop::try_new().unwrap(); diff --git a/src/platform_impl/linux/drm/window.rs b/src/platform_impl/linux/drm/window.rs index 8d3712203a..d648af9026 100644 --- a/src/platform_impl/linux/drm/window.rs +++ b/src/platform_impl/linux/drm/window.rs @@ -6,7 +6,6 @@ use crate::{ dpi::{PhysicalPosition, PhysicalSize, Position, Size}, error::{ExternalError, NotSupportedError}, platform::unix::Card, - platform_impl::DRM_DEVICE, window::{CursorIcon, Fullscreen}, }; @@ -25,33 +24,25 @@ impl Window { _attributes: crate::window::WindowAttributes, _platform_attributes: crate::platform_impl::PlatformSpecificWindowBuilderAttributes, ) -> Result { - let drm = DRM_DEVICE - .lock() - .as_ref() - .map_err(|_| { + let mut atomic_req = atomic::AtomicModeReq::new(); + atomic_req.add_property( + event_loop_window_target.connector.handle(), + find_prop_id( + &event_loop_window_target.device, + event_loop_window_target.connector.handle(), + "CRTC_ID", + ) + .ok_or_else(|| { crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::DrmMisc("GBM is not initialized"), + crate::platform_impl::OsError::DrmMisc("Could not get CRTC_ID"), ) - })? - .clone(); - - let mut atomic_req = atomic::AtomicModeReq::new(); - atomic_req.add_property( - event_loop_window_target.connector.handle(), - find_prop_id(&drm, event_loop_window_target.connector.handle(), "CRTC_ID").ok_or_else( - || { - crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc("Could not get CRTC_ID"), - ) - }, - )?, + })?, property::Value::CRTC(Some(event_loop_window_target.crtc.handle())), ); - let blob = drm + let blob = event_loop_window_target + .device .create_property_blob(&event_loop_window_target.mode) .map_err(|_| { crate::error::OsError::new( @@ -62,86 +53,130 @@ impl Window { })?; atomic_req.add_property( event_loop_window_target.crtc.handle(), - find_prop_id(&drm, event_loop_window_target.crtc.handle(), "MODE_ID").ok_or_else( - || { - crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc("Could not get MODE_ID"), - ) - }, - )?, + find_prop_id( + &event_loop_window_target.device, + event_loop_window_target.crtc.handle(), + "MODE_ID", + ) + .ok_or_else(|| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Could not get MODE_ID"), + ) + })?, blob, ); atomic_req.add_property( event_loop_window_target.crtc.handle(), - find_prop_id(&drm, event_loop_window_target.crtc.handle(), "ACTIVE").ok_or_else( - || { - crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc("Could not get ACTIVE"), - ) - }, - )?, + find_prop_id( + &event_loop_window_target.device, + event_loop_window_target.crtc.handle(), + "ACTIVE", + ) + .ok_or_else(|| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Could not get ACTIVE"), + ) + })?, property::Value::Boolean(true), ); atomic_req.add_property( event_loop_window_target.plane, - find_prop_id(&drm, event_loop_window_target.plane, "CRTC_ID") - .expect("Could not get CRTC_ID"), + find_prop_id( + &event_loop_window_target.device, + event_loop_window_target.plane, + "CRTC_ID", + ) + .expect("Could not get CRTC_ID"), property::Value::CRTC(Some(event_loop_window_target.crtc.handle())), ); atomic_req.add_property( event_loop_window_target.plane, - find_prop_id(&drm, event_loop_window_target.plane, "SRC_X") - .expect("Could not get SRC_X"), + find_prop_id( + &event_loop_window_target.device, + event_loop_window_target.plane, + "SRC_X", + ) + .expect("Could not get SRC_X"), property::Value::UnsignedRange(0), ); atomic_req.add_property( event_loop_window_target.plane, - find_prop_id(&drm, event_loop_window_target.plane, "SRC_Y") - .expect("Could not get SRC_Y"), + find_prop_id( + &event_loop_window_target.device, + event_loop_window_target.plane, + "SRC_Y", + ) + .expect("Could not get SRC_Y"), property::Value::UnsignedRange(0), ); atomic_req.add_property( event_loop_window_target.plane, - find_prop_id(&drm, event_loop_window_target.plane, "SRC_W") - .expect("Could not get SRC_W"), + find_prop_id( + &event_loop_window_target.device, + event_loop_window_target.plane, + "SRC_W", + ) + .expect("Could not get SRC_W"), property::Value::UnsignedRange((event_loop_window_target.mode.size().0 as u64) << 16), ); atomic_req.add_property( event_loop_window_target.plane, - find_prop_id(&drm, event_loop_window_target.plane, "SRC_H") - .expect("Could not get SRC_H"), + find_prop_id( + &event_loop_window_target.device, + event_loop_window_target.plane, + "SRC_H", + ) + .expect("Could not get SRC_H"), property::Value::UnsignedRange((event_loop_window_target.mode.size().1 as u64) << 16), ); atomic_req.add_property( event_loop_window_target.plane, - find_prop_id(&drm, event_loop_window_target.plane, "CRTC_X") - .expect("Could not get CRTC_X"), + find_prop_id( + &event_loop_window_target.device, + event_loop_window_target.plane, + "CRTC_X", + ) + .expect("Could not get CRTC_X"), property::Value::SignedRange(0), ); atomic_req.add_property( event_loop_window_target.plane, - find_prop_id(&drm, event_loop_window_target.plane, "CRTC_Y") - .expect("Could not get CRTC_Y"), + find_prop_id( + &event_loop_window_target.device, + event_loop_window_target.plane, + "CRTC_Y", + ) + .expect("Could not get CRTC_Y"), property::Value::SignedRange(0), ); atomic_req.add_property( event_loop_window_target.plane, - find_prop_id(&drm, event_loop_window_target.plane, "CRTC_W") - .expect("Could not get CRTC_W"), + find_prop_id( + &event_loop_window_target.device, + event_loop_window_target.plane, + "CRTC_W", + ) + .expect("Could not get CRTC_W"), property::Value::UnsignedRange(event_loop_window_target.mode.size().0 as u64), ); atomic_req.add_property( event_loop_window_target.plane, - find_prop_id(&drm, event_loop_window_target.plane, "CRTC_H") - .expect("Could not get CRTC_H"), + find_prop_id( + &event_loop_window_target.device, + event_loop_window_target.plane, + "CRTC_H", + ) + .expect("Could not get CRTC_H"), property::Value::UnsignedRange(event_loop_window_target.mode.size().1 as u64), ); - drm.atomic_commit(AtomicCommitFlags::ALLOW_MODESET, atomic_req) + event_loop_window_target + .device + .atomic_commit(AtomicCommitFlags::ALLOW_MODESET, atomic_req) .map_err(|_| { crate::error::OsError::new( line!(), @@ -154,7 +189,7 @@ impl Window { event_loop_window_target.mode.clone(), event_loop_window_target.connector.clone(), event_loop_window_target.event_loop_awakener.clone(), - drm, + event_loop_window_target.device.clone(), )) } #[inline] diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index 5696246c7f..75a1c14747 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -37,9 +37,6 @@ use crate::{ window::{CursorIcon, Fullscreen, UserAttentionType, WindowAttributes}, }; -#[cfg(feature = "kmsdrm")] -use crate::platform::unix::Card; - pub(crate) use crate::icon::RgbaIcon as PlatformIcon; #[cfg(feature = "kmsdrm")] @@ -142,12 +139,6 @@ lazy_static! { Mutex::new(XConnection::new(Some(x_error_callback)).map(Arc::new)); } -#[cfg(feature = "kmsdrm")] -lazy_static! { - pub static ref DRM_DEVICE: Mutex> = - Mutex::new(Card::open_global()); -} - #[derive(Debug, Clone)] pub enum OsError { #[cfg(feature = "x11")] From faccb7e420167a8a0629b94705bf3f26c531b3c2 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 3 May 2022 21:03:36 -0400 Subject: [PATCH 039/151] Open drm through seat manager --- src/platform_impl/linux/drm/event_loop.rs | 33 +++++------------------ 1 file changed, 6 insertions(+), 27 deletions(-) diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index a4a4c3533f..6d08022220 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -662,34 +662,13 @@ pub(crate) fn find_prop_id( impl EventLoop { pub fn new() -> Result, crate::error::OsError> { - let mut seat = { - let seat_active = std::sync::Arc::new((Mutex::new(false), Condvar::new())); - let callback_seat_active = std::sync::Arc::clone(&seat_active); - let s = libseat::Seat::open( - move |_, event| { - let (lock, cvar) = &*callback_seat_active; - let mut started = lock.lock(); - if let libseat::SeatEvent::Enable = event { - *started = true; - cvar.notify_one(); - } - }, - None, + let mut seat = libseat::Seat::open(move |_, _| {}, None).map_err(|_| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Failed to open libseat"), ) - .map_err(|_| { - crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc("Failed to open libseat"), - ) - })?; - let (lock, cvar) = &*seat_active; - let mut started = lock.lock(); - while !*started { - cvar.wait(&mut started); - } - s - }; + })?; let dev = seat.open_device(&"/dev/dri/card0").map_err(|_| { crate::error::OsError::new( line!(), From e5655af8597273dd27616f14d6dcdb742c66d168 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 3 May 2022 22:23:09 -0400 Subject: [PATCH 040/151] Safer seat handling --- src/platform_impl/linux/drm/event_loop.rs | 38 ++++++++++++++++++----- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index 6d08022220..e440f80cdd 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -3,7 +3,7 @@ use std::{ marker::PhantomData, os::unix::prelude::{AsRawFd, FromRawFd, RawFd}, path::Path, - sync::mpsc::SendError, + sync::{atomic::AtomicBool, mpsc::SendError, Arc}, }; use calloop::{EventSource, Interest, Mode, Poll, PostAction, Readiness, Token, TokenFactory}; @@ -19,7 +19,6 @@ use input::{ LibinputInterface, }; use instant::{Duration, Instant}; -use parking_lot::{Condvar, Mutex}; use crate::{ dpi::PhysicalPosition, @@ -662,13 +661,36 @@ pub(crate) fn find_prop_id( impl EventLoop { pub fn new() -> Result, crate::error::OsError> { - let mut seat = libseat::Seat::open(move |_, _| {}, None).map_err(|_| { - crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc("Failed to open libseat"), + let mut seat = { + let active = Arc::new(AtomicBool::new(false)); + let t_active = active.clone(); + let mut s = libseat::Seat::open( + move |_, event| { + if let libseat::SeatEvent::Enable = event { + t_active.store(true, std::sync::atomic::Ordering::SeqCst); + } + }, + None, ) - })?; + .map_err(|_| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Failed to open libseat"), + ) + })?; + + while !active.load(std::sync::atomic::Ordering::SeqCst) { + if let Err(_) = s.dispatch(-1) { + return Err(crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Failed to dispatch seat"), + )); + } + } + s + }; let dev = seat.open_device(&"/dev/dri/card0").map_err(|_| { crate::error::OsError::new( line!(), From 2b1834319d5e302b0a57222798e723594c154479 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Wed, 4 May 2022 11:08:12 -0400 Subject: [PATCH 041/151] Fix mode selection --- src/platform_impl/linux/drm/event_loop.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index e440f80cdd..0518725fcf 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -7,7 +7,7 @@ use std::{ }; use calloop::{EventSource, Interest, Mode, Poll, PostAction, Readiness, Token, TokenFactory}; -use drm::control::{property, Device, ResourceHandle}; +use drm::control::{property, Device, ModeTypeFlags, ResourceHandle}; use input::{ event::{ keyboard::KeyboardEventTrait, @@ -754,11 +754,16 @@ impl EventLoop { ))?; // Get the first (usually best) mode - let &mode = con.modes().get(0).ok_or(crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc("No modes found on connector"), - ))?; + let &mode = con + .modes() + .iter() + .find(|f| f.mode_type().contains(ModeTypeFlags::PREFERRED)) + .or(con.modes().get(0)) + .ok_or(crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("No modes found on connector"), + ))?; let planes = drm.plane_handles().or(Err(crate::error::OsError::new( line!(), From 9e03b4bbe9e9e12f5239d22da460809fef4528c4 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Wed, 4 May 2022 16:27:34 -0400 Subject: [PATCH 042/151] raw-window-handle has been merged --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index d241a3fbaf..612b7f438b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,7 +28,7 @@ instant = { version = "0.1.12", features = ["wasm-bindgen"] } lazy_static = "1.4.0" log = "0.4.17" serde = { version = "1.0.137", optional = true, features = ["serde_derive"] } -raw-window-handle = { git = "https://github.com/StratusFearMe21/raw-window-handle" } +raw-window-handle = { git = "https://github.com/rust-windowing/raw-window-handle" } bitflags = "1.3.2" mint = { version = "0.5.9", optional = true } From 6716677eb00208fa1a17986de1b979d22b919488 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Wed, 4 May 2022 18:49:29 -0400 Subject: [PATCH 043/151] Add key repeating --- src/platform_impl/linux/drm/event_loop.rs | 52 +++++++++++++++++++---- 1 file changed, 44 insertions(+), 8 deletions(-) diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index 0518725fcf..5eda4bef02 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -4,6 +4,7 @@ use std::{ os::unix::prelude::{AsRawFd, FromRawFd, RawFd}, path::Path, sync::{atomic::AtomicBool, mpsc::SendError, Arc}, + time::{Duration, Instant}, }; use calloop::{EventSource, Interest, Mode, Poll, PostAction, Readiness, Token, TokenFactory}; @@ -18,7 +19,6 @@ use input::{ }, LibinputInterface, }; -use instant::{Duration, Instant}; use crate::{ dpi::PhysicalPosition, @@ -58,6 +58,7 @@ pub struct LibinputInputBackend { screen_size: (u32, u32), modifiers: ModifiersState, cursor_positon: PhysicalPosition, + timer_handle: calloop::timer::TimerHandle, // cursor_plane: drm::control::plane::Handle, // cursor_buffer: drm::control::framebuffer::Handle, } @@ -68,8 +69,8 @@ impl LibinputInputBackend { pub fn new( context: input::Libinput, screen_size: (u32, u32), - // cursor_plane: drm::control::plane::Handle, - // cursor_buffer: drm::control::framebuffer::Handle, + timer_handle: calloop::timer::TimerHandle, // cursor_plane: drm::control::plane::Handle, + // cursor_buffer: drm::control::framebuffer::Handle ) -> Self { LibinputInputBackend { context, @@ -77,7 +78,7 @@ impl LibinputInputBackend { touch_location: PhysicalPosition::new(0.0, 0.0), cursor_positon: PhysicalPosition::new(0.0, 0.0), modifiers: ModifiersState::empty(), - screen_size, + screen_size,timer_handle // cursor_buffer, // cursor_plane, } @@ -539,13 +540,19 @@ impl EventSource for LibinputInputBackend { } k => { + let state = match ev.key_state() { + KeyState::Pressed => crate::event::ElementState::Pressed, + KeyState::Released => crate::event::ElementState::Released + }; + let input = KeyboardInput { scancode: k, state: state.clone(), virtual_keycode: CHAR_MAPPINGS[k as usize], modifiers: self.modifiers }; + self.timer_handle.cancel_all_timeouts(); + if let crate::event::ElementState::Pressed = state { + self.timer_handle.add_timeout(Duration::from_millis(500), input); + } callback(crate::event::Event::WindowEvent { window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), event: crate::event::WindowEvent::KeyboardInput { device_id: crate::event::DeviceId(crate:: platform_impl::DeviceId::Drm( super::DeviceId)), - input: KeyboardInput { scancode: k, state: match ev.key_state() { - KeyState::Pressed => crate::event::ElementState::Pressed, - KeyState::Released => crate::event::ElementState::Released - }, virtual_keycode: CHAR_MAPPINGS[k as usize], modifiers: self.modifiers } , is_synthetic: false }}, &mut ()); + input, is_synthetic: false }}, &mut ()); } }, _ => {} @@ -896,9 +903,37 @@ impl EventLoop { ) .unwrap(); + let repeat_handler = calloop::timer::Timer::new().unwrap(); + + let repeat_handle = repeat_handler.handle(); + + let repeat_loop: calloop::Dispatcher< + 'static, + calloop::timer::Timer, + EventSink, + > = calloop::Dispatcher::new( + repeat_handler, + move |event, metadata, data: &mut EventSink| { + data.push(crate::event::Event::WindowEvent { + window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm( + super::WindowId, + )), + event: crate::event::WindowEvent::KeyboardInput { + device_id: crate::event::DeviceId(crate::platform_impl::DeviceId::Drm( + super::DeviceId, + )), + input: event, + is_synthetic: false, + }, + }); + metadata.add_timeout(Duration::from_millis(100), event); + }, + ); + let input_backend: LibinputInputBackend = LibinputInputBackend::new( input, (disp_width.into(), disp_height.into()), // plane, fb + repeat_handle, ); let input_loop: calloop::Dispatcher<'static, LibinputInputBackend, EventSink> = @@ -910,6 +945,7 @@ impl EventLoop { ); handle.register_dispatcher(input_loop).unwrap(); + handle.register_dispatcher(repeat_loop).unwrap(); let window_target = crate::event_loop::EventLoopWindowTarget { p: crate::platform_impl::EventLoopWindowTarget::Drm(EventLoopWindowTarget { From 6c4f3d500d3142cf5b776f946f9ecb4c0f0078f5 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Wed, 4 May 2022 23:51:44 -0400 Subject: [PATCH 044/151] Fix features --- src/platform/unix.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/platform/unix.rs b/src/platform/unix.rs index 20a2a753f3..05691b6e47 100644 --- a/src/platform/unix.rs +++ b/src/platform/unix.rs @@ -8,7 +8,10 @@ use std::os::{raw, unix::prelude::FromRawFd}; #[cfg(feature = "x11")] -use std::{ptr, sync::Arc}; +use std::ptr; + +#[cfg(any(feature = "x11", feature = "kmsdrm"))] +use std::sync::Arc; use crate::{ event_loop::{EventLoopBuilder, EventLoopWindowTarget}, From 3a13ea25dad106c8217858742308721464f76d66 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Thu, 5 May 2022 00:32:52 -0400 Subject: [PATCH 045/151] Optimize repeat keys --- src/platform_impl/linux/drm/event_loop.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index 5eda4bef02..1e74c7aefa 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -547,7 +547,7 @@ impl EventSource for LibinputInputBackend { let input = KeyboardInput { scancode: k, state: state.clone(), virtual_keycode: CHAR_MAPPINGS[k as usize], modifiers: self.modifiers }; self.timer_handle.cancel_all_timeouts(); if let crate::event::ElementState::Pressed = state { - self.timer_handle.add_timeout(Duration::from_millis(500), input); + self.timer_handle.add_timeout(Duration::from_millis(600), input); } callback(crate::event::Event::WindowEvent { window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), @@ -926,7 +926,7 @@ impl EventLoop { is_synthetic: false, }, }); - metadata.add_timeout(Duration::from_millis(100), event); + metadata.add_timeout(Duration::from_millis(25), event); }, ); From 66cbe82aa41f55d57bdbd1d81fd06b0802292544 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Thu, 5 May 2022 10:12:06 -0400 Subject: [PATCH 046/151] Add beta RecievedChar --- src/event.rs | 81 +++++++++++++++++++++++ src/platform_impl/linux/drm/event_loop.rs | 12 +++- 2 files changed, 92 insertions(+), 1 deletion(-) diff --git a/src/event.rs b/src/event.rs index 5afb0ebfbd..effeb1195a 100644 --- a/src/event.rs +++ b/src/event.rs @@ -982,6 +982,87 @@ pub enum VirtualKeyCode { Cut, } +impl TryInto for VirtualKeyCode { + type Error = (); + fn try_into(self) -> Result { + match self { + VirtualKeyCode::Key1 => Ok('1'), + VirtualKeyCode::Key2 => Ok('2'), + VirtualKeyCode::Key3 => Ok('3'), + VirtualKeyCode::Key4 => Ok('4'), + VirtualKeyCode::Key5 => Ok('5'), + VirtualKeyCode::Key6 => Ok('6'), + VirtualKeyCode::Key7 => Ok('7'), + VirtualKeyCode::Key8 => Ok('8'), + VirtualKeyCode::Key9 => Ok('9'), + VirtualKeyCode::Key0 => Ok('0'), + VirtualKeyCode::A => Ok('a'), + VirtualKeyCode::B => Ok('b'), + VirtualKeyCode::C => Ok('c'), + VirtualKeyCode::D => Ok('d'), + VirtualKeyCode::E => Ok('e'), + VirtualKeyCode::F => Ok('f'), + VirtualKeyCode::G => Ok('g'), + VirtualKeyCode::H => Ok('h'), + VirtualKeyCode::I => Ok('i'), + VirtualKeyCode::J => Ok('j'), + VirtualKeyCode::K => Ok('k'), + VirtualKeyCode::L => Ok('l'), + VirtualKeyCode::M => Ok('m'), + VirtualKeyCode::N => Ok('n'), + VirtualKeyCode::O => Ok('o'), + VirtualKeyCode::P => Ok('p'), + VirtualKeyCode::Q => Ok('q'), + VirtualKeyCode::R => Ok('r'), + VirtualKeyCode::S => Ok('s'), + VirtualKeyCode::T => Ok('t'), + VirtualKeyCode::U => Ok('u'), + VirtualKeyCode::V => Ok('v'), + VirtualKeyCode::W => Ok('w'), + VirtualKeyCode::X => Ok('x'), + VirtualKeyCode::Y => Ok('y'), + VirtualKeyCode::Z => Ok('z'), + VirtualKeyCode::Return => Ok('\n'), + VirtualKeyCode::Space => Ok(' '), + VirtualKeyCode::Caret => Ok('^'), + VirtualKeyCode::Numpad0 => Ok('0'), + VirtualKeyCode::Numpad1 => Ok('1'), + VirtualKeyCode::Numpad2 => Ok('2'), + VirtualKeyCode::Numpad3 => Ok('3'), + VirtualKeyCode::Numpad4 => Ok('4'), + VirtualKeyCode::Numpad5 => Ok('5'), + VirtualKeyCode::Numpad6 => Ok('6'), + VirtualKeyCode::Numpad7 => Ok('7'), + VirtualKeyCode::Numpad8 => Ok('8'), + VirtualKeyCode::Numpad9 => Ok('9'), + VirtualKeyCode::NumpadAdd => Ok('+'), + VirtualKeyCode::NumpadDivide => Ok('/'), + VirtualKeyCode::NumpadDecimal => Ok('.'), + VirtualKeyCode::NumpadComma => Ok(','), + VirtualKeyCode::NumpadEnter => Ok('\n'), + VirtualKeyCode::NumpadEquals => Ok('='), + VirtualKeyCode::NumpadMultiply => Ok('*'), + VirtualKeyCode::NumpadSubtract => Ok('-'), + VirtualKeyCode::Apostrophe => Ok('\''), + VirtualKeyCode::Asterisk => Ok('*'), + VirtualKeyCode::Backslash => Ok('\\'), + VirtualKeyCode::Colon => Ok(';'), + VirtualKeyCode::Comma => Ok(','), + VirtualKeyCode::Equals => Ok('='), + VirtualKeyCode::Grave => Ok('`'), + VirtualKeyCode::LBracket => Ok('['), + VirtualKeyCode::Minus => Ok('-'), + VirtualKeyCode::Period => Ok('.'), + VirtualKeyCode::Plus => Ok('+'), + VirtualKeyCode::RBracket => Ok(']'), + VirtualKeyCode::Semicolon => Ok(';'), + VirtualKeyCode::Slash => Ok('/'), + VirtualKeyCode::Tab => Ok('\t'), + _ => Err(()), + } + } +} + impl ModifiersState { /// Returns `true` if the shift key is pressed. pub fn shift(&self) -> bool { diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index 1e74c7aefa..7aa044c04d 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -532,6 +532,7 @@ impl EventSource for LibinputInputBackend { 99 // SysRq => { if self.modifiers.is_empty() { + self.timer_handle.cancel_all_timeouts(); callback(crate::event::Event::WindowEvent { window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), event: crate::event::WindowEvent::CloseRequested @@ -544,7 +545,8 @@ impl EventSource for LibinputInputBackend { KeyState::Pressed => crate::event::ElementState::Pressed, KeyState::Released => crate::event::ElementState::Released }; - let input = KeyboardInput { scancode: k, state: state.clone(), virtual_keycode: CHAR_MAPPINGS[k as usize], modifiers: self.modifiers }; + let virtual_keycode = CHAR_MAPPINGS[k as usize]; + let input = KeyboardInput { scancode: k, state: state.clone(), virtual_keycode, modifiers: self.modifiers }; self.timer_handle.cancel_all_timeouts(); if let crate::event::ElementState::Pressed = state { self.timer_handle.add_timeout(Duration::from_millis(600), input); @@ -553,6 +555,14 @@ impl EventSource for LibinputInputBackend { window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), event: crate::event::WindowEvent::KeyboardInput { device_id: crate::event::DeviceId(crate:: platform_impl::DeviceId::Drm( super::DeviceId)), input, is_synthetic: false }}, &mut ()); + if let Some(vk) =virtual_keycode { + if let Ok(c) = vk.try_into() { + callback(crate::event::Event::WindowEvent { + window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), + event: crate::event::WindowEvent::ReceivedCharacter(c)}, &mut ()); + } + + } } }, _ => {} From a70ad3273bcadcc6161d6adeaae1f32af3ed95d9 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Thu, 5 May 2022 10:26:05 -0400 Subject: [PATCH 047/151] Complete RecievedChar --- src/event.rs | 200 +++++++++++++--------- src/platform_impl/linux/drm/event_loop.rs | 2 +- 2 files changed, 124 insertions(+), 78 deletions(-) diff --git a/src/event.rs b/src/event.rs index effeb1195a..2da111d6b8 100644 --- a/src/event.rs +++ b/src/event.rs @@ -982,83 +982,129 @@ pub enum VirtualKeyCode { Cut, } -impl TryInto for VirtualKeyCode { - type Error = (); - fn try_into(self) -> Result { - match self { - VirtualKeyCode::Key1 => Ok('1'), - VirtualKeyCode::Key2 => Ok('2'), - VirtualKeyCode::Key3 => Ok('3'), - VirtualKeyCode::Key4 => Ok('4'), - VirtualKeyCode::Key5 => Ok('5'), - VirtualKeyCode::Key6 => Ok('6'), - VirtualKeyCode::Key7 => Ok('7'), - VirtualKeyCode::Key8 => Ok('8'), - VirtualKeyCode::Key9 => Ok('9'), - VirtualKeyCode::Key0 => Ok('0'), - VirtualKeyCode::A => Ok('a'), - VirtualKeyCode::B => Ok('b'), - VirtualKeyCode::C => Ok('c'), - VirtualKeyCode::D => Ok('d'), - VirtualKeyCode::E => Ok('e'), - VirtualKeyCode::F => Ok('f'), - VirtualKeyCode::G => Ok('g'), - VirtualKeyCode::H => Ok('h'), - VirtualKeyCode::I => Ok('i'), - VirtualKeyCode::J => Ok('j'), - VirtualKeyCode::K => Ok('k'), - VirtualKeyCode::L => Ok('l'), - VirtualKeyCode::M => Ok('m'), - VirtualKeyCode::N => Ok('n'), - VirtualKeyCode::O => Ok('o'), - VirtualKeyCode::P => Ok('p'), - VirtualKeyCode::Q => Ok('q'), - VirtualKeyCode::R => Ok('r'), - VirtualKeyCode::S => Ok('s'), - VirtualKeyCode::T => Ok('t'), - VirtualKeyCode::U => Ok('u'), - VirtualKeyCode::V => Ok('v'), - VirtualKeyCode::W => Ok('w'), - VirtualKeyCode::X => Ok('x'), - VirtualKeyCode::Y => Ok('y'), - VirtualKeyCode::Z => Ok('z'), - VirtualKeyCode::Return => Ok('\n'), - VirtualKeyCode::Space => Ok(' '), - VirtualKeyCode::Caret => Ok('^'), - VirtualKeyCode::Numpad0 => Ok('0'), - VirtualKeyCode::Numpad1 => Ok('1'), - VirtualKeyCode::Numpad2 => Ok('2'), - VirtualKeyCode::Numpad3 => Ok('3'), - VirtualKeyCode::Numpad4 => Ok('4'), - VirtualKeyCode::Numpad5 => Ok('5'), - VirtualKeyCode::Numpad6 => Ok('6'), - VirtualKeyCode::Numpad7 => Ok('7'), - VirtualKeyCode::Numpad8 => Ok('8'), - VirtualKeyCode::Numpad9 => Ok('9'), - VirtualKeyCode::NumpadAdd => Ok('+'), - VirtualKeyCode::NumpadDivide => Ok('/'), - VirtualKeyCode::NumpadDecimal => Ok('.'), - VirtualKeyCode::NumpadComma => Ok(','), - VirtualKeyCode::NumpadEnter => Ok('\n'), - VirtualKeyCode::NumpadEquals => Ok('='), - VirtualKeyCode::NumpadMultiply => Ok('*'), - VirtualKeyCode::NumpadSubtract => Ok('-'), - VirtualKeyCode::Apostrophe => Ok('\''), - VirtualKeyCode::Asterisk => Ok('*'), - VirtualKeyCode::Backslash => Ok('\\'), - VirtualKeyCode::Colon => Ok(';'), - VirtualKeyCode::Comma => Ok(','), - VirtualKeyCode::Equals => Ok('='), - VirtualKeyCode::Grave => Ok('`'), - VirtualKeyCode::LBracket => Ok('['), - VirtualKeyCode::Minus => Ok('-'), - VirtualKeyCode::Period => Ok('.'), - VirtualKeyCode::Plus => Ok('+'), - VirtualKeyCode::RBracket => Ok(']'), - VirtualKeyCode::Semicolon => Ok(';'), - VirtualKeyCode::Slash => Ok('/'), - VirtualKeyCode::Tab => Ok('\t'), - _ => Err(()), +impl VirtualKeyCode { + pub fn into_char(self, shift: bool) -> Option { + match (self, shift) { + (VirtualKeyCode::Key1, false) => Some('1'), + (VirtualKeyCode::Key1, true) => Some('!'), + (VirtualKeyCode::Key2, false) => Some('2'), + (VirtualKeyCode::Key2, true) => Some('@'), + (VirtualKeyCode::Key3, false) => Some('3'), + (VirtualKeyCode::Key3, true) => Some('#'), + (VirtualKeyCode::Key4, false) => Some('4'), + (VirtualKeyCode::Key4, true) => Some('$'), + (VirtualKeyCode::Key5, false) => Some('5'), + (VirtualKeyCode::Key5, true) => Some('%'), + (VirtualKeyCode::Key6, false) => Some('6'), + (VirtualKeyCode::Key6, true) => Some('^'), + (VirtualKeyCode::Key7, false) => Some('7'), + (VirtualKeyCode::Key7, true) => Some('&'), + (VirtualKeyCode::Key8, false) => Some('8'), + (VirtualKeyCode::Key8, true) => Some('*'), + (VirtualKeyCode::Key9, false) => Some('9'), + (VirtualKeyCode::Key9, true) => Some('('), + (VirtualKeyCode::Key0, false) => Some('0'), + (VirtualKeyCode::Key0, true) => Some(')'), + (VirtualKeyCode::A, false) => Some('a'), + (VirtualKeyCode::A, true) => Some('A'), + (VirtualKeyCode::B, false) => Some('b'), + (VirtualKeyCode::B, true) => Some('B'), + (VirtualKeyCode::C, false) => Some('c'), + (VirtualKeyCode::C, true) => Some('C'), + (VirtualKeyCode::D, false) => Some('d'), + (VirtualKeyCode::D, true) => Some('D'), + (VirtualKeyCode::E, false) => Some('e'), + (VirtualKeyCode::E, true) => Some('E'), + (VirtualKeyCode::F, false) => Some('f'), + (VirtualKeyCode::F, true) => Some('F'), + (VirtualKeyCode::G, false) => Some('g'), + (VirtualKeyCode::G, true) => Some('G'), + (VirtualKeyCode::H, false) => Some('h'), + (VirtualKeyCode::H, true) => Some('H'), + (VirtualKeyCode::I, false) => Some('i'), + (VirtualKeyCode::I, true) => Some('I'), + (VirtualKeyCode::J, false) => Some('j'), + (VirtualKeyCode::J, true) => Some('J'), + (VirtualKeyCode::K, false) => Some('k'), + (VirtualKeyCode::K, true) => Some('K'), + (VirtualKeyCode::L, false) => Some('l'), + (VirtualKeyCode::L, true) => Some('L'), + (VirtualKeyCode::M, false) => Some('m'), + (VirtualKeyCode::M, true) => Some('M'), + (VirtualKeyCode::N, false) => Some('n'), + (VirtualKeyCode::N, true) => Some('N'), + (VirtualKeyCode::O, false) => Some('o'), + (VirtualKeyCode::O, true) => Some('O'), + (VirtualKeyCode::P, false) => Some('p'), + (VirtualKeyCode::P, true) => Some('P'), + (VirtualKeyCode::Q, false) => Some('q'), + (VirtualKeyCode::Q, true) => Some('Q'), + (VirtualKeyCode::R, false) => Some('r'), + (VirtualKeyCode::R, true) => Some('R'), + (VirtualKeyCode::S, false) => Some('s'), + (VirtualKeyCode::S, true) => Some('S'), + (VirtualKeyCode::T, false) => Some('t'), + (VirtualKeyCode::T, true) => Some('T'), + (VirtualKeyCode::U, false) => Some('u'), + (VirtualKeyCode::U, true) => Some('U'), + (VirtualKeyCode::V, false) => Some('v'), + (VirtualKeyCode::V, true) => Some('V'), + (VirtualKeyCode::W, false) => Some('w'), + (VirtualKeyCode::W, true) => Some('W'), + (VirtualKeyCode::X, false) => Some('x'), + (VirtualKeyCode::X, true) => Some('X'), + (VirtualKeyCode::Y, false) => Some('y'), + (VirtualKeyCode::Y, true) => Some('Y'), + (VirtualKeyCode::Z, false) => Some('z'), + (VirtualKeyCode::Z, true) => Some('Z'), + (VirtualKeyCode::Return, false) => Some('\n'), + (VirtualKeyCode::Space, false) => Some(' '), + (VirtualKeyCode::Caret, false) => Some('^'), + (VirtualKeyCode::Numpad0, false) => Some('0'), + (VirtualKeyCode::Numpad1, false) => Some('1'), + (VirtualKeyCode::Numpad2, false) => Some('2'), + (VirtualKeyCode::Numpad3, false) => Some('3'), + (VirtualKeyCode::Numpad4, false) => Some('4'), + (VirtualKeyCode::Numpad5, false) => Some('5'), + (VirtualKeyCode::Numpad6, false) => Some('6'), + (VirtualKeyCode::Numpad7, false) => Some('7'), + (VirtualKeyCode::Numpad8, false) => Some('8'), + (VirtualKeyCode::Numpad9, false) => Some('9'), + (VirtualKeyCode::NumpadAdd, false) => Some('+'), + (VirtualKeyCode::NumpadDivide, false) => Some('/'), + (VirtualKeyCode::NumpadDecimal, false) => Some('.'), + (VirtualKeyCode::NumpadComma, false) => Some(','), + (VirtualKeyCode::NumpadEnter, false) => Some('\n'), + (VirtualKeyCode::NumpadEquals, false) => Some('='), + (VirtualKeyCode::NumpadMultiply, false) => Some('*'), + (VirtualKeyCode::NumpadSubtract, false) => Some('-'), + (VirtualKeyCode::Apostrophe, false) => Some('\''), + (VirtualKeyCode::Apostrophe, true) => Some('"'), + (VirtualKeyCode::Asterisk, false) => Some('*'), + (VirtualKeyCode::Backslash, false) => Some('\\'), + (VirtualKeyCode::Backslash, true) => Some('|'), + (VirtualKeyCode::Colon, false) => Some(':'), + (VirtualKeyCode::Colon, true) => Some(';'), + (VirtualKeyCode::Comma, false) => Some(','), + (VirtualKeyCode::Comma, true) => Some('<'), + (VirtualKeyCode::Equals, false) => Some('='), + (VirtualKeyCode::Equals, true) => Some('+'), + (VirtualKeyCode::Grave, false) => Some('`'), + (VirtualKeyCode::Grave, true) => Some('~'), + (VirtualKeyCode::LBracket, false) => Some('['), + (VirtualKeyCode::LBracket, true) => Some('{'), + (VirtualKeyCode::Minus, false) => Some('-'), + (VirtualKeyCode::Minus, true) => Some('_'), + (VirtualKeyCode::Period, false) => Some('.'), + (VirtualKeyCode::Period, true) => Some('>'), + (VirtualKeyCode::Plus, false) => Some('+'), + (VirtualKeyCode::RBracket, false) => Some(']'), + (VirtualKeyCode::RBracket, true) => Some('}'), + (VirtualKeyCode::Semicolon, false) => Some(';'), + (VirtualKeyCode::Slash, false) => Some('/'), + (VirtualKeyCode::Slash, true) => Some('?'), + (VirtualKeyCode::Tab, false) => Some('\t'), + _ => None, } } } diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index 7aa044c04d..b5358338b3 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -556,7 +556,7 @@ impl EventSource for LibinputInputBackend { event: crate::event::WindowEvent::KeyboardInput { device_id: crate::event::DeviceId(crate:: platform_impl::DeviceId::Drm( super::DeviceId)), input, is_synthetic: false }}, &mut ()); if let Some(vk) =virtual_keycode { - if let Ok(c) = vk.try_into() { + if let Some(c) = vk.into_char(self.modifiers.shift()) { callback(crate::event::Event::WindowEvent { window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), event: crate::event::WindowEvent::ReceivedCharacter(c)}, &mut ()); From 37696121c2220b15fb8c581b6440f0011de8576e Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Thu, 5 May 2022 10:27:26 -0400 Subject: [PATCH 048/151] Bug --- src/platform_impl/linux/drm/event_loop.rs | 134 +++++++++++----------- 1 file changed, 68 insertions(+), 66 deletions(-) diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index b5358338b3..0096c4e205 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -79,8 +79,8 @@ impl LibinputInputBackend { cursor_positon: PhysicalPosition::new(0.0, 0.0), modifiers: ModifiersState::empty(), screen_size,timer_handle - // cursor_buffer, - // cursor_plane, + // cursor_buffer, + // cursor_plane, } } } @@ -530,21 +530,21 @@ impl EventSource for LibinputInputBackend { event: crate::event::WindowEvent::ModifiersChanged(self.modifiers)}, &mut ()); } 99 // SysRq - => { - if self.modifiers.is_empty() { - self.timer_handle.cancel_all_timeouts(); - callback(crate::event::Event::WindowEvent { - window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), - event: crate::event::WindowEvent::CloseRequested - }, &mut ()); + => { + if self.modifiers.is_empty() { + self.timer_handle.cancel_all_timeouts(); + callback(crate::event::Event::WindowEvent { + window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), + event: crate::event::WindowEvent::CloseRequested + }, &mut ()); + } } - } k => { let state = match ev.key_state() { - KeyState::Pressed => crate::event::ElementState::Pressed, - KeyState::Released => crate::event::ElementState::Released - }; + KeyState::Pressed => crate::event::ElementState::Pressed, + KeyState::Released => crate::event::ElementState::Released + }; let virtual_keycode = CHAR_MAPPINGS[k as usize]; let input = KeyboardInput { scancode: k, state: state.clone(), virtual_keycode, modifiers: self.modifiers }; self.timer_handle.cancel_all_timeouts(); @@ -555,13 +555,15 @@ impl EventSource for LibinputInputBackend { window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), event: crate::event::WindowEvent::KeyboardInput { device_id: crate::event::DeviceId(crate:: platform_impl::DeviceId::Drm( super::DeviceId)), input, is_synthetic: false }}, &mut ()); - if let Some(vk) =virtual_keycode { - if let Some(c) = vk.into_char(self.modifiers.shift()) { - callback(crate::event::Event::WindowEvent { - window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), - event: crate::event::WindowEvent::ReceivedCharacter(c)}, &mut ()); - } + if let crate::event::ElementState::Pressed = state { + if let Some(vk) =virtual_keycode { + if let Some(c) = vk.into_char(self.modifiers.shift()) { + callback(crate::event::Event::WindowEvent { + window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), + event: crate::event::WindowEvent::ReceivedCharacter(c)}, &mut ()); + } + } } } }, @@ -789,58 +791,58 @@ impl EventLoop { )))?; /* - let mut db = drm - .create_dumb_buffer((64, 64), drm::buffer::DrmFourcc::Xrgb8888, 32) - .or(Err(crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc("Could not create dumb buffer"), - )))?; - - { - let mut map = drm - .map_dumb_buffer(&mut db) - .expect("Could not map dumbbuffer"); - for b in map.as_mut() { - *b = 128; - } + let mut db = drm + .create_dumb_buffer((64, 64), drm::buffer::DrmFourcc::Xrgb8888, 32) + .or(Err(crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Could not create dumb buffer"), + )))?; + + { + let mut map = drm + .map_dumb_buffer(&mut db) + .expect("Could not map dumbbuffer"); + for b in map.as_mut() { + *b = 128; + } } let fb = drm - .add_framebuffer(&db, 24, 32) - .or(Err(crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc("Could not create FB"), - )))?; + .add_framebuffer(&db, 24, 32) + .or(Err(crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Could not create FB"), + )))?; - let (better_planes, compatible_planes): ( - Vec, - Vec, + let (better_planes, compatible_planes): ( + Vec, + Vec, ) = planes - .planes() - .iter() - .filter(|&&plane| { - drm.get_plane(plane) - .map(|plane_info| { - let compatible_crtcs = res.filter_crtcs(plane_info.possible_crtcs()); - compatible_crtcs.contains(&crtc.handle()) - }) - .unwrap_or(false) - }) - .partition(|&&plane| { - if let Ok(props) = drm.get_properties(plane) { - let (ids, vals) = props.as_props_and_values(); - for (&id, &val) in ids.iter().zip(vals.iter()) { - if let Ok(info) = drm.get_property(id) { - if info.name().to_str().map(|x| x == "type").unwrap_or(false) { - return val == (drm::control::PlaneType::Cursor as u32).into(); - } - } - } - } - false - }); + .planes() + .iter() + .filter(|&&plane| { + drm.get_plane(plane) + .map(|plane_info| { + let compatible_crtcs = res.filter_crtcs(plane_info.possible_crtcs()); + compatible_crtcs.contains(&crtc.handle()) + }) + .unwrap_or(false) + }) + .partition(|&&plane| { + if let Ok(props) = drm.get_properties(plane) { + let (ids, vals) = props.as_props_and_values(); + for (&id, &val) in ids.iter().zip(vals.iter()) { + if let Ok(info) = drm.get_property(id) { + if info.name().to_str().map(|x| x == "type").unwrap_or(false) { + return val == (drm::control::PlaneType::Cursor as u32).into(); + } + } + } + } + false + }); let plane = *better_planes.get(0).unwrap_or(&compatible_planes[0]); */ let (p_better_planes, p_compatible_planes): ( From f34258617e8f92a69a4a303d23fa6df40cea1832 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Thu, 5 May 2022 10:38:05 -0400 Subject: [PATCH 049/151] Better RecievedChar impl --- src/platform_impl/linux/drm/event_loop.rs | 24 +++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index 0096c4e205..cc98f66da9 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -58,7 +58,7 @@ pub struct LibinputInputBackend { screen_size: (u32, u32), modifiers: ModifiersState, cursor_positon: PhysicalPosition, - timer_handle: calloop::timer::TimerHandle, + timer_handle: calloop::timer::TimerHandle<(KeyboardInput, Option)>, // cursor_plane: drm::control::plane::Handle, // cursor_buffer: drm::control::framebuffer::Handle, } @@ -69,8 +69,8 @@ impl LibinputInputBackend { pub fn new( context: input::Libinput, screen_size: (u32, u32), - timer_handle: calloop::timer::TimerHandle, // cursor_plane: drm::control::plane::Handle, - // cursor_buffer: drm::control::framebuffer::Handle + timer_handle: calloop::timer::TimerHandle<(KeyboardInput, Option)>, // cursor_plane: drm::control::plane::Handle, + // cursor_buffer: drm::control::framebuffer::Handle ) -> Self { LibinputInputBackend { context, @@ -548,21 +548,21 @@ impl EventSource for LibinputInputBackend { let virtual_keycode = CHAR_MAPPINGS[k as usize]; let input = KeyboardInput { scancode: k, state: state.clone(), virtual_keycode, modifiers: self.modifiers }; self.timer_handle.cancel_all_timeouts(); - if let crate::event::ElementState::Pressed = state { - self.timer_handle.add_timeout(Duration::from_millis(600), input); - } callback(crate::event::Event::WindowEvent { window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), event: crate::event::WindowEvent::KeyboardInput { device_id: crate::event::DeviceId(crate:: platform_impl::DeviceId::Drm( super::DeviceId)), input, is_synthetic: false }}, &mut ()); if let crate::event::ElementState::Pressed = state { - if let Some(vk) =virtual_keycode { - if let Some(c) = vk.into_char(self.modifiers.shift()) { - callback(crate::event::Event::WindowEvent { - window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), - event: crate::event::WindowEvent::ReceivedCharacter(c)}, &mut ()); + if self.modifiers == ModifiersState::SHIFT || self.modifiers == ModifiersState::empty() { + if let Some(vk) = virtual_keycode { + let ch = vk.into_char(self.modifiers.shift()); + if let Some(c) = ch { + callback(crate::event::Event::WindowEvent { + window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), + event: crate::event::WindowEvent::ReceivedCharacter(c)}, &mut ()); + } + self.timer_handle.add_timeout(Duration::from_millis(600), (input, ch)); } - } } } From e44819c6cb9f692126ab84416a573f0beec0ea7a Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Thu, 5 May 2022 10:40:15 -0400 Subject: [PATCH 050/151] Better RecievedChar impl --- src/platform_impl/linux/drm/event_loop.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index cc98f66da9..8724e1fd81 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -921,7 +921,7 @@ impl EventLoop { let repeat_loop: calloop::Dispatcher< 'static, - calloop::timer::Timer, + calloop::timer::Timer<(KeyboardInput, Option)>, EventSink, > = calloop::Dispatcher::new( repeat_handler, @@ -934,10 +934,18 @@ impl EventLoop { device_id: crate::event::DeviceId(crate::platform_impl::DeviceId::Drm( super::DeviceId, )), - input: event, + input: event.0, is_synthetic: false, }, }); + if let Some(c) = event.1 { + data.push(crate::event::Event::WindowEvent { + window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm( + super::WindowId, + )), + event: crate::event::WindowEvent::ReceivedCharacter(c), + }); + } metadata.add_timeout(Duration::from_millis(25), event); }, ); From ffe9251316bd86ac4d6d9f4b43c6776a98030f13 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Thu, 5 May 2022 10:47:21 -0400 Subject: [PATCH 051/151] Better RecievedChar impl --- src/event.rs | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/event.rs b/src/event.rs index 2da111d6b8..efeaf8d873 100644 --- a/src/event.rs +++ b/src/event.rs @@ -1058,33 +1058,55 @@ impl VirtualKeyCode { (VirtualKeyCode::Z, false) => Some('z'), (VirtualKeyCode::Z, true) => Some('Z'), (VirtualKeyCode::Return, false) => Some('\n'), + (VirtualKeyCode::Return, true) => Some('\n'), (VirtualKeyCode::Space, false) => Some(' '), + (VirtualKeyCode::Space, true) => Some(' '), (VirtualKeyCode::Caret, false) => Some('^'), + (VirtualKeyCode::Caret, true) => Some('^'), (VirtualKeyCode::Numpad0, false) => Some('0'), + (VirtualKeyCode::Numpad0, true) => Some('0'), (VirtualKeyCode::Numpad1, false) => Some('1'), + (VirtualKeyCode::Numpad1, true) => Some('1'), (VirtualKeyCode::Numpad2, false) => Some('2'), + (VirtualKeyCode::Numpad2, true) => Some('2'), (VirtualKeyCode::Numpad3, false) => Some('3'), + (VirtualKeyCode::Numpad3, true) => Some('3'), (VirtualKeyCode::Numpad4, false) => Some('4'), + (VirtualKeyCode::Numpad4, true) => Some('4'), (VirtualKeyCode::Numpad5, false) => Some('5'), + (VirtualKeyCode::Numpad5, true) => Some('5'), (VirtualKeyCode::Numpad6, false) => Some('6'), + (VirtualKeyCode::Numpad6, true) => Some('6'), (VirtualKeyCode::Numpad7, false) => Some('7'), + (VirtualKeyCode::Numpad7, true) => Some('7'), (VirtualKeyCode::Numpad8, false) => Some('8'), + (VirtualKeyCode::Numpad8, true) => Some('8'), (VirtualKeyCode::Numpad9, false) => Some('9'), + (VirtualKeyCode::Numpad9, true) => Some('9'), (VirtualKeyCode::NumpadAdd, false) => Some('+'), + (VirtualKeyCode::NumpadAdd, true) => Some('+'), (VirtualKeyCode::NumpadDivide, false) => Some('/'), + (VirtualKeyCode::NumpadDivide, true) => Some('/'), (VirtualKeyCode::NumpadDecimal, false) => Some('.'), + (VirtualKeyCode::NumpadDecimal, true) => Some('.'), (VirtualKeyCode::NumpadComma, false) => Some(','), + (VirtualKeyCode::NumpadComma, true) => Some(','), (VirtualKeyCode::NumpadEnter, false) => Some('\n'), + (VirtualKeyCode::NumpadEnter, true) => Some('\n'), (VirtualKeyCode::NumpadEquals, false) => Some('='), + (VirtualKeyCode::NumpadEquals, true) => Some('='), (VirtualKeyCode::NumpadMultiply, false) => Some('*'), + (VirtualKeyCode::NumpadMultiply, true) => Some('*'), (VirtualKeyCode::NumpadSubtract, false) => Some('-'), + (VirtualKeyCode::NumpadSubtract, true) => Some('-'), (VirtualKeyCode::Apostrophe, false) => Some('\''), (VirtualKeyCode::Apostrophe, true) => Some('"'), (VirtualKeyCode::Asterisk, false) => Some('*'), + (VirtualKeyCode::Asterisk, true) => Some('*'), (VirtualKeyCode::Backslash, false) => Some('\\'), (VirtualKeyCode::Backslash, true) => Some('|'), (VirtualKeyCode::Colon, false) => Some(':'), - (VirtualKeyCode::Colon, true) => Some(';'), + (VirtualKeyCode::Colon, true) => Some(':'), (VirtualKeyCode::Comma, false) => Some(','), (VirtualKeyCode::Comma, true) => Some('<'), (VirtualKeyCode::Equals, false) => Some('='), @@ -1098,12 +1120,15 @@ impl VirtualKeyCode { (VirtualKeyCode::Period, false) => Some('.'), (VirtualKeyCode::Period, true) => Some('>'), (VirtualKeyCode::Plus, false) => Some('+'), + (VirtualKeyCode::Plus, true) => Some('+'), (VirtualKeyCode::RBracket, false) => Some(']'), (VirtualKeyCode::RBracket, true) => Some('}'), (VirtualKeyCode::Semicolon, false) => Some(';'), + (VirtualKeyCode::Semicolon, true) => Some(':'), (VirtualKeyCode::Slash, false) => Some('/'), (VirtualKeyCode::Slash, true) => Some('?'), (VirtualKeyCode::Tab, false) => Some('\t'), + (VirtualKeyCode::Tab, true) => Some('\t'), _ => None, } } From bf2fea07ce80d71e6790aa35bbe2a4c20bd0a6ec Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Thu, 5 May 2022 12:39:06 -0400 Subject: [PATCH 052/151] Better RecievedChar impl --- src/event.rs | 307 ++++++++++++---------- src/platform_impl/linux/drm/event_loop.rs | 4 +- 2 files changed, 162 insertions(+), 149 deletions(-) diff --git a/src/event.rs b/src/event.rs index efeaf8d873..20e58ac917 100644 --- a/src/event.rs +++ b/src/event.rs @@ -983,152 +983,167 @@ pub enum VirtualKeyCode { } impl VirtualKeyCode { - pub fn into_char(self, shift: bool) -> Option { - match (self, shift) { - (VirtualKeyCode::Key1, false) => Some('1'), - (VirtualKeyCode::Key1, true) => Some('!'), - (VirtualKeyCode::Key2, false) => Some('2'), - (VirtualKeyCode::Key2, true) => Some('@'), - (VirtualKeyCode::Key3, false) => Some('3'), - (VirtualKeyCode::Key3, true) => Some('#'), - (VirtualKeyCode::Key4, false) => Some('4'), - (VirtualKeyCode::Key4, true) => Some('$'), - (VirtualKeyCode::Key5, false) => Some('5'), - (VirtualKeyCode::Key5, true) => Some('%'), - (VirtualKeyCode::Key6, false) => Some('6'), - (VirtualKeyCode::Key6, true) => Some('^'), - (VirtualKeyCode::Key7, false) => Some('7'), - (VirtualKeyCode::Key7, true) => Some('&'), - (VirtualKeyCode::Key8, false) => Some('8'), - (VirtualKeyCode::Key8, true) => Some('*'), - (VirtualKeyCode::Key9, false) => Some('9'), - (VirtualKeyCode::Key9, true) => Some('('), - (VirtualKeyCode::Key0, false) => Some('0'), - (VirtualKeyCode::Key0, true) => Some(')'), - (VirtualKeyCode::A, false) => Some('a'), - (VirtualKeyCode::A, true) => Some('A'), - (VirtualKeyCode::B, false) => Some('b'), - (VirtualKeyCode::B, true) => Some('B'), - (VirtualKeyCode::C, false) => Some('c'), - (VirtualKeyCode::C, true) => Some('C'), - (VirtualKeyCode::D, false) => Some('d'), - (VirtualKeyCode::D, true) => Some('D'), - (VirtualKeyCode::E, false) => Some('e'), - (VirtualKeyCode::E, true) => Some('E'), - (VirtualKeyCode::F, false) => Some('f'), - (VirtualKeyCode::F, true) => Some('F'), - (VirtualKeyCode::G, false) => Some('g'), - (VirtualKeyCode::G, true) => Some('G'), - (VirtualKeyCode::H, false) => Some('h'), - (VirtualKeyCode::H, true) => Some('H'), - (VirtualKeyCode::I, false) => Some('i'), - (VirtualKeyCode::I, true) => Some('I'), - (VirtualKeyCode::J, false) => Some('j'), - (VirtualKeyCode::J, true) => Some('J'), - (VirtualKeyCode::K, false) => Some('k'), - (VirtualKeyCode::K, true) => Some('K'), - (VirtualKeyCode::L, false) => Some('l'), - (VirtualKeyCode::L, true) => Some('L'), - (VirtualKeyCode::M, false) => Some('m'), - (VirtualKeyCode::M, true) => Some('M'), - (VirtualKeyCode::N, false) => Some('n'), - (VirtualKeyCode::N, true) => Some('N'), - (VirtualKeyCode::O, false) => Some('o'), - (VirtualKeyCode::O, true) => Some('O'), - (VirtualKeyCode::P, false) => Some('p'), - (VirtualKeyCode::P, true) => Some('P'), - (VirtualKeyCode::Q, false) => Some('q'), - (VirtualKeyCode::Q, true) => Some('Q'), - (VirtualKeyCode::R, false) => Some('r'), - (VirtualKeyCode::R, true) => Some('R'), - (VirtualKeyCode::S, false) => Some('s'), - (VirtualKeyCode::S, true) => Some('S'), - (VirtualKeyCode::T, false) => Some('t'), - (VirtualKeyCode::T, true) => Some('T'), - (VirtualKeyCode::U, false) => Some('u'), - (VirtualKeyCode::U, true) => Some('U'), - (VirtualKeyCode::V, false) => Some('v'), - (VirtualKeyCode::V, true) => Some('V'), - (VirtualKeyCode::W, false) => Some('w'), - (VirtualKeyCode::W, true) => Some('W'), - (VirtualKeyCode::X, false) => Some('x'), - (VirtualKeyCode::X, true) => Some('X'), - (VirtualKeyCode::Y, false) => Some('y'), - (VirtualKeyCode::Y, true) => Some('Y'), - (VirtualKeyCode::Z, false) => Some('z'), - (VirtualKeyCode::Z, true) => Some('Z'), - (VirtualKeyCode::Return, false) => Some('\n'), - (VirtualKeyCode::Return, true) => Some('\n'), - (VirtualKeyCode::Space, false) => Some(' '), - (VirtualKeyCode::Space, true) => Some(' '), - (VirtualKeyCode::Caret, false) => Some('^'), - (VirtualKeyCode::Caret, true) => Some('^'), - (VirtualKeyCode::Numpad0, false) => Some('0'), - (VirtualKeyCode::Numpad0, true) => Some('0'), - (VirtualKeyCode::Numpad1, false) => Some('1'), - (VirtualKeyCode::Numpad1, true) => Some('1'), - (VirtualKeyCode::Numpad2, false) => Some('2'), - (VirtualKeyCode::Numpad2, true) => Some('2'), - (VirtualKeyCode::Numpad3, false) => Some('3'), - (VirtualKeyCode::Numpad3, true) => Some('3'), - (VirtualKeyCode::Numpad4, false) => Some('4'), - (VirtualKeyCode::Numpad4, true) => Some('4'), - (VirtualKeyCode::Numpad5, false) => Some('5'), - (VirtualKeyCode::Numpad5, true) => Some('5'), - (VirtualKeyCode::Numpad6, false) => Some('6'), - (VirtualKeyCode::Numpad6, true) => Some('6'), - (VirtualKeyCode::Numpad7, false) => Some('7'), - (VirtualKeyCode::Numpad7, true) => Some('7'), - (VirtualKeyCode::Numpad8, false) => Some('8'), - (VirtualKeyCode::Numpad8, true) => Some('8'), - (VirtualKeyCode::Numpad9, false) => Some('9'), - (VirtualKeyCode::Numpad9, true) => Some('9'), - (VirtualKeyCode::NumpadAdd, false) => Some('+'), - (VirtualKeyCode::NumpadAdd, true) => Some('+'), - (VirtualKeyCode::NumpadDivide, false) => Some('/'), - (VirtualKeyCode::NumpadDivide, true) => Some('/'), - (VirtualKeyCode::NumpadDecimal, false) => Some('.'), - (VirtualKeyCode::NumpadDecimal, true) => Some('.'), - (VirtualKeyCode::NumpadComma, false) => Some(','), - (VirtualKeyCode::NumpadComma, true) => Some(','), - (VirtualKeyCode::NumpadEnter, false) => Some('\n'), - (VirtualKeyCode::NumpadEnter, true) => Some('\n'), - (VirtualKeyCode::NumpadEquals, false) => Some('='), - (VirtualKeyCode::NumpadEquals, true) => Some('='), - (VirtualKeyCode::NumpadMultiply, false) => Some('*'), - (VirtualKeyCode::NumpadMultiply, true) => Some('*'), - (VirtualKeyCode::NumpadSubtract, false) => Some('-'), - (VirtualKeyCode::NumpadSubtract, true) => Some('-'), - (VirtualKeyCode::Apostrophe, false) => Some('\''), - (VirtualKeyCode::Apostrophe, true) => Some('"'), - (VirtualKeyCode::Asterisk, false) => Some('*'), - (VirtualKeyCode::Asterisk, true) => Some('*'), - (VirtualKeyCode::Backslash, false) => Some('\\'), - (VirtualKeyCode::Backslash, true) => Some('|'), - (VirtualKeyCode::Colon, false) => Some(':'), - (VirtualKeyCode::Colon, true) => Some(':'), - (VirtualKeyCode::Comma, false) => Some(','), - (VirtualKeyCode::Comma, true) => Some('<'), - (VirtualKeyCode::Equals, false) => Some('='), - (VirtualKeyCode::Equals, true) => Some('+'), - (VirtualKeyCode::Grave, false) => Some('`'), - (VirtualKeyCode::Grave, true) => Some('~'), - (VirtualKeyCode::LBracket, false) => Some('['), - (VirtualKeyCode::LBracket, true) => Some('{'), - (VirtualKeyCode::Minus, false) => Some('-'), - (VirtualKeyCode::Minus, true) => Some('_'), - (VirtualKeyCode::Period, false) => Some('.'), - (VirtualKeyCode::Period, true) => Some('>'), - (VirtualKeyCode::Plus, false) => Some('+'), - (VirtualKeyCode::Plus, true) => Some('+'), - (VirtualKeyCode::RBracket, false) => Some(']'), - (VirtualKeyCode::RBracket, true) => Some('}'), - (VirtualKeyCode::Semicolon, false) => Some(';'), - (VirtualKeyCode::Semicolon, true) => Some(':'), - (VirtualKeyCode::Slash, false) => Some('/'), - (VirtualKeyCode::Slash, true) => Some('?'), - (VirtualKeyCode::Tab, false) => Some('\t'), - (VirtualKeyCode::Tab, true) => Some('\t'), + pub fn into_char(self, shift: bool, ctrl: bool) -> Option { + match (self, shift, ctrl) { + (VirtualKeyCode::Key1, false, _) => Some('1'), + (VirtualKeyCode::Key1, true, _) => Some('!'), + (VirtualKeyCode::Key2, false, false) => Some('2'), + (VirtualKeyCode::Key2, true, false) => Some('@'), + (VirtualKeyCode::Key2, _, true) => Some('\u{0}'), + (VirtualKeyCode::Key3, false, false) => Some('3'), + (VirtualKeyCode::Key3, true, false) => Some('#'), + (VirtualKeyCode::Key3, _, true) => Some('\u{1b}'), + (VirtualKeyCode::Key4, false, false) => Some('4'), + (VirtualKeyCode::Key4, true, false) => Some('$'), + (VirtualKeyCode::Key4, _, true) => Some('\u{1c}'), + (VirtualKeyCode::Key5, false, false) => Some('5'), + (VirtualKeyCode::Key5, true, false) => Some('%'), + (VirtualKeyCode::Key5, _, true) => Some('\u{1d}'), + (VirtualKeyCode::Key6, false, false) => Some('6'), + (VirtualKeyCode::Key6, true, false) => Some('^'), + (VirtualKeyCode::Key6, _, true) => Some('\u{1e}'), + (VirtualKeyCode::Key7, false, false) => Some('7'), + (VirtualKeyCode::Key7, true, false) => Some('&'), + (VirtualKeyCode::Key7, _, true) => Some('\u{1f}'), + (VirtualKeyCode::Key8, false, false) => Some('8'), + (VirtualKeyCode::Key8, true, false) => Some('*'), + (VirtualKeyCode::Key8, _, true) => Some('\u{7f}'), + (VirtualKeyCode::Key9, false, _) => Some('9'), + (VirtualKeyCode::Key9, true, _) => Some('('), + (VirtualKeyCode::Key0, false, _) => Some('0'), + (VirtualKeyCode::Key0, true, _) => Some(')'), + (VirtualKeyCode::A, false, false) => Some('a'), + (VirtualKeyCode::A, true, false) => Some('A'), + (VirtualKeyCode::A, _, true) => Some('\u{1}'), + (VirtualKeyCode::B, false, false) => Some('b'), + (VirtualKeyCode::B, true, false) => Some('B'), + (VirtualKeyCode::B, _, true) => Some('\u{2}'), + (VirtualKeyCode::C, false, false) => Some('c'), + (VirtualKeyCode::C, true, false) => Some('C'), + (VirtualKeyCode::C, _, true) => Some('\u{3}'), + (VirtualKeyCode::D, false, false) => Some('d'), + (VirtualKeyCode::D, true, false) => Some('D'), + (VirtualKeyCode::D, _, true) => Some('\u{4}'), + (VirtualKeyCode::E, false, false) => Some('e'), + (VirtualKeyCode::E, true, false) => Some('E'), + (VirtualKeyCode::E, _, true) => Some('\u{5}'), + (VirtualKeyCode::F, false, false) => Some('f'), + (VirtualKeyCode::F, true, false) => Some('F'), + (VirtualKeyCode::F, _, true) => Some('\u{6}'), + (VirtualKeyCode::G, false, false) => Some('g'), + (VirtualKeyCode::G, true, false) => Some('G'), + (VirtualKeyCode::G, _, true) => Some('\u{7}'), + (VirtualKeyCode::H, false, false) => Some('h'), + (VirtualKeyCode::H, true, false) => Some('H'), + (VirtualKeyCode::H, _, true) => Some('\u{8}'), + (VirtualKeyCode::I, false, false) => Some('i'), + (VirtualKeyCode::I, true, false) => Some('I'), + (VirtualKeyCode::I, _, true) => Some('\t'), + (VirtualKeyCode::J, false, false) => Some('j'), + (VirtualKeyCode::J, true, false) => Some('J'), + (VirtualKeyCode::J, _, true) => Some('\n'), + (VirtualKeyCode::K, false, false) => Some('k'), + (VirtualKeyCode::K, true, false) => Some('K'), + (VirtualKeyCode::K, _, true) => Some('\u{b}'), + (VirtualKeyCode::L, false, false) => Some('l'), + (VirtualKeyCode::L, true, false) => Some('L'), + (VirtualKeyCode::L, _, true) => Some('\u{c}'), + (VirtualKeyCode::M, false, false) => Some('m'), + (VirtualKeyCode::M, true, false) => Some('M'), + (VirtualKeyCode::M, _, true) => Some('\r'), + (VirtualKeyCode::N, false, false) => Some('n'), + (VirtualKeyCode::N, true, false) => Some('N'), + (VirtualKeyCode::N, _, true) => Some('\u{e}'), + (VirtualKeyCode::O, false, false) => Some('o'), + (VirtualKeyCode::O, true, false) => Some('O'), + (VirtualKeyCode::O, _, true) => Some('\u{f}'), + (VirtualKeyCode::P, false, false) => Some('p'), + (VirtualKeyCode::P, true, false) => Some('P'), + (VirtualKeyCode::P, _, true) => Some('\u{10}'), + (VirtualKeyCode::Q, false, false) => Some('q'), + (VirtualKeyCode::Q, true, false) => Some('Q'), + (VirtualKeyCode::Q, _, true) => Some('\u{11}'), + (VirtualKeyCode::R, false, false) => Some('r'), + (VirtualKeyCode::R, true, false) => Some('R'), + (VirtualKeyCode::R, _, true) => Some('\u{12}'), + (VirtualKeyCode::S, false, false) => Some('s'), + (VirtualKeyCode::S, true, false) => Some('S'), + (VirtualKeyCode::Key8, true, false) => Some('*'), + (VirtualKeyCode::S, _, true) => Some('\u{13}'), + (VirtualKeyCode::T, false, false) => Some('t'), + (VirtualKeyCode::T, true, false) => Some('T'), + (VirtualKeyCode::T, _, true) => Some('\u{14}'), + (VirtualKeyCode::U, false, false) => Some('u'), + (VirtualKeyCode::U, true, false) => Some('U'), + (VirtualKeyCode::U, _, true) => Some('\u{15}'), + (VirtualKeyCode::V, false, false) => Some('v'), + (VirtualKeyCode::V, true, false) => Some('V'), + (VirtualKeyCode::V, _, true) => Some('\u{16}'), + (VirtualKeyCode::W, false, false) => Some('w'), + (VirtualKeyCode::W, true, false) => Some('W'), + (VirtualKeyCode::W, _, true) => Some('\u{17}'), + (VirtualKeyCode::X, false, false) => Some('x'), + (VirtualKeyCode::X, true, false) => Some('X'), + (VirtualKeyCode::X, _, true) => Some('\u{18}'), + (VirtualKeyCode::Y, false, false) => Some('y'), + (VirtualKeyCode::Y, true, false) => Some('Y'), + (VirtualKeyCode::Y, _, true) => Some('\u{19}'), + (VirtualKeyCode::Z, false, false) => Some('z'), + (VirtualKeyCode::Z, true, false) => Some('Z'), + (VirtualKeyCode::Z, _, true) => Some('\u{1a}'), + (VirtualKeyCode::Return, _, _) => Some('\r'), + (VirtualKeyCode::Space, _, false) => Some(' '), + (VirtualKeyCode::Space, _, true) => Some('\u{0}'), + (VirtualKeyCode::Caret, _, _) => Some('^'), + (VirtualKeyCode::Numpad0, _, _) => Some('0'), + (VirtualKeyCode::Numpad1, _, _) => Some('1'), + (VirtualKeyCode::Numpad2, _, _) => Some('2'), + (VirtualKeyCode::Numpad3, _, _) => Some('3'), + (VirtualKeyCode::Numpad4, _, _) => Some('4'), + (VirtualKeyCode::Numpad5, _, _) => Some('5'), + (VirtualKeyCode::Numpad6, _, _) => Some('6'), + (VirtualKeyCode::Numpad7, _, _) => Some('7'), + (VirtualKeyCode::Numpad8, _, _) => Some('8'), + (VirtualKeyCode::Numpad9, _, _) => Some('9'), + (VirtualKeyCode::NumpadAdd, _, _) => Some('+'), + (VirtualKeyCode::NumpadDivide, _, _) => Some('/'), + (VirtualKeyCode::NumpadDecimal, _, _) => Some('.'), + (VirtualKeyCode::NumpadComma, _, _) => Some(','), + (VirtualKeyCode::NumpadEnter, _, _) => Some('\n'), + (VirtualKeyCode::NumpadEquals, _, _) => Some('='), + (VirtualKeyCode::NumpadMultiply, _, _) => Some('*'), + (VirtualKeyCode::NumpadSubtract, _, _) => Some('-'), + (VirtualKeyCode::Apostrophe, false, _) => Some('\''), + (VirtualKeyCode::Apostrophe, true, _) => Some('"'), + (VirtualKeyCode::Asterisk, _, _) => Some('*'), + (VirtualKeyCode::Backslash, false, false) => Some('\\'), + (VirtualKeyCode::Backslash, true, false) => Some('|'), + (VirtualKeyCode::Backslash, _, true) => Some('\u{1c}'), + (VirtualKeyCode::Colon, _, _) => Some(':'), + (VirtualKeyCode::Comma, false, _) => Some(','), + (VirtualKeyCode::Comma, true, _) => Some('<'), + (VirtualKeyCode::Equals, false, _) => Some('='), + (VirtualKeyCode::Equals, true, _) => Some('+'), + (VirtualKeyCode::Grave, false, false) => Some('`'), + (VirtualKeyCode::Grave, true, false) => Some('~'), + (VirtualKeyCode::Grave, _, true) => Some('\u{0}'), + (VirtualKeyCode::LBracket, false, false) => Some('['), + (VirtualKeyCode::LBracket, true, false) => Some('{'), + (VirtualKeyCode::LBracket, _, true) => Some('\u{1b}'), + (VirtualKeyCode::Minus, false, _) => Some('-'), + (VirtualKeyCode::Minus, true, _) => Some('_'), + (VirtualKeyCode::Period, false, _) => Some('.'), + (VirtualKeyCode::Period, true, _) => Some('>'), + (VirtualKeyCode::Plus, _, _) => Some('+'), + (VirtualKeyCode::RBracket, false, false) => Some(']'), + (VirtualKeyCode::RBracket, true, false) => Some('}'), + (VirtualKeyCode::RBracket, _, true) => Some('\u{1d}'), + (VirtualKeyCode::Semicolon, false, _) => Some(';'), + (VirtualKeyCode::Semicolon, true, _) => Some(':'), + (VirtualKeyCode::Slash, false, false) => Some('/'), + (VirtualKeyCode::Slash, true, false) => Some('?'), + (VirtualKeyCode::Slash, _, true) => Some('\u{1f}'), + (VirtualKeyCode::Tab, _, _) => Some('\t'), _ => None, } } diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index 8724e1fd81..b3731fb5cb 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -553,9 +553,8 @@ impl EventSource for LibinputInputBackend { event: crate::event::WindowEvent::KeyboardInput { device_id: crate::event::DeviceId(crate:: platform_impl::DeviceId::Drm( super::DeviceId)), input, is_synthetic: false }}, &mut ()); if let crate::event::ElementState::Pressed = state { - if self.modifiers == ModifiersState::SHIFT || self.modifiers == ModifiersState::empty() { if let Some(vk) = virtual_keycode { - let ch = vk.into_char(self.modifiers.shift()); + let ch = vk.into_char(self.modifiers.shift(), self.modifiers.ctrl()); if let Some(c) = ch { callback(crate::event::Event::WindowEvent { window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), @@ -563,7 +562,6 @@ impl EventSource for LibinputInputBackend { } self.timer_handle.add_timeout(Duration::from_millis(600), (input, ch)); } - } } } }, From 0440c60a8886d07a6e87253ce9bdd4a293e0d1ba Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Thu, 5 May 2022 13:57:27 -0400 Subject: [PATCH 053/151] Better RecievedChar impl --- src/event.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/event.rs b/src/event.rs index 20e58ac917..1c4947a951 100644 --- a/src/event.rs +++ b/src/event.rs @@ -1144,6 +1144,7 @@ impl VirtualKeyCode { (VirtualKeyCode::Slash, true, false) => Some('?'), (VirtualKeyCode::Slash, _, true) => Some('\u{1f}'), (VirtualKeyCode::Tab, _, _) => Some('\t'), + (VirtualKeyCode::Back, _, true) => Some('\u{8}'), _ => None, } } From 2427a4a52fad98926e468e2a558e8325822555d0 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Thu, 5 May 2022 14:19:58 -0400 Subject: [PATCH 054/151] Fix github building --- src/event.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/event.rs b/src/event.rs index 1c4947a951..a74c9b17cd 100644 --- a/src/event.rs +++ b/src/event.rs @@ -1068,7 +1068,6 @@ impl VirtualKeyCode { (VirtualKeyCode::R, _, true) => Some('\u{12}'), (VirtualKeyCode::S, false, false) => Some('s'), (VirtualKeyCode::S, true, false) => Some('S'), - (VirtualKeyCode::Key8, true, false) => Some('*'), (VirtualKeyCode::S, _, true) => Some('\u{13}'), (VirtualKeyCode::T, false, false) => Some('t'), (VirtualKeyCode::T, true, false) => Some('T'), From c27fa3abd38a4816036c69d3c139351fa4d9ee4a Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Thu, 5 May 2022 17:40:27 -0400 Subject: [PATCH 055/151] Fix keymap handling with xkbcommon --- Cargo.toml | 3 +- src/event.rs | 167 ------- src/platform_impl/linux/drm/event_loop.rs | 234 ++++++---- src/platform_impl/linux/drm/input_to_vk.rs | 238 ---------- src/platform_impl/linux/drm/mod.rs | 1 - src/platform_impl/linux/mod.rs | 2 + .../linux/wayland/seat/keyboard/handlers.rs | 6 +- .../linux/wayland/seat/keyboard/keymap.rs | 192 -------- .../linux/wayland/seat/keyboard/mod.rs | 1 - src/platform_impl/linux/xkb_keymap.rs | 415 ++++++++++++++++++ 10 files changed, 567 insertions(+), 692 deletions(-) delete mode 100644 src/platform_impl/linux/drm/input_to_vk.rs delete mode 100644 src/platform_impl/linux/wayland/seat/keyboard/keymap.rs create mode 100644 src/platform_impl/linux/xkb_keymap.rs diff --git a/Cargo.toml b/Cargo.toml index 612b7f438b..2192841c1e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ default-target = "x86_64-unknown-linux-gnu" targets = ["i686-pc-windows-msvc", "x86_64-pc-windows-msvc", "i686-unknown-linux-gnu", "x86_64-unknown-linux-gnu", "x86_64-apple-darwin", "wasm32-unknown-unknown"] [features] -default = ["x11", "wayland", "wayland-dlopen", "kmsdrm"] +default = ["x11", "wayland", "wayland-dlopen", "kmsdrm", "xkbcommon"] x11 = ["x11-dl", "mio", "percent-encoding", "parking_lot"] wayland = ["wayland-client", "wayland-protocols", "sctk", "calloop"] wayland-dlopen = ["sctk/dlopen", "wayland-client/dlopen"] @@ -101,6 +101,7 @@ libc = "0.2.125" drm = { version = "0.6.2", optional = true } input = { version = "0.7.1", optional = true } libseat = { version = "0.1.4", optional = true } +xkbcommon = { version = "0.4.0", optional = true } [target.'cfg(target_arch = "wasm32")'.dependencies] wasm-bindgen= "0.2.80" diff --git a/src/event.rs b/src/event.rs index a74c9b17cd..5afb0ebfbd 100644 --- a/src/event.rs +++ b/src/event.rs @@ -982,173 +982,6 @@ pub enum VirtualKeyCode { Cut, } -impl VirtualKeyCode { - pub fn into_char(self, shift: bool, ctrl: bool) -> Option { - match (self, shift, ctrl) { - (VirtualKeyCode::Key1, false, _) => Some('1'), - (VirtualKeyCode::Key1, true, _) => Some('!'), - (VirtualKeyCode::Key2, false, false) => Some('2'), - (VirtualKeyCode::Key2, true, false) => Some('@'), - (VirtualKeyCode::Key2, _, true) => Some('\u{0}'), - (VirtualKeyCode::Key3, false, false) => Some('3'), - (VirtualKeyCode::Key3, true, false) => Some('#'), - (VirtualKeyCode::Key3, _, true) => Some('\u{1b}'), - (VirtualKeyCode::Key4, false, false) => Some('4'), - (VirtualKeyCode::Key4, true, false) => Some('$'), - (VirtualKeyCode::Key4, _, true) => Some('\u{1c}'), - (VirtualKeyCode::Key5, false, false) => Some('5'), - (VirtualKeyCode::Key5, true, false) => Some('%'), - (VirtualKeyCode::Key5, _, true) => Some('\u{1d}'), - (VirtualKeyCode::Key6, false, false) => Some('6'), - (VirtualKeyCode::Key6, true, false) => Some('^'), - (VirtualKeyCode::Key6, _, true) => Some('\u{1e}'), - (VirtualKeyCode::Key7, false, false) => Some('7'), - (VirtualKeyCode::Key7, true, false) => Some('&'), - (VirtualKeyCode::Key7, _, true) => Some('\u{1f}'), - (VirtualKeyCode::Key8, false, false) => Some('8'), - (VirtualKeyCode::Key8, true, false) => Some('*'), - (VirtualKeyCode::Key8, _, true) => Some('\u{7f}'), - (VirtualKeyCode::Key9, false, _) => Some('9'), - (VirtualKeyCode::Key9, true, _) => Some('('), - (VirtualKeyCode::Key0, false, _) => Some('0'), - (VirtualKeyCode::Key0, true, _) => Some(')'), - (VirtualKeyCode::A, false, false) => Some('a'), - (VirtualKeyCode::A, true, false) => Some('A'), - (VirtualKeyCode::A, _, true) => Some('\u{1}'), - (VirtualKeyCode::B, false, false) => Some('b'), - (VirtualKeyCode::B, true, false) => Some('B'), - (VirtualKeyCode::B, _, true) => Some('\u{2}'), - (VirtualKeyCode::C, false, false) => Some('c'), - (VirtualKeyCode::C, true, false) => Some('C'), - (VirtualKeyCode::C, _, true) => Some('\u{3}'), - (VirtualKeyCode::D, false, false) => Some('d'), - (VirtualKeyCode::D, true, false) => Some('D'), - (VirtualKeyCode::D, _, true) => Some('\u{4}'), - (VirtualKeyCode::E, false, false) => Some('e'), - (VirtualKeyCode::E, true, false) => Some('E'), - (VirtualKeyCode::E, _, true) => Some('\u{5}'), - (VirtualKeyCode::F, false, false) => Some('f'), - (VirtualKeyCode::F, true, false) => Some('F'), - (VirtualKeyCode::F, _, true) => Some('\u{6}'), - (VirtualKeyCode::G, false, false) => Some('g'), - (VirtualKeyCode::G, true, false) => Some('G'), - (VirtualKeyCode::G, _, true) => Some('\u{7}'), - (VirtualKeyCode::H, false, false) => Some('h'), - (VirtualKeyCode::H, true, false) => Some('H'), - (VirtualKeyCode::H, _, true) => Some('\u{8}'), - (VirtualKeyCode::I, false, false) => Some('i'), - (VirtualKeyCode::I, true, false) => Some('I'), - (VirtualKeyCode::I, _, true) => Some('\t'), - (VirtualKeyCode::J, false, false) => Some('j'), - (VirtualKeyCode::J, true, false) => Some('J'), - (VirtualKeyCode::J, _, true) => Some('\n'), - (VirtualKeyCode::K, false, false) => Some('k'), - (VirtualKeyCode::K, true, false) => Some('K'), - (VirtualKeyCode::K, _, true) => Some('\u{b}'), - (VirtualKeyCode::L, false, false) => Some('l'), - (VirtualKeyCode::L, true, false) => Some('L'), - (VirtualKeyCode::L, _, true) => Some('\u{c}'), - (VirtualKeyCode::M, false, false) => Some('m'), - (VirtualKeyCode::M, true, false) => Some('M'), - (VirtualKeyCode::M, _, true) => Some('\r'), - (VirtualKeyCode::N, false, false) => Some('n'), - (VirtualKeyCode::N, true, false) => Some('N'), - (VirtualKeyCode::N, _, true) => Some('\u{e}'), - (VirtualKeyCode::O, false, false) => Some('o'), - (VirtualKeyCode::O, true, false) => Some('O'), - (VirtualKeyCode::O, _, true) => Some('\u{f}'), - (VirtualKeyCode::P, false, false) => Some('p'), - (VirtualKeyCode::P, true, false) => Some('P'), - (VirtualKeyCode::P, _, true) => Some('\u{10}'), - (VirtualKeyCode::Q, false, false) => Some('q'), - (VirtualKeyCode::Q, true, false) => Some('Q'), - (VirtualKeyCode::Q, _, true) => Some('\u{11}'), - (VirtualKeyCode::R, false, false) => Some('r'), - (VirtualKeyCode::R, true, false) => Some('R'), - (VirtualKeyCode::R, _, true) => Some('\u{12}'), - (VirtualKeyCode::S, false, false) => Some('s'), - (VirtualKeyCode::S, true, false) => Some('S'), - (VirtualKeyCode::S, _, true) => Some('\u{13}'), - (VirtualKeyCode::T, false, false) => Some('t'), - (VirtualKeyCode::T, true, false) => Some('T'), - (VirtualKeyCode::T, _, true) => Some('\u{14}'), - (VirtualKeyCode::U, false, false) => Some('u'), - (VirtualKeyCode::U, true, false) => Some('U'), - (VirtualKeyCode::U, _, true) => Some('\u{15}'), - (VirtualKeyCode::V, false, false) => Some('v'), - (VirtualKeyCode::V, true, false) => Some('V'), - (VirtualKeyCode::V, _, true) => Some('\u{16}'), - (VirtualKeyCode::W, false, false) => Some('w'), - (VirtualKeyCode::W, true, false) => Some('W'), - (VirtualKeyCode::W, _, true) => Some('\u{17}'), - (VirtualKeyCode::X, false, false) => Some('x'), - (VirtualKeyCode::X, true, false) => Some('X'), - (VirtualKeyCode::X, _, true) => Some('\u{18}'), - (VirtualKeyCode::Y, false, false) => Some('y'), - (VirtualKeyCode::Y, true, false) => Some('Y'), - (VirtualKeyCode::Y, _, true) => Some('\u{19}'), - (VirtualKeyCode::Z, false, false) => Some('z'), - (VirtualKeyCode::Z, true, false) => Some('Z'), - (VirtualKeyCode::Z, _, true) => Some('\u{1a}'), - (VirtualKeyCode::Return, _, _) => Some('\r'), - (VirtualKeyCode::Space, _, false) => Some(' '), - (VirtualKeyCode::Space, _, true) => Some('\u{0}'), - (VirtualKeyCode::Caret, _, _) => Some('^'), - (VirtualKeyCode::Numpad0, _, _) => Some('0'), - (VirtualKeyCode::Numpad1, _, _) => Some('1'), - (VirtualKeyCode::Numpad2, _, _) => Some('2'), - (VirtualKeyCode::Numpad3, _, _) => Some('3'), - (VirtualKeyCode::Numpad4, _, _) => Some('4'), - (VirtualKeyCode::Numpad5, _, _) => Some('5'), - (VirtualKeyCode::Numpad6, _, _) => Some('6'), - (VirtualKeyCode::Numpad7, _, _) => Some('7'), - (VirtualKeyCode::Numpad8, _, _) => Some('8'), - (VirtualKeyCode::Numpad9, _, _) => Some('9'), - (VirtualKeyCode::NumpadAdd, _, _) => Some('+'), - (VirtualKeyCode::NumpadDivide, _, _) => Some('/'), - (VirtualKeyCode::NumpadDecimal, _, _) => Some('.'), - (VirtualKeyCode::NumpadComma, _, _) => Some(','), - (VirtualKeyCode::NumpadEnter, _, _) => Some('\n'), - (VirtualKeyCode::NumpadEquals, _, _) => Some('='), - (VirtualKeyCode::NumpadMultiply, _, _) => Some('*'), - (VirtualKeyCode::NumpadSubtract, _, _) => Some('-'), - (VirtualKeyCode::Apostrophe, false, _) => Some('\''), - (VirtualKeyCode::Apostrophe, true, _) => Some('"'), - (VirtualKeyCode::Asterisk, _, _) => Some('*'), - (VirtualKeyCode::Backslash, false, false) => Some('\\'), - (VirtualKeyCode::Backslash, true, false) => Some('|'), - (VirtualKeyCode::Backslash, _, true) => Some('\u{1c}'), - (VirtualKeyCode::Colon, _, _) => Some(':'), - (VirtualKeyCode::Comma, false, _) => Some(','), - (VirtualKeyCode::Comma, true, _) => Some('<'), - (VirtualKeyCode::Equals, false, _) => Some('='), - (VirtualKeyCode::Equals, true, _) => Some('+'), - (VirtualKeyCode::Grave, false, false) => Some('`'), - (VirtualKeyCode::Grave, true, false) => Some('~'), - (VirtualKeyCode::Grave, _, true) => Some('\u{0}'), - (VirtualKeyCode::LBracket, false, false) => Some('['), - (VirtualKeyCode::LBracket, true, false) => Some('{'), - (VirtualKeyCode::LBracket, _, true) => Some('\u{1b}'), - (VirtualKeyCode::Minus, false, _) => Some('-'), - (VirtualKeyCode::Minus, true, _) => Some('_'), - (VirtualKeyCode::Period, false, _) => Some('.'), - (VirtualKeyCode::Period, true, _) => Some('>'), - (VirtualKeyCode::Plus, _, _) => Some('+'), - (VirtualKeyCode::RBracket, false, false) => Some(']'), - (VirtualKeyCode::RBracket, true, false) => Some('}'), - (VirtualKeyCode::RBracket, _, true) => Some('\u{1d}'), - (VirtualKeyCode::Semicolon, false, _) => Some(';'), - (VirtualKeyCode::Semicolon, true, _) => Some(':'), - (VirtualKeyCode::Slash, false, false) => Some('/'), - (VirtualKeyCode::Slash, true, false) => Some('?'), - (VirtualKeyCode::Slash, _, true) => Some('\u{1f}'), - (VirtualKeyCode::Tab, _, _) => Some('\t'), - (VirtualKeyCode::Back, _, true) => Some('\u{8}'), - _ => None, - } - } -} - impl ModifiersState { /// Returns `true` if the shift key is pressed. pub fn shift(&self) -> bool { diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index b3731fb5cb..43805046cb 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -6,6 +6,7 @@ use std::{ sync::{atomic::AtomicBool, mpsc::SendError, Arc}, time::{Duration, Instant}, }; +use xkbcommon::xkb; use calloop::{EventSource, Interest, Mode, Poll, PostAction, Readiness, Token, TokenFactory}; use drm::control::{property, Device, ModeTypeFlags, ResourceHandle}; @@ -22,14 +23,12 @@ use input::{ use crate::{ dpi::PhysicalPosition, - event::{Force, KeyboardInput, ModifiersState, MouseScrollDelta, StartCause}, + event::{ElementState, Force, KeyboardInput, ModifiersState, MouseScrollDelta, StartCause}, event_loop::{ControlFlow, EventLoopClosed}, platform::unix::Card, - platform_impl::platform::sticky_exit_callback, + platform_impl::{platform::sticky_exit_callback, xkb_keymap}, }; -use super::input_to_vk::CHAR_MAPPINGS; - struct Interface(libseat::Seat, HashMap); impl LibinputInterface for Interface { @@ -50,9 +49,10 @@ impl LibinputInterface for Interface { } } -#[derive(Debug)] pub struct LibinputInputBackend { context: input::Libinput, + xkb_ctx: xkb::State, + xkb_keymap: xkb::Keymap, token: Token, touch_location: PhysicalPosition, screen_size: (u32, u32), @@ -69,8 +69,10 @@ impl LibinputInputBackend { pub fn new( context: input::Libinput, screen_size: (u32, u32), - timer_handle: calloop::timer::TimerHandle<(KeyboardInput, Option)>, // cursor_plane: drm::control::plane::Handle, - // cursor_buffer: drm::control::framebuffer::Handle + timer_handle: calloop::timer::TimerHandle<(KeyboardInput, Option)>, + xkb_ctx: xkb::State, + xkb_keymap: xkb::Keymap, // cursor_plane: drm::control::plane::Handle, + // cursor_buffer: drm::control::framebuffer::Handle ) -> Self { LibinputInputBackend { context, @@ -78,9 +80,12 @@ impl LibinputInputBackend { touch_location: PhysicalPosition::new(0.0, 0.0), cursor_positon: PhysicalPosition::new(0.0, 0.0), modifiers: ModifiersState::empty(), - screen_size,timer_handle - // cursor_buffer, - // cursor_plane, + screen_size, + timer_handle, + xkb_ctx, + xkb_keymap, + // cursor_buffer, + // cursor_plane, } } } @@ -481,92 +486,125 @@ impl EventSource for LibinputInputBackend { } _ => {} }, - input::Event::Keyboard(ev) => match &ev { - input::event::KeyboardEvent::Key(key) => match key.key() { - 56 // LAlt - | 100 // RAlt - => { - match key.key_state() { - KeyState::Pressed => self.modifiers |= ModifiersState::ALT, - KeyState::Released => self.modifiers.remove(ModifiersState::ALT) - } - callback(crate::event::Event::WindowEvent { - window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), - event:crate::event::WindowEvent::ModifiersChanged(self.modifiers)}, &mut ()); - } - | 42 // LShift - | 54 // RShift - => { - match key.key_state() { - KeyState::Pressed => self.modifiers |= ModifiersState::SHIFT, - KeyState::Released => self.modifiers.remove(ModifiersState::SHIFT) + input::Event::Keyboard(ev) => { + let state = match ev.key_state() { + KeyState::Pressed => crate::event::ElementState::Pressed, + KeyState::Released => crate::event::ElementState::Released, + }; + let k = if let input::event::KeyboardEvent::Key(key) = ev { + key.key() + } else { + unsafe { core::hint::unreachable_unchecked() } + }; + let keysym = self.xkb_ctx.key_get_one_sym(k + 8); + let virtual_keycode = xkb_keymap::keysym_to_vkey(keysym); + let should_repeat = self.xkb_keymap.key_repeats(keysym); + let ch = self.xkb_ctx.key_get_utf8(keysym).chars().next(); + self.xkb_ctx.update_key( + k + 8, + match state { + ElementState::Pressed => xkb::KeyDirection::Down, + ElementState::Released => xkb::KeyDirection::Down, + }, + ); + let input = KeyboardInput { + scancode: k, + state: state.clone(), + virtual_keycode, + modifiers: self.modifiers, + }; + self.timer_handle.cancel_all_timeouts(); + callback( + crate::event::Event::WindowEvent { + window_id: crate::window::WindowId( + crate::platform_impl::WindowId::Drm(super::WindowId), + ), + event: crate::event::WindowEvent::KeyboardInput { + device_id: crate::event::DeviceId( + crate::platform_impl::DeviceId::Drm(super::DeviceId), + ), + input, + is_synthetic: false, + }, + }, + &mut (), + ); + if let crate::event::ElementState::Pressed = state { + if should_repeat { + self.timer_handle + .add_timeout(Duration::from_millis(600), (input, ch)); + } + if let Some(c) = ch { + callback( + crate::event::Event::WindowEvent { + window_id: crate::window::WindowId( + crate::platform_impl::WindowId::Drm(super::WindowId), + ), + event: crate::event::WindowEvent::ReceivedCharacter(c), + }, + &mut (), + ); + } + } + match keysym { + xkb_keymap::XKB_KEY_Alt_L + | xkb_keymap::XKB_KEY_Alt_R + => { + match state { + ElementState::Pressed => self.modifiers |= ModifiersState::ALT, + ElementState::Released => self.modifiers.remove(ModifiersState::ALT) + } + callback(crate::event::Event::WindowEvent { + window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), + event:crate::event::WindowEvent::ModifiersChanged(self.modifiers)}, &mut ()); } - callback(crate::event::Event::WindowEvent { - window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), - event:crate::event::WindowEvent::ModifiersChanged(self.modifiers)}, &mut ()); - } - - | 29 // LCtrl - | 97 // RCtrl - => { - match key.key_state() { - KeyState::Pressed => self.modifiers |= ModifiersState::CTRL, - KeyState::Released => self.modifiers.remove(ModifiersState::CTRL) + | xkb_keymap::XKB_KEY_Shift_L // LShift + | xkb_keymap::XKB_KEY_Shift_R // RShift + => { + match state { + ElementState::Pressed => self.modifiers |= ModifiersState::SHIFT, + ElementState::Released => self.modifiers.remove(ModifiersState::SHIFT) + } + callback(crate::event::Event::WindowEvent { + window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), + event:crate::event::WindowEvent::ModifiersChanged(self.modifiers)}, &mut ()); } - callback(crate::event::Event::WindowEvent { - window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), - event:crate::event::WindowEvent::ModifiersChanged(self.modifiers)}, &mut ()); - } - - | 125 // LMeta - | 126 // RMeta - => { - match key.key_state() { - KeyState::Pressed => self.modifiers |= ModifiersState::LOGO, - KeyState::Released => self.modifiers.remove(ModifiersState::LOGO) + + | xkb_keymap::XKB_KEY_Control_L // LCtrl + | xkb_keymap::XKB_KEY_Control_R // RCtrl + => { + match state { + ElementState::Pressed => self.modifiers |= ModifiersState::CTRL, + ElementState::Released => self.modifiers.remove(ModifiersState::CTRL) + } + callback(crate::event::Event::WindowEvent { + window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), + event:crate::event::WindowEvent::ModifiersChanged(self.modifiers)}, &mut ()); } - callback(crate::event::Event::WindowEvent { - window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), - event: crate::event::WindowEvent::ModifiersChanged(self.modifiers)}, &mut ()); - } - 99 // SysRq - => { - if self.modifiers.is_empty() { - self.timer_handle.cancel_all_timeouts(); + + | xkb_keymap::XKB_KEY_Meta_L // LMeta + | xkb_keymap::XKB_KEY_Meta_R // RMeta + => { + match state { + ElementState::Pressed => self.modifiers |= ModifiersState::LOGO, + ElementState::Released => self.modifiers.remove(ModifiersState::LOGO) + } callback(crate::event::Event::WindowEvent { window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), - event: crate::event::WindowEvent::CloseRequested - }, &mut ()); + event: crate::event::WindowEvent::ModifiersChanged(self.modifiers)}, &mut ()); } - } - - k => { - let state = match ev.key_state() { - KeyState::Pressed => crate::event::ElementState::Pressed, - KeyState::Released => crate::event::ElementState::Released - }; - let virtual_keycode = CHAR_MAPPINGS[k as usize]; - let input = KeyboardInput { scancode: k, state: state.clone(), virtual_keycode, modifiers: self.modifiers }; - self.timer_handle.cancel_all_timeouts(); - callback(crate::event::Event::WindowEvent { - window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), - event: crate::event::WindowEvent::KeyboardInput { device_id: crate::event::DeviceId(crate:: platform_impl::DeviceId::Drm( super::DeviceId)), - input, is_synthetic: false }}, &mut ()); - if let crate::event::ElementState::Pressed = state { - if let Some(vk) = virtual_keycode { - let ch = vk.into_char(self.modifiers.shift(), self.modifiers.ctrl()); - if let Some(c) = ch { - callback(crate::event::Event::WindowEvent { - window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), - event: crate::event::WindowEvent::ReceivedCharacter(c)}, &mut ()); - } - self.timer_handle.add_timeout(Duration::from_millis(600), (input, ch)); + xkb_keymap::XKB_KEY_Sys_Req // SysRq + => { + if self.modifiers.is_empty() { + callback(crate::event::Event::WindowEvent { + window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), + event: crate::event::WindowEvent::CloseRequested + }, &mut ()); } - } - } - }, - _ => {} - }, + } + _ => {} + } + } _ => {} } } @@ -678,6 +716,22 @@ pub(crate) fn find_prop_id( impl EventLoop { pub fn new() -> Result, crate::error::OsError> { + let xkb_ctx = xkb::Context::new(xkb::CONTEXT_NO_FLAGS); + let keymap = xkb::Keymap::new_from_names( + &xkb_ctx, + "", + "", + "", + "", + None, + xkb::KEYMAP_COMPILE_NO_FLAGS, + ) + .ok_or(crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Failed to compile XKB keymap"), + ))?; + let state = xkb::State::new(&keymap); let mut seat = { let active = Arc::new(AtomicBool::new(false)); let t_active = active.clone(); @@ -952,6 +1006,8 @@ impl EventLoop { input, (disp_width.into(), disp_height.into()), // plane, fb repeat_handle, + state, + keymap, ); let input_loop: calloop::Dispatcher<'static, LibinputInputBackend, EventSink> = diff --git a/src/platform_impl/linux/drm/input_to_vk.rs b/src/platform_impl/linux/drm/input_to_vk.rs deleted file mode 100644 index 561f7ba7fa..0000000000 --- a/src/platform_impl/linux/drm/input_to_vk.rs +++ /dev/null @@ -1,238 +0,0 @@ -use crate::event::VirtualKeyCode; - -pub const CHAR_MAPPINGS: [Option; 234] = [ - Some(VirtualKeyCode::Space), - Some(VirtualKeyCode::Escape), - Some(VirtualKeyCode::Key1), - Some(VirtualKeyCode::Key2), - Some(VirtualKeyCode::Key3), - Some(VirtualKeyCode::Key4), - Some(VirtualKeyCode::Key5), - Some(VirtualKeyCode::Key6), - Some(VirtualKeyCode::Key7), - Some(VirtualKeyCode::Key8), - Some(VirtualKeyCode::Key9), - Some(VirtualKeyCode::Key0), - Some(VirtualKeyCode::Minus), - Some(VirtualKeyCode::Equals), - Some(VirtualKeyCode::Back), - Some(VirtualKeyCode::Tab), - Some(VirtualKeyCode::Q), - Some(VirtualKeyCode::W), - Some(VirtualKeyCode::E), - Some(VirtualKeyCode::R), - Some(VirtualKeyCode::T), - Some(VirtualKeyCode::Y), - Some(VirtualKeyCode::U), - Some(VirtualKeyCode::I), - Some(VirtualKeyCode::O), - Some(VirtualKeyCode::P), - Some(VirtualKeyCode::LBracket), - Some(VirtualKeyCode::RBracket), - Some(VirtualKeyCode::Return), - Some(VirtualKeyCode::LControl), - Some(VirtualKeyCode::A), - Some(VirtualKeyCode::S), - Some(VirtualKeyCode::D), - Some(VirtualKeyCode::F), - Some(VirtualKeyCode::G), - Some(VirtualKeyCode::H), - Some(VirtualKeyCode::J), - Some(VirtualKeyCode::K), - Some(VirtualKeyCode::L), - Some(VirtualKeyCode::Semicolon), - Some(VirtualKeyCode::Apostrophe), - Some(VirtualKeyCode::Grave), - Some(VirtualKeyCode::LShift), - Some(VirtualKeyCode::Backslash), - Some(VirtualKeyCode::Z), - Some(VirtualKeyCode::X), - Some(VirtualKeyCode::C), - Some(VirtualKeyCode::V), - Some(VirtualKeyCode::B), - Some(VirtualKeyCode::N), - Some(VirtualKeyCode::M), - Some(VirtualKeyCode::Comma), - Some(VirtualKeyCode::Period), - Some(VirtualKeyCode::Slash), - Some(VirtualKeyCode::RShift), - Some(VirtualKeyCode::Asterisk), - Some(VirtualKeyCode::LAlt), - Some(VirtualKeyCode::Space), - Some(VirtualKeyCode::Capital), - Some(VirtualKeyCode::F1), - Some(VirtualKeyCode::F2), - Some(VirtualKeyCode::F3), - Some(VirtualKeyCode::F4), - Some(VirtualKeyCode::F5), - Some(VirtualKeyCode::F6), - Some(VirtualKeyCode::F7), - Some(VirtualKeyCode::F8), - Some(VirtualKeyCode::F9), - Some(VirtualKeyCode::F10), - Some(VirtualKeyCode::Numlock), - Some(VirtualKeyCode::Scroll), - Some(VirtualKeyCode::Numpad7), - Some(VirtualKeyCode::Numpad8), - Some(VirtualKeyCode::Numpad9), - Some(VirtualKeyCode::NumpadSubtract), - Some(VirtualKeyCode::Numpad4), - Some(VirtualKeyCode::Numpad5), - Some(VirtualKeyCode::Numpad6), - Some(VirtualKeyCode::NumpadEquals), - Some(VirtualKeyCode::Numpad1), - Some(VirtualKeyCode::Numpad2), - Some(VirtualKeyCode::Numpad3), - Some(VirtualKeyCode::Numpad0), - Some(VirtualKeyCode::NumpadDecimal), - None, // NULL KEY - None, // KEY_ZENKAKUHANKAKU - Some(VirtualKeyCode::OEM102), - Some(VirtualKeyCode::F11), - Some(VirtualKeyCode::F12), - None, // Rollover key - Some(VirtualKeyCode::Kana), - None, // KEY_HIRAGANA - None, // KEY_HENKAN - None, // KEY_KATAKANAHIRAGANA - None, // KEY_MUHENKAN - None, // KEY_KPJPCOMMA - None, // KEY_KPENTER - Some(VirtualKeyCode::RControl), - None, // KEY_KPSLASH - Some(VirtualKeyCode::Sysrq), - Some(VirtualKeyCode::RAlt), - None, // KEY_LINEFEED - Some(VirtualKeyCode::Home), - Some(VirtualKeyCode::Up), - Some(VirtualKeyCode::PageUp), - Some(VirtualKeyCode::Left), - Some(VirtualKeyCode::Right), - Some(VirtualKeyCode::End), - Some(VirtualKeyCode::Down), - Some(VirtualKeyCode::PageDown), - Some(VirtualKeyCode::Insert), - Some(VirtualKeyCode::Delete), - None, // KEY_MACRO - Some(VirtualKeyCode::Mute), - Some(VirtualKeyCode::VolumeDown), - Some(VirtualKeyCode::VolumeUp), - Some(VirtualKeyCode::Power), - None, // KEY_KPEQUAL - None, // KEY_KPPLUSMINUS - Some(VirtualKeyCode::Pause), - None, // KEY_SCALE - None, // KEY_KPCOMMA - None, // KEY_HANGEUL - None, // KEY_HANJA - Some(VirtualKeyCode::Yen), - Some(VirtualKeyCode::LWin), - Some(VirtualKeyCode::RWin), - Some(VirtualKeyCode::Compose), - Some(VirtualKeyCode::Stop), - None, // KEY_AGAIN - None, // KEY_PROPS - None, // KEY_UNDO - None, // KEY_FRONT - Some(VirtualKeyCode::Copy), - None, // KEY_OPEN - Some(VirtualKeyCode::Paste), - None, // KEY_FIND - Some(VirtualKeyCode::Cut), - None, // KEY_HELP - None, // KEY_MENU - Some(VirtualKeyCode::Calculator), - None, // KEY_SETUP - Some(VirtualKeyCode::Sleep), - Some(VirtualKeyCode::Wake), - None, // KEY_FILE - None, // KEY_SENDFILE - None, // KEY_DELETEFILE - None, // KEY_XFER - None, // KEY_PROG1 - None, // KEY_PROG1 - None, // KEY_PROG2 - None, // KEY_WWW - None, // KEY_MSDOS - None, // KEY_COFFEE - None, // KEY_ROTATE_DISPLAY - None, // KEY_CYCLEWINDOWS - Some(VirtualKeyCode::Mail), - None, // KEY_BOOKMARKS - Some(VirtualKeyCode::MyComputer), - Some(VirtualKeyCode::NavigateBackward), - Some(VirtualKeyCode::NavigateForward), - None, // KEY_CLOSECD - None, // KEY_EJECTCD - None, // KEY_EJECTCLOSECD - Some(VirtualKeyCode::NextTrack), - Some(VirtualKeyCode::PlayPause), - Some(VirtualKeyCode::PrevTrack), - None, // KEY_STOPCD - Some(VirtualKeyCode::MediaStop), - None, // KEY_RECORD - None, // KEY_REWIND - None, // KEY_PHONE - None, // KEY_ISO - None, // KEY_CONFIG - Some(VirtualKeyCode::WebHome), - Some(VirtualKeyCode::WebRefresh), - None, // KEY_EXIT - None, // KEY_MOVE - None, // KEY_EDIT - None, // KEY_SCROLLUP - None, // KEY_SCROLLDOWN - None, // KEY_KPLEFTPAREN - None, // KEY_KPRIGHTPAREN - None, // KEY_NEW - None, // KEY_REDO - Some(VirtualKeyCode::F13), - Some(VirtualKeyCode::F14), - Some(VirtualKeyCode::F15), - Some(VirtualKeyCode::F16), - Some(VirtualKeyCode::F17), - Some(VirtualKeyCode::F18), - Some(VirtualKeyCode::F19), - Some(VirtualKeyCode::F20), - Some(VirtualKeyCode::F21), - Some(VirtualKeyCode::F22), - Some(VirtualKeyCode::F23), - Some(VirtualKeyCode::F24), - None, // KEY_PLAYCD - None, // KEY_PAUSECD - None, // KEY_PROG3 - None, // KEY_PROG4 - None, // KEY_DASHBOARD - None, // KEY_SUSPEND - None, // KEY_CLOSE - None, // KEY_PLAY - None, // KEY_FASTFORWARD - None, // KEY_BASSBOOST - None, // KEY_PRINT - None, // KEY_HP - None, // KEY_CAMERA - None, // KEY_SOUND - None, // KEY_QUESTION - None, // KEY_EMAIL - None, // KEY_CHAT - Some(VirtualKeyCode::WebSearch), - None, // KEY_CONNECT - None, // KEY_FINANCE - None, // KEY_SPORT - None, // KEY_SHOP - None, // KEY_ALTERASE - None, // KEY_CANCEL - None, // KEY_BRIGHTNESSDOWN - None, // KEY_BRIGHTNESSUP - Some(VirtualKeyCode::MediaSelect), - None, // KEY_SWITCHVIDEOMODE - None, // KEY_KBDILLUMTOGGLE - None, // KEY_KBDILLUMDOWN - None, // KEY_KBDILLUMUP - None, // KEY_SEND - None, // KEY_REPLY - None, // KEY_FORWARDMAIL - None, // KEY_SAVE - None, // KEY_DOCUMENTS - None, // KEY_BATTERY -]; diff --git a/src/platform_impl/linux/drm/mod.rs b/src/platform_impl/linux/drm/mod.rs index 86d300e46e..7b31ef324a 100644 --- a/src/platform_impl/linux/drm/mod.rs +++ b/src/platform_impl/linux/drm/mod.rs @@ -1,7 +1,6 @@ use crate::dpi::{PhysicalPosition, PhysicalSize}; pub mod event_loop; -mod input_to_vk; pub mod window; pub use drm::SystemError; pub use event_loop::EventLoop; diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index 75a1c14747..eca933ce04 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -45,6 +45,8 @@ pub mod drm; pub mod wayland; #[cfg(feature = "x11")] pub mod x11; +#[cfg(any(feature = "kmsdrm", feature = "wayland"))] +pub mod xkb_keymap; /// Environment variable specifying which backend should be used on unix platform. /// diff --git a/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs b/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs index 7c320973b8..1164b2fb22 100644 --- a/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs +++ b/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs @@ -8,8 +8,8 @@ use crate::event::{ElementState, KeyboardInput, ModifiersState, WindowEvent}; use crate::platform_impl::wayland::event_loop::WinitState; use crate::platform_impl::wayland::{self, DeviceId}; -use super::keymap; use super::KeyboardInner; +use crate::platform_impl::xkb_keymap; #[inline] pub(super) fn handle_keyboard( @@ -68,7 +68,7 @@ pub(super) fn handle_keyboard( _ => unreachable!(), }; - let virtual_keycode = keymap::keysym_to_vkey(keysym); + let virtual_keycode = xkb_keymap::keysym_to_vkey(keysym); event_sink.push_window_event( #[allow(deprecated)] @@ -109,7 +109,7 @@ pub(super) fn handle_keyboard( None => return, }; - let virtual_keycode = keymap::keysym_to_vkey(keysym); + let virtual_keycode = xkb_keymap::keysym_to_vkey(keysym); event_sink.push_window_event( #[allow(deprecated)] diff --git a/src/platform_impl/linux/wayland/seat/keyboard/keymap.rs b/src/platform_impl/linux/wayland/seat/keyboard/keymap.rs deleted file mode 100644 index 991afff2c9..0000000000 --- a/src/platform_impl/linux/wayland/seat/keyboard/keymap.rs +++ /dev/null @@ -1,192 +0,0 @@ -//! Convert Wayland keys to winit keys. - -use crate::event::VirtualKeyCode; - -pub fn keysym_to_vkey(keysym: u32) -> Option { - use sctk::seat::keyboard::keysyms; - match keysym { - // Numbers. - keysyms::XKB_KEY_1 => Some(VirtualKeyCode::Key1), - keysyms::XKB_KEY_2 => Some(VirtualKeyCode::Key2), - keysyms::XKB_KEY_3 => Some(VirtualKeyCode::Key3), - keysyms::XKB_KEY_4 => Some(VirtualKeyCode::Key4), - keysyms::XKB_KEY_5 => Some(VirtualKeyCode::Key5), - keysyms::XKB_KEY_6 => Some(VirtualKeyCode::Key6), - keysyms::XKB_KEY_7 => Some(VirtualKeyCode::Key7), - keysyms::XKB_KEY_8 => Some(VirtualKeyCode::Key8), - keysyms::XKB_KEY_9 => Some(VirtualKeyCode::Key9), - keysyms::XKB_KEY_0 => Some(VirtualKeyCode::Key0), - // Letters. - keysyms::XKB_KEY_A | keysyms::XKB_KEY_a => Some(VirtualKeyCode::A), - keysyms::XKB_KEY_B | keysyms::XKB_KEY_b => Some(VirtualKeyCode::B), - keysyms::XKB_KEY_C | keysyms::XKB_KEY_c => Some(VirtualKeyCode::C), - keysyms::XKB_KEY_D | keysyms::XKB_KEY_d => Some(VirtualKeyCode::D), - keysyms::XKB_KEY_E | keysyms::XKB_KEY_e => Some(VirtualKeyCode::E), - keysyms::XKB_KEY_F | keysyms::XKB_KEY_f => Some(VirtualKeyCode::F), - keysyms::XKB_KEY_G | keysyms::XKB_KEY_g => Some(VirtualKeyCode::G), - keysyms::XKB_KEY_H | keysyms::XKB_KEY_h => Some(VirtualKeyCode::H), - keysyms::XKB_KEY_I | keysyms::XKB_KEY_i => Some(VirtualKeyCode::I), - keysyms::XKB_KEY_J | keysyms::XKB_KEY_j => Some(VirtualKeyCode::J), - keysyms::XKB_KEY_K | keysyms::XKB_KEY_k => Some(VirtualKeyCode::K), - keysyms::XKB_KEY_L | keysyms::XKB_KEY_l => Some(VirtualKeyCode::L), - keysyms::XKB_KEY_M | keysyms::XKB_KEY_m => Some(VirtualKeyCode::M), - keysyms::XKB_KEY_N | keysyms::XKB_KEY_n => Some(VirtualKeyCode::N), - keysyms::XKB_KEY_O | keysyms::XKB_KEY_o => Some(VirtualKeyCode::O), - keysyms::XKB_KEY_P | keysyms::XKB_KEY_p => Some(VirtualKeyCode::P), - keysyms::XKB_KEY_Q | keysyms::XKB_KEY_q => Some(VirtualKeyCode::Q), - keysyms::XKB_KEY_R | keysyms::XKB_KEY_r => Some(VirtualKeyCode::R), - keysyms::XKB_KEY_S | keysyms::XKB_KEY_s => Some(VirtualKeyCode::S), - keysyms::XKB_KEY_T | keysyms::XKB_KEY_t => Some(VirtualKeyCode::T), - keysyms::XKB_KEY_U | keysyms::XKB_KEY_u => Some(VirtualKeyCode::U), - keysyms::XKB_KEY_V | keysyms::XKB_KEY_v => Some(VirtualKeyCode::V), - keysyms::XKB_KEY_W | keysyms::XKB_KEY_w => Some(VirtualKeyCode::W), - keysyms::XKB_KEY_X | keysyms::XKB_KEY_x => Some(VirtualKeyCode::X), - keysyms::XKB_KEY_Y | keysyms::XKB_KEY_y => Some(VirtualKeyCode::Y), - keysyms::XKB_KEY_Z | keysyms::XKB_KEY_z => Some(VirtualKeyCode::Z), - // Escape. - keysyms::XKB_KEY_Escape => Some(VirtualKeyCode::Escape), - // Function keys. - keysyms::XKB_KEY_F1 => Some(VirtualKeyCode::F1), - keysyms::XKB_KEY_F2 => Some(VirtualKeyCode::F2), - keysyms::XKB_KEY_F3 => Some(VirtualKeyCode::F3), - keysyms::XKB_KEY_F4 => Some(VirtualKeyCode::F4), - keysyms::XKB_KEY_F5 => Some(VirtualKeyCode::F5), - keysyms::XKB_KEY_F6 => Some(VirtualKeyCode::F6), - keysyms::XKB_KEY_F7 => Some(VirtualKeyCode::F7), - keysyms::XKB_KEY_F8 => Some(VirtualKeyCode::F8), - keysyms::XKB_KEY_F9 => Some(VirtualKeyCode::F9), - keysyms::XKB_KEY_F10 => Some(VirtualKeyCode::F10), - keysyms::XKB_KEY_F11 => Some(VirtualKeyCode::F11), - keysyms::XKB_KEY_F12 => Some(VirtualKeyCode::F12), - keysyms::XKB_KEY_F13 => Some(VirtualKeyCode::F13), - keysyms::XKB_KEY_F14 => Some(VirtualKeyCode::F14), - keysyms::XKB_KEY_F15 => Some(VirtualKeyCode::F15), - keysyms::XKB_KEY_F16 => Some(VirtualKeyCode::F16), - keysyms::XKB_KEY_F17 => Some(VirtualKeyCode::F17), - keysyms::XKB_KEY_F18 => Some(VirtualKeyCode::F18), - keysyms::XKB_KEY_F19 => Some(VirtualKeyCode::F19), - keysyms::XKB_KEY_F20 => Some(VirtualKeyCode::F20), - keysyms::XKB_KEY_F21 => Some(VirtualKeyCode::F21), - keysyms::XKB_KEY_F22 => Some(VirtualKeyCode::F22), - keysyms::XKB_KEY_F23 => Some(VirtualKeyCode::F23), - keysyms::XKB_KEY_F24 => Some(VirtualKeyCode::F24), - // Flow control. - keysyms::XKB_KEY_Print => Some(VirtualKeyCode::Snapshot), - keysyms::XKB_KEY_Scroll_Lock => Some(VirtualKeyCode::Scroll), - keysyms::XKB_KEY_Pause => Some(VirtualKeyCode::Pause), - keysyms::XKB_KEY_Insert => Some(VirtualKeyCode::Insert), - keysyms::XKB_KEY_Home => Some(VirtualKeyCode::Home), - keysyms::XKB_KEY_Delete => Some(VirtualKeyCode::Delete), - keysyms::XKB_KEY_End => Some(VirtualKeyCode::End), - keysyms::XKB_KEY_Page_Down => Some(VirtualKeyCode::PageDown), - keysyms::XKB_KEY_Page_Up => Some(VirtualKeyCode::PageUp), - // Arrows. - keysyms::XKB_KEY_Left => Some(VirtualKeyCode::Left), - keysyms::XKB_KEY_Up => Some(VirtualKeyCode::Up), - keysyms::XKB_KEY_Right => Some(VirtualKeyCode::Right), - keysyms::XKB_KEY_Down => Some(VirtualKeyCode::Down), - - keysyms::XKB_KEY_BackSpace => Some(VirtualKeyCode::Back), - keysyms::XKB_KEY_Return => Some(VirtualKeyCode::Return), - keysyms::XKB_KEY_space => Some(VirtualKeyCode::Space), - - keysyms::XKB_KEY_Multi_key => Some(VirtualKeyCode::Compose), - keysyms::XKB_KEY_caret => Some(VirtualKeyCode::Caret), - - // Keypad. - keysyms::XKB_KEY_Num_Lock => Some(VirtualKeyCode::Numlock), - keysyms::XKB_KEY_KP_0 => Some(VirtualKeyCode::Numpad0), - keysyms::XKB_KEY_KP_1 => Some(VirtualKeyCode::Numpad1), - keysyms::XKB_KEY_KP_2 => Some(VirtualKeyCode::Numpad2), - keysyms::XKB_KEY_KP_3 => Some(VirtualKeyCode::Numpad3), - keysyms::XKB_KEY_KP_4 => Some(VirtualKeyCode::Numpad4), - keysyms::XKB_KEY_KP_5 => Some(VirtualKeyCode::Numpad5), - keysyms::XKB_KEY_KP_6 => Some(VirtualKeyCode::Numpad6), - keysyms::XKB_KEY_KP_7 => Some(VirtualKeyCode::Numpad7), - keysyms::XKB_KEY_KP_8 => Some(VirtualKeyCode::Numpad8), - keysyms::XKB_KEY_KP_9 => Some(VirtualKeyCode::Numpad9), - // Misc. - // => Some(VirtualKeyCode::AbntC1), - // => Some(VirtualKeyCode::AbntC2), - keysyms::XKB_KEY_plus => Some(VirtualKeyCode::Plus), - keysyms::XKB_KEY_apostrophe => Some(VirtualKeyCode::Apostrophe), - // => Some(VirtualKeyCode::Apps), - keysyms::XKB_KEY_at => Some(VirtualKeyCode::At), - // => Some(VirtualKeyCode::Ax), - keysyms::XKB_KEY_backslash => Some(VirtualKeyCode::Backslash), - keysyms::XKB_KEY_XF86Calculator => Some(VirtualKeyCode::Calculator), - // => Some(VirtualKeyCode::Capital), - keysyms::XKB_KEY_colon => Some(VirtualKeyCode::Colon), - keysyms::XKB_KEY_comma => Some(VirtualKeyCode::Comma), - // => Some(VirtualKeyCode::Convert), - keysyms::XKB_KEY_equal => Some(VirtualKeyCode::Equals), - keysyms::XKB_KEY_grave => Some(VirtualKeyCode::Grave), - // => Some(VirtualKeyCode::Kana), - keysyms::XKB_KEY_Kanji => Some(VirtualKeyCode::Kanji), - keysyms::XKB_KEY_Alt_L => Some(VirtualKeyCode::LAlt), - keysyms::XKB_KEY_bracketleft => Some(VirtualKeyCode::LBracket), - keysyms::XKB_KEY_Control_L => Some(VirtualKeyCode::LControl), - keysyms::XKB_KEY_Shift_L => Some(VirtualKeyCode::LShift), - keysyms::XKB_KEY_Super_L => Some(VirtualKeyCode::LWin), - keysyms::XKB_KEY_XF86Mail => Some(VirtualKeyCode::Mail), - // => Some(VirtualKeyCode::MediaSelect), - // => Some(VirtualKeyCode::MediaStop), - keysyms::XKB_KEY_minus => Some(VirtualKeyCode::Minus), - keysyms::XKB_KEY_asterisk => Some(VirtualKeyCode::Asterisk), - keysyms::XKB_KEY_XF86AudioMute => Some(VirtualKeyCode::Mute), - // => Some(VirtualKeyCode::MyComputer), - keysyms::XKB_KEY_XF86AudioNext => Some(VirtualKeyCode::NextTrack), - // => Some(VirtualKeyCode::NoConvert), - keysyms::XKB_KEY_KP_Separator => Some(VirtualKeyCode::NumpadComma), - keysyms::XKB_KEY_KP_Enter => Some(VirtualKeyCode::NumpadEnter), - keysyms::XKB_KEY_KP_Equal => Some(VirtualKeyCode::NumpadEquals), - keysyms::XKB_KEY_KP_Add => Some(VirtualKeyCode::NumpadAdd), - keysyms::XKB_KEY_KP_Subtract => Some(VirtualKeyCode::NumpadSubtract), - keysyms::XKB_KEY_KP_Multiply => Some(VirtualKeyCode::NumpadMultiply), - keysyms::XKB_KEY_KP_Divide => Some(VirtualKeyCode::NumpadDivide), - keysyms::XKB_KEY_KP_Decimal => Some(VirtualKeyCode::NumpadDecimal), - keysyms::XKB_KEY_KP_Page_Up => Some(VirtualKeyCode::PageUp), - keysyms::XKB_KEY_KP_Page_Down => Some(VirtualKeyCode::PageDown), - keysyms::XKB_KEY_KP_Home => Some(VirtualKeyCode::Home), - keysyms::XKB_KEY_KP_End => Some(VirtualKeyCode::End), - keysyms::XKB_KEY_KP_Left => Some(VirtualKeyCode::Left), - keysyms::XKB_KEY_KP_Up => Some(VirtualKeyCode::Up), - keysyms::XKB_KEY_KP_Right => Some(VirtualKeyCode::Right), - keysyms::XKB_KEY_KP_Down => Some(VirtualKeyCode::Down), - // => Some(VirtualKeyCode::OEM102), - keysyms::XKB_KEY_period => Some(VirtualKeyCode::Period), - // => Some(VirtualKeyCode::Playpause), - keysyms::XKB_KEY_XF86PowerOff => Some(VirtualKeyCode::Power), - keysyms::XKB_KEY_XF86AudioPrev => Some(VirtualKeyCode::PrevTrack), - keysyms::XKB_KEY_Alt_R => Some(VirtualKeyCode::RAlt), - keysyms::XKB_KEY_bracketright => Some(VirtualKeyCode::RBracket), - keysyms::XKB_KEY_Control_R => Some(VirtualKeyCode::RControl), - keysyms::XKB_KEY_Shift_R => Some(VirtualKeyCode::RShift), - keysyms::XKB_KEY_Super_R => Some(VirtualKeyCode::RWin), - keysyms::XKB_KEY_semicolon => Some(VirtualKeyCode::Semicolon), - keysyms::XKB_KEY_slash => Some(VirtualKeyCode::Slash), - keysyms::XKB_KEY_XF86Sleep => Some(VirtualKeyCode::Sleep), - // => Some(VirtualKeyCode::Stop), - // => Some(VirtualKeyCode::Sysrq), - keysyms::XKB_KEY_Tab => Some(VirtualKeyCode::Tab), - keysyms::XKB_KEY_ISO_Left_Tab => Some(VirtualKeyCode::Tab), - keysyms::XKB_KEY_underscore => Some(VirtualKeyCode::Underline), - // => Some(VirtualKeyCode::Unlabeled), - keysyms::XKB_KEY_XF86AudioLowerVolume => Some(VirtualKeyCode::VolumeDown), - keysyms::XKB_KEY_XF86AudioRaiseVolume => Some(VirtualKeyCode::VolumeUp), - // => Some(VirtualKeyCode::Wake), - // => Some(VirtualKeyCode::Webback), - // => Some(VirtualKeyCode::WebFavorites), - // => Some(VirtualKeyCode::WebForward), - // => Some(VirtualKeyCode::WebHome), - // => Some(VirtualKeyCode::WebRefresh), - // => Some(VirtualKeyCode::WebSearch), - // => Some(VirtualKeyCode::WebStop), - keysyms::XKB_KEY_yen => Some(VirtualKeyCode::Yen), - keysyms::XKB_KEY_XF86Copy => Some(VirtualKeyCode::Copy), - keysyms::XKB_KEY_XF86Paste => Some(VirtualKeyCode::Paste), - keysyms::XKB_KEY_XF86Cut => Some(VirtualKeyCode::Cut), - // Fallback. - _ => None, - } -} diff --git a/src/platform_impl/linux/wayland/seat/keyboard/mod.rs b/src/platform_impl/linux/wayland/seat/keyboard/mod.rs index 368906a8cc..77872208fd 100644 --- a/src/platform_impl/linux/wayland/seat/keyboard/mod.rs +++ b/src/platform_impl/linux/wayland/seat/keyboard/mod.rs @@ -16,7 +16,6 @@ use crate::platform_impl::wayland::event_loop::WinitState; use crate::platform_impl::wayland::WindowId; mod handlers; -mod keymap; pub(crate) struct Keyboard { pub keyboard: WlKeyboard, diff --git a/src/platform_impl/linux/xkb_keymap.rs b/src/platform_impl/linux/xkb_keymap.rs new file mode 100644 index 0000000000..13d35b7095 --- /dev/null +++ b/src/platform_impl/linux/xkb_keymap.rs @@ -0,0 +1,415 @@ +//! Convert Wayland keys to winit keys. +#![allow(non_upper_case_globals)] + +use crate::event::VirtualKeyCode; + +/* + * TTY function keys, cleverly chosen to map to ASCII, for convenience of + * programming, but could have been arbitrary (at the cost of lookup + * tables in client code). + */ + +pub const XKB_KEY_BackSpace: u32 = 0xff08; /* Back space, back char */ +pub const XKB_KEY_Tab: u32 = 0xff09; +pub const XKB_KEY_Return: u32 = 0xff0d; /* Return, enter */ +pub const XKB_KEY_Pause: u32 = 0xff13; /* Pause, hold */ +pub const XKB_KEY_Scroll_Lock: u32 = 0xff14; +pub const XKB_KEY_Sys_Req: u32 = 0xff15; +pub const XKB_KEY_Escape: u32 = 0xff1b; +pub const XKB_KEY_Delete: u32 = 0xffff; /* Delete, rubout */ + +/* International & multi-key character composition */ + +pub const XKB_KEY_Multi_key: u32 = 0xff20; /* Multi-key character compose */ +/* Japanese keyboard support */ + +pub const XKB_KEY_Kanji: u32 = 0xff21; /* Kanji, Kanji convert */ +/* :u32 = 0xff31; thru :u32 = 0xff3f; are under XK_KOREAN */ + +/* Cursor control & motion */ + +pub const XKB_KEY_Home: u32 = 0xff50; +pub const XKB_KEY_Left: u32 = 0xff51; /* Move left, left arrow */ +pub const XKB_KEY_Up: u32 = 0xff52; /* Move up, up arrow */ +pub const XKB_KEY_Right: u32 = 0xff53; /* Move right, right arrow */ +pub const XKB_KEY_Down: u32 = 0xff54; /* Move down, down arrow */ +pub const XKB_KEY_Page_Up: u32 = 0xff55; +pub const XKB_KEY_Page_Down: u32 = 0xff56; +pub const XKB_KEY_End: u32 = 0xff57; /* EOL */ + +/* Misc functions */ + +pub const XKB_KEY_Print: u32 = 0xff61; +pub const XKB_KEY_Insert: u32 = 0xff63; /* Insert, insert here */ +pub const XKB_KEY_Num_Lock: u32 = 0xff7f; + +/* Keypad functions, keypad numbers cleverly chosen to map to ASCII */ + +pub const XKB_KEY_KP_Enter: u32 = 0xff8d; /* Enter */ +pub const XKB_KEY_KP_Home: u32 = 0xff95; +pub const XKB_KEY_KP_Left: u32 = 0xff96; +pub const XKB_KEY_KP_Up: u32 = 0xff97; +pub const XKB_KEY_KP_Right: u32 = 0xff98; +pub const XKB_KEY_KP_Down: u32 = 0xff99; +pub const XKB_KEY_KP_Page_Up: u32 = 0xff9a; +pub const XKB_KEY_KP_Page_Down: u32 = 0xff9b; +pub const XKB_KEY_KP_End: u32 = 0xff9c; +pub const XKB_KEY_KP_Equal: u32 = 0xffbd; /* Equals */ +pub const XKB_KEY_KP_Multiply: u32 = 0xffaa; +pub const XKB_KEY_KP_Add: u32 = 0xffab; +pub const XKB_KEY_KP_Separator: u32 = 0xffac; /* Separator, often comma */ +pub const XKB_KEY_KP_Subtract: u32 = 0xffad; +pub const XKB_KEY_KP_Decimal: u32 = 0xffae; +pub const XKB_KEY_KP_Divide: u32 = 0xffaf; + +pub const XKB_KEY_KP_0: u32 = 0xffb0; +pub const XKB_KEY_KP_1: u32 = 0xffb1; +pub const XKB_KEY_KP_2: u32 = 0xffb2; +pub const XKB_KEY_KP_3: u32 = 0xffb3; +pub const XKB_KEY_KP_4: u32 = 0xffb4; +pub const XKB_KEY_KP_5: u32 = 0xffb5; +pub const XKB_KEY_KP_6: u32 = 0xffb6; +pub const XKB_KEY_KP_7: u32 = 0xffb7; +pub const XKB_KEY_KP_8: u32 = 0xffb8; +pub const XKB_KEY_KP_9: u32 = 0xffb9; + +/* + * Auxiliary functions; note the duplicate definitions for left and right + * function keys; Sun keyboards and a few other manufacturers have such + * function key groups on the left and/or right sides of the keyboard. + * We've not found a keyboard with more than 35 function keys total. + */ + +pub const XKB_KEY_F1: u32 = 0xffbe; +pub const XKB_KEY_F2: u32 = 0xffbf; +pub const XKB_KEY_F3: u32 = 0xffc0; +pub const XKB_KEY_F4: u32 = 0xffc1; +pub const XKB_KEY_F5: u32 = 0xffc2; +pub const XKB_KEY_F6: u32 = 0xffc3; +pub const XKB_KEY_F7: u32 = 0xffc4; +pub const XKB_KEY_F8: u32 = 0xffc5; +pub const XKB_KEY_F9: u32 = 0xffc6; +pub const XKB_KEY_F10: u32 = 0xffc7; +pub const XKB_KEY_F11: u32 = 0xffc8; +pub const XKB_KEY_F12: u32 = 0xffc9; +pub const XKB_KEY_F13: u32 = 0xffca; +pub const XKB_KEY_F14: u32 = 0xffcb; +pub const XKB_KEY_F15: u32 = 0xffcc; +pub const XKB_KEY_F16: u32 = 0xffcd; +pub const XKB_KEY_F17: u32 = 0xffce; +pub const XKB_KEY_F18: u32 = 0xffcf; +pub const XKB_KEY_F19: u32 = 0xffd0; +pub const XKB_KEY_F20: u32 = 0xffd1; +pub const XKB_KEY_F21: u32 = 0xffd2; +pub const XKB_KEY_F22: u32 = 0xffd3; +pub const XKB_KEY_F23: u32 = 0xffd4; +pub const XKB_KEY_F24: u32 = 0xffd5; + +/* Modifiers */ + +pub const XKB_KEY_Shift_L: u32 = 0xffe1; /* Left shift */ +pub const XKB_KEY_Shift_R: u32 = 0xffe2; /* Right shift */ +pub const XKB_KEY_Control_L: u32 = 0xffe3; /* Left control */ +pub const XKB_KEY_Control_R: u32 = 0xffe4; /* Right control */ + +pub const XKB_KEY_Meta_L: u32 = 0xffe7; /* Left meta */ +pub const XKB_KEY_Meta_R: u32 = 0xffe8; /* Right meta */ +pub const XKB_KEY_Alt_L: u32 = 0xffe9; /* Left alt */ +pub const XKB_KEY_Alt_R: u32 = 0xffea; /* Right alt */ +pub const XKB_KEY_Super_L: u32 = 0xffeb; /* Left super */ +pub const XKB_KEY_Super_R: u32 = 0xffec; /* Right super */ + +pub const XKB_KEY_ISO_Left_Tab: u32 = 0xfe20; + +/* + * Latin 1 + * (ISO/IEC 8859-1 = Unicode U+0020..U+00FF) + * Byte 3 = 0 + */ +pub const XKB_KEY_space: u32 = 0x0020; /* U+0020 SPACE */ +pub const XKB_KEY_apostrophe: u32 = 0x0027; /* U+0027 APOSTROPHE */ +pub const XKB_KEY_asterisk: u32 = 0x002a; /* U+002A ASTERISK */ +pub const XKB_KEY_plus: u32 = 0x002b; /* U+002B PLUS SIGN */ +pub const XKB_KEY_comma: u32 = 0x002c; /* U+002C COMMA */ +pub const XKB_KEY_minus: u32 = 0x002d; /* U+002D HYPHEN-MINUS */ +pub const XKB_KEY_period: u32 = 0x002e; /* U+002E FULL STOP */ +pub const XKB_KEY_slash: u32 = 0x002f; /* U+002F SOLIDUS */ +pub const XKB_KEY_0: u32 = 0x0030; /* U+0030 DIGIT ZERO */ +pub const XKB_KEY_1: u32 = 0x0031; /* U+0031 DIGIT ONE */ +pub const XKB_KEY_2: u32 = 0x0032; /* U+0032 DIGIT TWO */ +pub const XKB_KEY_3: u32 = 0x0033; /* U+0033 DIGIT THREE */ +pub const XKB_KEY_4: u32 = 0x0034; /* U+0034 DIGIT FOUR */ +pub const XKB_KEY_5: u32 = 0x0035; /* U+0035 DIGIT FIVE */ +pub const XKB_KEY_6: u32 = 0x0036; /* U+0036 DIGIT SIX */ +pub const XKB_KEY_7: u32 = 0x0037; /* U+0037 DIGIT SEVEN */ +pub const XKB_KEY_8: u32 = 0x0038; /* U+0038 DIGIT EIGHT */ +pub const XKB_KEY_9: u32 = 0x0039; /* U+0039 DIGIT NINE */ +pub const XKB_KEY_colon: u32 = 0x003a; /* U+003A COLON */ +pub const XKB_KEY_semicolon: u32 = 0x003b; /* U+003B SEMICOLON */ +pub const XKB_KEY_equal: u32 = 0x003d; /* U+003D EQUALS SIGN */ +pub const XKB_KEY_at: u32 = 0x0040; /* U+0040 COMMERCIAL AT */ +pub const XKB_KEY_A: u32 = 0x0041; /* U+0041 LATIN CAPITAL LETTER A */ +pub const XKB_KEY_B: u32 = 0x0042; /* U+0042 LATIN CAPITAL LETTER B */ +pub const XKB_KEY_C: u32 = 0x0043; /* U+0043 LATIN CAPITAL LETTER C */ +pub const XKB_KEY_D: u32 = 0x0044; /* U+0044 LATIN CAPITAL LETTER D */ +pub const XKB_KEY_E: u32 = 0x0045; /* U+0045 LATIN CAPITAL LETTER E */ +pub const XKB_KEY_F: u32 = 0x0046; /* U+0046 LATIN CAPITAL LETTER F */ +pub const XKB_KEY_G: u32 = 0x0047; /* U+0047 LATIN CAPITAL LETTER G */ +pub const XKB_KEY_H: u32 = 0x0048; /* U+0048 LATIN CAPITAL LETTER H */ +pub const XKB_KEY_I: u32 = 0x0049; /* U+0049 LATIN CAPITAL LETTER I */ +pub const XKB_KEY_J: u32 = 0x004a; /* U+004A LATIN CAPITAL LETTER J */ +pub const XKB_KEY_K: u32 = 0x004b; /* U+004B LATIN CAPITAL LETTER K */ +pub const XKB_KEY_L: u32 = 0x004c; /* U+004C LATIN CAPITAL LETTER L */ +pub const XKB_KEY_M: u32 = 0x004d; /* U+004D LATIN CAPITAL LETTER M */ +pub const XKB_KEY_N: u32 = 0x004e; /* U+004E LATIN CAPITAL LETTER N */ +pub const XKB_KEY_O: u32 = 0x004f; /* U+004F LATIN CAPITAL LETTER O */ +pub const XKB_KEY_P: u32 = 0x0050; /* U+0050 LATIN CAPITAL LETTER P */ +pub const XKB_KEY_Q: u32 = 0x0051; /* U+0051 LATIN CAPITAL LETTER Q */ +pub const XKB_KEY_R: u32 = 0x0052; /* U+0052 LATIN CAPITAL LETTER R */ +pub const XKB_KEY_S: u32 = 0x0053; /* U+0053 LATIN CAPITAL LETTER S */ +pub const XKB_KEY_T: u32 = 0x0054; /* U+0054 LATIN CAPITAL LETTER T */ +pub const XKB_KEY_U: u32 = 0x0055; /* U+0055 LATIN CAPITAL LETTER U */ +pub const XKB_KEY_V: u32 = 0x0056; /* U+0056 LATIN CAPITAL LETTER V */ +pub const XKB_KEY_W: u32 = 0x0057; /* U+0057 LATIN CAPITAL LETTER W */ +pub const XKB_KEY_X: u32 = 0x0058; /* U+0058 LATIN CAPITAL LETTER X */ +pub const XKB_KEY_Y: u32 = 0x0059; /* U+0059 LATIN CAPITAL LETTER Y */ +pub const XKB_KEY_Z: u32 = 0x005a; /* U+005A LATIN CAPITAL LETTER Z */ +pub const XKB_KEY_bracketleft: u32 = 0x005b; /* U+005B LEFT SQUARE BRACKET */ +pub const XKB_KEY_backslash: u32 = 0x005c; /* U+005C REVERSE SOLIDUS */ +pub const XKB_KEY_bracketright: u32 = 0x005d; /* U+005D RIGHT SQUARE BRACKET */ +pub const XKB_KEY_underscore: u32 = 0x005f; /* U+005F LOW LINE */ +pub const XKB_KEY_grave: u32 = 0x0060; /* U+0060 GRAVE ACCENT */ +pub const XKB_KEY_a: u32 = 0x0061; /* U+0061 LATIN SMALL LETTER A */ +pub const XKB_KEY_b: u32 = 0x0062; /* U+0062 LATIN SMALL LETTER B */ +pub const XKB_KEY_c: u32 = 0x0063; /* U+0063 LATIN SMALL LETTER C */ +pub const XKB_KEY_d: u32 = 0x0064; /* U+0064 LATIN SMALL LETTER D */ +pub const XKB_KEY_e: u32 = 0x0065; /* U+0065 LATIN SMALL LETTER E */ +pub const XKB_KEY_f: u32 = 0x0066; /* U+0066 LATIN SMALL LETTER F */ +pub const XKB_KEY_g: u32 = 0x0067; /* U+0067 LATIN SMALL LETTER G */ +pub const XKB_KEY_h: u32 = 0x0068; /* U+0068 LATIN SMALL LETTER H */ +pub const XKB_KEY_i: u32 = 0x0069; /* U+0069 LATIN SMALL LETTER I */ +pub const XKB_KEY_j: u32 = 0x006a; /* U+006A LATIN SMALL LETTER J */ +pub const XKB_KEY_k: u32 = 0x006b; /* U+006B LATIN SMALL LETTER K */ +pub const XKB_KEY_l: u32 = 0x006c; /* U+006C LATIN SMALL LETTER L */ +pub const XKB_KEY_m: u32 = 0x006d; /* U+006D LATIN SMALL LETTER M */ +pub const XKB_KEY_n: u32 = 0x006e; /* U+006E LATIN SMALL LETTER N */ +pub const XKB_KEY_o: u32 = 0x006f; /* U+006F LATIN SMALL LETTER O */ +pub const XKB_KEY_p: u32 = 0x0070; /* U+0070 LATIN SMALL LETTER P */ +pub const XKB_KEY_q: u32 = 0x0071; /* U+0071 LATIN SMALL LETTER Q */ +pub const XKB_KEY_r: u32 = 0x0072; /* U+0072 LATIN SMALL LETTER R */ +pub const XKB_KEY_s: u32 = 0x0073; /* U+0073 LATIN SMALL LETTER S */ +pub const XKB_KEY_t: u32 = 0x0074; /* U+0074 LATIN SMALL LETTER T */ +pub const XKB_KEY_u: u32 = 0x0075; /* U+0075 LATIN SMALL LETTER U */ +pub const XKB_KEY_v: u32 = 0x0076; /* U+0076 LATIN SMALL LETTER V */ +pub const XKB_KEY_w: u32 = 0x0077; /* U+0077 LATIN SMALL LETTER W */ +pub const XKB_KEY_x: u32 = 0x0078; /* U+0078 LATIN SMALL LETTER X */ +pub const XKB_KEY_y: u32 = 0x0079; /* U+0079 LATIN SMALL LETTER Y */ +pub const XKB_KEY_z: u32 = 0x007a; /* U+007A LATIN SMALL LETTER Z */ +pub const XKB_KEY_yen: u32 = 0x00a5; /* U+00A5 YEN SIGN */ +pub const XKB_KEY_caret: u32 = 0x0afc; /* U+2038 CARET */ + +/* + * Keys found on some "Internet" keyboards. + */ +pub const XKB_KEY_XF86AudioLowerVolume: u32 = 0x1008FF11; /* Volume control down */ +pub const XKB_KEY_XF86AudioMute: u32 = 0x1008FF12; /* Mute sound from the system */ +pub const XKB_KEY_XF86AudioRaiseVolume: u32 = 0x1008FF13; /* Volume control up */ +pub const XKB_KEY_XF86AudioPrev: u32 = 0x1008FF16; /* Previous track */ +pub const XKB_KEY_XF86AudioNext: u32 = 0x1008FF17; /* Next track */ +pub const XKB_KEY_XF86Mail: u32 = 0x1008FF19; /* Invoke user's mail program */ + +/* These are sometimes found on PDA's (e.g. Palm, PocketPC or elsewhere) */ +pub const XKB_KEY_XF86Calculator: u32 = 0x1008FF1D; /* Invoke calculator program */ +pub const XKB_KEY_XF86PowerOff: u32 = 0x1008FF2A; /* Power off system entirely */ +pub const XKB_KEY_XF86Sleep: u32 = 0x1008FF2F; /* Put system to sleep */ +pub const XKB_KEY_XF86Copy: u32 = 0x1008FF57; /* Copy selection */ +pub const XKB_KEY_XF86Cut: u32 = 0x1008FF58; /* Cut selection */ +pub const XKB_KEY_XF86Paste: u32 = 0x1008FF6D; /* Paste */ + +pub fn keysym_to_vkey(keysym: u32) -> Option { + match keysym { + // Numbers. + XKB_KEY_1 => Some(VirtualKeyCode::Key1), + XKB_KEY_2 => Some(VirtualKeyCode::Key2), + XKB_KEY_3 => Some(VirtualKeyCode::Key3), + XKB_KEY_4 => Some(VirtualKeyCode::Key4), + XKB_KEY_5 => Some(VirtualKeyCode::Key5), + XKB_KEY_6 => Some(VirtualKeyCode::Key6), + XKB_KEY_7 => Some(VirtualKeyCode::Key7), + XKB_KEY_8 => Some(VirtualKeyCode::Key8), + XKB_KEY_9 => Some(VirtualKeyCode::Key9), + XKB_KEY_0 => Some(VirtualKeyCode::Key0), + // Letters. + XKB_KEY_A | XKB_KEY_a => Some(VirtualKeyCode::A), + XKB_KEY_B | XKB_KEY_b => Some(VirtualKeyCode::B), + XKB_KEY_C | XKB_KEY_c => Some(VirtualKeyCode::C), + XKB_KEY_D | XKB_KEY_d => Some(VirtualKeyCode::D), + XKB_KEY_E | XKB_KEY_e => Some(VirtualKeyCode::E), + XKB_KEY_F | XKB_KEY_f => Some(VirtualKeyCode::F), + XKB_KEY_G | XKB_KEY_g => Some(VirtualKeyCode::G), + XKB_KEY_H | XKB_KEY_h => Some(VirtualKeyCode::H), + XKB_KEY_I | XKB_KEY_i => Some(VirtualKeyCode::I), + XKB_KEY_J | XKB_KEY_j => Some(VirtualKeyCode::J), + XKB_KEY_K | XKB_KEY_k => Some(VirtualKeyCode::K), + XKB_KEY_L | XKB_KEY_l => Some(VirtualKeyCode::L), + XKB_KEY_M | XKB_KEY_m => Some(VirtualKeyCode::M), + XKB_KEY_N | XKB_KEY_n => Some(VirtualKeyCode::N), + XKB_KEY_O | XKB_KEY_o => Some(VirtualKeyCode::O), + XKB_KEY_P | XKB_KEY_p => Some(VirtualKeyCode::P), + XKB_KEY_Q | XKB_KEY_q => Some(VirtualKeyCode::Q), + XKB_KEY_R | XKB_KEY_r => Some(VirtualKeyCode::R), + XKB_KEY_S | XKB_KEY_s => Some(VirtualKeyCode::S), + XKB_KEY_T | XKB_KEY_t => Some(VirtualKeyCode::T), + XKB_KEY_U | XKB_KEY_u => Some(VirtualKeyCode::U), + XKB_KEY_V | XKB_KEY_v => Some(VirtualKeyCode::V), + XKB_KEY_W | XKB_KEY_w => Some(VirtualKeyCode::W), + XKB_KEY_X | XKB_KEY_x => Some(VirtualKeyCode::X), + XKB_KEY_Y | XKB_KEY_y => Some(VirtualKeyCode::Y), + XKB_KEY_Z | XKB_KEY_z => Some(VirtualKeyCode::Z), + // Escape. + XKB_KEY_Escape => Some(VirtualKeyCode::Escape), + // Function keys. + XKB_KEY_F1 => Some(VirtualKeyCode::F1), + XKB_KEY_F2 => Some(VirtualKeyCode::F2), + XKB_KEY_F3 => Some(VirtualKeyCode::F3), + XKB_KEY_F4 => Some(VirtualKeyCode::F4), + XKB_KEY_F5 => Some(VirtualKeyCode::F5), + XKB_KEY_F6 => Some(VirtualKeyCode::F6), + XKB_KEY_F7 => Some(VirtualKeyCode::F7), + XKB_KEY_F8 => Some(VirtualKeyCode::F8), + XKB_KEY_F9 => Some(VirtualKeyCode::F9), + XKB_KEY_F10 => Some(VirtualKeyCode::F10), + XKB_KEY_F11 => Some(VirtualKeyCode::F11), + XKB_KEY_F12 => Some(VirtualKeyCode::F12), + XKB_KEY_F13 => Some(VirtualKeyCode::F13), + XKB_KEY_F14 => Some(VirtualKeyCode::F14), + XKB_KEY_F15 => Some(VirtualKeyCode::F15), + XKB_KEY_F16 => Some(VirtualKeyCode::F16), + XKB_KEY_F17 => Some(VirtualKeyCode::F17), + XKB_KEY_F18 => Some(VirtualKeyCode::F18), + XKB_KEY_F19 => Some(VirtualKeyCode::F19), + XKB_KEY_F20 => Some(VirtualKeyCode::F20), + XKB_KEY_F21 => Some(VirtualKeyCode::F21), + XKB_KEY_F22 => Some(VirtualKeyCode::F22), + XKB_KEY_F23 => Some(VirtualKeyCode::F23), + XKB_KEY_F24 => Some(VirtualKeyCode::F24), + // Flow control. + XKB_KEY_Print => Some(VirtualKeyCode::Snapshot), + XKB_KEY_Scroll_Lock => Some(VirtualKeyCode::Scroll), + XKB_KEY_Pause => Some(VirtualKeyCode::Pause), + XKB_KEY_Insert => Some(VirtualKeyCode::Insert), + XKB_KEY_Home => Some(VirtualKeyCode::Home), + XKB_KEY_Delete => Some(VirtualKeyCode::Delete), + XKB_KEY_End => Some(VirtualKeyCode::End), + XKB_KEY_Page_Down => Some(VirtualKeyCode::PageDown), + XKB_KEY_Page_Up => Some(VirtualKeyCode::PageUp), + // Arrows. + XKB_KEY_Left => Some(VirtualKeyCode::Left), + XKB_KEY_Up => Some(VirtualKeyCode::Up), + XKB_KEY_Right => Some(VirtualKeyCode::Right), + XKB_KEY_Down => Some(VirtualKeyCode::Down), + + XKB_KEY_BackSpace => Some(VirtualKeyCode::Back), + XKB_KEY_Return => Some(VirtualKeyCode::Return), + XKB_KEY_space => Some(VirtualKeyCode::Space), + + XKB_KEY_Multi_key => Some(VirtualKeyCode::Compose), + XKB_KEY_caret => Some(VirtualKeyCode::Caret), + + // Keypad. + XKB_KEY_Num_Lock => Some(VirtualKeyCode::Numlock), + XKB_KEY_KP_0 => Some(VirtualKeyCode::Numpad0), + XKB_KEY_KP_1 => Some(VirtualKeyCode::Numpad1), + XKB_KEY_KP_2 => Some(VirtualKeyCode::Numpad2), + XKB_KEY_KP_3 => Some(VirtualKeyCode::Numpad3), + XKB_KEY_KP_4 => Some(VirtualKeyCode::Numpad4), + XKB_KEY_KP_5 => Some(VirtualKeyCode::Numpad5), + XKB_KEY_KP_6 => Some(VirtualKeyCode::Numpad6), + XKB_KEY_KP_7 => Some(VirtualKeyCode::Numpad7), + XKB_KEY_KP_8 => Some(VirtualKeyCode::Numpad8), + XKB_KEY_KP_9 => Some(VirtualKeyCode::Numpad9), + // Misc. + // => Some(VirtualKeyCode::AbntC1), + // => Some(VirtualKeyCode::AbntC2), + XKB_KEY_plus => Some(VirtualKeyCode::Plus), + XKB_KEY_apostrophe => Some(VirtualKeyCode::Apostrophe), + // => Some(VirtualKeyCode::Apps), + XKB_KEY_at => Some(VirtualKeyCode::At), + // => Some(VirtualKeyCode::Ax), + XKB_KEY_backslash => Some(VirtualKeyCode::Backslash), + XKB_KEY_XF86Calculator => Some(VirtualKeyCode::Calculator), + // => Some(VirtualKeyCode::Capital), + XKB_KEY_colon => Some(VirtualKeyCode::Colon), + XKB_KEY_comma => Some(VirtualKeyCode::Comma), + // => Some(VirtualKeyCode::Convert), + XKB_KEY_equal => Some(VirtualKeyCode::Equals), + XKB_KEY_grave => Some(VirtualKeyCode::Grave), + // => Some(VirtualKeyCode::Kana), + XKB_KEY_Kanji => Some(VirtualKeyCode::Kanji), + XKB_KEY_Alt_L => Some(VirtualKeyCode::LAlt), + XKB_KEY_bracketleft => Some(VirtualKeyCode::LBracket), + XKB_KEY_Control_L => Some(VirtualKeyCode::LControl), + XKB_KEY_Shift_L => Some(VirtualKeyCode::LShift), + XKB_KEY_Super_L => Some(VirtualKeyCode::LWin), + XKB_KEY_XF86Mail => Some(VirtualKeyCode::Mail), + // => Some(VirtualKeyCode::MediaSelect), + // => Some(VirtualKeyCode::MediaStop), + XKB_KEY_minus => Some(VirtualKeyCode::Minus), + XKB_KEY_asterisk => Some(VirtualKeyCode::Asterisk), + XKB_KEY_XF86AudioMute => Some(VirtualKeyCode::Mute), + // => Some(VirtualKeyCode::MyComputer), + XKB_KEY_XF86AudioNext => Some(VirtualKeyCode::NextTrack), + // => Some(VirtualKeyCode::NoConvert), + XKB_KEY_KP_Separator => Some(VirtualKeyCode::NumpadComma), + XKB_KEY_KP_Enter => Some(VirtualKeyCode::NumpadEnter), + XKB_KEY_KP_Equal => Some(VirtualKeyCode::NumpadEquals), + XKB_KEY_KP_Add => Some(VirtualKeyCode::NumpadAdd), + XKB_KEY_KP_Subtract => Some(VirtualKeyCode::NumpadSubtract), + XKB_KEY_KP_Multiply => Some(VirtualKeyCode::NumpadMultiply), + XKB_KEY_KP_Divide => Some(VirtualKeyCode::NumpadDivide), + XKB_KEY_KP_Decimal => Some(VirtualKeyCode::NumpadDecimal), + XKB_KEY_KP_Page_Up => Some(VirtualKeyCode::PageUp), + XKB_KEY_KP_Page_Down => Some(VirtualKeyCode::PageDown), + XKB_KEY_KP_Home => Some(VirtualKeyCode::Home), + XKB_KEY_KP_End => Some(VirtualKeyCode::End), + XKB_KEY_KP_Left => Some(VirtualKeyCode::Left), + XKB_KEY_KP_Up => Some(VirtualKeyCode::Up), + XKB_KEY_KP_Right => Some(VirtualKeyCode::Right), + XKB_KEY_KP_Down => Some(VirtualKeyCode::Down), + // => Some(VirtualKeyCode::OEM102), + XKB_KEY_period => Some(VirtualKeyCode::Period), + // => Some(VirtualKeyCode::Playpause), + XKB_KEY_XF86PowerOff => Some(VirtualKeyCode::Power), + XKB_KEY_XF86AudioPrev => Some(VirtualKeyCode::PrevTrack), + XKB_KEY_Alt_R => Some(VirtualKeyCode::RAlt), + XKB_KEY_bracketright => Some(VirtualKeyCode::RBracket), + XKB_KEY_Control_R => Some(VirtualKeyCode::RControl), + XKB_KEY_Shift_R => Some(VirtualKeyCode::RShift), + XKB_KEY_Super_R => Some(VirtualKeyCode::RWin), + XKB_KEY_semicolon => Some(VirtualKeyCode::Semicolon), + XKB_KEY_slash => Some(VirtualKeyCode::Slash), + XKB_KEY_XF86Sleep => Some(VirtualKeyCode::Sleep), + // => Some(VirtualKeyCode::Stop), + // => Some(VirtualKeyCode::Sysrq), + XKB_KEY_Tab => Some(VirtualKeyCode::Tab), + XKB_KEY_ISO_Left_Tab => Some(VirtualKeyCode::Tab), + XKB_KEY_underscore => Some(VirtualKeyCode::Underline), + // => Some(VirtualKeyCode::Unlabeled), + XKB_KEY_XF86AudioLowerVolume => Some(VirtualKeyCode::VolumeDown), + XKB_KEY_XF86AudioRaiseVolume => Some(VirtualKeyCode::VolumeUp), + // => Some(VirtualKeyCode::Wake), + // => Some(VirtualKeyCode::Webback), + // => Some(VirtualKeyCode::WebFavorites), + // => Some(VirtualKeyCode::WebForward), + // => Some(VirtualKeyCode::WebHome), + // => Some(VirtualKeyCode::WebRefresh), + // => Some(VirtualKeyCode::WebSearch), + // => Some(VirtualKeyCode::WebStop), + XKB_KEY_yen => Some(VirtualKeyCode::Yen), + XKB_KEY_XF86Copy => Some(VirtualKeyCode::Copy), + XKB_KEY_XF86Paste => Some(VirtualKeyCode::Paste), + XKB_KEY_XF86Cut => Some(VirtualKeyCode::Cut), + // Fallback. + _ => None, + } +} From f9458b0194bf84dd3a4a2cdbcf7de73092472b4c Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Thu, 5 May 2022 17:42:07 -0400 Subject: [PATCH 056/151] Fix dependencies --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2192841c1e..fffc8666cd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,11 +17,11 @@ default-target = "x86_64-unknown-linux-gnu" targets = ["i686-pc-windows-msvc", "x86_64-pc-windows-msvc", "i686-unknown-linux-gnu", "x86_64-unknown-linux-gnu", "x86_64-apple-darwin", "wasm32-unknown-unknown"] [features] -default = ["x11", "wayland", "wayland-dlopen", "kmsdrm", "xkbcommon"] +default = ["x11", "wayland", "wayland-dlopen", "kmsdrm"] x11 = ["x11-dl", "mio", "percent-encoding", "parking_lot"] wayland = ["wayland-client", "wayland-protocols", "sctk", "calloop"] wayland-dlopen = ["sctk/dlopen", "wayland-client/dlopen"] -kmsdrm = ["drm", "input", "calloop", "libseat"] +kmsdrm = ["drm", "input", "calloop", "libseat", "xkbcommon"] [dependencies] instant = { version = "0.1.12", features = ["wasm-bindgen"] } From 0c6fe1a3b9427dbdbc3bc62278ecedb53adf5375 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Thu, 5 May 2022 18:01:57 -0400 Subject: [PATCH 057/151] Fix xkb --- src/platform_impl/linux/drm/event_loop.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index 43805046cb..6a4b67b149 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -720,9 +720,9 @@ impl EventLoop { let keymap = xkb::Keymap::new_from_names( &xkb_ctx, "", - "", - "", - "", + "pc101", + "us", + "qwerty", None, xkb::KEYMAP_COMPILE_NO_FLAGS, ) From 54b29a15f76db73b63facb5324c8c2f711117c4f Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Thu, 5 May 2022 18:08:19 -0400 Subject: [PATCH 058/151] Fix xkb --- src/platform_impl/linux/drm/event_loop.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index 6a4b67b149..f17a86e46f 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -720,7 +720,7 @@ impl EventLoop { let keymap = xkb::Keymap::new_from_names( &xkb_ctx, "", - "pc101", + "pc105", "us", "qwerty", None, From d752b519a3bf0b269ab436b6dcf7833afe9b0c7d Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Thu, 5 May 2022 18:46:54 -0400 Subject: [PATCH 059/151] Fix xkb --- src/platform_impl/linux/drm/event_loop.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index f17a86e46f..67387b1b5d 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -494,7 +494,7 @@ impl EventSource for LibinputInputBackend { let k = if let input::event::KeyboardEvent::Key(key) = ev { key.key() } else { - unsafe { core::hint::unreachable_unchecked() } + unreachable!() }; let keysym = self.xkb_ctx.key_get_one_sym(k + 8); let virtual_keycode = xkb_keymap::keysym_to_vkey(keysym); @@ -504,7 +504,7 @@ impl EventSource for LibinputInputBackend { k + 8, match state { ElementState::Pressed => xkb::KeyDirection::Down, - ElementState::Released => xkb::KeyDirection::Down, + ElementState::Released => xkb::KeyDirection::Up, }, ); let input = KeyboardInput { @@ -720,9 +720,9 @@ impl EventLoop { let keymap = xkb::Keymap::new_from_names( &xkb_ctx, "", - "pc105", - "us", - "qwerty", + "", + "", + "", None, xkb::KEYMAP_COMPILE_NO_FLAGS, ) From ff6666b06f7096a9a71c40b5cd630498b49607e4 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Thu, 5 May 2022 19:00:22 -0400 Subject: [PATCH 060/151] Fix xkb --- src/platform_impl/linux/drm/event_loop.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index 67387b1b5d..3269b9ca35 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -496,12 +496,13 @@ impl EventSource for LibinputInputBackend { } else { unreachable!() }; - let keysym = self.xkb_ctx.key_get_one_sym(k + 8); + let key_offset = k + 8; + let keysym = self.xkb_ctx.key_get_one_sym(key_offset); let virtual_keycode = xkb_keymap::keysym_to_vkey(keysym); - let should_repeat = self.xkb_keymap.key_repeats(keysym); - let ch = self.xkb_ctx.key_get_utf8(keysym).chars().next(); + let should_repeat = self.xkb_keymap.key_repeats(key_offset); + let ch = self.xkb_ctx.key_get_utf8(key_offset).chars().next(); self.xkb_ctx.update_key( - k + 8, + key_offset, match state { ElementState::Pressed => xkb::KeyDirection::Down, ElementState::Released => xkb::KeyDirection::Up, @@ -593,7 +594,7 @@ impl EventSource for LibinputInputBackend { window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), event: crate::event::WindowEvent::ModifiersChanged(self.modifiers)}, &mut ()); } - xkb_keymap::XKB_KEY_Sys_Req // SysRq + xkb_keymap::XKB_KEY_Sys_Req | xkb_keymap::XKB_KEY_Print => { if self.modifiers.is_empty() { callback(crate::event::Event::WindowEvent { From 7c95388fcccdbce564d2c1e90f477c7d6d0d2a82 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Thu, 5 May 2022 20:30:06 -0400 Subject: [PATCH 061/151] Add customizability support --- src/platform_impl/linux/drm/event_loop.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index 3269b9ca35..c9fe58cbc5 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -724,7 +724,7 @@ impl EventLoop { "", "", "", - None, + std::env::var("WINIT_XKB_OPTIONS").ok(), xkb::KEYMAP_COMPILE_NO_FLAGS, ) .ok_or(crate::error::OsError::new( From 3889680ad3000202a643c0df2ea0f2f1e870fbd7 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Thu, 5 May 2022 21:25:31 -0400 Subject: [PATCH 062/151] xkbcommon pointer fix --- Cargo.toml | 2 +- src/platform_impl/linux/drm/event_loop.rs | 32 +++++++++++------------ 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index fffc8666cd..9af291a476 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -101,7 +101,7 @@ libc = "0.2.125" drm = { version = "0.6.2", optional = true } input = { version = "0.7.1", optional = true } libseat = { version = "0.1.4", optional = true } -xkbcommon = { version = "0.4.0", optional = true } +xkbcommon = { git = "https://github.com/StratusFearMe21/xkbcommon-rs", optional = true } [target.'cfg(target_arch = "wasm32")'.dependencies] wasm-bindgen= "0.2.80" diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index c9fe58cbc5..f0239e42e6 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -717,22 +717,6 @@ pub(crate) fn find_prop_id( impl EventLoop { pub fn new() -> Result, crate::error::OsError> { - let xkb_ctx = xkb::Context::new(xkb::CONTEXT_NO_FLAGS); - let keymap = xkb::Keymap::new_from_names( - &xkb_ctx, - "", - "", - "", - "", - std::env::var("WINIT_XKB_OPTIONS").ok(), - xkb::KEYMAP_COMPILE_NO_FLAGS, - ) - .ok_or(crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc("Failed to compile XKB keymap"), - ))?; - let state = xkb::State::new(&keymap); let mut seat = { let active = Arc::new(AtomicBool::new(false)); let t_active = active.clone(); @@ -773,6 +757,22 @@ impl EventLoop { let drm = Card(std::sync::Arc::new(dev.1)); let mut input = input::Libinput::new_with_udev(Interface(seat, HashMap::new())); input.udev_assign_seat("seat0").unwrap(); + let xkb_ctx = xkb::Context::new(xkb::CONTEXT_NO_FLAGS); + let keymap = xkb::Keymap::new_from_names( + &xkb_ctx, + "", + "", + "", + "", + std::env::var("WINIT_XKB_OPTIONS").ok(), + xkb::KEYMAP_COMPILE_NO_FLAGS, + ) + .ok_or(crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Failed to compile XKB keymap"), + ))?; + let state = xkb::State::new(&keymap); drm::Device::set_client_capability(&drm, drm::ClientCapability::UniversalPlanes, true).or( Err(crate::error::OsError::new( From 9c78f8b01ea4772496bb5883614ba41f31f6bc6d Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Thu, 5 May 2022 22:18:50 -0400 Subject: [PATCH 063/151] Add compose support --- src/platform_impl/linux/drm/event_loop.rs | 117 ++++++++++++++++++---- 1 file changed, 99 insertions(+), 18 deletions(-) diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index f0239e42e6..d6d12dffc2 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -53,6 +53,8 @@ pub struct LibinputInputBackend { context: input::Libinput, xkb_ctx: xkb::State, xkb_keymap: xkb::Keymap, + xkb_compose: xkb::compose::State, + compose_state: bool, token: Token, touch_location: PhysicalPosition, screen_size: (u32, u32), @@ -71,8 +73,9 @@ impl LibinputInputBackend { screen_size: (u32, u32), timer_handle: calloop::timer::TimerHandle<(KeyboardInput, Option)>, xkb_ctx: xkb::State, - xkb_keymap: xkb::Keymap, // cursor_plane: drm::control::plane::Handle, - // cursor_buffer: drm::control::framebuffer::Handle + xkb_keymap: xkb::Keymap, + xkb_compose: xkb::compose::State, // cursor_plane: drm::control::plane::Handle, + // cursor_buffer: drm::control::framebuffer::Handle ) -> Self { LibinputInputBackend { context, @@ -84,6 +87,8 @@ impl LibinputInputBackend { timer_handle, xkb_ctx, xkb_keymap, + xkb_compose, + compose_state: false // cursor_buffer, // cursor_plane, } @@ -499,8 +504,6 @@ impl EventSource for LibinputInputBackend { let key_offset = k + 8; let keysym = self.xkb_ctx.key_get_one_sym(key_offset); let virtual_keycode = xkb_keymap::keysym_to_vkey(keysym); - let should_repeat = self.xkb_keymap.key_repeats(key_offset); - let ch = self.xkb_ctx.key_get_utf8(key_offset).chars().next(); self.xkb_ctx.update_key( key_offset, match state { @@ -531,20 +534,80 @@ impl EventSource for LibinputInputBackend { &mut (), ); if let crate::event::ElementState::Pressed = state { - if should_repeat { - self.timer_handle - .add_timeout(Duration::from_millis(600), (input, ch)); - } - if let Some(c) = ch { - callback( - crate::event::Event::WindowEvent { - window_id: crate::window::WindowId( - crate::platform_impl::WindowId::Drm(super::WindowId), - ), - event: crate::event::WindowEvent::ReceivedCharacter(c), - }, - &mut (), - ); + if !self.compose_state { + let should_repeat = self.xkb_keymap.key_repeats(key_offset); + let ch = self.xkb_ctx.key_get_utf8(key_offset).chars().next(); + if should_repeat { + self.timer_handle + .add_timeout(Duration::from_millis(600), (input, ch)); + } + if let Some(c) = ch { + callback( + crate::event::Event::WindowEvent { + window_id: crate::window::WindowId( + crate::platform_impl::WindowId::Drm( + super::WindowId, + ), + ), + event: crate::event::WindowEvent::ReceivedCharacter(c), + }, + &mut (), + ); + } + } else { + self.xkb_compose.feed(keysym); + match self.xkb_compose.status() { + xkb::compose::Status::Composed => { + if let Some(c) = + self.xkb_compose.utf8().and_then(|f| f.chars().next()) + { + callback( + crate::event::Event::WindowEvent { + window_id: crate::window::WindowId( + crate::platform_impl::WindowId::Drm( + super::WindowId, + ), + ), + event: + crate::event::WindowEvent::ReceivedCharacter( + c, + ), + }, + &mut (), + ); + self.compose_state = false; + self.xkb_compose.reset(); + } + } + xkb::compose::Status::Cancelled => { + let should_repeat = self.xkb_keymap.key_repeats(key_offset); + let ch = + self.xkb_ctx.key_get_utf8(key_offset).chars().next(); + if should_repeat { + self.timer_handle.add_timeout( + Duration::from_millis(600), + (input, ch), + ); + } + if let Some(c) = ch { + callback( + crate::event::Event::WindowEvent { + window_id: crate::window::WindowId( + crate::platform_impl::WindowId::Drm( + super::WindowId, + ), + ), + event: + crate::event::WindowEvent::ReceivedCharacter( + c, + ), + }, + &mut (), + ); + } + } + _ => {} + } } } match keysym { @@ -773,6 +836,23 @@ impl EventLoop { crate::platform_impl::OsError::DrmMisc("Failed to compile XKB keymap"), ))?; let state = xkb::State::new(&keymap); + let compose_table = xkb::compose::Table::new_from_locale( + &xkb_ctx, + std::env::var_os("LC_ALL") + .unwrap_or_else(|| { + std::env::var_os("LC_CTYPE").unwrap_or_else(|| { + std::env::var_os("LANG").unwrap_or_else(|| std::ffi::OsString::from("C")) + }) + }) + .as_os_str(), + xkb::compose::COMPILE_NO_FLAGS, + ) + .or(Err(crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Failed to compile XKB compose table"), + )))?; + let xkb_compose = xkb::compose::State::new(&compose_table, xkb::compose::STATE_NO_FLAGS); drm::Device::set_client_capability(&drm, drm::ClientCapability::UniversalPlanes, true).or( Err(crate::error::OsError::new( @@ -1009,6 +1089,7 @@ impl EventLoop { repeat_handle, state, keymap, + xkb_compose, ); let input_loop: calloop::Dispatcher<'static, LibinputInputBackend, EventSink> = From acf190aaa11b6bf67d23237f11bf90a605ae07b7 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Thu, 5 May 2022 22:26:02 -0400 Subject: [PATCH 064/151] Add compose support --- src/platform_impl/linux/drm/event_loop.rs | 5 +++++ src/platform_impl/linux/xkb_keymap.rs | 1 + 2 files changed, 6 insertions(+) diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index d6d12dffc2..b296f6283a 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -605,6 +605,8 @@ impl EventSource for LibinputInputBackend { &mut (), ); } + self.compose_state = false; + self.xkb_compose.reset(); } _ => {} } @@ -666,6 +668,9 @@ impl EventSource for LibinputInputBackend { }, &mut ()); } } + xkb_keymap::XKB_KEY_Multi_key => { + self.compose_state = true; + } _ => {} } } diff --git a/src/platform_impl/linux/xkb_keymap.rs b/src/platform_impl/linux/xkb_keymap.rs index 13d35b7095..5968ed57cb 100644 --- a/src/platform_impl/linux/xkb_keymap.rs +++ b/src/platform_impl/linux/xkb_keymap.rs @@ -17,6 +17,7 @@ pub const XKB_KEY_Scroll_Lock: u32 = 0xff14; pub const XKB_KEY_Sys_Req: u32 = 0xff15; pub const XKB_KEY_Escape: u32 = 0xff1b; pub const XKB_KEY_Delete: u32 = 0xffff; /* Delete, rubout */ +pub const XKB_KEY_Multi_key: u32 = 0xff20; /* Multi-key character compose */ /* International & multi-key character composition */ From 675773bbf9fe40c897fa201080e9cd6ebb6b0f5b Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Thu, 5 May 2022 22:27:06 -0400 Subject: [PATCH 065/151] Add compose support --- src/platform_impl/linux/xkb_keymap.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/platform_impl/linux/xkb_keymap.rs b/src/platform_impl/linux/xkb_keymap.rs index 5968ed57cb..13d35b7095 100644 --- a/src/platform_impl/linux/xkb_keymap.rs +++ b/src/platform_impl/linux/xkb_keymap.rs @@ -17,7 +17,6 @@ pub const XKB_KEY_Scroll_Lock: u32 = 0xff14; pub const XKB_KEY_Sys_Req: u32 = 0xff15; pub const XKB_KEY_Escape: u32 = 0xff1b; pub const XKB_KEY_Delete: u32 = 0xffff; /* Delete, rubout */ -pub const XKB_KEY_Multi_key: u32 = 0xff20; /* Multi-key character compose */ /* International & multi-key character composition */ From 818b73c5c959c4190f833fff52e090fac26cc97b Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Thu, 5 May 2022 22:46:07 -0400 Subject: [PATCH 066/151] Add compose support --- src/platform_impl/linux/drm/event_loop.rs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index b296f6283a..fb88af1255 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -54,7 +54,6 @@ pub struct LibinputInputBackend { xkb_ctx: xkb::State, xkb_keymap: xkb::Keymap, xkb_compose: xkb::compose::State, - compose_state: bool, token: Token, touch_location: PhysicalPosition, screen_size: (u32, u32), @@ -88,7 +87,6 @@ impl LibinputInputBackend { xkb_ctx, xkb_keymap, xkb_compose, - compose_state: false // cursor_buffer, // cursor_plane, } @@ -534,7 +532,7 @@ impl EventSource for LibinputInputBackend { &mut (), ); if let crate::event::ElementState::Pressed = state { - if !self.compose_state { + if self.xkb_compose.feed(keysym) == xkb::compose::FeedResult::Ignored { let should_repeat = self.xkb_keymap.key_repeats(key_offset); let ch = self.xkb_ctx.key_get_utf8(key_offset).chars().next(); if should_repeat { @@ -555,8 +553,7 @@ impl EventSource for LibinputInputBackend { ); } } else { - self.xkb_compose.feed(keysym); - match self.xkb_compose.status() { + match dbg!(self.xkb_compose.status()) { xkb::compose::Status::Composed => { if let Some(c) = self.xkb_compose.utf8().and_then(|f| f.chars().next()) @@ -668,10 +665,7 @@ impl EventSource for LibinputInputBackend { }, &mut ()); } } - xkb_keymap::XKB_KEY_Multi_key => { - self.compose_state = true; - } - _ => {} + _ => {} } } _ => {} From 432de8ad50d8d85f93a563176a6df39a7080fc35 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Thu, 5 May 2022 22:47:12 -0400 Subject: [PATCH 067/151] Add compose support --- src/platform_impl/linux/drm/event_loop.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index fb88af1255..b3b474830e 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -572,8 +572,6 @@ impl EventSource for LibinputInputBackend { }, &mut (), ); - self.compose_state = false; - self.xkb_compose.reset(); } } xkb::compose::Status::Cancelled => { @@ -602,8 +600,6 @@ impl EventSource for LibinputInputBackend { &mut (), ); } - self.compose_state = false; - self.xkb_compose.reset(); } _ => {} } From bcdd5a494b3acf9474d075ceec6e945ce51f7a0f Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Thu, 5 May 2022 23:01:07 -0400 Subject: [PATCH 068/151] Add compose support --- src/platform_impl/linux/drm/event_loop.rs | 125 +++++++++++----------- 1 file changed, 61 insertions(+), 64 deletions(-) diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index b3b474830e..4f0a975ab2 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -532,77 +532,74 @@ impl EventSource for LibinputInputBackend { &mut (), ); if let crate::event::ElementState::Pressed = state { - if self.xkb_compose.feed(keysym) == xkb::compose::FeedResult::Ignored { - let should_repeat = self.xkb_keymap.key_repeats(key_offset); - let ch = self.xkb_ctx.key_get_utf8(key_offset).chars().next(); - if should_repeat { - self.timer_handle - .add_timeout(Duration::from_millis(600), (input, ch)); - } - if let Some(c) = ch { - callback( - crate::event::Event::WindowEvent { - window_id: crate::window::WindowId( - crate::platform_impl::WindowId::Drm( - super::WindowId, + self.xkb_compose.feed(keysym); + match self.xkb_compose.status() { + xkb::compose::Status::Composed => { + if let Some(c) = + self.xkb_compose.utf8().and_then(|f| f.chars().next()) + { + callback( + crate::event::Event::WindowEvent { + window_id: crate::window::WindowId( + crate::platform_impl::WindowId::Drm( + super::WindowId, + ), ), - ), - event: crate::event::WindowEvent::ReceivedCharacter(c), - }, - &mut (), - ); + event: crate::event::WindowEvent::ReceivedCharacter( + c, + ), + }, + &mut (), + ); + } } - } else { - match dbg!(self.xkb_compose.status()) { - xkb::compose::Status::Composed => { - if let Some(c) = - self.xkb_compose.utf8().and_then(|f| f.chars().next()) - { - callback( - crate::event::Event::WindowEvent { - window_id: crate::window::WindowId( - crate::platform_impl::WindowId::Drm( - super::WindowId, - ), + xkb::compose::Status::Cancelled => { + let should_repeat = self.xkb_keymap.key_repeats(key_offset); + let ch = self.xkb_ctx.key_get_utf8(key_offset).chars().next(); + if should_repeat { + self.timer_handle + .add_timeout(Duration::from_millis(600), (input, ch)); + } + if let Some(c) = ch { + callback( + crate::event::Event::WindowEvent { + window_id: crate::window::WindowId( + crate::platform_impl::WindowId::Drm( + super::WindowId, ), - event: - crate::event::WindowEvent::ReceivedCharacter( - c, - ), - }, - &mut (), - ); - } + ), + event: crate::event::WindowEvent::ReceivedCharacter( + c, + ), + }, + &mut (), + ); } - xkb::compose::Status::Cancelled => { - let should_repeat = self.xkb_keymap.key_repeats(key_offset); - let ch = - self.xkb_ctx.key_get_utf8(key_offset).chars().next(); - if should_repeat { - self.timer_handle.add_timeout( - Duration::from_millis(600), - (input, ch), - ); - } - if let Some(c) = ch { - callback( - crate::event::Event::WindowEvent { - window_id: crate::window::WindowId( - crate::platform_impl::WindowId::Drm( - super::WindowId, - ), + } + xkb::compose::Status::Nothing => { + let should_repeat = self.xkb_keymap.key_repeats(key_offset); + let ch = self.xkb_ctx.key_get_utf8(key_offset).chars().next(); + if should_repeat { + self.timer_handle + .add_timeout(Duration::from_millis(600), (input, ch)); + } + if let Some(c) = ch { + callback( + crate::event::Event::WindowEvent { + window_id: crate::window::WindowId( + crate::platform_impl::WindowId::Drm( + super::WindowId, ), - event: - crate::event::WindowEvent::ReceivedCharacter( - c, - ), - }, - &mut (), - ); - } + ), + event: crate::event::WindowEvent::ReceivedCharacter( + c, + ), + }, + &mut (), + ); } - _ => {} } + _ => {} } } match keysym { From 4f487c6b8a538e505a2c04b4eb4856cd0b52d060 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Fri, 6 May 2022 01:37:42 -0400 Subject: [PATCH 069/151] Custom cursor rendering --- src/platform_impl/linux/drm/event_loop.rs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index 4f0a975ab2..7475e2557b 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -59,6 +59,7 @@ pub struct LibinputInputBackend { screen_size: (u32, u32), modifiers: ModifiersState, cursor_positon: PhysicalPosition, + cursor_sender: std::sync::mpsc::Sender>, timer_handle: calloop::timer::TimerHandle<(KeyboardInput, Option)>, // cursor_plane: drm::control::plane::Handle, // cursor_buffer: drm::control::framebuffer::Handle, @@ -73,8 +74,10 @@ impl LibinputInputBackend { timer_handle: calloop::timer::TimerHandle<(KeyboardInput, Option)>, xkb_ctx: xkb::State, xkb_keymap: xkb::Keymap, - xkb_compose: xkb::compose::State, // cursor_plane: drm::control::plane::Handle, - // cursor_buffer: drm::control::framebuffer::Handle + xkb_compose: xkb::compose::State, + cursor_sender: std::sync::mpsc::Sender>, + // cursor_plane: drm::control::plane::Handle, + // cursor_buffer: drm::control::framebuffer::Handle ) -> Self { LibinputInputBackend { context, @@ -87,6 +90,7 @@ impl LibinputInputBackend { xkb_ctx, xkb_keymap, xkb_compose, + cursor_sender // cursor_buffer, // cursor_plane, } @@ -325,6 +329,7 @@ impl EventSource for LibinputInputBackend { self.cursor_positon.y += e.dy(); self.cursor_positon.y = self.cursor_positon.y.clamp(0.0, self.screen_size.1 as f64); + self.cursor_sender.send(self.cursor_positon).unwrap(); callback( crate::event::Event::WindowEvent { window_id: crate::window::WindowId( @@ -471,6 +476,7 @@ impl EventSource for LibinputInputBackend { input::event::PointerEvent::MotionAbsolute(e) => { self.cursor_positon.x = e.absolute_x_transformed(self.screen_size.0); self.cursor_positon.y = e.absolute_y_transformed(self.screen_size.1); + self.cursor_sender.send(self.cursor_positon).unwrap(); callback( crate::event::Event::WindowEvent { window_id: crate::window::WindowId( @@ -701,6 +707,9 @@ pub struct EventLoopWindowTarget { /// drm plane pub plane: drm::control::plane::Handle, + /// recieves the cursor position when the mouse moves + pub cursor_reciever: std::sync::mpsc::Receiver>, + // /// drm dumbbuffer containing the cursor // pub cursor_buffer: drm::control::framebuffer::Handle, /// drm device @@ -1075,6 +1084,8 @@ impl EventLoop { }, ); + let (cursor_sender, cursor_reciever) = std::sync::mpsc::channel(); + let input_backend: LibinputInputBackend = LibinputInputBackend::new( input, (disp_width.into(), disp_height.into()), // plane, fb @@ -1082,6 +1093,7 @@ impl EventLoop { state, keymap, xkb_compose, + cursor_sender, ); let input_loop: calloop::Dispatcher<'static, LibinputInputBackend, EventSink> = @@ -1105,6 +1117,7 @@ impl EventLoop { mode, event_loop_handle: handle, event_sink, + cursor_reciever, event_loop_awakener, _marker: PhantomData, }), From de25634b0cc6c0fde0bca6749350afada2f5f075 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Fri, 6 May 2022 01:50:48 -0400 Subject: [PATCH 070/151] bad cursor rendering --- src/platform_impl/linux/drm/event_loop.rs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index 7475e2557b..e47429d72b 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -59,7 +59,6 @@ pub struct LibinputInputBackend { screen_size: (u32, u32), modifiers: ModifiersState, cursor_positon: PhysicalPosition, - cursor_sender: std::sync::mpsc::Sender>, timer_handle: calloop::timer::TimerHandle<(KeyboardInput, Option)>, // cursor_plane: drm::control::plane::Handle, // cursor_buffer: drm::control::framebuffer::Handle, @@ -75,7 +74,6 @@ impl LibinputInputBackend { xkb_ctx: xkb::State, xkb_keymap: xkb::Keymap, xkb_compose: xkb::compose::State, - cursor_sender: std::sync::mpsc::Sender>, // cursor_plane: drm::control::plane::Handle, // cursor_buffer: drm::control::framebuffer::Handle ) -> Self { @@ -90,7 +88,6 @@ impl LibinputInputBackend { xkb_ctx, xkb_keymap, xkb_compose, - cursor_sender // cursor_buffer, // cursor_plane, } @@ -329,7 +326,6 @@ impl EventSource for LibinputInputBackend { self.cursor_positon.y += e.dy(); self.cursor_positon.y = self.cursor_positon.y.clamp(0.0, self.screen_size.1 as f64); - self.cursor_sender.send(self.cursor_positon).unwrap(); callback( crate::event::Event::WindowEvent { window_id: crate::window::WindowId( @@ -476,7 +472,6 @@ impl EventSource for LibinputInputBackend { input::event::PointerEvent::MotionAbsolute(e) => { self.cursor_positon.x = e.absolute_x_transformed(self.screen_size.0); self.cursor_positon.y = e.absolute_y_transformed(self.screen_size.1); - self.cursor_sender.send(self.cursor_positon).unwrap(); callback( crate::event::Event::WindowEvent { window_id: crate::window::WindowId( @@ -707,9 +702,6 @@ pub struct EventLoopWindowTarget { /// drm plane pub plane: drm::control::plane::Handle, - /// recieves the cursor position when the mouse moves - pub cursor_reciever: std::sync::mpsc::Receiver>, - // /// drm dumbbuffer containing the cursor // pub cursor_buffer: drm::control::framebuffer::Handle, /// drm device @@ -1084,8 +1076,6 @@ impl EventLoop { }, ); - let (cursor_sender, cursor_reciever) = std::sync::mpsc::channel(); - let input_backend: LibinputInputBackend = LibinputInputBackend::new( input, (disp_width.into(), disp_height.into()), // plane, fb @@ -1093,7 +1083,6 @@ impl EventLoop { state, keymap, xkb_compose, - cursor_sender, ); let input_loop: calloop::Dispatcher<'static, LibinputInputBackend, EventSink> = @@ -1117,7 +1106,6 @@ impl EventLoop { mode, event_loop_handle: handle, event_sink, - cursor_reciever, event_loop_awakener, _marker: PhantomData, }), From caaa188a81bf3594f7af7df66346aa343032ac8f Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Fri, 6 May 2022 06:45:27 -0400 Subject: [PATCH 071/151] Fix seat management --- src/platform_impl/linux/drm/event_loop.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index e47429d72b..5549ec4341 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -811,8 +811,9 @@ impl EventLoop { ) })?; let drm = Card(std::sync::Arc::new(dev.1)); + let seat_name = seat.name().to_owned(); let mut input = input::Libinput::new_with_udev(Interface(seat, HashMap::new())); - input.udev_assign_seat("seat0").unwrap(); + input.udev_assign_seat(&seat_name).unwrap(); let xkb_ctx = xkb::Context::new(xkb::CONTEXT_NO_FLAGS); let keymap = xkb::Keymap::new_from_names( &xkb_ctx, From 53b15f8139e9f40da6ba234ce29e9150e5f62757 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Fri, 6 May 2022 08:36:18 -0400 Subject: [PATCH 072/151] Add GPU enumeration --- Cargo.toml | 3 +- src/platform_impl/linux/drm/event_loop.rs | 76 ++++++++++++++++++++++- 2 files changed, 75 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9af291a476..7238a784bf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ default = ["x11", "wayland", "wayland-dlopen", "kmsdrm"] x11 = ["x11-dl", "mio", "percent-encoding", "parking_lot"] wayland = ["wayland-client", "wayland-protocols", "sctk", "calloop"] wayland-dlopen = ["sctk/dlopen", "wayland-client/dlopen"] -kmsdrm = ["drm", "input", "calloop", "libseat", "xkbcommon"] +kmsdrm = ["drm", "input", "calloop", "libseat", "xkbcommon", "udev"] [dependencies] instant = { version = "0.1.12", features = ["wasm-bindgen"] } @@ -101,6 +101,7 @@ libc = "0.2.125" drm = { version = "0.6.2", optional = true } input = { version = "0.7.1", optional = true } libseat = { version = "0.1.4", optional = true } +udev = { version = "0.6.3", optional = true } xkbcommon = { git = "https://github.com/StratusFearMe21/xkbcommon-rs", optional = true } [target.'cfg(target_arch = "wasm32")'.dependencies] diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index 5549ec4341..c714282de8 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -6,6 +6,7 @@ use std::{ sync::{atomic::AtomicBool, mpsc::SendError, Arc}, time::{Duration, Instant}, }; +use udev::Enumerator; use xkbcommon::xkb; use calloop::{EventSource, Interest, Mode, Poll, PostAction, Readiness, Token, TokenFactory}; @@ -803,7 +804,77 @@ impl EventLoop { } s }; - let dev = seat.open_device(&"/dev/dri/card0").map_err(|_| { + // Safety + // + // This string value has the same lifetime as the seat in question, and will not be dropped + // until the seat is, which is after `udev_assign_seat` is run. + let seat_name = unsafe { std::mem::transmute::<&str, &'static str>(seat.name()) }; + let mut enumerator = Enumerator::new().map_err(|_| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Failed to open udev enumerator"), + ) + })?; + enumerator.match_subsystem("drm").map_err(|_| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Failed to enumerate drm subsystem"), + ) + })?; + enumerator.match_sysname("card[0-9]*").map_err(|_| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Failed to find a valid card"), + ) + })?; + let card_path = enumerator + .scan_devices() + .map_err(|_| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Failed to scan devices"), + ) + })? + .filter(|device| { + let dev_seat_name = device + .property_value("ID_SEAT") + .map(|x| x.to_os_string()) + .unwrap_or_else(|| std::ffi::OsString::from("seat0")); + if dev_seat_name == seat_name { + if let Ok(Some(pci)) = device.parent_with_subsystem(Path::new("pci")) { + if let Some(id) = pci.attribute_value("boot_vga") { + return id == "1"; + } + } + } + false + }) + .flat_map(|device| device.devnode().map(std::path::PathBuf::from)) + .next() + .or_else(|| { + enumerator + .scan_devices() + .ok()? + .filter(|device| { + device + .property_value("ID_SEAT") + .map(|x| x.to_os_string()) + .unwrap_or_else(|| std::ffi::OsString::from("seat0")) + == seat_name + }) + .flat_map(|device| device.devnode().map(std::path::PathBuf::from)) + .next() + }) + .ok_or(crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Failed to find suitable GPU"), + ))?; + let dev = seat.open_device(&card_path).map_err(|_| { crate::error::OsError::new( line!(), file!(), @@ -811,9 +882,8 @@ impl EventLoop { ) })?; let drm = Card(std::sync::Arc::new(dev.1)); - let seat_name = seat.name().to_owned(); let mut input = input::Libinput::new_with_udev(Interface(seat, HashMap::new())); - input.udev_assign_seat(&seat_name).unwrap(); + input.udev_assign_seat(seat_name).unwrap(); let xkb_ctx = xkb::Context::new(xkb::CONTEXT_NO_FLAGS); let keymap = xkb::Keymap::new_from_names( &xkb_ctx, From c3fb5ae47f778e464bc6aab47a154c8b774dfd18 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Fri, 6 May 2022 08:37:28 -0400 Subject: [PATCH 073/151] Clarify safety --- src/platform_impl/linux/drm/event_loop.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index c714282de8..b7a1fb1b39 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -807,7 +807,7 @@ impl EventLoop { // Safety // // This string value has the same lifetime as the seat in question, and will not be dropped - // until the seat is, which is after `udev_assign_seat` is run. + // until the seat is, which is not before `udev_assign_seat` is run. let seat_name = unsafe { std::mem::transmute::<&str, &'static str>(seat.name()) }; let mut enumerator = Enumerator::new().map_err(|_| { crate::error::OsError::new( From 0b1123bc8f2ffe1adce3511969487528d39f4bd3 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Fri, 6 May 2022 08:41:53 -0400 Subject: [PATCH 074/151] Add configurability --- src/platform_impl/linux/drm/event_loop.rs | 122 +++++++++++----------- 1 file changed, 63 insertions(+), 59 deletions(-) diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index b7a1fb1b39..288c444d43 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -809,71 +809,75 @@ impl EventLoop { // This string value has the same lifetime as the seat in question, and will not be dropped // until the seat is, which is not before `udev_assign_seat` is run. let seat_name = unsafe { std::mem::transmute::<&str, &'static str>(seat.name()) }; - let mut enumerator = Enumerator::new().map_err(|_| { - crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc("Failed to open udev enumerator"), - ) - })?; - enumerator.match_subsystem("drm").map_err(|_| { - crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc("Failed to enumerate drm subsystem"), - ) - })?; - enumerator.match_sysname("card[0-9]*").map_err(|_| { - crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc("Failed to find a valid card"), - ) - })?; - let card_path = enumerator - .scan_devices() - .map_err(|_| { + let card_path = if let Some(p) = std::env::var("WINIT_DRM_CARD").ok() { + p.into() + } else { + let mut enumerator = Enumerator::new().map_err(|_| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Failed to open udev enumerator"), + ) + })?; + enumerator.match_subsystem("drm").map_err(|_| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Failed to enumerate drm subsystem"), + ) + })?; + enumerator.match_sysname("card[0-9]*").map_err(|_| { crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::DrmMisc("Failed to scan devices"), + crate::platform_impl::OsError::DrmMisc("Failed to find a valid card"), ) - })? - .filter(|device| { - let dev_seat_name = device - .property_value("ID_SEAT") - .map(|x| x.to_os_string()) - .unwrap_or_else(|| std::ffi::OsString::from("seat0")); - if dev_seat_name == seat_name { - if let Ok(Some(pci)) = device.parent_with_subsystem(Path::new("pci")) { - if let Some(id) = pci.attribute_value("boot_vga") { - return id == "1"; + })?; + enumerator + .scan_devices() + .map_err(|_| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Failed to scan devices"), + ) + })? + .filter(|device| { + let dev_seat_name = device + .property_value("ID_SEAT") + .map(|x| x.to_os_string()) + .unwrap_or_else(|| std::ffi::OsString::from("seat0")); + if dev_seat_name == seat_name { + if let Ok(Some(pci)) = device.parent_with_subsystem(Path::new("pci")) { + if let Some(id) = pci.attribute_value("boot_vga") { + return id == "1"; + } } } - } - false - }) - .flat_map(|device| device.devnode().map(std::path::PathBuf::from)) - .next() - .or_else(|| { - enumerator - .scan_devices() - .ok()? - .filter(|device| { - device - .property_value("ID_SEAT") - .map(|x| x.to_os_string()) - .unwrap_or_else(|| std::ffi::OsString::from("seat0")) - == seat_name - }) - .flat_map(|device| device.devnode().map(std::path::PathBuf::from)) - .next() - }) - .ok_or(crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc("Failed to find suitable GPU"), - ))?; + false + }) + .flat_map(|device| device.devnode().map(std::path::PathBuf::from)) + .next() + .or_else(|| { + enumerator + .scan_devices() + .ok()? + .filter(|device| { + device + .property_value("ID_SEAT") + .map(|x| x.to_os_string()) + .unwrap_or_else(|| std::ffi::OsString::from("seat0")) + == seat_name + }) + .flat_map(|device| device.devnode().map(std::path::PathBuf::from)) + .next() + }) + .ok_or(crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Failed to find suitable GPU"), + ))? + }; let dev = seat.open_device(&card_path).map_err(|_| { crate::error::OsError::new( line!(), From fc023aff4c3d06352a4aec22af1392cd4400aca0 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Fri, 6 May 2022 09:03:41 -0400 Subject: [PATCH 075/151] Optimize emumeration function --- src/platform_impl/linux/drm/event_loop.rs | 223 +++++++++++----------- 1 file changed, 112 insertions(+), 111 deletions(-) diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/drm/event_loop.rs index 288c444d43..d64b2696ec 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/drm/event_loop.rs @@ -605,62 +605,62 @@ impl EventSource for LibinputInputBackend { } } match keysym { - xkb_keymap::XKB_KEY_Alt_L - | xkb_keymap::XKB_KEY_Alt_R - => { - match state { - ElementState::Pressed => self.modifiers |= ModifiersState::ALT, - ElementState::Released => self.modifiers.remove(ModifiersState::ALT) - } - callback(crate::event::Event::WindowEvent { - window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), - event:crate::event::WindowEvent::ModifiersChanged(self.modifiers)}, &mut ()); + xkb_keymap::XKB_KEY_Alt_L + | xkb_keymap::XKB_KEY_Alt_R + => { + match state { + ElementState::Pressed => self.modifiers |= ModifiersState::ALT, + ElementState::Released => self.modifiers.remove(ModifiersState::ALT) } - | xkb_keymap::XKB_KEY_Shift_L // LShift - | xkb_keymap::XKB_KEY_Shift_R // RShift - => { - match state { - ElementState::Pressed => self.modifiers |= ModifiersState::SHIFT, - ElementState::Released => self.modifiers.remove(ModifiersState::SHIFT) - } - callback(crate::event::Event::WindowEvent { - window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), - event:crate::event::WindowEvent::ModifiersChanged(self.modifiers)}, &mut ()); + callback(crate::event::Event::WindowEvent { + window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), + event:crate::event::WindowEvent::ModifiersChanged(self.modifiers)}, &mut ()); + } + | xkb_keymap::XKB_KEY_Shift_L // LShift + | xkb_keymap::XKB_KEY_Shift_R // RShift + => { + match state { + ElementState::Pressed => self.modifiers |= ModifiersState::SHIFT, + ElementState::Released => self.modifiers.remove(ModifiersState::SHIFT) } + callback(crate::event::Event::WindowEvent { + window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), + event:crate::event::WindowEvent::ModifiersChanged(self.modifiers)}, &mut ()); + } - | xkb_keymap::XKB_KEY_Control_L // LCtrl - | xkb_keymap::XKB_KEY_Control_R // RCtrl - => { - match state { - ElementState::Pressed => self.modifiers |= ModifiersState::CTRL, - ElementState::Released => self.modifiers.remove(ModifiersState::CTRL) - } - callback(crate::event::Event::WindowEvent { - window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), - event:crate::event::WindowEvent::ModifiersChanged(self.modifiers)}, &mut ()); + | xkb_keymap::XKB_KEY_Control_L // LCtrl + | xkb_keymap::XKB_KEY_Control_R // RCtrl + => { + match state { + ElementState::Pressed => self.modifiers |= ModifiersState::CTRL, + ElementState::Released => self.modifiers.remove(ModifiersState::CTRL) } + callback(crate::event::Event::WindowEvent { + window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), + event:crate::event::WindowEvent::ModifiersChanged(self.modifiers)}, &mut ()); + } - | xkb_keymap::XKB_KEY_Meta_L // LMeta - | xkb_keymap::XKB_KEY_Meta_R // RMeta - => { - match state { - ElementState::Pressed => self.modifiers |= ModifiersState::LOGO, - ElementState::Released => self.modifiers.remove(ModifiersState::LOGO) - } + | xkb_keymap::XKB_KEY_Meta_L // LMeta + | xkb_keymap::XKB_KEY_Meta_R // RMeta + => { + match state { + ElementState::Pressed => self.modifiers |= ModifiersState::LOGO, + ElementState::Released => self.modifiers.remove(ModifiersState::LOGO) + } + callback(crate::event::Event::WindowEvent { + window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), + event: crate::event::WindowEvent::ModifiersChanged(self.modifiers)}, &mut ()); + } + xkb_keymap::XKB_KEY_Sys_Req | xkb_keymap::XKB_KEY_Print + => { + if self.modifiers.is_empty() { callback(crate::event::Event::WindowEvent { window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), - event: crate::event::WindowEvent::ModifiersChanged(self.modifiers)}, &mut ()); - } - xkb_keymap::XKB_KEY_Sys_Req | xkb_keymap::XKB_KEY_Print - => { - if self.modifiers.is_empty() { - callback(crate::event::Event::WindowEvent { - window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), - event: crate::event::WindowEvent::CloseRequested - }, &mut ()); - } + event: crate::event::WindowEvent::CloseRequested + }, &mut ()); } - _ => {} + } + _ => {} } } _ => {} @@ -809,75 +809,76 @@ impl EventLoop { // This string value has the same lifetime as the seat in question, and will not be dropped // until the seat is, which is not before `udev_assign_seat` is run. let seat_name = unsafe { std::mem::transmute::<&str, &'static str>(seat.name()) }; - let card_path = if let Some(p) = std::env::var("WINIT_DRM_CARD").ok() { - p.into() - } else { - let mut enumerator = Enumerator::new().map_err(|_| { - crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc("Failed to open udev enumerator"), - ) - })?; - enumerator.match_subsystem("drm").map_err(|_| { - crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc("Failed to enumerate drm subsystem"), - ) - })?; - enumerator.match_sysname("card[0-9]*").map_err(|_| { - crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc("Failed to find a valid card"), - ) - })?; - enumerator - .scan_devices() - .map_err(|_| { + let card_path = std::env::var("WINIT_DRM_CARD").ok().map_or_else( + || { + let mut enumerator = Enumerator::new().map_err(|_| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Failed to open udev enumerator"), + ) + })?; + enumerator.match_subsystem("drm").map_err(|_| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Failed to enumerate drm subsystem"), + ) + })?; + enumerator.match_sysname("card[0-9]*").map_err(|_| { crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::DrmMisc("Failed to scan devices"), + crate::platform_impl::OsError::DrmMisc("Failed to find a valid card"), ) - })? - .filter(|device| { - let dev_seat_name = device - .property_value("ID_SEAT") - .map(|x| x.to_os_string()) - .unwrap_or_else(|| std::ffi::OsString::from("seat0")); - if dev_seat_name == seat_name { - if let Ok(Some(pci)) = device.parent_with_subsystem(Path::new("pci")) { - if let Some(id) = pci.attribute_value("boot_vga") { - return id == "1"; + })?; + enumerator + .scan_devices() + .map_err(|_| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Failed to scan devices"), + ) + })? + .filter(|device| { + let dev_seat_name = device + .property_value("ID_SEAT") + .map(|x| x.to_os_string()) + .unwrap_or_else(|| std::ffi::OsString::from("seat0")); + if dev_seat_name == seat_name { + if let Ok(Some(pci)) = device.parent_with_subsystem(Path::new("pci")) { + if let Some(id) = pci.attribute_value("boot_vga") { + return id == "1"; + } } } - } - false - }) - .flat_map(|device| device.devnode().map(std::path::PathBuf::from)) - .next() - .or_else(|| { - enumerator - .scan_devices() - .ok()? - .filter(|device| { - device - .property_value("ID_SEAT") - .map(|x| x.to_os_string()) - .unwrap_or_else(|| std::ffi::OsString::from("seat0")) - == seat_name - }) - .flat_map(|device| device.devnode().map(std::path::PathBuf::from)) - .next() - }) - .ok_or(crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::DrmMisc("Failed to find suitable GPU"), - ))? - }; + false + }) + .flat_map(|device| device.devnode().map(std::path::PathBuf::from)) + .next() + .or_else(|| { + enumerator + .scan_devices() + .ok()? + .filter(|device| { + device + .property_value("ID_SEAT") + .map(|x| x.to_os_string()) + .unwrap_or_else(|| std::ffi::OsString::from("seat0")) + == seat_name + }) + .flat_map(|device| device.devnode().map(std::path::PathBuf::from)) + .next() + }) + .ok_or(crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::DrmMisc("Failed to find suitable GPU"), + )) + }, + |p| Ok(Into::into(p)), + )?; let dev = seat.open_device(&card_path).map_err(|_| { crate::error::OsError::new( line!(), From a31c243b62dfc27b77e8e9c50c22d8adec45093e Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Fri, 6 May 2022 11:54:16 -0400 Subject: [PATCH 076/151] Proper error handling --- src/platform_impl/linux/drm/window.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/platform_impl/linux/drm/window.rs b/src/platform_impl/linux/drm/window.rs index d648af9026..60221f9c89 100644 --- a/src/platform_impl/linux/drm/window.rs +++ b/src/platform_impl/linux/drm/window.rs @@ -270,7 +270,7 @@ impl Window { #[inline] pub fn set_cursor_hittest(&self, _hittest: bool) -> Result<(), ExternalError> { - unimplemented!() + Err(ExternalError::NotSupported(NotSupportedError::new())) } #[inline] @@ -280,7 +280,7 @@ impl Window { #[inline] pub fn set_cursor_position(&self, _position: Position) -> Result<(), ExternalError> { - unimplemented!() + Err(ExternalError::NotSupported(NotSupportedError::new())) } #[inline] From d8d67c1d1e956d3b289d385b4268f5631d432c06 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Mon, 9 May 2022 09:32:41 -0400 Subject: [PATCH 077/151] Remove C Style comments --- CHANGELOG.md | 2 +- src/platform_impl/linux/xkb_keymap.rs | 284 +++++++++++++------------- 2 files changed, 140 insertions(+), 146 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 187e48fdf1..2561f6dc61 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ And please only add new entries to the top of this list, right below the `# Unre # Unreleased -- On Linux, initial support has been added for a kmsdrm backend +- On Linux, initial support has been added for a DRM backend. This is a breaking change - On Wayland, fix bug where the cursor wouldn't hide in GNOME. - On macOS, Windows, and Wayland, add `set_cursor_hittest` to let the window ignore mouse events. - On Windows, added `WindowExtWindows::set_skip_taskbar` and `WindowBuilderExtWindows::with_skip_taskbar`. diff --git a/src/platform_impl/linux/xkb_keymap.rs b/src/platform_impl/linux/xkb_keymap.rs index 13d35b7095..09d5c32224 100644 --- a/src/platform_impl/linux/xkb_keymap.rs +++ b/src/platform_impl/linux/xkb_keymap.rs @@ -3,49 +3,47 @@ use crate::event::VirtualKeyCode; -/* - * TTY function keys, cleverly chosen to map to ASCII, for convenience of - * programming, but could have been arbitrary (at the cost of lookup - * tables in client code). - */ +// TTY function keys, cleverly chosen to map to ASCII, for convenience of +// programming, but could have been arbitrary (at the cost of lookup +// tables in client code). -pub const XKB_KEY_BackSpace: u32 = 0xff08; /* Back space, back char */ +pub const XKB_KEY_BackSpace: u32 = 0xff08; // Back space, back char pub const XKB_KEY_Tab: u32 = 0xff09; -pub const XKB_KEY_Return: u32 = 0xff0d; /* Return, enter */ -pub const XKB_KEY_Pause: u32 = 0xff13; /* Pause, hold */ +pub const XKB_KEY_Return: u32 = 0xff0d; // Return, enter +pub const XKB_KEY_Pause: u32 = 0xff13; // Pause, hold pub const XKB_KEY_Scroll_Lock: u32 = 0xff14; pub const XKB_KEY_Sys_Req: u32 = 0xff15; pub const XKB_KEY_Escape: u32 = 0xff1b; -pub const XKB_KEY_Delete: u32 = 0xffff; /* Delete, rubout */ +pub const XKB_KEY_Delete: u32 = 0xffff; // Delete, rubout -/* International & multi-key character composition */ +// International & multi-key character composition -pub const XKB_KEY_Multi_key: u32 = 0xff20; /* Multi-key character compose */ -/* Japanese keyboard support */ +pub const XKB_KEY_Multi_key: u32 = 0xff20; // Multi-key character compose -pub const XKB_KEY_Kanji: u32 = 0xff21; /* Kanji, Kanji convert */ -/* :u32 = 0xff31; thru :u32 = 0xff3f; are under XK_KOREAN */ +// Japanese keyboard support -/* Cursor control & motion */ +pub const XKB_KEY_Kanji: u32 = 0xff21; // Kanji, Kanji convert + +// Cursor control & motion pub const XKB_KEY_Home: u32 = 0xff50; -pub const XKB_KEY_Left: u32 = 0xff51; /* Move left, left arrow */ -pub const XKB_KEY_Up: u32 = 0xff52; /* Move up, up arrow */ -pub const XKB_KEY_Right: u32 = 0xff53; /* Move right, right arrow */ -pub const XKB_KEY_Down: u32 = 0xff54; /* Move down, down arrow */ +pub const XKB_KEY_Left: u32 = 0xff51; // Move left, left arrow +pub const XKB_KEY_Up: u32 = 0xff52; // Move up, up arrow +pub const XKB_KEY_Right: u32 = 0xff53; // Move right, right arrow +pub const XKB_KEY_Down: u32 = 0xff54; // Move down, down arrow pub const XKB_KEY_Page_Up: u32 = 0xff55; pub const XKB_KEY_Page_Down: u32 = 0xff56; -pub const XKB_KEY_End: u32 = 0xff57; /* EOL */ +pub const XKB_KEY_End: u32 = 0xff57; // EOL -/* Misc functions */ +// Misc functions pub const XKB_KEY_Print: u32 = 0xff61; -pub const XKB_KEY_Insert: u32 = 0xff63; /* Insert, insert here */ +pub const XKB_KEY_Insert: u32 = 0xff63; // Insert, insert here pub const XKB_KEY_Num_Lock: u32 = 0xff7f; -/* Keypad functions, keypad numbers cleverly chosen to map to ASCII */ +// Keypad functions, keypad numbers cleverly chosen to map to ASCII -pub const XKB_KEY_KP_Enter: u32 = 0xff8d; /* Enter */ +pub const XKB_KEY_KP_Enter: u32 = 0xff8d; // Enter pub const XKB_KEY_KP_Home: u32 = 0xff95; pub const XKB_KEY_KP_Left: u32 = 0xff96; pub const XKB_KEY_KP_Up: u32 = 0xff97; @@ -54,10 +52,10 @@ pub const XKB_KEY_KP_Down: u32 = 0xff99; pub const XKB_KEY_KP_Page_Up: u32 = 0xff9a; pub const XKB_KEY_KP_Page_Down: u32 = 0xff9b; pub const XKB_KEY_KP_End: u32 = 0xff9c; -pub const XKB_KEY_KP_Equal: u32 = 0xffbd; /* Equals */ +pub const XKB_KEY_KP_Equal: u32 = 0xffbd; // Equals pub const XKB_KEY_KP_Multiply: u32 = 0xffaa; pub const XKB_KEY_KP_Add: u32 = 0xffab; -pub const XKB_KEY_KP_Separator: u32 = 0xffac; /* Separator, often comma */ +pub const XKB_KEY_KP_Separator: u32 = 0xffac; // Separator, often comma pub const XKB_KEY_KP_Subtract: u32 = 0xffad; pub const XKB_KEY_KP_Decimal: u32 = 0xffae; pub const XKB_KEY_KP_Divide: u32 = 0xffaf; @@ -73,12 +71,10 @@ pub const XKB_KEY_KP_7: u32 = 0xffb7; pub const XKB_KEY_KP_8: u32 = 0xffb8; pub const XKB_KEY_KP_9: u32 = 0xffb9; -/* - * Auxiliary functions; note the duplicate definitions for left and right - * function keys; Sun keyboards and a few other manufacturers have such - * function key groups on the left and/or right sides of the keyboard. - * We've not found a keyboard with more than 35 function keys total. - */ +// Auxiliary functions; note the duplicate definitions for left and right +// function keys; Sun keyboards and a few other manufacturers have such +// function key groups on the left and/or right sides of the keyboard. +// We've not found a keyboard with more than 35 function keys total. pub const XKB_KEY_F1: u32 = 0xffbe; pub const XKB_KEY_F2: u32 = 0xffbf; @@ -105,126 +101,124 @@ pub const XKB_KEY_F22: u32 = 0xffd3; pub const XKB_KEY_F23: u32 = 0xffd4; pub const XKB_KEY_F24: u32 = 0xffd5; -/* Modifiers */ +// Modifiers -pub const XKB_KEY_Shift_L: u32 = 0xffe1; /* Left shift */ -pub const XKB_KEY_Shift_R: u32 = 0xffe2; /* Right shift */ -pub const XKB_KEY_Control_L: u32 = 0xffe3; /* Left control */ -pub const XKB_KEY_Control_R: u32 = 0xffe4; /* Right control */ +pub const XKB_KEY_Shift_L: u32 = 0xffe1; // Left shift +pub const XKB_KEY_Shift_R: u32 = 0xffe2; // Right shift +pub const XKB_KEY_Control_L: u32 = 0xffe3; // Left control +pub const XKB_KEY_Control_R: u32 = 0xffe4; // Right control -pub const XKB_KEY_Meta_L: u32 = 0xffe7; /* Left meta */ -pub const XKB_KEY_Meta_R: u32 = 0xffe8; /* Right meta */ -pub const XKB_KEY_Alt_L: u32 = 0xffe9; /* Left alt */ -pub const XKB_KEY_Alt_R: u32 = 0xffea; /* Right alt */ -pub const XKB_KEY_Super_L: u32 = 0xffeb; /* Left super */ -pub const XKB_KEY_Super_R: u32 = 0xffec; /* Right super */ +pub const XKB_KEY_Meta_L: u32 = 0xffe7; // Left meta +pub const XKB_KEY_Meta_R: u32 = 0xffe8; // Right meta +pub const XKB_KEY_Alt_L: u32 = 0xffe9; // Left alt +pub const XKB_KEY_Alt_R: u32 = 0xffea; // Right alt +pub const XKB_KEY_Super_L: u32 = 0xffeb; // Left super +pub const XKB_KEY_Super_R: u32 = 0xffec; // Right super pub const XKB_KEY_ISO_Left_Tab: u32 = 0xfe20; -/* - * Latin 1 - * (ISO/IEC 8859-1 = Unicode U+0020..U+00FF) - * Byte 3 = 0 - */ -pub const XKB_KEY_space: u32 = 0x0020; /* U+0020 SPACE */ -pub const XKB_KEY_apostrophe: u32 = 0x0027; /* U+0027 APOSTROPHE */ -pub const XKB_KEY_asterisk: u32 = 0x002a; /* U+002A ASTERISK */ -pub const XKB_KEY_plus: u32 = 0x002b; /* U+002B PLUS SIGN */ -pub const XKB_KEY_comma: u32 = 0x002c; /* U+002C COMMA */ -pub const XKB_KEY_minus: u32 = 0x002d; /* U+002D HYPHEN-MINUS */ -pub const XKB_KEY_period: u32 = 0x002e; /* U+002E FULL STOP */ -pub const XKB_KEY_slash: u32 = 0x002f; /* U+002F SOLIDUS */ -pub const XKB_KEY_0: u32 = 0x0030; /* U+0030 DIGIT ZERO */ -pub const XKB_KEY_1: u32 = 0x0031; /* U+0031 DIGIT ONE */ -pub const XKB_KEY_2: u32 = 0x0032; /* U+0032 DIGIT TWO */ -pub const XKB_KEY_3: u32 = 0x0033; /* U+0033 DIGIT THREE */ -pub const XKB_KEY_4: u32 = 0x0034; /* U+0034 DIGIT FOUR */ -pub const XKB_KEY_5: u32 = 0x0035; /* U+0035 DIGIT FIVE */ -pub const XKB_KEY_6: u32 = 0x0036; /* U+0036 DIGIT SIX */ -pub const XKB_KEY_7: u32 = 0x0037; /* U+0037 DIGIT SEVEN */ -pub const XKB_KEY_8: u32 = 0x0038; /* U+0038 DIGIT EIGHT */ -pub const XKB_KEY_9: u32 = 0x0039; /* U+0039 DIGIT NINE */ -pub const XKB_KEY_colon: u32 = 0x003a; /* U+003A COLON */ -pub const XKB_KEY_semicolon: u32 = 0x003b; /* U+003B SEMICOLON */ -pub const XKB_KEY_equal: u32 = 0x003d; /* U+003D EQUALS SIGN */ -pub const XKB_KEY_at: u32 = 0x0040; /* U+0040 COMMERCIAL AT */ -pub const XKB_KEY_A: u32 = 0x0041; /* U+0041 LATIN CAPITAL LETTER A */ -pub const XKB_KEY_B: u32 = 0x0042; /* U+0042 LATIN CAPITAL LETTER B */ -pub const XKB_KEY_C: u32 = 0x0043; /* U+0043 LATIN CAPITAL LETTER C */ -pub const XKB_KEY_D: u32 = 0x0044; /* U+0044 LATIN CAPITAL LETTER D */ -pub const XKB_KEY_E: u32 = 0x0045; /* U+0045 LATIN CAPITAL LETTER E */ -pub const XKB_KEY_F: u32 = 0x0046; /* U+0046 LATIN CAPITAL LETTER F */ -pub const XKB_KEY_G: u32 = 0x0047; /* U+0047 LATIN CAPITAL LETTER G */ -pub const XKB_KEY_H: u32 = 0x0048; /* U+0048 LATIN CAPITAL LETTER H */ -pub const XKB_KEY_I: u32 = 0x0049; /* U+0049 LATIN CAPITAL LETTER I */ -pub const XKB_KEY_J: u32 = 0x004a; /* U+004A LATIN CAPITAL LETTER J */ -pub const XKB_KEY_K: u32 = 0x004b; /* U+004B LATIN CAPITAL LETTER K */ -pub const XKB_KEY_L: u32 = 0x004c; /* U+004C LATIN CAPITAL LETTER L */ -pub const XKB_KEY_M: u32 = 0x004d; /* U+004D LATIN CAPITAL LETTER M */ -pub const XKB_KEY_N: u32 = 0x004e; /* U+004E LATIN CAPITAL LETTER N */ -pub const XKB_KEY_O: u32 = 0x004f; /* U+004F LATIN CAPITAL LETTER O */ -pub const XKB_KEY_P: u32 = 0x0050; /* U+0050 LATIN CAPITAL LETTER P */ -pub const XKB_KEY_Q: u32 = 0x0051; /* U+0051 LATIN CAPITAL LETTER Q */ -pub const XKB_KEY_R: u32 = 0x0052; /* U+0052 LATIN CAPITAL LETTER R */ -pub const XKB_KEY_S: u32 = 0x0053; /* U+0053 LATIN CAPITAL LETTER S */ -pub const XKB_KEY_T: u32 = 0x0054; /* U+0054 LATIN CAPITAL LETTER T */ -pub const XKB_KEY_U: u32 = 0x0055; /* U+0055 LATIN CAPITAL LETTER U */ -pub const XKB_KEY_V: u32 = 0x0056; /* U+0056 LATIN CAPITAL LETTER V */ -pub const XKB_KEY_W: u32 = 0x0057; /* U+0057 LATIN CAPITAL LETTER W */ -pub const XKB_KEY_X: u32 = 0x0058; /* U+0058 LATIN CAPITAL LETTER X */ -pub const XKB_KEY_Y: u32 = 0x0059; /* U+0059 LATIN CAPITAL LETTER Y */ -pub const XKB_KEY_Z: u32 = 0x005a; /* U+005A LATIN CAPITAL LETTER Z */ -pub const XKB_KEY_bracketleft: u32 = 0x005b; /* U+005B LEFT SQUARE BRACKET */ -pub const XKB_KEY_backslash: u32 = 0x005c; /* U+005C REVERSE SOLIDUS */ -pub const XKB_KEY_bracketright: u32 = 0x005d; /* U+005D RIGHT SQUARE BRACKET */ -pub const XKB_KEY_underscore: u32 = 0x005f; /* U+005F LOW LINE */ -pub const XKB_KEY_grave: u32 = 0x0060; /* U+0060 GRAVE ACCENT */ -pub const XKB_KEY_a: u32 = 0x0061; /* U+0061 LATIN SMALL LETTER A */ -pub const XKB_KEY_b: u32 = 0x0062; /* U+0062 LATIN SMALL LETTER B */ -pub const XKB_KEY_c: u32 = 0x0063; /* U+0063 LATIN SMALL LETTER C */ -pub const XKB_KEY_d: u32 = 0x0064; /* U+0064 LATIN SMALL LETTER D */ -pub const XKB_KEY_e: u32 = 0x0065; /* U+0065 LATIN SMALL LETTER E */ -pub const XKB_KEY_f: u32 = 0x0066; /* U+0066 LATIN SMALL LETTER F */ -pub const XKB_KEY_g: u32 = 0x0067; /* U+0067 LATIN SMALL LETTER G */ -pub const XKB_KEY_h: u32 = 0x0068; /* U+0068 LATIN SMALL LETTER H */ -pub const XKB_KEY_i: u32 = 0x0069; /* U+0069 LATIN SMALL LETTER I */ -pub const XKB_KEY_j: u32 = 0x006a; /* U+006A LATIN SMALL LETTER J */ -pub const XKB_KEY_k: u32 = 0x006b; /* U+006B LATIN SMALL LETTER K */ -pub const XKB_KEY_l: u32 = 0x006c; /* U+006C LATIN SMALL LETTER L */ -pub const XKB_KEY_m: u32 = 0x006d; /* U+006D LATIN SMALL LETTER M */ -pub const XKB_KEY_n: u32 = 0x006e; /* U+006E LATIN SMALL LETTER N */ -pub const XKB_KEY_o: u32 = 0x006f; /* U+006F LATIN SMALL LETTER O */ -pub const XKB_KEY_p: u32 = 0x0070; /* U+0070 LATIN SMALL LETTER P */ -pub const XKB_KEY_q: u32 = 0x0071; /* U+0071 LATIN SMALL LETTER Q */ -pub const XKB_KEY_r: u32 = 0x0072; /* U+0072 LATIN SMALL LETTER R */ -pub const XKB_KEY_s: u32 = 0x0073; /* U+0073 LATIN SMALL LETTER S */ -pub const XKB_KEY_t: u32 = 0x0074; /* U+0074 LATIN SMALL LETTER T */ -pub const XKB_KEY_u: u32 = 0x0075; /* U+0075 LATIN SMALL LETTER U */ -pub const XKB_KEY_v: u32 = 0x0076; /* U+0076 LATIN SMALL LETTER V */ -pub const XKB_KEY_w: u32 = 0x0077; /* U+0077 LATIN SMALL LETTER W */ -pub const XKB_KEY_x: u32 = 0x0078; /* U+0078 LATIN SMALL LETTER X */ -pub const XKB_KEY_y: u32 = 0x0079; /* U+0079 LATIN SMALL LETTER Y */ -pub const XKB_KEY_z: u32 = 0x007a; /* U+007A LATIN SMALL LETTER Z */ -pub const XKB_KEY_yen: u32 = 0x00a5; /* U+00A5 YEN SIGN */ -pub const XKB_KEY_caret: u32 = 0x0afc; /* U+2038 CARET */ +// Latin 1 +// (ISO/IEC 8859-1 = Unicode U+0020..U+00FF) +// Byte 3 = 0 + +pub const XKB_KEY_space: u32 = 0x0020; // U+0020 SPACE +pub const XKB_KEY_apostrophe: u32 = 0x0027; // U+0027 APOSTROPHE +pub const XKB_KEY_asterisk: u32 = 0x002a; // U+002A ASTERISK +pub const XKB_KEY_plus: u32 = 0x002b; // U+002B PLUS SIGN +pub const XKB_KEY_comma: u32 = 0x002c; // U+002C COMMA +pub const XKB_KEY_minus: u32 = 0x002d; // U+002D HYPHEN-MINUS +pub const XKB_KEY_period: u32 = 0x002e; // U+002E FULL STOP +pub const XKB_KEY_slash: u32 = 0x002f; // U+002F SOLIDUS +pub const XKB_KEY_0: u32 = 0x0030; // U+0030 DIGIT ZERO +pub const XKB_KEY_1: u32 = 0x0031; // U+0031 DIGIT ONE +pub const XKB_KEY_2: u32 = 0x0032; // U+0032 DIGIT TWO +pub const XKB_KEY_3: u32 = 0x0033; // U+0033 DIGIT THREE +pub const XKB_KEY_4: u32 = 0x0034; // U+0034 DIGIT FOUR +pub const XKB_KEY_5: u32 = 0x0035; // U+0035 DIGIT FIVE +pub const XKB_KEY_6: u32 = 0x0036; // U+0036 DIGIT SIX +pub const XKB_KEY_7: u32 = 0x0037; // U+0037 DIGIT SEVEN +pub const XKB_KEY_8: u32 = 0x0038; // U+0038 DIGIT EIGHT +pub const XKB_KEY_9: u32 = 0x0039; // U+0039 DIGIT NINE +pub const XKB_KEY_colon: u32 = 0x003a; // U+003A COLON +pub const XKB_KEY_semicolon: u32 = 0x003b; // U+003B SEMICOLON +pub const XKB_KEY_equal: u32 = 0x003d; // U+003D EQUALS SIGN +pub const XKB_KEY_at: u32 = 0x0040; // U+0040 COMMERCIAL AT +pub const XKB_KEY_A: u32 = 0x0041; // U+0041 LATIN CAPITAL LETTER A +pub const XKB_KEY_B: u32 = 0x0042; // U+0042 LATIN CAPITAL LETTER B +pub const XKB_KEY_C: u32 = 0x0043; // U+0043 LATIN CAPITAL LETTER C +pub const XKB_KEY_D: u32 = 0x0044; // U+0044 LATIN CAPITAL LETTER D +pub const XKB_KEY_E: u32 = 0x0045; // U+0045 LATIN CAPITAL LETTER E +pub const XKB_KEY_F: u32 = 0x0046; // U+0046 LATIN CAPITAL LETTER F +pub const XKB_KEY_G: u32 = 0x0047; // U+0047 LATIN CAPITAL LETTER G +pub const XKB_KEY_H: u32 = 0x0048; // U+0048 LATIN CAPITAL LETTER H +pub const XKB_KEY_I: u32 = 0x0049; // U+0049 LATIN CAPITAL LETTER I +pub const XKB_KEY_J: u32 = 0x004a; // U+004A LATIN CAPITAL LETTER J +pub const XKB_KEY_K: u32 = 0x004b; // U+004B LATIN CAPITAL LETTER K +pub const XKB_KEY_L: u32 = 0x004c; // U+004C LATIN CAPITAL LETTER L +pub const XKB_KEY_M: u32 = 0x004d; // U+004D LATIN CAPITAL LETTER M +pub const XKB_KEY_N: u32 = 0x004e; // U+004E LATIN CAPITAL LETTER N +pub const XKB_KEY_O: u32 = 0x004f; // U+004F LATIN CAPITAL LETTER O +pub const XKB_KEY_P: u32 = 0x0050; // U+0050 LATIN CAPITAL LETTER P +pub const XKB_KEY_Q: u32 = 0x0051; // U+0051 LATIN CAPITAL LETTER Q +pub const XKB_KEY_R: u32 = 0x0052; // U+0052 LATIN CAPITAL LETTER R +pub const XKB_KEY_S: u32 = 0x0053; // U+0053 LATIN CAPITAL LETTER S +pub const XKB_KEY_T: u32 = 0x0054; // U+0054 LATIN CAPITAL LETTER T +pub const XKB_KEY_U: u32 = 0x0055; // U+0055 LATIN CAPITAL LETTER U +pub const XKB_KEY_V: u32 = 0x0056; // U+0056 LATIN CAPITAL LETTER V +pub const XKB_KEY_W: u32 = 0x0057; // U+0057 LATIN CAPITAL LETTER W +pub const XKB_KEY_X: u32 = 0x0058; // U+0058 LATIN CAPITAL LETTER X +pub const XKB_KEY_Y: u32 = 0x0059; // U+0059 LATIN CAPITAL LETTER Y +pub const XKB_KEY_Z: u32 = 0x005a; // U+005A LATIN CAPITAL LETTER Z +pub const XKB_KEY_bracketleft: u32 = 0x005b; // U+005B LEFT SQUARE BRACKET +pub const XKB_KEY_backslash: u32 = 0x005c; // U+005C REVERSE SOLIDUS +pub const XKB_KEY_bracketright: u32 = 0x005d; // U+005D RIGHT SQUARE BRACKET +pub const XKB_KEY_underscore: u32 = 0x005f; // U+005F LOW LINE +pub const XKB_KEY_grave: u32 = 0x0060; // U+0060 GRAVE ACCENT +pub const XKB_KEY_a: u32 = 0x0061; // U+0061 LATIN SMALL LETTER A +pub const XKB_KEY_b: u32 = 0x0062; // U+0062 LATIN SMALL LETTER B +pub const XKB_KEY_c: u32 = 0x0063; // U+0063 LATIN SMALL LETTER C +pub const XKB_KEY_d: u32 = 0x0064; // U+0064 LATIN SMALL LETTER D +pub const XKB_KEY_e: u32 = 0x0065; // U+0065 LATIN SMALL LETTER E +pub const XKB_KEY_f: u32 = 0x0066; // U+0066 LATIN SMALL LETTER F +pub const XKB_KEY_g: u32 = 0x0067; // U+0067 LATIN SMALL LETTER G +pub const XKB_KEY_h: u32 = 0x0068; // U+0068 LATIN SMALL LETTER H +pub const XKB_KEY_i: u32 = 0x0069; // U+0069 LATIN SMALL LETTER I +pub const XKB_KEY_j: u32 = 0x006a; // U+006A LATIN SMALL LETTER J +pub const XKB_KEY_k: u32 = 0x006b; // U+006B LATIN SMALL LETTER K +pub const XKB_KEY_l: u32 = 0x006c; // U+006C LATIN SMALL LETTER L +pub const XKB_KEY_m: u32 = 0x006d; // U+006D LATIN SMALL LETTER M +pub const XKB_KEY_n: u32 = 0x006e; // U+006E LATIN SMALL LETTER N +pub const XKB_KEY_o: u32 = 0x006f; // U+006F LATIN SMALL LETTER O +pub const XKB_KEY_p: u32 = 0x0070; // U+0070 LATIN SMALL LETTER P +pub const XKB_KEY_q: u32 = 0x0071; // U+0071 LATIN SMALL LETTER Q +pub const XKB_KEY_r: u32 = 0x0072; // U+0072 LATIN SMALL LETTER R +pub const XKB_KEY_s: u32 = 0x0073; // U+0073 LATIN SMALL LETTER S +pub const XKB_KEY_t: u32 = 0x0074; // U+0074 LATIN SMALL LETTER T +pub const XKB_KEY_u: u32 = 0x0075; // U+0075 LATIN SMALL LETTER U +pub const XKB_KEY_v: u32 = 0x0076; // U+0076 LATIN SMALL LETTER V +pub const XKB_KEY_w: u32 = 0x0077; // U+0077 LATIN SMALL LETTER W +pub const XKB_KEY_x: u32 = 0x0078; // U+0078 LATIN SMALL LETTER X +pub const XKB_KEY_y: u32 = 0x0079; // U+0079 LATIN SMALL LETTER Y +pub const XKB_KEY_z: u32 = 0x007a; // U+007A LATIN SMALL LETTER Z +pub const XKB_KEY_yen: u32 = 0x00a5; // U+00A5 YEN SIGN +pub const XKB_KEY_caret: u32 = 0x0afc; // U+2038 CARET + +// Keys found on some "Internet" keyboards. -/* - * Keys found on some "Internet" keyboards. - */ -pub const XKB_KEY_XF86AudioLowerVolume: u32 = 0x1008FF11; /* Volume control down */ -pub const XKB_KEY_XF86AudioMute: u32 = 0x1008FF12; /* Mute sound from the system */ -pub const XKB_KEY_XF86AudioRaiseVolume: u32 = 0x1008FF13; /* Volume control up */ -pub const XKB_KEY_XF86AudioPrev: u32 = 0x1008FF16; /* Previous track */ -pub const XKB_KEY_XF86AudioNext: u32 = 0x1008FF17; /* Next track */ -pub const XKB_KEY_XF86Mail: u32 = 0x1008FF19; /* Invoke user's mail program */ +pub const XKB_KEY_XF86AudioLowerVolume: u32 = 0x1008FF11; // Volume control down +pub const XKB_KEY_XF86AudioMute: u32 = 0x1008FF12; // Mute sound from the system +pub const XKB_KEY_XF86AudioRaiseVolume: u32 = 0x1008FF13; // Volume control up +pub const XKB_KEY_XF86AudioPrev: u32 = 0x1008FF16; // Previous track +pub const XKB_KEY_XF86AudioNext: u32 = 0x1008FF17; // Next track +pub const XKB_KEY_XF86Mail: u32 = 0x1008FF19; // Invoke user's mail program -/* These are sometimes found on PDA's (e.g. Palm, PocketPC or elsewhere) */ -pub const XKB_KEY_XF86Calculator: u32 = 0x1008FF1D; /* Invoke calculator program */ -pub const XKB_KEY_XF86PowerOff: u32 = 0x1008FF2A; /* Power off system entirely */ -pub const XKB_KEY_XF86Sleep: u32 = 0x1008FF2F; /* Put system to sleep */ -pub const XKB_KEY_XF86Copy: u32 = 0x1008FF57; /* Copy selection */ -pub const XKB_KEY_XF86Cut: u32 = 0x1008FF58; /* Cut selection */ -pub const XKB_KEY_XF86Paste: u32 = 0x1008FF6D; /* Paste */ +// These are sometimes found on PDA's (e.g. Palm, PocketPC or elsewhere) +pub const XKB_KEY_XF86Calculator: u32 = 0x1008FF1D; // Invoke calculator program +pub const XKB_KEY_XF86PowerOff: u32 = 0x1008FF2A; // Power off system entirely +pub const XKB_KEY_XF86Sleep: u32 = 0x1008FF2F; // Put system to sleep +pub const XKB_KEY_XF86Copy: u32 = 0x1008FF57; // Copy selection +pub const XKB_KEY_XF86Cut: u32 = 0x1008FF58; // Cut selection +pub const XKB_KEY_XF86Paste: u32 = 0x1008FF6D; // Paste pub fn keysym_to_vkey(keysym: u32) -> Option { match keysym { From bf417670911a03ffbca058db73aa439718cc8f5b Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Mon, 9 May 2022 09:35:52 -0400 Subject: [PATCH 078/151] Change naming for kms --- Cargo.toml | 4 +- src/platform/unix.rs | 72 ++++++++-------- .../linux/{drm => kms}/event_loop.rs | 6 +- src/platform_impl/linux/{drm => kms}/mod.rs | 0 .../linux/{drm => kms}/window.rs | 0 src/platform_impl/linux/mod.rs | 84 +++++++++---------- .../linux/wayland/event_loop/mod.rs | 6 +- src/platform_impl/linux/wayland/window/mod.rs | 4 +- 8 files changed, 88 insertions(+), 88 deletions(-) rename src/platform_impl/linux/{drm => kms}/event_loop.rs (99%) rename src/platform_impl/linux/{drm => kms}/mod.rs (100%) rename src/platform_impl/linux/{drm => kms}/window.rs (100%) diff --git a/Cargo.toml b/Cargo.toml index 7238a784bf..6366cab0ae 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,11 +17,11 @@ default-target = "x86_64-unknown-linux-gnu" targets = ["i686-pc-windows-msvc", "x86_64-pc-windows-msvc", "i686-unknown-linux-gnu", "x86_64-unknown-linux-gnu", "x86_64-apple-darwin", "wasm32-unknown-unknown"] [features] -default = ["x11", "wayland", "wayland-dlopen", "kmsdrm"] +default = ["x11", "wayland", "wayland-dlopen", "kms"] x11 = ["x11-dl", "mio", "percent-encoding", "parking_lot"] wayland = ["wayland-client", "wayland-protocols", "sctk", "calloop"] wayland-dlopen = ["sctk/dlopen", "wayland-client/dlopen"] -kmsdrm = ["drm", "input", "calloop", "libseat", "xkbcommon", "udev"] +kms = ["drm", "input", "calloop", "libseat", "xkbcommon", "udev"] [dependencies] instant = { version = "0.1.12", features = ["wasm-bindgen"] } diff --git a/src/platform/unix.rs b/src/platform/unix.rs index 05691b6e47..bd421b942a 100644 --- a/src/platform/unix.rs +++ b/src/platform/unix.rs @@ -10,7 +10,7 @@ use std::os::{raw, unix::prelude::FromRawFd}; #[cfg(feature = "x11")] use std::ptr; -#[cfg(any(feature = "x11", feature = "kmsdrm"))] +#[cfg(any(feature = "x11", feature = "kms"))] use std::sync::Arc; use crate::{ @@ -28,7 +28,7 @@ use crate::platform_impl::{ Window as LinuxWindow, }; -#[cfg(feature = "kmsdrm")] +#[cfg(feature = "kms")] use ::drm::{control::Device as ControlDevice, Device}; // TODO: stupid hack so that glutin can do its work @@ -38,12 +38,12 @@ pub use crate::platform_impl::x11; #[cfg(feature = "x11")] pub use crate::platform_impl::{x11::util::WindowType as XWindowType, XNotSupported}; -#[cfg(feature = "kmsdrm")] +#[cfg(feature = "kms")] #[derive(Debug, Clone)] /// A simple wrapper for a device node. pub struct Card(pub(crate) Arc); -#[cfg(feature = "kmsdrm")] +#[cfg(feature = "kms")] /// Implementing `AsRawFd` is a prerequisite to implementing the traits found /// in this crate. Here, we are just calling `as_raw_fd()` on the inner File. impl std::os::unix::io::AsRawFd for Card { @@ -52,17 +52,17 @@ impl std::os::unix::io::AsRawFd for Card { } } -#[cfg(feature = "kmsdrm")] +#[cfg(feature = "kms")] impl Drop for Card { fn drop(&mut self) { unsafe { std::fs::File::from_raw_fd(*self.0) }; } } -#[cfg(feature = "kmsdrm")] +#[cfg(feature = "kms")] /// With `AsRawFd` implemented, we can now implement `drm::Device`. impl Device for Card {} -#[cfg(feature = "kmsdrm")] +#[cfg(feature = "kms")] impl ControlDevice for Card {} /// Additional methods on `EventLoopWindowTarget` that are specific to Unix. @@ -75,7 +75,7 @@ pub trait EventLoopWindowTargetExtUnix { #[cfg(feature = "x11")] fn is_x11(&self) -> bool; - #[cfg(feature = "kmsdrm")] + #[cfg(feature = "kms")] fn is_drm(&self) -> bool; #[doc(hidden)] @@ -93,32 +93,32 @@ pub trait EventLoopWindowTargetExtUnix { /// Returns the drm device of the event loop's fd /// - /// Returns `None` if the `EventLoop` doesn't use kmsdrm (if it uses wayland for example). - #[cfg(feature = "kmsdrm")] + /// Returns `None` if the `EventLoop` doesn't use kms (if it uses wayland for example). + #[cfg(feature = "kms")] fn drm_device(&self) -> Option<&crate::platform::unix::Card>; /// Returns the current crtc of the drm device /// - /// Returns `None` if the `EventLoop` doesn't use kmsdrm (if it uses wayland for example). - #[cfg(feature = "kmsdrm")] + /// Returns `None` if the `EventLoop` doesn't use kms (if it uses wayland for example). + #[cfg(feature = "kms")] fn drm_crtc(&self) -> Option<&drm::control::crtc::Info>; /// Returns the current connector of the drm device /// - /// Returns `None` if the `EventLoop` doesn't use kmsdrm (if it uses wayland for example). - #[cfg(feature = "kmsdrm")] + /// Returns `None` if the `EventLoop` doesn't use kms (if it uses wayland for example). + #[cfg(feature = "kms")] fn drm_connector(&self) -> Option<&drm::control::connector::Info>; /// Returns the current mode of the drm device /// - /// Returns `None` if the `EventLoop` doesn't use kmsdrm (if it uses wayland for example). - #[cfg(feature = "kmsdrm")] + /// Returns `None` if the `EventLoop` doesn't use kms (if it uses wayland for example). + #[cfg(feature = "kms")] fn drm_mode(&self) -> Option; /// Returns the primary plane of the drm device /// - /// Returns `None` if the `EventLoop` doesn't use kmsdrm (if it uses wayland for example). - #[cfg(feature = "kmsdrm")] + /// Returns `None` if the `EventLoop` doesn't use kms (if it uses wayland for example). + #[cfg(feature = "kms")] fn drm_plane(&self) -> Option; } @@ -136,7 +136,7 @@ impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { } #[inline] - #[cfg(feature = "kmsdrm")] + #[cfg(feature = "kms")] fn is_drm(&self) -> bool { self.p.is_drm() } @@ -147,7 +147,7 @@ impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { fn xlib_xconnection(&self) -> Option> { match self.p { LinuxEventLoopWindowTarget::X(ref e) => Some(e.x_connection().clone()), - #[cfg(any(feature = "wayland", feature = "kmsdrm"))] + #[cfg(any(feature = "wayland", feature = "kms"))] _ => None, } } @@ -159,13 +159,13 @@ impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { LinuxEventLoopWindowTarget::Wayland(ref p) => { Some(p.display().get_display_ptr() as *mut _) } - #[cfg(any(feature = "x11", feature = "kmsdrm"))] + #[cfg(any(feature = "x11", feature = "kms"))] _ => None, } } #[inline] - #[cfg(feature = "kmsdrm")] + #[cfg(feature = "kms")] fn drm_device(&self) -> Option<&crate::platform::unix::Card> { match self.p { crate::platform_impl::EventLoopWindowTarget::Drm(ref evlp) => Some(&evlp.device), @@ -175,7 +175,7 @@ impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { } #[inline] - #[cfg(feature = "kmsdrm")] + #[cfg(feature = "kms")] fn drm_crtc(&self) -> Option<&drm::control::crtc::Info> { match self.p { crate::platform_impl::EventLoopWindowTarget::Drm(ref window) => Some(&window.crtc), @@ -185,7 +185,7 @@ impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { } #[inline] - #[cfg(feature = "kmsdrm")] + #[cfg(feature = "kms")] fn drm_connector(&self) -> Option<&drm::control::connector::Info> { match self.p { crate::platform_impl::EventLoopWindowTarget::Drm(ref window) => Some(&window.connector), @@ -195,7 +195,7 @@ impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { } #[inline] - #[cfg(feature = "kmsdrm")] + #[cfg(feature = "kms")] fn drm_mode(&self) -> Option { match self.p { crate::platform_impl::EventLoopWindowTarget::Drm(ref window) => Some(window.mode), @@ -205,7 +205,7 @@ impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { } #[inline] - #[cfg(feature = "kmsdrm")] + #[cfg(feature = "kms")] fn drm_plane(&self) -> Option { match self.p { crate::platform_impl::EventLoopWindowTarget::Drm(ref window) => Some(window.plane), @@ -225,8 +225,8 @@ pub trait EventLoopBuilderExtUnix { #[cfg(feature = "wayland")] fn with_wayland(&mut self) -> &mut Self; - /// Force using kmsdrm - #[cfg(feature = "kmsdrm")] + /// Force using kms + #[cfg(feature = "kms")] fn with_drm(&mut self) -> &mut Self; /// Whether to allow the event loop to be created off of the main thread. @@ -252,7 +252,7 @@ impl EventLoopBuilderExtUnix for EventLoopBuilder { } #[inline] - #[cfg(feature = "kmsdrm")] + #[cfg(feature = "kms")] fn with_drm(&mut self) -> &mut Self { self.platform_specific.forced_backend = Some(Backend::Drm); self @@ -328,7 +328,7 @@ impl WindowExtUnix for Window { fn xlib_window(&self) -> Option { match self.window { LinuxWindow::X(ref w) => Some(w.xlib_window()), - #[cfg(any(feature = "wayland", feature = "kmsdrm"))] + #[cfg(any(feature = "wayland", feature = "kms"))] _ => None, } } @@ -338,7 +338,7 @@ impl WindowExtUnix for Window { fn xlib_display(&self) -> Option<*mut raw::c_void> { match self.window { LinuxWindow::X(ref w) => Some(w.xlib_display()), - #[cfg(any(feature = "wayland", feature = "kmsdrm"))] + #[cfg(any(feature = "wayland", feature = "kms"))] _ => None, } } @@ -348,7 +348,7 @@ impl WindowExtUnix for Window { fn xlib_screen_id(&self) -> Option { match self.window { LinuxWindow::X(ref w) => Some(w.xlib_screen_id()), - #[cfg(any(feature = "wayland", feature = "kmsdrm"))] + #[cfg(any(feature = "wayland", feature = "kms"))] _ => None, } } @@ -359,7 +359,7 @@ impl WindowExtUnix for Window { fn xlib_xconnection(&self) -> Option> { match self.window { LinuxWindow::X(ref w) => Some(w.xlib_xconnection()), - #[cfg(any(feature = "wayland", feature = "kmsdrm"))] + #[cfg(any(feature = "wayland", feature = "kms"))] _ => None, } } @@ -369,7 +369,7 @@ impl WindowExtUnix for Window { fn xcb_connection(&self) -> Option<*mut raw::c_void> { match self.window { LinuxWindow::X(ref w) => Some(w.xcb_connection()), - #[cfg(any(feature = "wayland", feature = "kmsdrm"))] + #[cfg(any(feature = "wayland", feature = "kms"))] _ => None, } } @@ -379,7 +379,7 @@ impl WindowExtUnix for Window { fn wayland_surface(&self) -> Option<*mut raw::c_void> { match self.window { LinuxWindow::Wayland(ref w) => Some(w.surface().as_ref().c_ptr() as *mut _), - #[cfg(any(feature = "x11", feature = "kmsdrm"))] + #[cfg(any(feature = "x11", feature = "kms"))] _ => None, } } @@ -389,7 +389,7 @@ impl WindowExtUnix for Window { fn wayland_display(&self) -> Option<*mut raw::c_void> { match self.window { LinuxWindow::Wayland(ref w) => Some(w.display().get_display_ptr() as *mut _), - #[cfg(any(feature = "x11", feature = "kmsdrm"))] + #[cfg(any(feature = "x11", feature = "kms"))] _ => None, } } diff --git a/src/platform_impl/linux/drm/event_loop.rs b/src/platform_impl/linux/kms/event_loop.rs similarity index 99% rename from src/platform_impl/linux/drm/event_loop.rs rename to src/platform_impl/linux/kms/event_loop.rs index d64b2696ec..f688c5250a 100644 --- a/src/platform_impl/linux/drm/event_loop.rs +++ b/src/platform_impl/linux/kms/event_loop.rs @@ -928,7 +928,7 @@ impl EventLoop { line!(), file!(), crate::platform_impl::OsError::DrmMisc( - "kmsdrm device does not support universal planes", + "kms device does not support universal planes", ), )), )?; @@ -937,7 +937,7 @@ impl EventLoop { line!(), file!(), crate::platform_impl::OsError::DrmMisc( - "kmsdrm device does not support atomic modesetting", + "kms device does not support atomic modesetting", ), ), ))?; @@ -1383,7 +1383,7 @@ impl EventLoop { crate::platform_impl::EventLoopWindowTarget::Drm(window_target) => { &mut window_target.event_sink } - #[cfg(any(feature = "x11", feature = "kmsdrm"))] + #[cfg(any(feature = "x11", feature = "kms"))] _ => unreachable!(), }; diff --git a/src/platform_impl/linux/drm/mod.rs b/src/platform_impl/linux/kms/mod.rs similarity index 100% rename from src/platform_impl/linux/drm/mod.rs rename to src/platform_impl/linux/kms/mod.rs diff --git a/src/platform_impl/linux/drm/window.rs b/src/platform_impl/linux/kms/window.rs similarity index 100% rename from src/platform_impl/linux/drm/window.rs rename to src/platform_impl/linux/kms/window.rs diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index eca933ce04..708df4941f 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -9,9 +9,9 @@ #[cfg(all( not(feature = "x11"), not(feature = "wayland"), - not(feature = "kmsdrm") + not(feature = "kms") ))] -compile_error!("Please select a feature to build for unix: `x11`, `wayland`, `kmsdrm`"); +compile_error!("Please select a feature to build for unix: `x11`, `wayland`, `kms`"); #[cfg(feature = "wayland")] use std::error::Error; @@ -39,13 +39,13 @@ use crate::{ pub(crate) use crate::icon::RgbaIcon as PlatformIcon; -#[cfg(feature = "kmsdrm")] +#[cfg(feature = "kms")] pub mod drm; #[cfg(feature = "wayland")] pub mod wayland; #[cfg(feature = "x11")] pub mod x11; -#[cfg(any(feature = "kmsdrm", feature = "wayland"))] +#[cfg(any(feature = "kms", feature = "wayland"))] pub mod xkb_keymap; /// Environment variable specifying which backend should be used on unix platform. @@ -63,7 +63,7 @@ pub(crate) enum Backend { X, #[cfg(feature = "wayland")] Wayland, - #[cfg(feature = "kmsdrm")] + #[cfg(feature = "kms")] Drm, } @@ -149,7 +149,7 @@ pub enum OsError { XMisc(&'static str), #[cfg(feature = "wayland")] WaylandMisc(&'static str), - #[cfg(feature = "kmsdrm")] + #[cfg(feature = "kms")] DrmMisc(&'static str), } @@ -162,7 +162,7 @@ impl fmt::Display for OsError { OsError::XMisc(e) => _f.pad(e), #[cfg(feature = "wayland")] OsError::WaylandMisc(e) => _f.pad(e), - #[cfg(feature = "kmsdrm")] + #[cfg(feature = "kms")] OsError::DrmMisc(e) => _f.pad(e), } } @@ -173,7 +173,7 @@ pub enum Window { X(x11::Window), #[cfg(feature = "wayland")] Wayland(wayland::Window), - #[cfg(feature = "kmsdrm")] + #[cfg(feature = "kms")] Drm(drm::Window), } @@ -183,7 +183,7 @@ pub enum WindowId { X(x11::WindowId), #[cfg(feature = "wayland")] Wayland(wayland::WindowId), - #[cfg(feature = "kmsdrm")] + #[cfg(feature = "kms")] Drm(drm::WindowId), } @@ -191,9 +191,9 @@ impl WindowId { pub const unsafe fn dummy() -> Self { #[cfg(feature = "wayland")] return WindowId::Wayland(wayland::WindowId::dummy()); - #[cfg(all(not(all(feature = "wayland", feature = "kmsdrm")), feature = "x11"))] + #[cfg(all(not(all(feature = "wayland", feature = "kms")), feature = "x11"))] return WindowId::X(x11::WindowId::dummy()); - #[cfg(all(not(all(feature = "wayland", feature = "x11")), feature = "kmsdrm"))] + #[cfg(all(not(all(feature = "wayland", feature = "x11")), feature = "kms"))] return WindowId::Drm(drm::WindowId::dummy()); } } @@ -204,7 +204,7 @@ pub enum DeviceId { X(x11::DeviceId), #[cfg(feature = "wayland")] Wayland(wayland::DeviceId), - #[cfg(feature = "kmsdrm")] + #[cfg(feature = "kms")] Drm(drm::DeviceId), } @@ -214,7 +214,7 @@ impl DeviceId { return DeviceId::Wayland(wayland::DeviceId::dummy()); #[cfg(all(not(feature = "wayland"), feature = "x11"))] return DeviceId::X(x11::DeviceId::dummy()); - #[cfg(all(not(all(feature = "wayland", feature = "x11")), feature = "kmsdrm"))] + #[cfg(all(not(all(feature = "wayland", feature = "x11")), feature = "kms"))] return DeviceId::Drm(drm::DeviceId::dummy()); } } @@ -225,7 +225,7 @@ pub enum MonitorHandle { X(x11::MonitorHandle), #[cfg(feature = "wayland")] Wayland(wayland::MonitorHandle), - #[cfg(feature = "kmsdrm")] + #[cfg(feature = "kms")] Drm(drm::MonitorHandle), } @@ -245,7 +245,7 @@ macro_rules! x11_or_wayland_or_drm { $enum::X($($c1)*) => $enum2::X($x), #[cfg(feature = "wayland")] $enum::Wayland($($c1)*) => $enum2::Wayland($x), - #[cfg(feature = "kmsdrm")] + #[cfg(feature = "kms")] $enum::Drm($($c1)*) => $enum2::Drm($x) } }; @@ -255,7 +255,7 @@ macro_rules! x11_or_wayland_or_drm { $enum::X($($c1)*) => $x, #[cfg(feature = "wayland")] $enum::Wayland($($c1)*) => $x, - #[cfg(feature = "kmsdrm")] + #[cfg(feature = "kms")] $enum::Drm($($c1)*) => $x } }; @@ -299,7 +299,7 @@ pub enum VideoMode { X(x11::VideoMode), #[cfg(feature = "wayland")] Wayland(wayland::VideoMode), - #[cfg(feature = "kmsdrm")] + #[cfg(feature = "kms")] Drm(drm::VideoMode), } @@ -341,7 +341,7 @@ impl Window { EventLoopWindowTarget::X(ref window_target) => { x11::Window::new(window_target, attribs, pl_attribs).map(Window::X) } - #[cfg(feature = "kmsdrm")] + #[cfg(feature = "kms")] EventLoopWindowTarget::Drm(ref window_target) => { drm::Window::new(window_target, attribs, pl_attribs).map(Window::Drm) } @@ -495,7 +495,7 @@ impl Window { Window::X(ref w) => w.set_always_on_top(_always_on_top), #[cfg(feature = "wayland")] Window::Wayland(_) => (), - #[cfg(feature = "kmsdrm")] + #[cfg(feature = "kms")] Window::Drm(_) => (), } } @@ -507,7 +507,7 @@ impl Window { Window::X(ref w) => w.set_window_icon(_window_icon), #[cfg(feature = "wayland")] Window::Wayland(_) => (), - #[cfg(feature = "kmsdrm")] + #[cfg(feature = "kms")] Window::Drm(_) => (), } } @@ -524,7 +524,7 @@ impl Window { Window::X(ref w) => w.focus_window(), #[cfg(feature = "wayland")] Window::Wayland(_) => (), - #[cfg(feature = "kmsdrm")] + #[cfg(feature = "kms")] Window::Drm(_) => (), } } @@ -534,7 +534,7 @@ impl Window { Window::X(ref w) => w.request_user_attention(request_type), #[cfg(feature = "wayland")] Window::Wayland(ref w) => w.request_user_attention(request_type), - #[cfg(feature = "kmsdrm")] + #[cfg(feature = "kms")] Window::Drm(_) => (), } } @@ -561,7 +561,7 @@ impl Window { inner: current_monitor, }) } - #[cfg(feature = "kmsdrm")] + #[cfg(feature = "kms")] Window::Drm(ref window) => { let current_monitor = MonitorHandle::Drm(window.current_monitor()?); Some(RootMonitorHandle { @@ -586,7 +586,7 @@ impl Window { .into_iter() .map(MonitorHandle::Wayland) .collect(), - #[cfg(feature = "kmsdrm")] + #[cfg(feature = "kms")] Window::Drm(ref window) => window .available_monitors() .into_iter() @@ -607,7 +607,7 @@ impl Window { } #[cfg(feature = "wayland")] Window::Wayland(ref window) => window.primary_monitor(), - #[cfg(feature = "kmsdrm")] + #[cfg(feature = "kms")] Window::Drm(ref window) => window.primary_monitor(), } } @@ -618,7 +618,7 @@ impl Window { Window::X(ref window) => RawWindowHandle::Xlib(window.raw_window_handle()), #[cfg(feature = "wayland")] Window::Wayland(ref window) => RawWindowHandle::Wayland(window.raw_window_handle()), - #[cfg(feature = "kmsdrm")] + #[cfg(feature = "kms")] Window::Drm(ref window) => RawWindowHandle::Drm(window.raw_window_handle()), } } @@ -662,7 +662,7 @@ pub enum EventLoop { Wayland(wayland::EventLoop), #[cfg(feature = "x11")] X(x11::EventLoop), - #[cfg(feature = "kmsdrm")] + #[cfg(feature = "kms")] Drm(drm::EventLoop), } @@ -671,7 +671,7 @@ pub enum EventLoopProxy { X(x11::EventLoopProxy), #[cfg(feature = "wayland")] Wayland(wayland::EventLoopProxy), - #[cfg(feature = "kmsdrm")] + #[cfg(feature = "kms")] Drm(drm::EventLoopProxy), } @@ -704,7 +704,7 @@ impl EventLoop { return EventLoop::new_wayland_any_thread().expect("failed to open Wayland connection"); } - #[cfg(feature = "kmsdrm")] + #[cfg(feature = "kms")] if attributes.forced_backend == Some(Backend::Drm) { // TODO: Propagate return EventLoop::new_drm_any_thread().expect("failed to open drm connection"); @@ -727,12 +727,12 @@ impl EventLoop { #[cfg(not(feature = "wayland"))] panic!("wayland feature is not enabled"); } - "drm" | "kmsdrm" | "gbm" | "tty" => { - #[cfg(feature = "kmsdrm")] + "drm" | "kms" | "gbm" | "tty" => { + #[cfg(feature = "kms")] return EventLoop::new_drm_any_thread() .expect("Failed to initialize drm backend"); - #[cfg(not(feature = "kmsdrm"))] - panic!("kmsdrm feature is not enabled"); + #[cfg(not(feature = "kms"))] + panic!("kms feature is not enabled"); } _ => panic!( "Unknown environment variable value for {}, try one of `x11`,`wayland`", @@ -753,7 +753,7 @@ impl EventLoop { Err(err) => err, }; - #[cfg(feature = "kmsdrm")] + #[cfg(feature = "kms")] let drm_err = match EventLoop::new_drm_any_thread() { Ok(event_loop) => return event_loop, Err(err) => err, @@ -763,7 +763,7 @@ impl EventLoop { let wayland_err = "backend disabled"; #[cfg(not(feature = "x11"))] let x11_err = "backend disabled"; - #[cfg(not(feature = "kmsdrm"))] + #[cfg(not(feature = "kms"))] let drm_err = "backend disabled"; panic!( @@ -787,7 +787,7 @@ impl EventLoop { Ok(EventLoop::X(x11::EventLoop::new(xconn))) } - #[cfg(feature = "kmsdrm")] + #[cfg(feature = "kms")] fn new_drm_any_thread() -> Result, RootOsError> { drm::EventLoop::new().map(EventLoop::Drm) } @@ -826,7 +826,7 @@ pub enum EventLoopWindowTarget { Wayland(wayland::EventLoopWindowTarget), #[cfg(feature = "x11")] X(x11::EventLoopWindowTarget), - #[cfg(feature = "kmsdrm")] + #[cfg(feature = "kms")] Drm(drm::EventLoopWindowTarget), } @@ -836,7 +836,7 @@ impl EventLoopWindowTarget { match *self { #[cfg(feature = "wayland")] EventLoopWindowTarget::Wayland(_) => true, - #[cfg(any(feature = "x11", feature = "kmsdrm"))] + #[cfg(any(feature = "x11", feature = "kms"))] _ => false, } } @@ -846,7 +846,7 @@ impl EventLoopWindowTarget { match *self { #[cfg(feature = "x11")] EventLoopWindowTarget::X(_) => true, - #[cfg(any(feature = "kmsdrm", feature = "wayland"))] + #[cfg(any(feature = "kms", feature = "wayland"))] _ => false, } } @@ -854,7 +854,7 @@ impl EventLoopWindowTarget { #[inline] pub fn is_drm(&self) -> bool { match *self { - #[cfg(feature = "kmsdrm")] + #[cfg(feature = "kms")] EventLoopWindowTarget::Drm(_) => true, #[cfg(any(feature = "x11", feature = "wayland"))] _ => false, @@ -877,7 +877,7 @@ impl EventLoopWindowTarget { .into_iter() .map(MonitorHandle::X) .collect(), - #[cfg(feature = "kmsdrm")] + #[cfg(feature = "kms")] EventLoopWindowTarget::Drm(ref evlp) => evlp .available_monitors() .into_iter() @@ -898,7 +898,7 @@ impl EventLoopWindowTarget { inner: primary_monitor, }) } - #[cfg(feature = "kmsdrm")] + #[cfg(feature = "kms")] EventLoopWindowTarget::Drm(ref evlp) => evlp.primary_monitor(), } } diff --git a/src/platform_impl/linux/wayland/event_loop/mod.rs b/src/platform_impl/linux/wayland/event_loop/mod.rs index 05aac6a186..cbc3296980 100644 --- a/src/platform_impl/linux/wayland/event_loop/mod.rs +++ b/src/platform_impl/linux/wayland/event_loop/mod.rs @@ -248,7 +248,7 @@ impl EventLoop { PlatformEventLoopWindowTarget::Wayland(window_target) => { window_target.state.get_mut() } - #[cfg(any(feature = "x11", feature = "kmsdrm"))] + #[cfg(any(feature = "x11", feature = "kms"))] _ => unreachable!(), }; @@ -537,7 +537,7 @@ impl EventLoop { fn with_window_target) -> U>(&mut self, f: F) -> U { let state = match &mut self.window_target.p { PlatformEventLoopWindowTarget::Wayland(window_target) => window_target, - #[cfg(any(feature = "x11", feature = "kmsdrm"))] + #[cfg(any(feature = "x11", feature = "kms"))] _ => unreachable!(), }; @@ -547,7 +547,7 @@ impl EventLoop { fn loop_dispatch>>(&mut self, timeout: D) -> IOResult<()> { let state = match &mut self.window_target.p { PlatformEventLoopWindowTarget::Wayland(window_target) => window_target.state.get_mut(), - #[cfg(any(feature = "x11", feature = "kmsdrm"))] + #[cfg(any(feature = "x11", feature = "kms"))] _ => unreachable!(), }; diff --git a/src/platform_impl/linux/wayland/window/mod.rs b/src/platform_impl/linux/wayland/window/mod.rs index 36cac4aea0..23c522a932 100644 --- a/src/platform_impl/linux/wayland/window/mod.rs +++ b/src/platform_impl/linux/wayland/window/mod.rs @@ -179,7 +179,7 @@ impl Window { PlatformMonitorHandle::Wayland(monitor) => Some(monitor.proxy), #[cfg(feature = "x11")] PlatformMonitorHandle::X(_) => None, - #[cfg(feature = "kmsdrm")] + #[cfg(feature = "kms")] PlatformMonitorHandle::Drm(_) => None, }); @@ -426,7 +426,7 @@ impl Window { PlatformMonitorHandle::Wayland(monitor) => Some(monitor.proxy), #[cfg(feature = "x11")] PlatformMonitorHandle::X(_) => None, - #[cfg(feature = "kmsdrm")] + #[cfg(feature = "kms")] PlatformMonitorHandle::Drm(_) => None, }); From 5338ea173a3455d7c91a416b5c404c93967aa865 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Mon, 9 May 2022 09:42:22 -0400 Subject: [PATCH 079/151] Change naming for kms --- src/platform/unix.rs | 12 +- src/platform_impl/linux/kms/event_loop.rs | 136 +++++++++--------- src/platform_impl/linux/kms/mod.rs | 4 +- src/platform_impl/linux/kms/window.rs | 14 +- src/platform_impl/linux/mod.rs | 75 +++++----- src/platform_impl/linux/wayland/window/mod.rs | 4 +- 6 files changed, 120 insertions(+), 125 deletions(-) diff --git a/src/platform/unix.rs b/src/platform/unix.rs index bd421b942a..472dfb443c 100644 --- a/src/platform/unix.rs +++ b/src/platform/unix.rs @@ -168,7 +168,7 @@ impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { #[cfg(feature = "kms")] fn drm_device(&self) -> Option<&crate::platform::unix::Card> { match self.p { - crate::platform_impl::EventLoopWindowTarget::Drm(ref evlp) => Some(&evlp.device), + crate::platform_impl::EventLoopWindowTarget::Kms(ref evlp) => Some(&evlp.device), #[cfg(any(feature = "x11", feature = "wayland"))] _ => None, } @@ -178,7 +178,7 @@ impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { #[cfg(feature = "kms")] fn drm_crtc(&self) -> Option<&drm::control::crtc::Info> { match self.p { - crate::platform_impl::EventLoopWindowTarget::Drm(ref window) => Some(&window.crtc), + crate::platform_impl::EventLoopWindowTarget::Kms(ref window) => Some(&window.crtc), #[cfg(any(feature = "x11", feature = "wayland"))] _ => None, } @@ -188,7 +188,7 @@ impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { #[cfg(feature = "kms")] fn drm_connector(&self) -> Option<&drm::control::connector::Info> { match self.p { - crate::platform_impl::EventLoopWindowTarget::Drm(ref window) => Some(&window.connector), + crate::platform_impl::EventLoopWindowTarget::Kms(ref window) => Some(&window.connector), #[cfg(any(feature = "x11", feature = "wayland"))] _ => None, } @@ -198,7 +198,7 @@ impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { #[cfg(feature = "kms")] fn drm_mode(&self) -> Option { match self.p { - crate::platform_impl::EventLoopWindowTarget::Drm(ref window) => Some(window.mode), + crate::platform_impl::EventLoopWindowTarget::Kms(ref window) => Some(window.mode), #[cfg(any(feature = "x11", feature = "wayland"))] _ => None, } @@ -208,7 +208,7 @@ impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { #[cfg(feature = "kms")] fn drm_plane(&self) -> Option { match self.p { - crate::platform_impl::EventLoopWindowTarget::Drm(ref window) => Some(window.plane), + crate::platform_impl::EventLoopWindowTarget::Kms(ref window) => Some(window.plane), #[cfg(any(feature = "x11", feature = "wayland"))] _ => None, } @@ -254,7 +254,7 @@ impl EventLoopBuilderExtUnix for EventLoopBuilder { #[inline] #[cfg(feature = "kms")] fn with_drm(&mut self) -> &mut Self { - self.platform_specific.forced_backend = Some(Backend::Drm); + self.platform_specific.forced_backend = Some(Backend::Kms); self } diff --git a/src/platform_impl/linux/kms/event_loop.rs b/src/platform_impl/linux/kms/event_loop.rs index f688c5250a..370b60a546 100644 --- a/src/platform_impl/linux/kms/event_loop.rs +++ b/src/platform_impl/linux/kms/event_loop.rs @@ -125,7 +125,7 @@ impl EventSource for LibinputInputBackend { callback( crate::event::Event::DeviceEvent { device_id: crate::event::DeviceId( - crate::platform_impl::DeviceId::Drm(super::DeviceId), + crate::platform_impl::DeviceId::Kms(super::DeviceId), ), event: crate::event::DeviceEvent::Added, }, @@ -136,7 +136,7 @@ impl EventSource for LibinputInputBackend { callback( crate::event::Event::DeviceEvent { device_id: crate::event::DeviceId( - crate::platform_impl::DeviceId::Drm(super::DeviceId), + crate::platform_impl::DeviceId::Kms(super::DeviceId), ), event: crate::event::DeviceEvent::Removed, }, @@ -149,11 +149,11 @@ impl EventSource for LibinputInputBackend { input::event::TouchEvent::Up(e) => callback( crate::event::Event::WindowEvent { window_id: crate::window::WindowId( - crate::platform_impl::WindowId::Drm(super::WindowId), + crate::platform_impl::WindowId::Kms(super::WindowId), ), event: crate::event::WindowEvent::Touch(crate::event::Touch { device_id: crate::event::DeviceId( - crate::platform_impl::DeviceId::Drm(super::DeviceId), + crate::platform_impl::DeviceId::Kms(super::DeviceId), ), phase: crate::event::TouchPhase::Ended, location: self.touch_location, @@ -169,11 +169,11 @@ impl EventSource for LibinputInputBackend { callback( crate::event::Event::WindowEvent { window_id: crate::window::WindowId( - crate::platform_impl::WindowId::Drm(super::WindowId), + crate::platform_impl::WindowId::Kms(super::WindowId), ), event: crate::event::WindowEvent::Touch(crate::event::Touch { device_id: crate::event::DeviceId( - crate::platform_impl::DeviceId::Drm(super::DeviceId), + crate::platform_impl::DeviceId::Kms(super::DeviceId), ), phase: crate::event::TouchPhase::Started, location: self.touch_location, @@ -190,11 +190,11 @@ impl EventSource for LibinputInputBackend { callback( crate::event::Event::WindowEvent { window_id: crate::window::WindowId( - crate::platform_impl::WindowId::Drm(super::WindowId), + crate::platform_impl::WindowId::Kms(super::WindowId), ), event: crate::event::WindowEvent::Touch(crate::event::Touch { device_id: crate::event::DeviceId( - crate::platform_impl::DeviceId::Drm(super::DeviceId), + crate::platform_impl::DeviceId::Kms(super::DeviceId), ), phase: crate::event::TouchPhase::Moved, location: self.touch_location, @@ -208,11 +208,11 @@ impl EventSource for LibinputInputBackend { input::event::TouchEvent::Cancel(e) => callback( crate::event::Event::WindowEvent { window_id: crate::window::WindowId( - crate::platform_impl::WindowId::Drm(super::WindowId), + crate::platform_impl::WindowId::Kms(super::WindowId), ), event: crate::event::WindowEvent::Touch(crate::event::Touch { device_id: crate::event::DeviceId( - crate::platform_impl::DeviceId::Drm(super::DeviceId), + crate::platform_impl::DeviceId::Kms(super::DeviceId), ), phase: crate::event::TouchPhase::Cancelled, location: self.touch_location, @@ -225,11 +225,11 @@ impl EventSource for LibinputInputBackend { input::event::TouchEvent::Frame(_) => callback( crate::event::Event::WindowEvent { window_id: crate::window::WindowId( - crate::platform_impl::WindowId::Drm(super::WindowId), + crate::platform_impl::WindowId::Kms(super::WindowId), ), event: crate::event::WindowEvent::Touch(crate::event::Touch { device_id: crate::event::DeviceId( - crate::platform_impl::DeviceId::Drm(super::DeviceId), + crate::platform_impl::DeviceId::Kms(super::DeviceId), ), phase: crate::event::TouchPhase::Ended, location: self.touch_location, @@ -245,11 +245,11 @@ impl EventSource for LibinputInputBackend { input::event::TabletToolEvent::Tip(e) => callback( crate::event::Event::WindowEvent { window_id: crate::window::WindowId( - crate::platform_impl::WindowId::Drm(super::WindowId), + crate::platform_impl::WindowId::Kms(super::WindowId), ), event: crate::event::WindowEvent::Touch(crate::event::Touch { device_id: crate::event::DeviceId( - crate::platform_impl::DeviceId::Drm(super::DeviceId), + crate::platform_impl::DeviceId::Kms(super::DeviceId), ), phase: match e.tip_state() { TipState::Down => crate::event::TouchPhase::Started, @@ -273,11 +273,11 @@ impl EventSource for LibinputInputBackend { callback( crate::event::Event::WindowEvent { window_id: crate::window::WindowId( - crate::platform_impl::WindowId::Drm(super::WindowId), + crate::platform_impl::WindowId::Kms(super::WindowId), ), event: crate::event::WindowEvent::MouseInput { device_id: crate::event::DeviceId( - crate::platform_impl::DeviceId::Drm(super::DeviceId), + crate::platform_impl::DeviceId::Kms(super::DeviceId), ), state: match e.button_state() { ButtonState::Pressed => { @@ -300,7 +300,7 @@ impl EventSource for LibinputInputBackend { callback( crate::event::Event::DeviceEvent { device_id: crate::event::DeviceId( - crate::platform_impl::DeviceId::Drm(super::DeviceId), + crate::platform_impl::DeviceId::Kms(super::DeviceId), ), event: crate::event::DeviceEvent::Button { button: e.button(), @@ -330,11 +330,11 @@ impl EventSource for LibinputInputBackend { callback( crate::event::Event::WindowEvent { window_id: crate::window::WindowId( - crate::platform_impl::WindowId::Drm(super::WindowId), + crate::platform_impl::WindowId::Kms(super::WindowId), ), event: crate::event::WindowEvent::CursorMoved { device_id: crate::event::DeviceId( - crate::platform_impl::DeviceId::Drm(super::DeviceId), + crate::platform_impl::DeviceId::Kms(super::DeviceId), ), position: self.cursor_positon, modifiers: self.modifiers, @@ -345,7 +345,7 @@ impl EventSource for LibinputInputBackend { callback( crate::event::Event::DeviceEvent { device_id: crate::event::DeviceId( - crate::platform_impl::DeviceId::Drm(super::DeviceId), + crate::platform_impl::DeviceId::Kms(super::DeviceId), ), event: crate::event::DeviceEvent::MouseMotion { delta: (e.dx(), e.dy()), @@ -358,11 +358,11 @@ impl EventSource for LibinputInputBackend { callback( crate::event::Event::WindowEvent { window_id: crate::window::WindowId( - crate::platform_impl::WindowId::Drm(super::WindowId), + crate::platform_impl::WindowId::Kms(super::WindowId), ), event: crate::event::WindowEvent::MouseInput { device_id: crate::event::DeviceId( - crate::platform_impl::DeviceId::Drm(super::DeviceId), + crate::platform_impl::DeviceId::Kms(super::DeviceId), ), state: match e.button_state() { ButtonState::Pressed => { @@ -385,7 +385,7 @@ impl EventSource for LibinputInputBackend { callback( crate::event::Event::DeviceEvent { device_id: crate::event::DeviceId( - crate::platform_impl::DeviceId::Drm(super::DeviceId), + crate::platform_impl::DeviceId::Kms(super::DeviceId), ), event: crate::event::DeviceEvent::Button { button: e.button(), @@ -406,11 +406,11 @@ impl EventSource for LibinputInputBackend { callback( crate::event::Event::WindowEvent { window_id: crate::window::WindowId( - crate::platform_impl::WindowId::Drm(super::WindowId), + crate::platform_impl::WindowId::Kms(super::WindowId), ), event: crate::event::WindowEvent::MouseWheel { device_id: crate::event::DeviceId( - crate::platform_impl::DeviceId::Drm(super::DeviceId), + crate::platform_impl::DeviceId::Kms(super::DeviceId), ), delta: MouseScrollDelta::LineDelta( if e.has_axis(input::event::pointer::Axis::Horizontal) { @@ -441,11 +441,11 @@ impl EventSource for LibinputInputBackend { callback( crate::event::Event::WindowEvent { window_id: crate::window::WindowId( - crate::platform_impl::WindowId::Drm(super::WindowId), + crate::platform_impl::WindowId::Kms(super::WindowId), ), event: crate::event::WindowEvent::MouseWheel { device_id: crate::event::DeviceId( - crate::platform_impl::DeviceId::Drm(super::DeviceId), + crate::platform_impl::DeviceId::Kms(super::DeviceId), ), delta: MouseScrollDelta::PixelDelta(PhysicalPosition::new( if e.has_axis(input::event::pointer::Axis::Horizontal) { @@ -476,11 +476,11 @@ impl EventSource for LibinputInputBackend { callback( crate::event::Event::WindowEvent { window_id: crate::window::WindowId( - crate::platform_impl::WindowId::Drm(super::WindowId), + crate::platform_impl::WindowId::Kms(super::WindowId), ), event: crate::event::WindowEvent::CursorMoved { device_id: crate::event::DeviceId( - crate::platform_impl::DeviceId::Drm(super::DeviceId), + crate::platform_impl::DeviceId::Kms(super::DeviceId), ), position: self.cursor_positon, modifiers: self.modifiers, @@ -521,11 +521,11 @@ impl EventSource for LibinputInputBackend { callback( crate::event::Event::WindowEvent { window_id: crate::window::WindowId( - crate::platform_impl::WindowId::Drm(super::WindowId), + crate::platform_impl::WindowId::Kms(super::WindowId), ), event: crate::event::WindowEvent::KeyboardInput { device_id: crate::event::DeviceId( - crate::platform_impl::DeviceId::Drm(super::DeviceId), + crate::platform_impl::DeviceId::Kms(super::DeviceId), ), input, is_synthetic: false, @@ -543,7 +543,7 @@ impl EventSource for LibinputInputBackend { callback( crate::event::Event::WindowEvent { window_id: crate::window::WindowId( - crate::platform_impl::WindowId::Drm( + crate::platform_impl::WindowId::Kms( super::WindowId, ), ), @@ -566,7 +566,7 @@ impl EventSource for LibinputInputBackend { callback( crate::event::Event::WindowEvent { window_id: crate::window::WindowId( - crate::platform_impl::WindowId::Drm( + crate::platform_impl::WindowId::Kms( super::WindowId, ), ), @@ -589,7 +589,7 @@ impl EventSource for LibinputInputBackend { callback( crate::event::Event::WindowEvent { window_id: crate::window::WindowId( - crate::platform_impl::WindowId::Drm( + crate::platform_impl::WindowId::Kms( super::WindowId, ), ), @@ -613,7 +613,7 @@ impl EventSource for LibinputInputBackend { ElementState::Released => self.modifiers.remove(ModifiersState::ALT) } callback(crate::event::Event::WindowEvent { - window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), + window_id: crate::window::WindowId(crate::platform_impl::WindowId::Kms(super::WindowId)), event:crate::event::WindowEvent::ModifiersChanged(self.modifiers)}, &mut ()); } | xkb_keymap::XKB_KEY_Shift_L // LShift @@ -624,7 +624,7 @@ impl EventSource for LibinputInputBackend { ElementState::Released => self.modifiers.remove(ModifiersState::SHIFT) } callback(crate::event::Event::WindowEvent { - window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), + window_id: crate::window::WindowId(crate::platform_impl::WindowId::Kms(super::WindowId)), event:crate::event::WindowEvent::ModifiersChanged(self.modifiers)}, &mut ()); } @@ -636,7 +636,7 @@ impl EventSource for LibinputInputBackend { ElementState::Released => self.modifiers.remove(ModifiersState::CTRL) } callback(crate::event::Event::WindowEvent { - window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), + window_id: crate::window::WindowId(crate::platform_impl::WindowId::Kms(super::WindowId)), event:crate::event::WindowEvent::ModifiersChanged(self.modifiers)}, &mut ()); } @@ -648,14 +648,14 @@ impl EventSource for LibinputInputBackend { ElementState::Released => self.modifiers.remove(ModifiersState::LOGO) } callback(crate::event::Event::WindowEvent { - window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), + window_id: crate::window::WindowId(crate::platform_impl::WindowId::Kms(super::WindowId)), event: crate::event::WindowEvent::ModifiersChanged(self.modifiers)}, &mut ()); } xkb_keymap::XKB_KEY_Sys_Req | xkb_keymap::XKB_KEY_Print => { if self.modifiers.is_empty() { callback(crate::event::Event::WindowEvent { - window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm(super::WindowId)), + window_id: crate::window::WindowId(crate::platform_impl::WindowId::Kms(super::WindowId)), event: crate::event::WindowEvent::CloseRequested }, &mut ()); } @@ -723,7 +723,7 @@ impl EventLoopWindowTarget { #[inline] pub fn primary_monitor(&self) -> Option { Some(crate::monitor::MonitorHandle { - inner: crate::platform_impl::MonitorHandle::Drm(super::MonitorHandle( + inner: crate::platform_impl::MonitorHandle::Kms(super::MonitorHandle( self.connector.clone(), )), }) @@ -789,7 +789,7 @@ impl EventLoop { crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::DrmMisc("Failed to open libseat"), + crate::platform_impl::OsError::KmsMisc("Failed to open libseat"), ) })?; @@ -798,7 +798,7 @@ impl EventLoop { return Err(crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::DrmMisc("Failed to dispatch seat"), + crate::platform_impl::OsError::KmsMisc("Failed to dispatch seat"), )); } } @@ -815,21 +815,21 @@ impl EventLoop { crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::DrmMisc("Failed to open udev enumerator"), + crate::platform_impl::OsError::KmsMisc("Failed to open udev enumerator"), ) })?; enumerator.match_subsystem("drm").map_err(|_| { crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::DrmMisc("Failed to enumerate drm subsystem"), + crate::platform_impl::OsError::KmsMisc("Failed to enumerate drm subsystem"), ) })?; enumerator.match_sysname("card[0-9]*").map_err(|_| { crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::DrmMisc("Failed to find a valid card"), + crate::platform_impl::OsError::KmsMisc("Failed to find a valid card"), ) })?; enumerator @@ -838,7 +838,7 @@ impl EventLoop { crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::DrmMisc("Failed to scan devices"), + crate::platform_impl::OsError::KmsMisc("Failed to scan devices"), ) })? .filter(|device| { @@ -874,7 +874,7 @@ impl EventLoop { .ok_or(crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::DrmMisc("Failed to find suitable GPU"), + crate::platform_impl::OsError::KmsMisc("Failed to find suitable GPU"), )) }, |p| Ok(Into::into(p)), @@ -883,7 +883,7 @@ impl EventLoop { crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::DrmMisc("Failed to initialize DRM"), + crate::platform_impl::OsError::KmsMisc("Failed to initialize DRM"), ) })?; let drm = Card(std::sync::Arc::new(dev.1)); @@ -902,7 +902,7 @@ impl EventLoop { .ok_or(crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::DrmMisc("Failed to compile XKB keymap"), + crate::platform_impl::OsError::KmsMisc("Failed to compile XKB keymap"), ))?; let state = xkb::State::new(&keymap); let compose_table = xkb::compose::Table::new_from_locale( @@ -919,7 +919,7 @@ impl EventLoop { .or(Err(crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::DrmMisc("Failed to compile XKB compose table"), + crate::platform_impl::OsError::KmsMisc("Failed to compile XKB compose table"), )))?; let xkb_compose = xkb::compose::State::new(&compose_table, xkb::compose::STATE_NO_FLAGS); @@ -927,7 +927,7 @@ impl EventLoop { Err(crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::DrmMisc( + crate::platform_impl::OsError::KmsMisc( "kms device does not support universal planes", ), )), @@ -936,7 +936,7 @@ impl EventLoop { crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::DrmMisc( + crate::platform_impl::OsError::KmsMisc( "kms device does not support atomic modesetting", ), ), @@ -946,7 +946,7 @@ impl EventLoop { let res = drm.resource_handles().or(Err(crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::DrmMisc("Could not load normal resource ids."), + crate::platform_impl::OsError::KmsMisc("Could not load normal resource ids."), )))?; let coninfo: Vec = res .connectors() @@ -965,13 +965,13 @@ impl EventLoop { .ok_or(crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::DrmMisc("No connected connectors"), + crate::platform_impl::OsError::KmsMisc("No connected connectors"), ))?; let crtc = crtcinfo.get(0).ok_or(crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::DrmMisc("No crtcs found"), + crate::platform_impl::OsError::KmsMisc("No crtcs found"), ))?; // Get the first (usually best) mode @@ -983,22 +983,22 @@ impl EventLoop { .ok_or(crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::DrmMisc("No modes found on connector"), + crate::platform_impl::OsError::KmsMisc("No modes found on connector"), ))?; let planes = drm.plane_handles().or(Err(crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::DrmMisc("Could not list planes"), + crate::platform_impl::OsError::KmsMisc("Could not list planes"), )))?; /* let mut db = drm - .create_dumb_buffer((64, 64), drm::buffer::DrmFourcc::Xrgb8888, 32) + .create_dumb_buffer((64, 64), drm::buffer::KmsFourcc::Xrgb8888, 32) .or(Err(crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::DrmMisc("Could not create dumb buffer"), + crate::platform_impl::OsError::KmsMisc("Could not create dumb buffer"), )))?; { @@ -1015,7 +1015,7 @@ impl EventLoop { .or(Err(crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::DrmMisc("Could not create FB"), + crate::platform_impl::OsError::KmsMisc("Could not create FB"), )))?; let (better_planes, compatible_planes): ( @@ -1109,7 +1109,7 @@ impl EventLoop { event_loop_awakener_source, move |_event, _metadata, data| { data.push(crate::event::Event::RedrawRequested( - crate::window::WindowId(crate::platform_impl::WindowId::Drm( + crate::window::WindowId(crate::platform_impl::WindowId::Kms( super::WindowId, )), )); @@ -1129,11 +1129,11 @@ impl EventLoop { repeat_handler, move |event, metadata, data: &mut EventSink| { data.push(crate::event::Event::WindowEvent { - window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm( + window_id: crate::window::WindowId(crate::platform_impl::WindowId::Kms( super::WindowId, )), event: crate::event::WindowEvent::KeyboardInput { - device_id: crate::event::DeviceId(crate::platform_impl::DeviceId::Drm( + device_id: crate::event::DeviceId(crate::platform_impl::DeviceId::Kms( super::DeviceId, )), input: event.0, @@ -1142,7 +1142,7 @@ impl EventLoop { }); if let Some(c) = event.1 { data.push(crate::event::Event::WindowEvent { - window_id: crate::window::WindowId(crate::platform_impl::WindowId::Drm( + window_id: crate::window::WindowId(crate::platform_impl::WindowId::Kms( super::WindowId, )), event: crate::event::WindowEvent::ReceivedCharacter(c), @@ -1173,7 +1173,7 @@ impl EventLoop { handle.register_dispatcher(repeat_loop).unwrap(); let window_target = crate::event_loop::EventLoopWindowTarget { - p: crate::platform_impl::EventLoopWindowTarget::Drm(EventLoopWindowTarget { + p: crate::platform_impl::EventLoopWindowTarget::Kms(EventLoopWindowTarget { connector: con.clone(), crtc: crtc.clone(), device: drm, @@ -1228,7 +1228,7 @@ impl EventLoop { callback( crate::event::Event::RedrawRequested(crate::window::WindowId( - crate::platform_impl::WindowId::Drm(super::WindowId), + crate::platform_impl::WindowId::Kms(super::WindowId), )), &self.window_target, &mut control_flow, @@ -1367,7 +1367,7 @@ impl EventLoop { fn with_window_target) -> U>(&mut self, f: F) -> U { let state = match &mut self.window_target.p { - crate::platform_impl::EventLoopWindowTarget::Drm(window_target) => window_target, + crate::platform_impl::EventLoopWindowTarget::Kms(window_target) => window_target, #[cfg(any(feature = "x11", feature = "wayland"))] _ => unreachable!(), }; @@ -1380,7 +1380,7 @@ impl EventLoop { timeout: D, ) -> std::io::Result<()> { let mut state = match &mut self.window_target.p { - crate::platform_impl::EventLoopWindowTarget::Drm(window_target) => { + crate::platform_impl::EventLoopWindowTarget::Kms(window_target) => { &mut window_target.event_sink } #[cfg(any(feature = "x11", feature = "kms"))] diff --git a/src/platform_impl/linux/kms/mod.rs b/src/platform_impl/linux/kms/mod.rs index 7b31ef324a..f7a3203942 100644 --- a/src/platform_impl/linux/kms/mod.rs +++ b/src/platform_impl/linux/kms/mod.rs @@ -64,7 +64,7 @@ impl MonitorHandle { let modes = self.0.modes().to_vec(); let monitor = self.0.clone(); modes.into_iter().map(move |f| crate::monitor::VideoMode { - video_mode: crate::platform_impl::VideoMode::Drm(VideoMode(f, monitor.clone())), + video_mode: crate::platform_impl::VideoMode::Kms(VideoMode(f, monitor.clone())), }) } } @@ -92,7 +92,7 @@ impl VideoMode { #[inline] pub fn monitor(&self) -> crate::monitor::MonitorHandle { crate::monitor::MonitorHandle { - inner: crate::platform_impl::MonitorHandle::Drm(MonitorHandle(self.1.clone())), + inner: crate::platform_impl::MonitorHandle::Kms(MonitorHandle(self.1.clone())), } } } diff --git a/src/platform_impl/linux/kms/window.rs b/src/platform_impl/linux/kms/window.rs index 60221f9c89..9b2a6f3747 100644 --- a/src/platform_impl/linux/kms/window.rs +++ b/src/platform_impl/linux/kms/window.rs @@ -36,7 +36,7 @@ impl Window { crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::DrmMisc("Could not get CRTC_ID"), + crate::platform_impl::OsError::KmsMisc("Could not get CRTC_ID"), ) })?, property::Value::CRTC(Some(event_loop_window_target.crtc.handle())), @@ -48,7 +48,7 @@ impl Window { crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::DrmMisc("Failed to create blob"), + crate::platform_impl::OsError::KmsMisc("Failed to create blob"), ) })?; atomic_req.add_property( @@ -62,7 +62,7 @@ impl Window { crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::DrmMisc("Could not get MODE_ID"), + crate::platform_impl::OsError::KmsMisc("Could not get MODE_ID"), ) })?, blob, @@ -78,7 +78,7 @@ impl Window { crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::DrmMisc("Could not get ACTIVE"), + crate::platform_impl::OsError::KmsMisc("Could not get ACTIVE"), ) })?, property::Value::Boolean(true), @@ -181,7 +181,7 @@ impl Window { crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::DrmMisc("Failed to set mode"), + crate::platform_impl::OsError::KmsMisc("Failed to set mode"), ) })?; @@ -297,7 +297,7 @@ impl Window { #[inline] pub fn fullscreen(&self) -> Option { Some(Fullscreen::Exclusive(crate::monitor::VideoMode { - video_mode: crate::platform_impl::VideoMode::Drm(super::VideoMode( + video_mode: crate::platform_impl::VideoMode::Kms(super::VideoMode( self.0, self.1.clone(), )), @@ -348,7 +348,7 @@ impl Window { #[inline] pub fn primary_monitor(&self) -> Option { Some(crate::monitor::MonitorHandle { - inner: crate::platform_impl::MonitorHandle::Drm(super::MonitorHandle(self.1.clone())), + inner: crate::platform_impl::MonitorHandle::Kms(super::MonitorHandle(self.1.clone())), }) } } diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index 708df4941f..63ab1823fb 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -6,11 +6,7 @@ target_os = "openbsd" ))] -#[cfg(all( - not(feature = "x11"), - not(feature = "wayland"), - not(feature = "kms") -))] +#[cfg(all(not(feature = "x11"), not(feature = "wayland"), not(feature = "kms")))] compile_error!("Please select a feature to build for unix: `x11`, `wayland`, `kms`"); #[cfg(feature = "wayland")] @@ -40,7 +36,7 @@ use crate::{ pub(crate) use crate::icon::RgbaIcon as PlatformIcon; #[cfg(feature = "kms")] -pub mod drm; +pub mod kms; #[cfg(feature = "wayland")] pub mod wayland; #[cfg(feature = "x11")] @@ -64,7 +60,7 @@ pub(crate) enum Backend { #[cfg(feature = "wayland")] Wayland, #[cfg(feature = "kms")] - Drm, + Kms, } #[derive(Debug, Copy, Clone, PartialEq, Hash)] @@ -150,7 +146,7 @@ pub enum OsError { #[cfg(feature = "wayland")] WaylandMisc(&'static str), #[cfg(feature = "kms")] - DrmMisc(&'static str), + KmsMisc(&'static str), } impl fmt::Display for OsError { @@ -163,7 +159,7 @@ impl fmt::Display for OsError { #[cfg(feature = "wayland")] OsError::WaylandMisc(e) => _f.pad(e), #[cfg(feature = "kms")] - OsError::DrmMisc(e) => _f.pad(e), + OsError::KmsMisc(e) => _f.pad(e), } } } @@ -174,7 +170,7 @@ pub enum Window { #[cfg(feature = "wayland")] Wayland(wayland::Window), #[cfg(feature = "kms")] - Drm(drm::Window), + Kms(kms::Window), } #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -184,7 +180,7 @@ pub enum WindowId { #[cfg(feature = "wayland")] Wayland(wayland::WindowId), #[cfg(feature = "kms")] - Drm(drm::WindowId), + Kms(kms::WindowId), } impl WindowId { @@ -194,10 +190,9 @@ impl WindowId { #[cfg(all(not(all(feature = "wayland", feature = "kms")), feature = "x11"))] return WindowId::X(x11::WindowId::dummy()); #[cfg(all(not(all(feature = "wayland", feature = "x11")), feature = "kms"))] - return WindowId::Drm(drm::WindowId::dummy()); + return WindowId::Kms(kms::WindowId::dummy()); } } - #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum DeviceId { #[cfg(feature = "x11")] @@ -205,7 +200,7 @@ pub enum DeviceId { #[cfg(feature = "wayland")] Wayland(wayland::DeviceId), #[cfg(feature = "kms")] - Drm(drm::DeviceId), + Kms(kms::DeviceId), } impl DeviceId { @@ -215,7 +210,7 @@ impl DeviceId { #[cfg(all(not(feature = "wayland"), feature = "x11"))] return DeviceId::X(x11::DeviceId::dummy()); #[cfg(all(not(all(feature = "wayland", feature = "x11")), feature = "kms"))] - return DeviceId::Drm(drm::DeviceId::dummy()); + return DeviceId::Kms(kms::DeviceId::dummy()); } } @@ -226,7 +221,7 @@ pub enum MonitorHandle { #[cfg(feature = "wayland")] Wayland(wayland::MonitorHandle), #[cfg(feature = "kms")] - Drm(drm::MonitorHandle), + Kms(kms::MonitorHandle), } /// `x11_or_wayland!(match expr; Enum(foo) => foo.something())` @@ -246,7 +241,7 @@ macro_rules! x11_or_wayland_or_drm { #[cfg(feature = "wayland")] $enum::Wayland($($c1)*) => $enum2::Wayland($x), #[cfg(feature = "kms")] - $enum::Drm($($c1)*) => $enum2::Drm($x) + $enum::Kms($($c1)*) => $enum2::Kms($x) } }; (match $what:expr; $enum:ident ( $($c1:tt)* ) => $x:expr) => { @@ -256,7 +251,7 @@ macro_rules! x11_or_wayland_or_drm { #[cfg(feature = "wayland")] $enum::Wayland($($c1)*) => $x, #[cfg(feature = "kms")] - $enum::Drm($($c1)*) => $x + $enum::Kms($($c1)*) => $x } }; } @@ -300,7 +295,7 @@ pub enum VideoMode { #[cfg(feature = "wayland")] Wayland(wayland::VideoMode), #[cfg(feature = "kms")] - Drm(drm::VideoMode), + Kms(kms::VideoMode), } impl VideoMode { @@ -342,8 +337,8 @@ impl Window { x11::Window::new(window_target, attribs, pl_attribs).map(Window::X) } #[cfg(feature = "kms")] - EventLoopWindowTarget::Drm(ref window_target) => { - drm::Window::new(window_target, attribs, pl_attribs).map(Window::Drm) + EventLoopWindowTarget::Kms(ref window_target) => { + kms::Window::new(window_target, attribs, pl_attribs).map(Window::Kms) } } } @@ -496,7 +491,7 @@ impl Window { #[cfg(feature = "wayland")] Window::Wayland(_) => (), #[cfg(feature = "kms")] - Window::Drm(_) => (), + Window::Kms(_) => (), } } @@ -508,7 +503,7 @@ impl Window { #[cfg(feature = "wayland")] Window::Wayland(_) => (), #[cfg(feature = "kms")] - Window::Drm(_) => (), + Window::Kms(_) => (), } } @@ -525,7 +520,7 @@ impl Window { #[cfg(feature = "wayland")] Window::Wayland(_) => (), #[cfg(feature = "kms")] - Window::Drm(_) => (), + Window::Kms(_) => (), } } pub fn request_user_attention(&self, request_type: Option) { @@ -535,7 +530,7 @@ impl Window { #[cfg(feature = "wayland")] Window::Wayland(ref w) => w.request_user_attention(request_type), #[cfg(feature = "kms")] - Window::Drm(_) => (), + Window::Kms(_) => (), } } @@ -562,8 +557,8 @@ impl Window { }) } #[cfg(feature = "kms")] - Window::Drm(ref window) => { - let current_monitor = MonitorHandle::Drm(window.current_monitor()?); + Window::Kms(ref window) => { + let current_monitor = MonitorHandle::Kms(window.current_monitor()?); Some(RootMonitorHandle { inner: current_monitor, }) @@ -587,10 +582,10 @@ impl Window { .map(MonitorHandle::Wayland) .collect(), #[cfg(feature = "kms")] - Window::Drm(ref window) => window + Window::Kms(ref window) => window .available_monitors() .into_iter() - .map(MonitorHandle::Drm) + .map(MonitorHandle::Kms) .collect(), } } @@ -608,7 +603,7 @@ impl Window { #[cfg(feature = "wayland")] Window::Wayland(ref window) => window.primary_monitor(), #[cfg(feature = "kms")] - Window::Drm(ref window) => window.primary_monitor(), + Window::Kms(ref window) => window.primary_monitor(), } } @@ -619,7 +614,7 @@ impl Window { #[cfg(feature = "wayland")] Window::Wayland(ref window) => RawWindowHandle::Wayland(window.raw_window_handle()), #[cfg(feature = "kms")] - Window::Drm(ref window) => RawWindowHandle::Drm(window.raw_window_handle()), + Window::Kms(ref window) => RawWindowHandle::Drm(window.raw_window_handle()), } } } @@ -663,7 +658,7 @@ pub enum EventLoop { #[cfg(feature = "x11")] X(x11::EventLoop), #[cfg(feature = "kms")] - Drm(drm::EventLoop), + Kms(kms::EventLoop), } pub enum EventLoopProxy { @@ -672,7 +667,7 @@ pub enum EventLoopProxy { #[cfg(feature = "wayland")] Wayland(wayland::EventLoopProxy), #[cfg(feature = "kms")] - Drm(drm::EventLoopProxy), + Kms(kms::EventLoopProxy), } impl Clone for EventLoopProxy { @@ -705,7 +700,7 @@ impl EventLoop { } #[cfg(feature = "kms")] - if attributes.forced_backend == Some(Backend::Drm) { + if attributes.forced_backend == Some(Backend::Kms) { // TODO: Propagate return EventLoop::new_drm_any_thread().expect("failed to open drm connection"); } @@ -789,7 +784,7 @@ impl EventLoop { #[cfg(feature = "kms")] fn new_drm_any_thread() -> Result, RootOsError> { - drm::EventLoop::new().map(EventLoop::Drm) + kms::EventLoop::new().map(EventLoop::Kms) } pub fn create_proxy(&self) -> EventLoopProxy { @@ -827,7 +822,7 @@ pub enum EventLoopWindowTarget { #[cfg(feature = "x11")] X(x11::EventLoopWindowTarget), #[cfg(feature = "kms")] - Drm(drm::EventLoopWindowTarget), + Kms(kms::EventLoopWindowTarget), } impl EventLoopWindowTarget { @@ -855,7 +850,7 @@ impl EventLoopWindowTarget { pub fn is_drm(&self) -> bool { match *self { #[cfg(feature = "kms")] - EventLoopWindowTarget::Drm(_) => true, + EventLoopWindowTarget::Kms(_) => true, #[cfg(any(feature = "x11", feature = "wayland"))] _ => false, } @@ -878,10 +873,10 @@ impl EventLoopWindowTarget { .map(MonitorHandle::X) .collect(), #[cfg(feature = "kms")] - EventLoopWindowTarget::Drm(ref evlp) => evlp + EventLoopWindowTarget::Kms(ref evlp) => evlp .available_monitors() .into_iter() - .map(MonitorHandle::Drm) + .map(MonitorHandle::Kms) .collect(), } } @@ -899,7 +894,7 @@ impl EventLoopWindowTarget { }) } #[cfg(feature = "kms")] - EventLoopWindowTarget::Drm(ref evlp) => evlp.primary_monitor(), + EventLoopWindowTarget::Kms(ref evlp) => evlp.primary_monitor(), } } } diff --git a/src/platform_impl/linux/wayland/window/mod.rs b/src/platform_impl/linux/wayland/window/mod.rs index 23c522a932..e3400ce8a9 100644 --- a/src/platform_impl/linux/wayland/window/mod.rs +++ b/src/platform_impl/linux/wayland/window/mod.rs @@ -180,7 +180,7 @@ impl Window { #[cfg(feature = "x11")] PlatformMonitorHandle::X(_) => None, #[cfg(feature = "kms")] - PlatformMonitorHandle::Drm(_) => None, + PlatformMonitorHandle::Kms(_) => None, }); window.set_fullscreen(monitor.as_ref()); @@ -427,7 +427,7 @@ impl Window { #[cfg(feature = "x11")] PlatformMonitorHandle::X(_) => None, #[cfg(feature = "kms")] - PlatformMonitorHandle::Drm(_) => None, + PlatformMonitorHandle::Kms(_) => None, }); WindowRequest::Fullscreen(monitor) From 7a105286174570cda52fc782ee21a8deb3d36fe1 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Mon, 9 May 2022 10:09:08 -0400 Subject: [PATCH 080/151] Add seat-ext --- Cargo.toml | 159 +++++++++++----------- src/platform_impl/linux/kms/event_loop.rs | 74 ++++++++-- 2 files changed, 144 insertions(+), 89 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6366cab0ae..d69660eb86 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,8 @@ default = ["x11", "wayland", "wayland-dlopen", "kms"] x11 = ["x11-dl", "mio", "percent-encoding", "parking_lot"] wayland = ["wayland-client", "wayland-protocols", "sctk", "calloop"] wayland-dlopen = ["sctk/dlopen", "wayland-client/dlopen"] -kms = ["drm", "input", "calloop", "libseat", "xkbcommon", "udev"] +kms = ["drm", "input", "calloop", "xkbcommon", "udev"] +kms-ext = ["libseat"] [dependencies] instant = { version = "0.1.12", features = ["wasm-bindgen"] } @@ -62,81 +63,81 @@ parking_lot = "0.12.0" version = "0.36.1" features = [ - "Win32_Devices_HumanInterfaceDevice", - "Win32_Foundation", - "Win32_Globalization", - "Win32_Graphics_Dwm", - "Win32_Graphics_Gdi", - "Win32_Media", - "Win32_System_Com_StructuredStorage", - "Win32_System_Com", - "Win32_System_LibraryLoader", - "Win32_System_Ole", - "Win32_System_SystemInformation", - "Win32_System_SystemServices", - "Win32_System_Threading", - "Win32_System_WindowsProgramming", - "Win32_UI_Accessibility", - "Win32_UI_Controls", - "Win32_UI_HiDpi", - "Win32_UI_Input_Ime", - "Win32_UI_Input_KeyboardAndMouse", - "Win32_UI_Input_Pointer", - "Win32_UI_Input_Touch", - "Win32_UI_Shell", - "Win32_UI_TextServices", - "Win32_UI_WindowsAndMessaging", -] - -[target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))'.dependencies] -wayland-client = { version = "0.29.4", default_features = false, features = ["use_system_lib"], optional = true } -wayland-protocols = { version = "0.29.4", features = [ "staging_protocols"], optional = true } -sctk = { package = "smithay-client-toolkit", version = "0.15.4", default_features = false, features = ["calloop"], optional = true } -calloop = { version = "0.9.3", optional = true } -mio = { version = "0.8.2", features = ["os-ext"], optional = true } -x11-dl = { version = "2.19.1", optional = true } -percent-encoding = { version = "2.1.0", optional = true } -parking_lot = { version = "0.12.0", optional = true } -libc = "0.2.125" -drm = { version = "0.6.2", optional = true } -input = { version = "0.7.1", optional = true } -libseat = { version = "0.1.4", optional = true } -udev = { version = "0.6.3", optional = true } -xkbcommon = { git = "https://github.com/StratusFearMe21/xkbcommon-rs", optional = true } - -[target.'cfg(target_arch = "wasm32")'.dependencies] -wasm-bindgen= "0.2.80" - -[target.'cfg(target_arch = "wasm32")'.dependencies.web_sys] -package = "web-sys" -version = "0.3.57" -features = [ - 'console', - "AddEventListenerOptions", - 'CssStyleDeclaration', - 'BeforeUnloadEvent', - 'Document', - 'DomRect', - 'Element', - 'Event', - 'EventTarget', - 'FocusEvent', - 'HtmlCanvasElement', - 'HtmlElement', - 'KeyboardEvent', - 'MediaQueryList', - 'MediaQueryListEvent', - 'MouseEvent', - 'Node', - 'PointerEvent', - 'Window', - 'WheelEvent' -] - -[target.'cfg(target_arch = "wasm32")'.dev-dependencies] -console_log = "0.2.0" - -[workspace] -members = [ - "run-wasm", -] + "Win32_Devices_HumanInterfaceDevice", + "Win32_Foundation", + "Win32_Globalization", + "Win32_Graphics_Dwm", + "Win32_Graphics_Gdi", + "Win32_Media", + "Win32_System_Com_StructuredStorage", + "Win32_System_Com", + "Win32_System_LibraryLoader", + "Win32_System_Ole", + "Win32_System_SystemInformation", + "Win32_System_SystemServices", + "Win32_System_Threading", + "Win32_System_WindowsProgramming", + "Win32_UI_Accessibility", + "Win32_UI_Controls", + "Win32_UI_HiDpi", + "Win32_UI_Input_Ime", + "Win32_UI_Input_KeyboardAndMouse", + "Win32_UI_Input_Pointer", + "Win32_UI_Input_Touch", + "Win32_UI_Shell", + "Win32_UI_TextServices", + "Win32_UI_WindowsAndMessaging", + ] + + [target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))'.dependencies] + wayland-client = { version = "0.29.4", default_features = false, features = ["use_system_lib"], optional = true } + wayland-protocols = { version = "0.29.4", features = [ "staging_protocols"], optional = true } + sctk = { package = "smithay-client-toolkit", version = "0.15.4", default_features = false, features = ["calloop"], optional = true } + calloop = { version = "0.9.3", optional = true } + mio = { version = "0.8.2", features = ["os-ext"], optional = true } + x11-dl = { version = "2.19.1", optional = true } + percent-encoding = { version = "2.1.0", optional = true } + parking_lot = { version = "0.12.0", optional = true } + libc = "0.2.125" + drm = { version = "0.6.2", optional = true } + input = { version = "0.7.1", optional = true } + libseat = { version = "0.1.4", optional = true } + udev = { version = "0.6.3", optional = true } + xkbcommon = { git = "https://github.com/StratusFearMe21/xkbcommon-rs", optional = true } + + [target.'cfg(target_arch = "wasm32")'.dependencies] + wasm-bindgen= "0.2.80" + + [target.'cfg(target_arch = "wasm32")'.dependencies.web_sys] + package = "web-sys" + version = "0.3.57" + features = [ + 'console', + "AddEventListenerOptions", + 'CssStyleDeclaration', + 'BeforeUnloadEvent', + 'Document', + 'DomRect', + 'Element', + 'Event', + 'EventTarget', + 'FocusEvent', + 'HtmlCanvasElement', + 'HtmlElement', + 'KeyboardEvent', + 'MediaQueryList', + 'MediaQueryListEvent', + 'MouseEvent', + 'Node', + 'PointerEvent', + 'Window', + 'WheelEvent' + ] + + [target.'cfg(target_arch = "wasm32")'.dev-dependencies] + console_log = "0.2.0" + + [workspace] + members = [ + "run-wasm", + ] diff --git a/src/platform_impl/linux/kms/event_loop.rs b/src/platform_impl/linux/kms/event_loop.rs index 370b60a546..78e30a5722 100644 --- a/src/platform_impl/linux/kms/event_loop.rs +++ b/src/platform_impl/linux/kms/event_loop.rs @@ -1,9 +1,14 @@ +#[cfg(feature = "kms-ext")] use std::{ - collections::{HashMap, VecDeque}, + collections::HashMap, + sync::{atomic::AtomicBool, Arc}, +}; +use std::{ + collections::VecDeque, marker::PhantomData, os::unix::prelude::{AsRawFd, FromRawFd, RawFd}, path::Path, - sync::{atomic::AtomicBool, mpsc::SendError, Arc}, + sync::mpsc::SendError, time::{Duration, Instant}, }; use udev::Enumerator; @@ -30,8 +35,12 @@ use crate::{ platform_impl::{platform::sticky_exit_callback, xkb_keymap}, }; +#[cfg(feature = "kms-ext")] struct Interface(libseat::Seat, HashMap); +#[cfg(not(feature = "kms-ext"))] +struct Interface; +#[cfg(feature = "kms-ext")] impl LibinputInterface for Interface { fn open_restricted(&mut self, path: &Path, _flags: i32) -> Result { self.0 @@ -50,6 +59,26 @@ impl LibinputInterface for Interface { } } +#[cfg(not(feature = "kms-ext"))] +impl LibinputInterface for Interface { + fn open_restricted(&mut self, path: &Path, flags: i32) -> Result { + use std::os::unix::prelude::*; + + std::fs::OpenOptions::new() + .custom_flags(flags) + .read((flags & libc::O_RDONLY != 0) | (flags & libc::O_RDWR != 0)) + .write((flags & libc::O_WRONLY != 0) | (flags & libc::O_RDWR != 0)) + .open(path) + .map(|file| file.into_raw_fd()) + .map_err(|err| err.raw_os_error().unwrap()) + } + fn close_restricted(&mut self, fd: RawFd) { + unsafe { + std::fs::File::from_raw_fd(fd); + } + } +} + pub struct LibinputInputBackend { context: input::Libinput, xkb_ctx: xkb::State, @@ -774,6 +803,7 @@ pub(crate) fn find_prop_id( impl EventLoop { pub fn new() -> Result, crate::error::OsError> { + #[cfg(feature = "kms-ext")] let mut seat = { let active = Arc::new(AtomicBool::new(false)); let t_active = active.clone(); @@ -808,7 +838,10 @@ impl EventLoop { // // This string value has the same lifetime as the seat in question, and will not be dropped // until the seat is, which is not before `udev_assign_seat` is run. + #[cfg(feature = "kms-ext")] let seat_name = unsafe { std::mem::transmute::<&str, &'static str>(seat.name()) }; + #[cfg(not(feature = "kms-ext"))] + let seat_name = "seat0"; let card_path = std::env::var("WINIT_DRM_CARD").ok().map_or_else( || { let mut enumerator = Enumerator::new().map_err(|_| { @@ -879,15 +912,36 @@ impl EventLoop { }, |p| Ok(Into::into(p)), )?; - let dev = seat.open_device(&card_path).map_err(|_| { - crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::KmsMisc("Failed to initialize DRM"), - ) - })?; - let drm = Card(std::sync::Arc::new(dev.1)); + #[cfg(feature = "kms-ext")] + let dev = seat + .open_device(&card_path) + .map_err(|_| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::KmsMisc("Failed to initialize DRM"), + ) + })? + .1; + #[cfg(not(feature = "kms-ext"))] + let dev = std::os::unix::prelude::IntoRawFd::into_raw_fd( + std::fs::OpenOptions::new() + .read(true) + .write(true) + .open(&card_path) + .map_err(|_| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::KmsMisc("Failed to initialize DRM"), + ) + })?, + ); + let drm = Card(std::sync::Arc::new(dev)); + #[cfg(feature = "kms-ext")] let mut input = input::Libinput::new_with_udev(Interface(seat, HashMap::new())); + #[cfg(not(feature = "kms-ext"))] + let mut input = input::Libinput::new_with_udev(Interface); input.udev_assign_seat(seat_name).unwrap(); let xkb_ctx = xkb::Context::new(xkb::CONTEXT_NO_FLAGS); let keymap = xkb::Keymap::new_from_names( From 1c6ce63f7d4df9272681ac4a30ecfa13eb1f11cf Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Mon, 9 May 2022 10:22:38 -0400 Subject: [PATCH 081/151] Fix merge --- Cargo.toml | 1 + src/platform_impl/linux/kms/window.rs | 3 +++ src/platform_impl/linux/mod.rs | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index e43a850b73..2a41dbf9aa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -101,6 +101,7 @@ drm = { version = "0.6.2", optional = true } input = { version = "0.7.1", optional = true } libseat = { version = "0.1.4", optional = true } udev = { version = "0.6.3", optional = true } +calloop = { version = "0.9.3", optional = true } xkbcommon = { git = "https://github.com/StratusFearMe21/xkbcommon-rs", optional = true } [target.'cfg(target_arch = "wasm32")'.dependencies] diff --git a/src/platform_impl/linux/kms/window.rs b/src/platform_impl/linux/kms/window.rs index 9b2a6f3747..0f0ff86ddf 100644 --- a/src/platform_impl/linux/kms/window.rs +++ b/src/platform_impl/linux/kms/window.rs @@ -317,6 +317,9 @@ impl Window { #[inline] pub fn set_ime_position(&self, _position: Position) {} + #[inline] + pub fn set_ime_allowed(&self, _allowed: bool) {} + #[inline] pub fn request_redraw(&self) { self.2.ping(); diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index cac1f491e7..cdff20dc7e 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -514,7 +514,7 @@ impl Window { #[inline] pub fn set_ime_allowed(&self, allowed: bool) { - x11_or_wayland!(match self; Window(w) => w.set_ime_allowed(allowed)) + x11_or_wayland_or_drm!(match self; Window(w) => w.set_ime_allowed(allowed)) } #[inline] From 97a68aefc3e672c0552328fa4516601ea5711436 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Mon, 9 May 2022 10:27:27 -0400 Subject: [PATCH 082/151] Fix Card in unix backend --- src/platform/unix.rs | 36 ++++-------------------------- src/platform_impl/linux/kms/mod.rs | 25 +++++++++++++++++++++ 2 files changed, 29 insertions(+), 32 deletions(-) diff --git a/src/platform/unix.rs b/src/platform/unix.rs index 472dfb443c..e264356d96 100644 --- a/src/platform/unix.rs +++ b/src/platform/unix.rs @@ -6,11 +6,11 @@ target_os = "openbsd" ))] -use std::os::{raw, unix::prelude::FromRawFd}; +use std::os::raw; #[cfg(feature = "x11")] use std::ptr; -#[cfg(any(feature = "x11", feature = "kms"))] +#[cfg(feature = "x11")] use std::sync::Arc; use crate::{ @@ -28,43 +28,15 @@ use crate::platform_impl::{ Window as LinuxWindow, }; -#[cfg(feature = "kms")] -use ::drm::{control::Device as ControlDevice, Device}; - // TODO: stupid hack so that glutin can do its work +#[cfg(feature = "kms")] +pub use crate::platform_impl::kms::Card; #[doc(hidden)] #[cfg(feature = "x11")] pub use crate::platform_impl::x11; #[cfg(feature = "x11")] pub use crate::platform_impl::{x11::util::WindowType as XWindowType, XNotSupported}; -#[cfg(feature = "kms")] -#[derive(Debug, Clone)] -/// A simple wrapper for a device node. -pub struct Card(pub(crate) Arc); - -#[cfg(feature = "kms")] -/// Implementing `AsRawFd` is a prerequisite to implementing the traits found -/// in this crate. Here, we are just calling `as_raw_fd()` on the inner File. -impl std::os::unix::io::AsRawFd for Card { - fn as_raw_fd(&self) -> std::os::unix::io::RawFd { - *self.0 - } -} - -#[cfg(feature = "kms")] -impl Drop for Card { - fn drop(&mut self) { - unsafe { std::fs::File::from_raw_fd(*self.0) }; - } -} - -#[cfg(feature = "kms")] -/// With `AsRawFd` implemented, we can now implement `drm::Device`. -impl Device for Card {} -#[cfg(feature = "kms")] -impl ControlDevice for Card {} - /// Additional methods on `EventLoopWindowTarget` that are specific to Unix. pub trait EventLoopWindowTargetExtUnix { /// True if the `EventLoopWindowTarget` uses Wayland. diff --git a/src/platform_impl/linux/kms/mod.rs b/src/platform_impl/linux/kms/mod.rs index f7a3203942..54f52d223e 100644 --- a/src/platform_impl/linux/kms/mod.rs +++ b/src/platform_impl/linux/kms/mod.rs @@ -3,11 +3,36 @@ use crate::dpi::{PhysicalPosition, PhysicalSize}; pub mod event_loop; pub mod window; pub use drm::SystemError; +use drm::{control::Device as ControlDevice, Device}; pub use event_loop::EventLoop; pub use event_loop::EventLoopProxy; pub use event_loop::EventLoopWindowTarget; +use std::os::unix::prelude::FromRawFd; +use std::sync::Arc; pub use window::Window; +#[derive(Debug, Clone)] +/// A simple wrapper for a device node. +pub struct Card(pub(crate) Arc); + +/// Implementing `AsRawFd` is a prerequisite to implementing the traits found +/// in this crate. Here, we are just calling `as_raw_fd()` on the inner File. +impl std::os::unix::io::AsRawFd for Card { + fn as_raw_fd(&self) -> std::os::unix::io::RawFd { + *self.0 + } +} + +impl Drop for Card { + fn drop(&mut self) { + unsafe { std::fs::File::from_raw_fd(*self.0) }; + } +} + +/// With `AsRawFd` implemented, we can now implement `drm::Device`. +impl Device for Card {} +impl ControlDevice for Card {} + #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct DeviceId; From f693f5a0f77125bb3695c105a2b0220265ebea16 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Mon, 9 May 2022 10:32:00 -0400 Subject: [PATCH 083/151] Fix Window declaration --- src/platform_impl/linux/kms/window.rs | 47 +++++++++++++++------------ 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/src/platform_impl/linux/kms/window.rs b/src/platform_impl/linux/kms/window.rs index 0f0ff86ddf..dfb3fa3cb8 100644 --- a/src/platform_impl/linux/kms/window.rs +++ b/src/platform_impl/linux/kms/window.rs @@ -11,12 +11,13 @@ use crate::{ use super::event_loop::find_prop_id; -pub struct Window( - drm::control::Mode, - drm::control::connector::Info, - calloop::ping::Ping, - Card, -); +pub struct Window { + mode: drm::control::Mode, + connector: drm::control::connector::Info, + ping: calloop::ping::Ping, + plane: drm::control::plane::Handle, + card: Card, +} impl Window { pub fn new( @@ -185,12 +186,13 @@ impl Window { ) })?; - Ok(Self( - event_loop_window_target.mode.clone(), - event_loop_window_target.connector.clone(), - event_loop_window_target.event_loop_awakener.clone(), - event_loop_window_target.device.clone(), - )) + Ok(Self { + mode: event_loop_window_target.mode.clone(), + connector: event_loop_window_target.connector.clone(), + plane: event_loop_window_target.plane.clone(), + ping: event_loop_window_target.event_loop_awakener.clone(), + card: event_loop_window_target.device.clone(), + }) } #[inline] pub fn id(&self) -> super::WindowId { @@ -223,7 +225,7 @@ impl Window { #[inline] pub fn inner_size(&self) -> PhysicalSize { - let size = self.0.size(); + let size = self.mode.size(); PhysicalSize::new(size.0 as u32, size.1 as u32) } @@ -298,8 +300,8 @@ impl Window { pub fn fullscreen(&self) -> Option { Some(Fullscreen::Exclusive(crate::monitor::VideoMode { video_mode: crate::platform_impl::VideoMode::Kms(super::VideoMode( - self.0, - self.1.clone(), + self.mode, + self.connector.clone(), )), })) } @@ -322,36 +324,39 @@ impl Window { #[inline] pub fn request_redraw(&self) { - self.2.ping(); + self.ping.ping(); } #[inline] pub fn current_monitor(&self) -> Option { - Some(super::MonitorHandle(self.1.clone())) + Some(super::MonitorHandle(self.connector.clone())) } #[inline] pub fn available_monitors(&self) -> VecDeque { - self.3 + self.card .resource_handles() .unwrap() .connectors() .iter() - .map(|f| super::MonitorHandle(self.3.get_connector(*f).unwrap())) + .map(|f| super::MonitorHandle(self.card.get_connector(*f).unwrap())) .collect() } #[inline] pub fn raw_window_handle(&self) -> raw_window_handle::DrmHandle { let mut rwh = raw_window_handle::DrmHandle::empty(); - rwh.fd = self.3.as_raw_fd(); + rwh.fd = self.card.as_raw_fd(); + rwh.plane = self.plane.into(); rwh } #[inline] pub fn primary_monitor(&self) -> Option { Some(crate::monitor::MonitorHandle { - inner: crate::platform_impl::MonitorHandle::Kms(super::MonitorHandle(self.1.clone())), + inner: crate::platform_impl::MonitorHandle::Kms(super::MonitorHandle( + self.connector.clone(), + )), }) } } From 6eb3afee52d421388f3c70633a9a71b31cb136aa Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Mon, 9 May 2022 10:52:18 -0400 Subject: [PATCH 084/151] Fix cursor position setting --- src/platform_impl/linux/kms/event_loop.rs | 98 +++++------------------ src/platform_impl/linux/kms/window.rs | 20 +++-- 2 files changed, 33 insertions(+), 85 deletions(-) diff --git a/src/platform_impl/linux/kms/event_loop.rs b/src/platform_impl/linux/kms/event_loop.rs index 78e30a5722..ef90173b50 100644 --- a/src/platform_impl/linux/kms/event_loop.rs +++ b/src/platform_impl/linux/kms/event_loop.rs @@ -1,3 +1,4 @@ +use parking_lot::Mutex; #[cfg(feature = "kms-ext")] use std::{ collections::HashMap, @@ -8,7 +9,7 @@ use std::{ marker::PhantomData, os::unix::prelude::{AsRawFd, FromRawFd, RawFd}, path::Path, - sync::mpsc::SendError, + sync::{mpsc::SendError, Arc}, time::{Duration, Instant}, }; use udev::Enumerator; @@ -88,10 +89,8 @@ pub struct LibinputInputBackend { touch_location: PhysicalPosition, screen_size: (u32, u32), modifiers: ModifiersState, - cursor_positon: PhysicalPosition, + cursor_positon: Arc>>, timer_handle: calloop::timer::TimerHandle<(KeyboardInput, Option)>, - // cursor_plane: drm::control::plane::Handle, - // cursor_buffer: drm::control::framebuffer::Handle, } impl LibinputInputBackend { @@ -104,22 +103,19 @@ impl LibinputInputBackend { xkb_ctx: xkb::State, xkb_keymap: xkb::Keymap, xkb_compose: xkb::compose::State, - // cursor_plane: drm::control::plane::Handle, - // cursor_buffer: drm::control::framebuffer::Handle + cursor_positon: Arc>>, ) -> Self { LibinputInputBackend { context, token: Token::invalid(), touch_location: PhysicalPosition::new(0.0, 0.0), - cursor_positon: PhysicalPosition::new(0.0, 0.0), modifiers: ModifiersState::empty(), + cursor_positon, screen_size, timer_handle, xkb_ctx, xkb_keymap, xkb_compose, - // cursor_buffer, - // cursor_plane, } } } @@ -350,12 +346,11 @@ impl EventSource for LibinputInputBackend { }, input::Event::Pointer(e) => match e { input::event::PointerEvent::Motion(e) => { - self.cursor_positon.x += e.dx(); - self.cursor_positon.x = - self.cursor_positon.x.clamp(0.0, self.screen_size.0 as f64); - self.cursor_positon.y += e.dy(); - self.cursor_positon.y = - self.cursor_positon.y.clamp(0.0, self.screen_size.1 as f64); + let mut lock = self.cursor_positon.lock(); + lock.x += e.dx(); + lock.x = lock.x.clamp(0.0, self.screen_size.0 as f64); + lock.y += e.dy(); + lock.y = lock.y.clamp(0.0, self.screen_size.1 as f64); callback( crate::event::Event::WindowEvent { window_id: crate::window::WindowId( @@ -365,7 +360,7 @@ impl EventSource for LibinputInputBackend { device_id: crate::event::DeviceId( crate::platform_impl::DeviceId::Kms(super::DeviceId), ), - position: self.cursor_positon, + position: *lock, modifiers: self.modifiers, }, }, @@ -500,8 +495,9 @@ impl EventSource for LibinputInputBackend { ); } input::event::PointerEvent::MotionAbsolute(e) => { - self.cursor_positon.x = e.absolute_x_transformed(self.screen_size.0); - self.cursor_positon.y = e.absolute_y_transformed(self.screen_size.1); + let mut lock = self.cursor_positon.lock(); + lock.x = e.absolute_x_transformed(self.screen_size.0); + lock.y = e.absolute_y_transformed(self.screen_size.1); callback( crate::event::Event::WindowEvent { window_id: crate::window::WindowId( @@ -511,7 +507,7 @@ impl EventSource for LibinputInputBackend { device_id: crate::event::DeviceId( crate::platform_impl::DeviceId::Kms(super::DeviceId), ), - position: self.cursor_positon, + position: *lock, modifiers: self.modifiers, }, }, @@ -732,8 +728,9 @@ pub struct EventLoopWindowTarget { /// drm plane pub plane: drm::control::plane::Handle, - // /// drm dumbbuffer containing the cursor - // pub cursor_buffer: drm::control::framebuffer::Handle, + /// Allows window to edit cursor position + pub(crate) cursor_arc: Arc>>, + /// drm device pub device: Card, @@ -1046,61 +1043,6 @@ impl EventLoop { crate::platform_impl::OsError::KmsMisc("Could not list planes"), )))?; - /* - let mut db = drm - .create_dumb_buffer((64, 64), drm::buffer::KmsFourcc::Xrgb8888, 32) - .or(Err(crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::KmsMisc("Could not create dumb buffer"), - )))?; - - { - let mut map = drm - .map_dumb_buffer(&mut db) - .expect("Could not map dumbbuffer"); - for b in map.as_mut() { - *b = 128; - } - } - - let fb = drm - .add_framebuffer(&db, 24, 32) - .or(Err(crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::KmsMisc("Could not create FB"), - )))?; - - let (better_planes, compatible_planes): ( - Vec, - Vec, - ) = planes - .planes() - .iter() - .filter(|&&plane| { - drm.get_plane(plane) - .map(|plane_info| { - let compatible_crtcs = res.filter_crtcs(plane_info.possible_crtcs()); - compatible_crtcs.contains(&crtc.handle()) - }) - .unwrap_or(false) - }) - .partition(|&&plane| { - if let Ok(props) = drm.get_properties(plane) { - let (ids, vals) = props.as_props_and_values(); - for (&id, &val) in ids.iter().zip(vals.iter()) { - if let Ok(info) = drm.get_property(id) { - if info.name().to_str().map(|x| x == "type").unwrap_or(false) { - return val == (drm::control::PlaneType::Cursor as u32).into(); - } - } - } - } - false - }); - let plane = *better_planes.get(0).unwrap_or(&compatible_planes[0]); - */ let (p_better_planes, p_compatible_planes): ( Vec, Vec, @@ -1206,6 +1148,7 @@ impl EventLoop { }, ); + let cursor_arc = Arc::new(Mutex::new(PhysicalPosition::new(0.0, 0.0))); let input_backend: LibinputInputBackend = LibinputInputBackend::new( input, (disp_width.into(), disp_height.into()), // plane, fb @@ -1213,6 +1156,7 @@ impl EventLoop { state, keymap, xkb_compose, + cursor_arc, ); let input_loop: calloop::Dispatcher<'static, LibinputInputBackend, EventSink> = @@ -1232,7 +1176,7 @@ impl EventLoop { crtc: crtc.clone(), device: drm, plane: p_plane, - // cursor_buffer: fb, + cursor_arc, mode, event_loop_handle: handle, event_sink, diff --git a/src/platform_impl/linux/kms/window.rs b/src/platform_impl/linux/kms/window.rs index dfb3fa3cb8..13314171d1 100644 --- a/src/platform_impl/linux/kms/window.rs +++ b/src/platform_impl/linux/kms/window.rs @@ -1,6 +1,7 @@ -use std::{collections::VecDeque, os::unix::prelude::AsRawFd}; +use std::{collections::VecDeque, os::unix::prelude::AsRawFd, sync::Arc}; use drm::control::{atomic, property, AtomicCommitFlags, Device}; +use parking_lot::Mutex; use crate::{ dpi::{PhysicalPosition, PhysicalSize, Position, Size}, @@ -16,6 +17,7 @@ pub struct Window { connector: drm::control::connector::Info, ping: calloop::ping::Ping, plane: drm::control::plane::Handle, + cursor: Arc>>, card: Card, } @@ -190,6 +192,7 @@ impl Window { mode: event_loop_window_target.mode.clone(), connector: event_loop_window_target.connector.clone(), plane: event_loop_window_target.plane.clone(), + cursor: event_loop_window_target.cursor_arc.clone(), ping: event_loop_window_target.event_loop_awakener.clone(), card: event_loop_window_target.device.clone(), }) @@ -212,12 +215,12 @@ impl Window { #[inline] pub fn outer_position(&self) -> Result, NotSupportedError> { - Err(NotSupportedError::new()) + Ok(PhysicalPosition::new(0, 0)) } #[inline] pub fn inner_position(&self) -> Result, NotSupportedError> { - Err(NotSupportedError::new()) + Ok(PhysicalPosition::new(0, 0)) } #[inline] @@ -259,7 +262,7 @@ impl Window { #[inline] pub fn set_cursor_grab(&self, _grab: bool) -> Result<(), ExternalError> { - Err(ExternalError::NotSupported(NotSupportedError::new())) + Ok(()) } #[inline] @@ -267,12 +270,12 @@ impl Window { #[inline] pub fn drag_window(&self) -> Result<(), ExternalError> { - Err(ExternalError::NotSupported(NotSupportedError::new())) + Ok(()) } #[inline] pub fn set_cursor_hittest(&self, _hittest: bool) -> Result<(), ExternalError> { - Err(ExternalError::NotSupported(NotSupportedError::new())) + Ok(()) } #[inline] @@ -281,8 +284,9 @@ impl Window { } #[inline] - pub fn set_cursor_position(&self, _position: Position) -> Result<(), ExternalError> { - Err(ExternalError::NotSupported(NotSupportedError::new())) + pub fn set_cursor_position(&self, position: Position) -> Result<(), ExternalError> { + *self.cursor.lock() = position.to_physical(1.0); + Ok(()) } #[inline] From 67f564a9561f5aca61471941e3ebaccef5a8fb6c Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Mon, 9 May 2022 10:53:10 -0400 Subject: [PATCH 085/151] Fix cursor position setting --- src/platform_impl/linux/kms/event_loop.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform_impl/linux/kms/event_loop.rs b/src/platform_impl/linux/kms/event_loop.rs index ef90173b50..adc6b871cb 100644 --- a/src/platform_impl/linux/kms/event_loop.rs +++ b/src/platform_impl/linux/kms/event_loop.rs @@ -1156,7 +1156,7 @@ impl EventLoop { state, keymap, xkb_compose, - cursor_arc, + cursor_arc.clone(), ); let input_loop: calloop::Dispatcher<'static, LibinputInputBackend, EventSink> = From b2d80232080c321668c639ce87a21562473e55e1 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Mon, 9 May 2022 11:05:48 -0400 Subject: [PATCH 086/151] Fix dangerous API change --- src/platform/unix.rs | 39 +++++++++++----------------------- src/platform_impl/linux/mod.rs | 32 +--------------------------- 2 files changed, 13 insertions(+), 58 deletions(-) diff --git a/src/platform/unix.rs b/src/platform/unix.rs index e264356d96..49703887a2 100644 --- a/src/platform/unix.rs +++ b/src/platform/unix.rs @@ -24,10 +24,12 @@ use crate::dpi::Size; #[cfg(feature = "x11")] use crate::platform_impl::x11::{ffi::XVisualInfo, XConnection}; use crate::platform_impl::{ - ApplicationName, Backend, EventLoopWindowTarget as LinuxEventLoopWindowTarget, - Window as LinuxWindow, + ApplicationName, EventLoopWindowTarget as LinuxEventLoopWindowTarget, Window as LinuxWindow, }; +#[cfg(any(feature = "x11", feature = "wayland", feature = "kms"))] +pub use crate::platform_impl::Backend; + // TODO: stupid hack so that glutin can do its work #[cfg(feature = "kms")] pub use crate::platform_impl::kms::Card; @@ -39,16 +41,8 @@ pub use crate::platform_impl::{x11::util::WindowType as XWindowType, XNotSupport /// Additional methods on `EventLoopWindowTarget` that are specific to Unix. pub trait EventLoopWindowTargetExtUnix { - /// True if the `EventLoopWindowTarget` uses Wayland. - #[cfg(feature = "wayland")] - fn is_wayland(&self) -> bool; - - /// True if the `EventLoopWindowTarget` uses X11. - #[cfg(feature = "x11")] - fn is_x11(&self) -> bool; - - #[cfg(feature = "kms")] - fn is_drm(&self) -> bool; + /// Find out what backend winit is currently using. + fn unix_backend(&self) -> Backend; #[doc(hidden)] #[cfg(feature = "x11")] @@ -96,21 +90,12 @@ pub trait EventLoopWindowTargetExtUnix { impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { #[inline] - #[cfg(feature = "wayland")] - fn is_wayland(&self) -> bool { - self.p.is_wayland() - } - - #[inline] - #[cfg(feature = "x11")] - fn is_x11(&self) -> bool { - self.p.is_x11() - } - - #[inline] - #[cfg(feature = "kms")] - fn is_drm(&self) -> bool { - self.p.is_drm() + fn unix_backend(&self) -> Backend { + match self.p { + LinuxEventLoopWindowTarget::X(_) => Backend::X, + LinuxEventLoopWindowTarget::Wayland(_) => Backend::Wayland, + LinuxEventLoopWindowTarget::Kms(_) => Backend::Kms, + } } #[inline] diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index cdff20dc7e..8f3b2d26ed 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -54,7 +54,7 @@ pub mod xkb_keymap; const BACKEND_PREFERENCE_ENV_VAR: &str = "WINIT_UNIX_BACKEND"; #[derive(Debug, Copy, Clone, PartialEq, Hash)] -pub(crate) enum Backend { +pub enum Backend { #[cfg(feature = "x11")] X, #[cfg(feature = "wayland")] @@ -831,36 +831,6 @@ pub enum EventLoopWindowTarget { } impl EventLoopWindowTarget { - #[inline] - pub fn is_wayland(&self) -> bool { - match *self { - #[cfg(feature = "wayland")] - EventLoopWindowTarget::Wayland(_) => true, - #[cfg(any(feature = "x11", feature = "kms"))] - _ => false, - } - } - - #[inline] - pub fn is_x11(&self) -> bool { - match *self { - #[cfg(feature = "x11")] - EventLoopWindowTarget::X(_) => true, - #[cfg(any(feature = "kms", feature = "wayland"))] - _ => false, - } - } - - #[inline] - pub fn is_drm(&self) -> bool { - match *self { - #[cfg(feature = "kms")] - EventLoopWindowTarget::Kms(_) => true, - #[cfg(any(feature = "x11", feature = "wayland"))] - _ => false, - } - } - #[inline] pub fn available_monitors(&self) -> VecDeque { match *self { From 26ac5292b3a7c6b845ffc8726cfe0b3c5080145b Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Mon, 9 May 2022 11:22:36 -0400 Subject: [PATCH 087/151] Fix unclear docs --- src/platform/unix.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/platform/unix.rs b/src/platform/unix.rs index 49703887a2..f741017d44 100644 --- a/src/platform/unix.rs +++ b/src/platform/unix.rs @@ -51,7 +51,7 @@ pub trait EventLoopWindowTargetExtUnix { /// Returns a pointer to the `wl_display` object of wayland that is used by this /// `EventLoopWindowTarget`. /// - /// Returns `None` if the `EventLoop` doesn't use wayland (if it uses xlib for example). + /// Returns `None` if the `EventLoop` doesn't use wayland. /// /// The pointer will become invalid when the winit `EventLoop` is destroyed. #[cfg(feature = "wayland")] @@ -59,31 +59,31 @@ pub trait EventLoopWindowTargetExtUnix { /// Returns the drm device of the event loop's fd /// - /// Returns `None` if the `EventLoop` doesn't use kms (if it uses wayland for example). + /// Returns `None` if the `EventLoop` doesn't use drm. #[cfg(feature = "kms")] fn drm_device(&self) -> Option<&crate::platform::unix::Card>; /// Returns the current crtc of the drm device /// - /// Returns `None` if the `EventLoop` doesn't use kms (if it uses wayland for example). + /// Returns `None` if the `EventLoop` doesn't use drm. #[cfg(feature = "kms")] fn drm_crtc(&self) -> Option<&drm::control::crtc::Info>; /// Returns the current connector of the drm device /// - /// Returns `None` if the `EventLoop` doesn't use kms (if it uses wayland for example). + /// Returns `None` if the `EventLoop` doesn't use drm. #[cfg(feature = "kms")] fn drm_connector(&self) -> Option<&drm::control::connector::Info>; /// Returns the current mode of the drm device /// - /// Returns `None` if the `EventLoop` doesn't use kms (if it uses wayland for example). + /// Returns `None` if the `EventLoop` doesn't use drm. #[cfg(feature = "kms")] fn drm_mode(&self) -> Option; /// Returns the primary plane of the drm device /// - /// Returns `None` if the `EventLoop` doesn't use kms (if it uses wayland for example). + /// Returns `None` if the `EventLoop` doesn't use drm. #[cfg(feature = "kms")] fn drm_plane(&self) -> Option; } @@ -226,13 +226,13 @@ impl EventLoopBuilderExtUnix for EventLoopBuilder { pub trait WindowExtUnix { /// Returns the ID of the `Window` xlib object that is used by this window. /// - /// Returns `None` if the window doesn't use xlib (if it uses wayland for example). + /// Returns `None` if the window doesn't use xlib. #[cfg(feature = "x11")] fn xlib_window(&self) -> Option; /// Returns a pointer to the `Display` object of xlib that is used by this window. /// - /// Returns `None` if the window doesn't use xlib (if it uses wayland for example). + /// Returns `None` if the window doesn't use xlib. /// /// The pointer will become invalid when the glutin `Window` is destroyed. #[cfg(feature = "x11")] @@ -247,7 +247,7 @@ pub trait WindowExtUnix { /// This function returns the underlying `xcb_connection_t` of an xlib `Display`. /// - /// Returns `None` if the window doesn't use xlib (if it uses wayland for example). + /// Returns `None` if the window doesn't use xlib. /// /// The pointer will become invalid when the glutin `Window` is destroyed. #[cfg(feature = "x11")] @@ -255,7 +255,7 @@ pub trait WindowExtUnix { /// Returns a pointer to the `wl_surface` object of wayland that is used by this window. /// - /// Returns `None` if the window doesn't use wayland (if it uses xlib for example). + /// Returns `None` if the window doesn't use wayland. /// /// The pointer will become invalid when the glutin `Window` is destroyed. #[cfg(feature = "wayland")] @@ -263,7 +263,7 @@ pub trait WindowExtUnix { /// Returns a pointer to the `wl_display` object of wayland that is used by this window. /// - /// Returns `None` if the window doesn't use wayland (if it uses xlib for example). + /// Returns `None` if the window doesn't use wayland. /// /// The pointer will become invalid when the glutin `Window` is destroyed. #[cfg(feature = "wayland")] From fc63f299d8e625fa73bb3c9af2d8cf91dd31450c Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Mon, 9 May 2022 11:23:49 -0400 Subject: [PATCH 088/151] Fix incorrect features --- FEATURES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FEATURES.md b/FEATURES.md index da622f093c..77aba2a4e8 100644 --- a/FEATURES.md +++ b/FEATURES.md @@ -200,7 +200,7 @@ Legend: |Mouse events |✔️ |▢[#63] |✔️ |✔️ |✔️ |**N/A**|**N/A**|✔️ | |Mouse set location |✔️ |✔️ |✔️ |❓ |✔️ |**N/A**|**N/A**|**N/A**| |Cursor grab |✔️ |▢[#165] |▢[#242] |✔️ |✔️ |**N/A**|**N/A**|✔️ | -|Cursor icon |✔️ |✔️ |✔️ |✔️ |✔️ |**N/A**|**N/A**|✔️ | +|Cursor icon |✔️ |✔️ |✔️ |✔️ |❌ |**N/A**|**N/A**|✔️ | |Cursor hittest |✔️ |✔️ |❌ |✔️ |❌ |**N/A**|**N/A**|❌ | |Touch events |✔️ |❌ |✔️ |✔️ |✔️ |✔️ |✔️ |❌ | |Touch pressure |✔️ |❌ |❌ |❌ |✔️ |❌ |✔️ |❌ | From 28780a14d1e9fc17cd3e4f06282d5e1d2d23eb5e Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Mon, 9 May 2022 12:07:31 -0400 Subject: [PATCH 089/151] Fix docs capitalization --- src/platform_impl/linux/kms/event_loop.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/platform_impl/linux/kms/event_loop.rs b/src/platform_impl/linux/kms/event_loop.rs index adc6b871cb..f69d9dbb98 100644 --- a/src/platform_impl/linux/kms/event_loop.rs +++ b/src/platform_impl/linux/kms/event_loop.rs @@ -716,22 +716,22 @@ impl EventSource for LibinputInputBackend { type EventSink = Vec>; pub struct EventLoopWindowTarget { - /// drm Connector + /// Drm Connector pub connector: drm::control::connector::Info, - /// drm crtc + /// Drm crtc pub crtc: drm::control::crtc::Info, - /// drm mode + /// Drm mode pub mode: drm::control::Mode, - /// drm plane + /// Drm plane pub plane: drm::control::plane::Handle, /// Allows window to edit cursor position pub(crate) cursor_arc: Arc>>, - /// drm device + /// Drm device pub device: Card, /// Event loop handle. From d2d8d7248d6682e5cfd065f5508bc0626c85f43d Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Mon, 9 May 2022 12:15:09 -0400 Subject: [PATCH 090/151] Fix error messages --- src/platform_impl/linux/kms/event_loop.rs | 53 ++++-------- src/platform_impl/linux/kms/window.rs | 101 ++++++++++++++++++---- 2 files changed, 102 insertions(+), 52 deletions(-) diff --git a/src/platform_impl/linux/kms/event_loop.rs b/src/platform_impl/linux/kms/event_loop.rs index f69d9dbb98..19ae3a901c 100644 --- a/src/platform_impl/linux/kms/event_loop.rs +++ b/src/platform_impl/linux/kms/event_loop.rs @@ -781,23 +781,6 @@ pub struct EventLoop { window_target: crate::event_loop::EventLoopWindowTarget, } -pub(crate) fn find_prop_id( - card: &Card, - handle: T, - name: &'static str, -) -> Option { - let props = card - .get_properties(handle) - .expect("Could not get props of connector"); - let (ids, _vals) = props.as_props_and_values(); - ids.iter() - .find(|&id| { - let info = card.get_property(*id).unwrap(); - info.name().to_str().map(|x| x == name).unwrap_or(false) - }) - .cloned() -} - impl EventLoop { pub fn new() -> Result, crate::error::OsError> { #[cfg(feature = "kms-ext")] @@ -816,7 +799,7 @@ impl EventLoop { crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("Failed to open libseat"), + crate::platform_impl::OsError::KmsMisc("failed to open libseat"), ) })?; @@ -825,7 +808,7 @@ impl EventLoop { return Err(crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("Failed to dispatch seat"), + crate::platform_impl::OsError::KmsMisc("failed to dispatch seat"), )); } } @@ -845,21 +828,21 @@ impl EventLoop { crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("Failed to open udev enumerator"), + crate::platform_impl::OsError::KmsMisc("failed to open udev enumerator"), ) })?; enumerator.match_subsystem("drm").map_err(|_| { crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("Failed to enumerate drm subsystem"), + crate::platform_impl::OsError::KmsMisc("failed to enumerate drm subsystem"), ) })?; enumerator.match_sysname("card[0-9]*").map_err(|_| { crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("Failed to find a valid card"), + crate::platform_impl::OsError::KmsMisc("failed to find a valid card"), ) })?; enumerator @@ -868,7 +851,7 @@ impl EventLoop { crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("Failed to scan devices"), + crate::platform_impl::OsError::KmsMisc("failed to scan devices"), ) })? .filter(|device| { @@ -904,7 +887,7 @@ impl EventLoop { .ok_or(crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("Failed to find suitable GPU"), + crate::platform_impl::OsError::KmsMisc("failed to find suitable GPU"), )) }, |p| Ok(Into::into(p)), @@ -916,7 +899,7 @@ impl EventLoop { crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("Failed to initialize DRM"), + crate::platform_impl::OsError::KmsMisc("failed to initialize DRM"), ) })? .1; @@ -930,7 +913,7 @@ impl EventLoop { crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("Failed to initialize DRM"), + crate::platform_impl::OsError::KmsMisc("failed to initialize DRM"), ) })?, ); @@ -953,7 +936,7 @@ impl EventLoop { .ok_or(crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("Failed to compile XKB keymap"), + crate::platform_impl::OsError::KmsMisc("failed to compile XKB keymap"), ))?; let state = xkb::State::new(&keymap); let compose_table = xkb::compose::Table::new_from_locale( @@ -970,7 +953,7 @@ impl EventLoop { .or(Err(crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("Failed to compile XKB compose table"), + crate::platform_impl::OsError::KmsMisc("failed to compile XKB compose table"), )))?; let xkb_compose = xkb::compose::State::new(&compose_table, xkb::compose::STATE_NO_FLAGS); @@ -979,7 +962,7 @@ impl EventLoop { line!(), file!(), crate::platform_impl::OsError::KmsMisc( - "kms device does not support universal planes", + "drm device does not support universal planes", ), )), )?; @@ -988,7 +971,7 @@ impl EventLoop { line!(), file!(), crate::platform_impl::OsError::KmsMisc( - "kms device does not support atomic modesetting", + "drm device does not support atomic modesetting", ), ), ))?; @@ -997,7 +980,7 @@ impl EventLoop { let res = drm.resource_handles().or(Err(crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("Could not load normal resource ids."), + crate::platform_impl::OsError::KmsMisc("could not load normal resource ids."), )))?; let coninfo: Vec = res .connectors() @@ -1016,13 +999,13 @@ impl EventLoop { .ok_or(crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("No connected connectors"), + crate::platform_impl::OsError::KmsMisc("no connected connectors"), ))?; let crtc = crtcinfo.get(0).ok_or(crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("No crtcs found"), + crate::platform_impl::OsError::KmsMisc("no crtcs found"), ))?; // Get the first (usually best) mode @@ -1034,13 +1017,13 @@ impl EventLoop { .ok_or(crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("No modes found on connector"), + crate::platform_impl::OsError::KmsMisc("no modes found on connector"), ))?; let planes = drm.plane_handles().or(Err(crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("Could not list planes"), + crate::platform_impl::OsError::KmsMisc("could not list planes"), )))?; let (p_better_planes, p_compatible_planes): ( diff --git a/src/platform_impl/linux/kms/window.rs b/src/platform_impl/linux/kms/window.rs index 13314171d1..1a2b9cc2c2 100644 --- a/src/platform_impl/linux/kms/window.rs +++ b/src/platform_impl/linux/kms/window.rs @@ -1,6 +1,6 @@ use std::{collections::VecDeque, os::unix::prelude::AsRawFd, sync::Arc}; -use drm::control::{atomic, property, AtomicCommitFlags, Device}; +use drm::control::{atomic, property, AtomicCommitFlags, Device, ResourceHandle}; use parking_lot::Mutex; use crate::{ @@ -10,8 +10,6 @@ use crate::{ window::{CursorIcon, Fullscreen}, }; -use super::event_loop::find_prop_id; - pub struct Window { mode: drm::control::Mode, connector: drm::control::connector::Info, @@ -21,6 +19,21 @@ pub struct Window { card: Card, } +fn find_prop_id( + card: &Card, + handle: T, + name: &'static str, +) -> Option { + let props = card.get_properties(handle).ok()?; + let (ids, _vals) = props.as_props_and_values(); + ids.iter() + .find(|&id| { + let info = card.get_property(*id).unwrap(); + info.name().to_str().map(|x| x == name).unwrap_or(false) + }) + .cloned() +} + impl Window { pub fn new( event_loop_window_target: &super::event_loop::EventLoopWindowTarget, @@ -39,7 +52,7 @@ impl Window { crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("Could not get CRTC_ID"), + crate::platform_impl::OsError::KmsMisc("could not get CRTC_ID"), ) })?, property::Value::CRTC(Some(event_loop_window_target.crtc.handle())), @@ -51,7 +64,7 @@ impl Window { crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("Failed to create blob"), + crate::platform_impl::OsError::KmsMisc("failed to create blob"), ) })?; atomic_req.add_property( @@ -65,7 +78,7 @@ impl Window { crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("Could not get MODE_ID"), + crate::platform_impl::OsError::KmsMisc("could not get MODE_ID"), ) })?, blob, @@ -81,7 +94,7 @@ impl Window { crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("Could not get ACTIVE"), + crate::platform_impl::OsError::KmsMisc("could not get ACTIVE"), ) })?, property::Value::Boolean(true), @@ -93,7 +106,13 @@ impl Window { event_loop_window_target.plane, "CRTC_ID", ) - .expect("Could not get CRTC_ID"), + .ok_or_else(|| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::KmsMisc("could not get CRTC_ID"), + ) + })?, property::Value::CRTC(Some(event_loop_window_target.crtc.handle())), ); atomic_req.add_property( @@ -103,7 +122,13 @@ impl Window { event_loop_window_target.plane, "SRC_X", ) - .expect("Could not get SRC_X"), + .ok_or_else(|| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::KmsMisc("could not get SRC_X"), + ) + })?, property::Value::UnsignedRange(0), ); atomic_req.add_property( @@ -113,7 +138,13 @@ impl Window { event_loop_window_target.plane, "SRC_Y", ) - .expect("Could not get SRC_Y"), + .ok_or_else(|| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::KmsMisc("could not get SRC_Y"), + ) + })?, property::Value::UnsignedRange(0), ); atomic_req.add_property( @@ -123,7 +154,13 @@ impl Window { event_loop_window_target.plane, "SRC_W", ) - .expect("Could not get SRC_W"), + .ok_or_else(|| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::KmsMisc("could not get SRC_W"), + ) + })?, property::Value::UnsignedRange((event_loop_window_target.mode.size().0 as u64) << 16), ); atomic_req.add_property( @@ -133,7 +170,13 @@ impl Window { event_loop_window_target.plane, "SRC_H", ) - .expect("Could not get SRC_H"), + .ok_or_else(|| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::KmsMisc("could not get SRC_H"), + ) + })?, property::Value::UnsignedRange((event_loop_window_target.mode.size().1 as u64) << 16), ); atomic_req.add_property( @@ -143,7 +186,13 @@ impl Window { event_loop_window_target.plane, "CRTC_X", ) - .expect("Could not get CRTC_X"), + .ok_or_else(|| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::KmsMisc("could not get CRTC_X"), + ) + })?, property::Value::SignedRange(0), ); atomic_req.add_property( @@ -153,7 +202,13 @@ impl Window { event_loop_window_target.plane, "CRTC_Y", ) - .expect("Could not get CRTC_Y"), + .ok_or_else(|| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::KmsMisc("could not get CRTC_Y"), + ) + })?, property::Value::SignedRange(0), ); atomic_req.add_property( @@ -163,7 +218,13 @@ impl Window { event_loop_window_target.plane, "CRTC_W", ) - .expect("Could not get CRTC_W"), + .ok_or_else(|| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::KmsMisc("could not get CRTC_W"), + ) + })?, property::Value::UnsignedRange(event_loop_window_target.mode.size().0 as u64), ); atomic_req.add_property( @@ -173,7 +234,13 @@ impl Window { event_loop_window_target.plane, "CRTC_H", ) - .expect("Could not get CRTC_H"), + .ok_or_else(|| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::KmsMisc("could not get CRTC_H"), + ) + })?, property::Value::UnsignedRange(event_loop_window_target.mode.size().1 as u64), ); @@ -184,7 +251,7 @@ impl Window { crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("Failed to set mode"), + crate::platform_impl::OsError::KmsMisc("failed to set mode"), ) })?; From acdbec6e897d32a0691a0f51fff22a9b62eb6586 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Mon, 9 May 2022 12:32:43 -0400 Subject: [PATCH 091/151] Fix error handling --- src/platform_impl/linux/kms/event_loop.rs | 197 ++++++++++++++-------- src/platform_impl/linux/kms/window.rs | 4 +- src/platform_impl/linux/mod.rs | 4 + 3 files changed, 129 insertions(+), 76 deletions(-) diff --git a/src/platform_impl/linux/kms/event_loop.rs b/src/platform_impl/linux/kms/event_loop.rs index 19ae3a901c..faa979227a 100644 --- a/src/platform_impl/linux/kms/event_loop.rs +++ b/src/platform_impl/linux/kms/event_loop.rs @@ -16,7 +16,7 @@ use udev::Enumerator; use xkbcommon::xkb; use calloop::{EventSource, Interest, Mode, Poll, PostAction, Readiness, Token, TokenFactory}; -use drm::control::{property, Device, ModeTypeFlags, ResourceHandle}; +use drm::control::{Device, ModeTypeFlags}; use input::{ event::{ keyboard::KeyboardEventTrait, @@ -795,22 +795,28 @@ impl EventLoop { }, None, ) - .map_err(|_| { + .map_err(|e| { crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("failed to open libseat"), + crate::platform_impl::OsError::KmsError(format!( + "failed to open libseat: {}", + e + )), ) })?; while !active.load(std::sync::atomic::Ordering::SeqCst) { - if let Err(_) = s.dispatch(-1) { - return Err(crate::error::OsError::new( + s.dispatch(-1).map_err(|e| { + crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("failed to dispatch seat"), - )); - } + crate::platform_impl::OsError::KmsError(format!( + "failed to dispatch seat: {}", + e + )), + ) + })?; } s }; @@ -824,34 +830,46 @@ impl EventLoop { let seat_name = "seat0"; let card_path = std::env::var("WINIT_DRM_CARD").ok().map_or_else( || { - let mut enumerator = Enumerator::new().map_err(|_| { + let mut enumerator = Enumerator::new().map_err(|e| { crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("failed to open udev enumerator"), + crate::platform_impl::OsError::KmsError(format!( + "failed to open udev enumerator: {}", + e + )), ) })?; - enumerator.match_subsystem("drm").map_err(|_| { + enumerator.match_subsystem("drm").map_err(|e| { crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("failed to enumerate drm subsystem"), + crate::platform_impl::OsError::KmsError(format!( + "failed to enumerate drm subsystem: {}", + e + )), ) })?; - enumerator.match_sysname("card[0-9]*").map_err(|_| { + enumerator.match_sysname("card[0-9]*").map_err(|e| { crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("failed to find a valid card"), + crate::platform_impl::OsError::KmsError(format!( + "failed to find a valid card: {}", + e + )), ) })?; enumerator .scan_devices() - .map_err(|_| { + .map_err(|e| { crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("failed to scan devices"), + crate::platform_impl::OsError::KmsError(format!( + "failed to scan devices: {}", + e + )), ) })? .filter(|device| { @@ -884,22 +902,27 @@ impl EventLoop { .flat_map(|device| device.devnode().map(std::path::PathBuf::from)) .next() }) - .ok_or(crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::KmsMisc("failed to find suitable GPU"), - )) + .ok_or_else(|| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::KmsMisc("failed to find suitable GPU"), + ) + }) }, |p| Ok(Into::into(p)), )?; #[cfg(feature = "kms-ext")] let dev = seat .open_device(&card_path) - .map_err(|_| { + .map_err(|e| { crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("failed to initialize DRM"), + crate::platform_impl::OsError::KmsError(format!( + "failed to initialize DRM: {}", + e + )), ) })? .1; @@ -909,11 +932,14 @@ impl EventLoop { .read(true) .write(true) .open(&card_path) - .map_err(|_| { + .map_err(|e| { crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("failed to initialize DRM"), + crate::platform_impl::OsError::KmsError(format!( + "failed to initialize DRM: {}", + e + )), ) })?, ); @@ -933,11 +959,13 @@ impl EventLoop { std::env::var("WINIT_XKB_OPTIONS").ok(), xkb::KEYMAP_COMPILE_NO_FLAGS, ) - .ok_or(crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::KmsMisc("failed to compile XKB keymap"), - ))?; + .ok_or_else(|| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::KmsMisc("failed to compile XKB keymap"), + ) + })?; let state = xkb::State::new(&keymap); let compose_table = xkb::compose::Table::new_from_locale( &xkb_ctx, @@ -950,38 +978,51 @@ impl EventLoop { .as_os_str(), xkb::compose::COMPILE_NO_FLAGS, ) - .or(Err(crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::KmsMisc("failed to compile XKB compose table"), - )))?; - let xkb_compose = xkb::compose::State::new(&compose_table, xkb::compose::STATE_NO_FLAGS); - - drm::Device::set_client_capability(&drm, drm::ClientCapability::UniversalPlanes, true).or( - Err(crate::error::OsError::new( + .map_err(|_| { + // e ^^^ would return () + crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc( - "drm device does not support universal planes", - ), - )), + crate::platform_impl::OsError::KmsMisc("failed to compile XKB compose table"), + ) + })?; + let xkb_compose = xkb::compose::State::new(&compose_table, xkb::compose::STATE_NO_FLAGS); + + drm::Device::set_client_capability(&drm, drm::ClientCapability::UniversalPlanes, true) + .map_err(|e| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::KmsError(format!( + "drm device does not support universal planes :{}", + e + )), + ) + })?; + drm::Device::set_client_capability(&drm, drm::ClientCapability::Atomic, true).map_err( + |e| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::KmsError(format!( + "drm device does not support atomic modesetting :{}", + e + )), + ) + }, )?; - drm::Device::set_client_capability(&drm, drm::ClientCapability::Atomic, true).or(Err( + + // Load the information. + let res = drm.resource_handles().map_err(|e| { crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc( - "drm device does not support atomic modesetting", - ), - ), - ))?; - - // Load the information. - let res = drm.resource_handles().or(Err(crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::KmsMisc("could not load normal resource ids."), - )))?; + crate::platform_impl::OsError::KmsError(format!( + "could not load normal resource ids: {}", + e + )), + ) + })?; let coninfo: Vec = res .connectors() .iter() @@ -996,17 +1037,21 @@ impl EventLoop { let con = coninfo .iter() .find(|&i| i.state() == drm::control::connector::State::Connected) - .ok_or(crate::error::OsError::new( + .ok_or_else(|| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::KmsMisc("no connected connectors"), + ) + })?; + + let crtc = crtcinfo.get(0).ok_or_else(|| { + crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("no connected connectors"), - ))?; - - let crtc = crtcinfo.get(0).ok_or(crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::KmsMisc("no crtcs found"), - ))?; + crate::platform_impl::OsError::KmsMisc("no crtcs found"), + ) + })?; // Get the first (usually best) mode let &mode = con @@ -1014,17 +1059,21 @@ impl EventLoop { .iter() .find(|f| f.mode_type().contains(ModeTypeFlags::PREFERRED)) .or(con.modes().get(0)) - .ok_or(crate::error::OsError::new( + .ok_or_else(|| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::KmsMisc("no modes found on connector"), + ) + })?; + + let planes = drm.plane_handles().map_err(|e| { + crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("no modes found on connector"), - ))?; - - let planes = drm.plane_handles().or(Err(crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::KmsMisc("could not list planes"), - )))?; + crate::platform_impl::OsError::KmsError(format!("could not list planes: {}", e)), + ) + })?; let (p_better_planes, p_compatible_planes): ( Vec, diff --git a/src/platform_impl/linux/kms/window.rs b/src/platform_impl/linux/kms/window.rs index 1a2b9cc2c2..e99987a69c 100644 --- a/src/platform_impl/linux/kms/window.rs +++ b/src/platform_impl/linux/kms/window.rs @@ -247,11 +247,11 @@ impl Window { event_loop_window_target .device .atomic_commit(AtomicCommitFlags::ALLOW_MODESET, atomic_req) - .map_err(|_| { + .map_err(|e| { crate::error::OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("failed to set mode"), + crate::platform_impl::OsError::KmsError(format!("failed to set mode: {}", e)), ) })?; diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index 8f3b2d26ed..e1f9c49e92 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -146,6 +146,8 @@ pub enum OsError { #[cfg(feature = "wayland")] WaylandMisc(&'static str), #[cfg(feature = "kms")] + KmsError(String), + #[cfg(feature = "kms")] KmsMisc(&'static str), } @@ -159,6 +161,8 @@ impl fmt::Display for OsError { #[cfg(feature = "wayland")] OsError::WaylandMisc(e) => _f.pad(e), #[cfg(feature = "kms")] + OsError::KmsError(ref e) => _f.pad(e), + #[cfg(feature = "kms")] OsError::KmsMisc(e) => _f.pad(e), } } From 948261a7d358805097d0df4a1bcbfcdf097a624f Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Mon, 9 May 2022 12:37:58 -0400 Subject: [PATCH 092/151] Fix unreadable closure --- src/platform_impl/linux/kms/event_loop.rs | 168 +++++++++++----------- 1 file changed, 82 insertions(+), 86 deletions(-) diff --git a/src/platform_impl/linux/kms/event_loop.rs b/src/platform_impl/linux/kms/event_loop.rs index faa979227a..62678db91f 100644 --- a/src/platform_impl/linux/kms/event_loop.rs +++ b/src/platform_impl/linux/kms/event_loop.rs @@ -8,7 +8,7 @@ use std::{ collections::VecDeque, marker::PhantomData, os::unix::prelude::{AsRawFd, FromRawFd, RawFd}, - path::Path, + path::{Path, PathBuf}, sync::{mpsc::SendError, Arc}, time::{Duration, Instant}, }; @@ -30,6 +30,7 @@ use input::{ use crate::{ dpi::PhysicalPosition, + error::OsError, event::{ElementState, Force, KeyboardInput, ModifiersState, MouseScrollDelta, StartCause}, event_loop::{ControlFlow, EventLoopClosed}, platform::unix::Card, @@ -767,6 +768,82 @@ impl EventLoopWindowTarget { } } +fn find_card_path(seat_name: &str) -> Result { + let mut enumerator = Enumerator::new().map_err(|e| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::KmsError(format!( + "failed to open udev enumerator: {}", + e + )), + ) + })?; + enumerator.match_subsystem("drm").map_err(|e| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::KmsError(format!( + "failed to enumerate drm subsystem: {}", + e + )), + ) + })?; + enumerator.match_sysname("card[0-9]*").map_err(|e| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::KmsError(format!("failed to find a valid card: {}", e)), + ) + })?; + enumerator + .scan_devices() + .map_err(|e| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::KmsError(format!("failed to scan devices: {}", e)), + ) + })? + .filter(|device| { + let dev_seat_name = device + .property_value("ID_SEAT") + .map(|x| x.to_os_string()) + .unwrap_or_else(|| std::ffi::OsString::from("seat0")); + if dev_seat_name == seat_name { + if let Ok(Some(pci)) = device.parent_with_subsystem(Path::new("pci")) { + if let Some(id) = pci.attribute_value("boot_vga") { + return id == "1"; + } + } + } + false + }) + .flat_map(|device| device.devnode().map(std::path::PathBuf::from)) + .next() + .or_else(|| { + enumerator + .scan_devices() + .ok()? + .filter(|device| { + device + .property_value("ID_SEAT") + .map(|x| x.to_os_string()) + .unwrap_or_else(|| std::ffi::OsString::from("seat0")) + == seat_name + }) + .flat_map(|device| device.devnode().map(std::path::PathBuf::from)) + .next() + }) + .ok_or_else(|| { + crate::error::OsError::new( + line!(), + file!(), + crate::platform_impl::OsError::KmsMisc("failed to find suitable GPU"), + ) + }) +} + pub struct EventLoop { /// Event loop. event_loop: calloop::EventLoop<'static, EventSink>, @@ -820,98 +897,17 @@ impl EventLoop { } s }; + #[cfg(feature = "kms-ext")] // Safety // // This string value has the same lifetime as the seat in question, and will not be dropped // until the seat is, which is not before `udev_assign_seat` is run. - #[cfg(feature = "kms-ext")] let seat_name = unsafe { std::mem::transmute::<&str, &'static str>(seat.name()) }; #[cfg(not(feature = "kms-ext"))] let seat_name = "seat0"; - let card_path = std::env::var("WINIT_DRM_CARD").ok().map_or_else( - || { - let mut enumerator = Enumerator::new().map_err(|e| { - crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::KmsError(format!( - "failed to open udev enumerator: {}", - e - )), - ) - })?; - enumerator.match_subsystem("drm").map_err(|e| { - crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::KmsError(format!( - "failed to enumerate drm subsystem: {}", - e - )), - ) - })?; - enumerator.match_sysname("card[0-9]*").map_err(|e| { - crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::KmsError(format!( - "failed to find a valid card: {}", - e - )), - ) - })?; - enumerator - .scan_devices() - .map_err(|e| { - crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::KmsError(format!( - "failed to scan devices: {}", - e - )), - ) - })? - .filter(|device| { - let dev_seat_name = device - .property_value("ID_SEAT") - .map(|x| x.to_os_string()) - .unwrap_or_else(|| std::ffi::OsString::from("seat0")); - if dev_seat_name == seat_name { - if let Ok(Some(pci)) = device.parent_with_subsystem(Path::new("pci")) { - if let Some(id) = pci.attribute_value("boot_vga") { - return id == "1"; - } - } - } - false - }) - .flat_map(|device| device.devnode().map(std::path::PathBuf::from)) - .next() - .or_else(|| { - enumerator - .scan_devices() - .ok()? - .filter(|device| { - device - .property_value("ID_SEAT") - .map(|x| x.to_os_string()) - .unwrap_or_else(|| std::ffi::OsString::from("seat0")) - == seat_name - }) - .flat_map(|device| device.devnode().map(std::path::PathBuf::from)) - .next() - }) - .ok_or_else(|| { - crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::KmsMisc("failed to find suitable GPU"), - ) - }) - }, - |p| Ok(Into::into(p)), - )?; + let card_path = std::env::var("WINIT_DRM_CARD") + .ok() + .map_or_else(|| find_card_path(seat_name), |p| Ok(Into::into(p)))?; #[cfg(feature = "kms-ext")] let dev = seat .open_device(&card_path) From 787cd2511a1ba7aa7f34159e1726e430592ee8d2 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Mon, 9 May 2022 12:59:06 -0400 Subject: [PATCH 093/151] Fix code spacing --- src/platform_impl/linux/kms/event_loop.rs | 56 +++++++++++++++++++++-- src/platform_impl/linux/kms/window.rs | 13 ++++++ 2 files changed, 66 insertions(+), 3 deletions(-) diff --git a/src/platform_impl/linux/kms/event_loop.rs b/src/platform_impl/linux/kms/event_loop.rs index 62678db91f..110ec4c195 100644 --- a/src/platform_impl/linux/kms/event_loop.rs +++ b/src/platform_impl/linux/kms/event_loop.rs @@ -37,6 +37,9 @@ use crate::{ platform_impl::{platform::sticky_exit_callback, xkb_keymap}, }; +const REPEAT_RATE: u64 = 25; +const REPEAT_DELAY: u64 = 600; + #[cfg(feature = "kms-ext")] struct Interface(libseat::Seat, HashMap); #[cfg(not(feature = "kms-ext"))] @@ -53,10 +56,12 @@ impl LibinputInterface for Interface { }) .map_err(|err| err.into()) } + fn close_restricted(&mut self, fd: RawFd) { if let Some(dev) = self.1.get(&fd).copied() { self.0.close_device(dev).unwrap(); } + unsafe { std::fs::File::from_raw_fd(fd) }; } } @@ -192,6 +197,7 @@ impl EventSource for LibinputInputBackend { input::event::TouchEvent::Down(e) => { self.touch_location.x = e.x_transformed(self.screen_size.0); self.touch_location.y = e.y_transformed(self.screen_size.1); + callback( crate::event::Event::WindowEvent { window_id: crate::window::WindowId( @@ -213,6 +219,7 @@ impl EventSource for LibinputInputBackend { input::event::TouchEvent::Motion(e) => { self.touch_location.x = e.x_transformed(self.screen_size.0); self.touch_location.y = e.y_transformed(self.screen_size.1); + callback( crate::event::Event::WindowEvent { window_id: crate::window::WindowId( @@ -323,6 +330,7 @@ impl EventSource for LibinputInputBackend { }, &mut (), ); + callback( crate::event::Event::DeviceEvent { device_id: crate::event::DeviceId( @@ -348,10 +356,13 @@ impl EventSource for LibinputInputBackend { input::Event::Pointer(e) => match e { input::event::PointerEvent::Motion(e) => { let mut lock = self.cursor_positon.lock(); + lock.x += e.dx(); lock.x = lock.x.clamp(0.0, self.screen_size.0 as f64); + lock.y += e.dy(); lock.y = lock.y.clamp(0.0, self.screen_size.1 as f64); + callback( crate::event::Event::WindowEvent { window_id: crate::window::WindowId( @@ -367,6 +378,7 @@ impl EventSource for LibinputInputBackend { }, &mut (), ); + callback( crate::event::Event::DeviceEvent { device_id: crate::event::DeviceId( @@ -407,6 +419,7 @@ impl EventSource for LibinputInputBackend { }, &mut (), ); + callback( crate::event::Event::DeviceEvent { device_id: crate::event::DeviceId( @@ -497,8 +510,11 @@ impl EventSource for LibinputInputBackend { } input::event::PointerEvent::MotionAbsolute(e) => { let mut lock = self.cursor_positon.lock(); + lock.x = e.absolute_x_transformed(self.screen_size.0); + lock.y = e.absolute_y_transformed(self.screen_size.1); + callback( crate::event::Event::WindowEvent { window_id: crate::window::WindowId( @@ -522,14 +538,17 @@ impl EventSource for LibinputInputBackend { KeyState::Pressed => crate::event::ElementState::Pressed, KeyState::Released => crate::event::ElementState::Released, }; + let k = if let input::event::KeyboardEvent::Key(key) = ev { key.key() } else { unreachable!() }; + let key_offset = k + 8; let keysym = self.xkb_ctx.key_get_one_sym(key_offset); let virtual_keycode = xkb_keymap::keysym_to_vkey(keysym); + self.xkb_ctx.update_key( key_offset, match state { @@ -537,13 +556,16 @@ impl EventSource for LibinputInputBackend { ElementState::Released => xkb::KeyDirection::Up, }, ); + let input = KeyboardInput { scancode: k, state: state.clone(), virtual_keycode, modifiers: self.modifiers, }; + self.timer_handle.cancel_all_timeouts(); + callback( crate::event::Event::WindowEvent { window_id: crate::window::WindowId( @@ -559,8 +581,10 @@ impl EventSource for LibinputInputBackend { }, &mut (), ); + if let crate::event::ElementState::Pressed = state { self.xkb_compose.feed(keysym); + match self.xkb_compose.status() { xkb::compose::Status::Composed => { if let Some(c) = @@ -584,10 +608,14 @@ impl EventSource for LibinputInputBackend { xkb::compose::Status::Cancelled => { let should_repeat = self.xkb_keymap.key_repeats(key_offset); let ch = self.xkb_ctx.key_get_utf8(key_offset).chars().next(); + if should_repeat { - self.timer_handle - .add_timeout(Duration::from_millis(600), (input, ch)); + self.timer_handle.add_timeout( + Duration::from_millis(REPEAT_DELAY), + (input, ch), + ); } + if let Some(c) = ch { callback( crate::event::Event::WindowEvent { @@ -607,10 +635,12 @@ impl EventSource for LibinputInputBackend { xkb::compose::Status::Nothing => { let should_repeat = self.xkb_keymap.key_repeats(key_offset); let ch = self.xkb_ctx.key_get_utf8(key_offset).chars().next(); + if should_repeat { self.timer_handle .add_timeout(Duration::from_millis(600), (input, ch)); } + if let Some(c) = ch { callback( crate::event::Event::WindowEvent { @@ -638,6 +668,7 @@ impl EventSource for LibinputInputBackend { ElementState::Pressed => self.modifiers |= ModifiersState::ALT, ElementState::Released => self.modifiers.remove(ModifiersState::ALT) } + callback(crate::event::Event::WindowEvent { window_id: crate::window::WindowId(crate::platform_impl::WindowId::Kms(super::WindowId)), event:crate::event::WindowEvent::ModifiersChanged(self.modifiers)}, &mut ()); @@ -649,6 +680,7 @@ impl EventSource for LibinputInputBackend { ElementState::Pressed => self.modifiers |= ModifiersState::SHIFT, ElementState::Released => self.modifiers.remove(ModifiersState::SHIFT) } + callback(crate::event::Event::WindowEvent { window_id: crate::window::WindowId(crate::platform_impl::WindowId::Kms(super::WindowId)), event:crate::event::WindowEvent::ModifiersChanged(self.modifiers)}, &mut ()); @@ -661,6 +693,7 @@ impl EventSource for LibinputInputBackend { ElementState::Pressed => self.modifiers |= ModifiersState::CTRL, ElementState::Released => self.modifiers.remove(ModifiersState::CTRL) } + callback(crate::event::Event::WindowEvent { window_id: crate::window::WindowId(crate::platform_impl::WindowId::Kms(super::WindowId)), event:crate::event::WindowEvent::ModifiersChanged(self.modifiers)}, &mut ()); @@ -673,6 +706,7 @@ impl EventSource for LibinputInputBackend { ElementState::Pressed => self.modifiers |= ModifiersState::LOGO, ElementState::Released => self.modifiers.remove(ModifiersState::LOGO) } + callback(crate::event::Event::WindowEvent { window_id: crate::window::WindowId(crate::platform_impl::WindowId::Kms(super::WindowId)), event: crate::event::WindowEvent::ModifiersChanged(self.modifiers)}, &mut ()); @@ -779,6 +813,7 @@ fn find_card_path(seat_name: &str) -> Result { )), ) })?; + enumerator.match_subsystem("drm").map_err(|e| { crate::error::OsError::new( line!(), @@ -789,6 +824,7 @@ fn find_card_path(seat_name: &str) -> Result { )), ) })?; + enumerator.match_sysname("card[0-9]*").map_err(|e| { crate::error::OsError::new( line!(), @@ -796,6 +832,7 @@ fn find_card_path(seat_name: &str) -> Result { crate::platform_impl::OsError::KmsError(format!("failed to find a valid card: {}", e)), ) })?; + enumerator .scan_devices() .map_err(|e| { @@ -897,6 +934,7 @@ impl EventLoop { } s }; + #[cfg(feature = "kms-ext")] // Safety // @@ -905,6 +943,7 @@ impl EventLoop { let seat_name = unsafe { std::mem::transmute::<&str, &'static str>(seat.name()) }; #[cfg(not(feature = "kms-ext"))] let seat_name = "seat0"; + let card_path = std::env::var("WINIT_DRM_CARD") .ok() .map_or_else(|| find_card_path(seat_name), |p| Ok(Into::into(p)))?; @@ -922,6 +961,7 @@ impl EventLoop { ) })? .1; + #[cfg(not(feature = "kms-ext"))] let dev = std::os::unix::prelude::IntoRawFd::into_raw_fd( std::fs::OpenOptions::new() @@ -939,12 +979,14 @@ impl EventLoop { ) })?, ); + let drm = Card(std::sync::Arc::new(dev)); #[cfg(feature = "kms-ext")] let mut input = input::Libinput::new_with_udev(Interface(seat, HashMap::new())); #[cfg(not(feature = "kms-ext"))] let mut input = input::Libinput::new_with_udev(Interface); input.udev_assign_seat(seat_name).unwrap(); + let xkb_ctx = xkb::Context::new(xkb::CONTEXT_NO_FLAGS); let keymap = xkb::Keymap::new_from_names( &xkb_ctx, @@ -962,6 +1004,7 @@ impl EventLoop { crate::platform_impl::OsError::KmsMisc("failed to compile XKB keymap"), ) })?; + let state = xkb::State::new(&keymap); let compose_table = xkb::compose::Table::new_from_locale( &xkb_ctx, @@ -995,6 +1038,7 @@ impl EventLoop { )), ) })?; + drm::Device::set_client_capability(&drm, drm::ClientCapability::Atomic, true).map_err( |e| { crate::error::OsError::new( @@ -1019,16 +1063,19 @@ impl EventLoop { )), ) })?; + let coninfo: Vec = res .connectors() .iter() .flat_map(|con| drm.get_connector(*con)) .collect(); + let crtcinfo: Vec = res .crtcs() .iter() .flat_map(|crtc| drm.get_crtc(*crtc)) .collect(); + // Filter each connector until we find one that's connected. let con = coninfo .iter() @@ -1164,6 +1211,7 @@ impl EventLoop { is_synthetic: false, }, }); + if let Some(c) = event.1 { data.push(crate::event::Event::WindowEvent { window_id: crate::window::WindowId(crate::platform_impl::WindowId::Kms( @@ -1172,11 +1220,13 @@ impl EventLoop { event: crate::event::WindowEvent::ReceivedCharacter(c), }); } - metadata.add_timeout(Duration::from_millis(25), event); + + metadata.add_timeout(Duration::from_millis(REPEAT_RATE), event); }, ); let cursor_arc = Arc::new(Mutex::new(PhysicalPosition::new(0.0, 0.0))); + let input_backend: LibinputInputBackend = LibinputInputBackend::new( input, (disp_width.into(), disp_height.into()), // plane, fb diff --git a/src/platform_impl/linux/kms/window.rs b/src/platform_impl/linux/kms/window.rs index e99987a69c..00d9e1f6ca 100644 --- a/src/platform_impl/linux/kms/window.rs +++ b/src/platform_impl/linux/kms/window.rs @@ -41,6 +41,7 @@ impl Window { _platform_attributes: crate::platform_impl::PlatformSpecificWindowBuilderAttributes, ) -> Result { let mut atomic_req = atomic::AtomicModeReq::new(); + atomic_req.add_property( event_loop_window_target.connector.handle(), find_prop_id( @@ -57,6 +58,7 @@ impl Window { })?, property::Value::CRTC(Some(event_loop_window_target.crtc.handle())), ); + let blob = event_loop_window_target .device .create_property_blob(&event_loop_window_target.mode) @@ -67,6 +69,7 @@ impl Window { crate::platform_impl::OsError::KmsMisc("failed to create blob"), ) })?; + atomic_req.add_property( event_loop_window_target.crtc.handle(), find_prop_id( @@ -83,6 +86,7 @@ impl Window { })?, blob, ); + atomic_req.add_property( event_loop_window_target.crtc.handle(), find_prop_id( @@ -99,6 +103,7 @@ impl Window { })?, property::Value::Boolean(true), ); + atomic_req.add_property( event_loop_window_target.plane, find_prop_id( @@ -115,6 +120,7 @@ impl Window { })?, property::Value::CRTC(Some(event_loop_window_target.crtc.handle())), ); + atomic_req.add_property( event_loop_window_target.plane, find_prop_id( @@ -131,6 +137,7 @@ impl Window { })?, property::Value::UnsignedRange(0), ); + atomic_req.add_property( event_loop_window_target.plane, find_prop_id( @@ -147,6 +154,7 @@ impl Window { })?, property::Value::UnsignedRange(0), ); + atomic_req.add_property( event_loop_window_target.plane, find_prop_id( @@ -163,6 +171,7 @@ impl Window { })?, property::Value::UnsignedRange((event_loop_window_target.mode.size().0 as u64) << 16), ); + atomic_req.add_property( event_loop_window_target.plane, find_prop_id( @@ -179,6 +188,7 @@ impl Window { })?, property::Value::UnsignedRange((event_loop_window_target.mode.size().1 as u64) << 16), ); + atomic_req.add_property( event_loop_window_target.plane, find_prop_id( @@ -195,6 +205,7 @@ impl Window { })?, property::Value::SignedRange(0), ); + atomic_req.add_property( event_loop_window_target.plane, find_prop_id( @@ -211,6 +222,7 @@ impl Window { })?, property::Value::SignedRange(0), ); + atomic_req.add_property( event_loop_window_target.plane, find_prop_id( @@ -227,6 +239,7 @@ impl Window { })?, property::Value::UnsignedRange(event_loop_window_target.mode.size().0 as u64), ); + atomic_req.add_property( event_loop_window_target.plane, find_prop_id( From 5e5df64c33a2de40e070b09e9f235d13d538f7ac Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Mon, 9 May 2022 15:01:55 -0400 Subject: [PATCH 094/151] Fix building --- src/platform_impl/linux/kms/event_loop.rs | 70 ++++++++++++++++------- 1 file changed, 50 insertions(+), 20 deletions(-) diff --git a/src/platform_impl/linux/kms/event_loop.rs b/src/platform_impl/linux/kms/event_loop.rs index 110ec4c195..63c0a691eb 100644 --- a/src/platform_impl/linux/kms/event_loop.rs +++ b/src/platform_impl/linux/kms/event_loop.rs @@ -1,9 +1,6 @@ use parking_lot::Mutex; #[cfg(feature = "kms-ext")] -use std::{ - collections::HashMap, - sync::{atomic::AtomicBool, Arc}, -}; +use std::{collections::HashMap, sync::atomic::AtomicBool}; use std::{ collections::VecDeque, marker::PhantomData, @@ -898,7 +895,10 @@ pub struct EventLoop { impl EventLoop { pub fn new() -> Result, crate::error::OsError> { #[cfg(feature = "kms-ext")] + // When we create the seat here, we should probably wait for it to become active before we + // use it. let mut seat = { + // Allows us to know when the seat becomes active let active = Arc::new(AtomicBool::new(false)); let t_active = active.clone(); let mut s = libseat::Seat::open( @@ -920,6 +920,7 @@ impl EventLoop { ) })?; + // While our seat is not active dispatch it so that the seat will activate while !active.load(std::sync::atomic::Ordering::SeqCst) { s.dispatch(-1).map_err(|e| { crate::error::OsError::new( @@ -944,10 +945,14 @@ impl EventLoop { #[cfg(not(feature = "kms-ext"))] let seat_name = "seat0"; + // find_card_path uses `udev` to enumerate the cards that are currently available, and then + // choose the first (usually perferred) one let card_path = std::env::var("WINIT_DRM_CARD") .ok() .map_or_else(|| find_card_path(seat_name), |p| Ok(Into::into(p)))?; + #[cfg(feature = "kms-ext")] + // Opening the card using our seat allows us to do so unprivallaged let dev = seat .open_device(&card_path) .map_err(|e| { @@ -963,6 +968,8 @@ impl EventLoop { .1; #[cfg(not(feature = "kms-ext"))] + // Opening this card with no seat present means that we must have root + // (or be part of the `video` user group) let dev = std::os::unix::prelude::IntoRawFd::into_raw_fd( std::fs::OpenOptions::new() .read(true) @@ -979,15 +986,22 @@ impl EventLoop { ) })?, ); - let drm = Card(std::sync::Arc::new(dev)); + #[cfg(feature = "kms-ext")] + // Using our seat to open our input manager allows us to do so unprivallaged let mut input = input::Libinput::new_with_udev(Interface(seat, HashMap::new())); #[cfg(not(feature = "kms-ext"))] + // Opening our input manager with no seat means we must do so as root + // (or be part of the `input` user group) let mut input = input::Libinput::new_with_udev(Interface); + input.udev_assign_seat(seat_name).unwrap(); + // XKB allows us to keep track of the state of the keyboard and produce keyboard events + // very similarly to how a Wayland Compositor would. let xkb_ctx = xkb::Context::new(xkb::CONTEXT_NO_FLAGS); + // Empty strings translates to "default" for XKB (in this context) let keymap = xkb::Keymap::new_from_names( &xkb_ctx, "", @@ -1006,8 +1020,17 @@ impl EventLoop { })?; let state = xkb::State::new(&keymap); + + // It's not a strict requirement that we use a compose table, but it's ***sooo*** useful + // when using an english keyboard to write in other languages. Or even just speacial + // charecters + // + // For example, to type è, you would use + + + // Or to type •, you would use + <.> + <=> let compose_table = xkb::compose::Table::new_from_locale( &xkb_ctx, + // These env variables in Linux are the most likely to contain your locale, + // "en_US.UTF-8" for example std::env::var_os("LC_ALL") .unwrap_or_else(|| { std::env::var_os("LC_CTYPE").unwrap_or_else(|| { @@ -1027,18 +1050,7 @@ impl EventLoop { })?; let xkb_compose = xkb::compose::State::new(&compose_table, xkb::compose::STATE_NO_FLAGS); - drm::Device::set_client_capability(&drm, drm::ClientCapability::UniversalPlanes, true) - .map_err(|e| { - crate::error::OsError::new( - line!(), - file!(), - crate::platform_impl::OsError::KmsError(format!( - "drm device does not support universal planes :{}", - e - )), - ) - })?; - + // Allows use to use the non-legacy atomic system drm::Device::set_client_capability(&drm, drm::ClientCapability::Atomic, true).map_err( |e| { crate::error::OsError::new( @@ -1064,12 +1076,14 @@ impl EventLoop { ) })?; + // Enumerate available connectors let coninfo: Vec = res .connectors() .iter() .flat_map(|con| drm.get_connector(*con)) .collect(); + // Enumerate available CRTCs let crtcinfo: Vec = res .crtcs() .iter() @@ -1088,6 +1102,7 @@ impl EventLoop { ) })?; + // Get the first (usually perferred) CRTC let crtc = crtcinfo.get(0).ok_or_else(|| { crate::error::OsError::new( line!(), @@ -1096,7 +1111,7 @@ impl EventLoop { ) })?; - // Get the first (usually best) mode + // Get the perferred (or first) mode let &mode = con .modes() .iter() @@ -1110,6 +1125,7 @@ impl EventLoop { ) })?; + // Enumerate available planes let planes = drm.plane_handles().map_err(|e| { crate::error::OsError::new( line!(), @@ -1119,24 +1135,31 @@ impl EventLoop { })?; let (p_better_planes, p_compatible_planes): ( + // The primary planes available to us Vec, + // Other, not-ideal planes that are however useable Vec, ) = planes .planes() .iter() .filter(|&&plane| { + // Get the plane info from a handle drm.get_plane(plane) .map(|plane_info| { let compatible_crtcs = res.filter_crtcs(plane_info.possible_crtcs()); + // Makes sure that the plane can be used with the CRTC we selected earlier compatible_crtcs.contains(&crtc.handle()) }) .unwrap_or(false) }) .partition(|&&plane| { + // Get the plane properties from a handle if let Ok(props) = drm.get_properties(plane) { let (ids, vals) = props.as_props_and_values(); for (&id, &val) in ids.iter().zip(vals.iter()) { if let Ok(info) = drm.get_property(id) { + // Checks if the plane is a primary plane, and returns true if it is, + // if not it returns false if info.name().to_str().map(|x| x == "type").unwrap_or(false) { return val == (drm::control::PlaneType::Primary as u32).into(); } @@ -1146,6 +1169,7 @@ impl EventLoop { false }); + // Get the first (best) plane we find, or the first compatibile plane let p_plane = *p_better_planes.get(0).unwrap_or(&p_compatible_planes[0]); let (disp_width, disp_height) = mode.size(); @@ -1169,12 +1193,12 @@ impl EventLoop { }) .unwrap(); - // An event's loop awakener to wake up for window events from winit's windows. + // An event's loop awakener to wake up for redraw events from winit's windows. let (event_loop_awakener, event_loop_awakener_source) = calloop::ping::make_ping().unwrap(); let event_sink = EventSink::new(); - // Handler of window requests. + // Handler of redraw requests. handle .insert_source( event_loop_awakener_source, @@ -1188,6 +1212,8 @@ impl EventLoop { ) .unwrap(); + // This is used so that when you hold down a key, the same `KeyboardInput` event will be + // repeated until the key is released or another key is pressed down let repeat_handler = calloop::timer::Timer::new().unwrap(); let repeat_handle = repeat_handler.handle(); @@ -1221,12 +1247,15 @@ impl EventLoop { }); } + // Repeat the key with the same key event as was input from the LibinputInterface metadata.add_timeout(Duration::from_millis(REPEAT_RATE), event); }, ); + // It is an Arc> so that windows can change the cursor position let cursor_arc = Arc::new(Mutex::new(PhysicalPosition::new(0.0, 0.0))); + // Our input handler let input_backend: LibinputInputBackend = LibinputInputBackend::new( input, (disp_width.into(), disp_height.into()), // plane, fb @@ -1237,6 +1266,7 @@ impl EventLoop { cursor_arc.clone(), ); + // When an input is received, add it to our EventSink let input_loop: calloop::Dispatcher<'static, LibinputInputBackend, EventSink> = calloop::Dispatcher::new( input_backend, From 756a1a0f9fc5b38016c5781713fed0027ccd3630 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Mon, 9 May 2022 16:29:33 -0400 Subject: [PATCH 095/151] Remove full paths --- src/platform_impl/linux/kms/event_loop.rs | 754 ++++++++++------------ src/platform_impl/linux/kms/mod.rs | 22 +- src/platform_impl/linux/kms/window.rs | 80 +-- 3 files changed, 406 insertions(+), 450 deletions(-) diff --git a/src/platform_impl/linux/kms/event_loop.rs b/src/platform_impl/linux/kms/event_loop.rs index 63c0a691eb..8a6ef6c95d 100644 --- a/src/platform_impl/linux/kms/event_loop.rs +++ b/src/platform_impl/linux/kms/event_loop.rs @@ -1,19 +1,21 @@ use parking_lot::Mutex; -#[cfg(feature = "kms-ext")] -use std::{collections::HashMap, sync::atomic::AtomicBool}; use std::{ + cell::RefCell, collections::VecDeque, marker::PhantomData, os::unix::prelude::{AsRawFd, FromRawFd, RawFd}, path::{Path, PathBuf}, + rc::Rc, sync::{mpsc::SendError, Arc}, time::{Duration, Instant}, }; +#[cfg(feature = "kms-ext")] +use std::{collections::HashMap, sync::atomic::AtomicBool}; use udev::Enumerator; use xkbcommon::xkb; use calloop::{EventSource, Interest, Mode, Poll, PostAction, Readiness, Token, TokenFactory}; -use drm::control::{Device, ModeTypeFlags}; +use drm::control::*; use input::{ event::{ keyboard::KeyboardEventTrait, @@ -28,10 +30,15 @@ use input::{ use crate::{ dpi::PhysicalPosition, error::OsError, - event::{ElementState, Force, KeyboardInput, ModifiersState, MouseScrollDelta, StartCause}, - event_loop::{ControlFlow, EventLoopClosed}, + event::{ + DeviceEvent, DeviceId, ElementState, Event, Force, KeyboardInput, ModifiersState, + MouseButton, MouseScrollDelta, StartCause, Touch, TouchPhase, WindowEvent, + }, + event_loop::{self, ControlFlow, EventLoopClosed}, + monitor::MonitorHandle, platform::unix::Card, - platform_impl::{platform::sticky_exit_callback, xkb_keymap}, + platform_impl::{self, platform::sticky_exit_callback, xkb_keymap}, + window::WindowId, }; const REPEAT_RATE: u64 = 25; @@ -98,7 +105,7 @@ pub struct LibinputInputBackend { impl LibinputInputBackend { /// Initialize a new [`LibinputInputBackend`] from a given already initialized - /// [libinput context](libinput::Libinput). + /// [libinput context](input::Libinput). pub fn new( context: input::Libinput, screen_size: (u32, u32), @@ -130,7 +137,7 @@ impl AsRawFd for LibinputInputBackend { } impl EventSource for LibinputInputBackend { - type Event = crate::event::Event<'static, ()>; + type Event = Event<'static, ()>; type Metadata = (); type Ret = (); @@ -151,22 +158,22 @@ impl EventSource for LibinputInputBackend { input::Event::Device(ev) => match ev { input::event::DeviceEvent::Added(_) => { callback( - crate::event::Event::DeviceEvent { - device_id: crate::event::DeviceId( - crate::platform_impl::DeviceId::Kms(super::DeviceId), - ), - event: crate::event::DeviceEvent::Added, + Event::DeviceEvent { + device_id: DeviceId(platform_impl::DeviceId::Kms( + super::DeviceId, + )), + event: DeviceEvent::Added, }, &mut (), ); } input::event::DeviceEvent::Removed(_) => { callback( - crate::event::Event::DeviceEvent { - device_id: crate::event::DeviceId( - crate::platform_impl::DeviceId::Kms(super::DeviceId), - ), - event: crate::event::DeviceEvent::Removed, + Event::DeviceEvent { + device_id: DeviceId(platform_impl::DeviceId::Kms( + super::DeviceId, + )), + event: DeviceEvent::Removed, }, &mut (), ); @@ -175,15 +182,13 @@ impl EventSource for LibinputInputBackend { }, input::Event::Touch(ev) => match ev { input::event::TouchEvent::Up(e) => callback( - crate::event::Event::WindowEvent { - window_id: crate::window::WindowId( - crate::platform_impl::WindowId::Kms(super::WindowId), - ), - event: crate::event::WindowEvent::Touch(crate::event::Touch { - device_id: crate::event::DeviceId( - crate::platform_impl::DeviceId::Kms(super::DeviceId), - ), - phase: crate::event::TouchPhase::Ended, + Event::WindowEvent { + window_id: WindowId(platform_impl::WindowId::Kms(super::WindowId)), + event: WindowEvent::Touch(Touch { + device_id: DeviceId(platform_impl::DeviceId::Kms( + super::DeviceId, + )), + phase: TouchPhase::Ended, location: self.touch_location, force: None, id: e.slot().unwrap() as u64, @@ -196,15 +201,15 @@ impl EventSource for LibinputInputBackend { self.touch_location.y = e.y_transformed(self.screen_size.1); callback( - crate::event::Event::WindowEvent { - window_id: crate::window::WindowId( - crate::platform_impl::WindowId::Kms(super::WindowId), - ), - event: crate::event::WindowEvent::Touch(crate::event::Touch { - device_id: crate::event::DeviceId( - crate::platform_impl::DeviceId::Kms(super::DeviceId), - ), - phase: crate::event::TouchPhase::Started, + Event::WindowEvent { + window_id: WindowId(platform_impl::WindowId::Kms( + super::WindowId, + )), + event: WindowEvent::Touch(Touch { + device_id: DeviceId(platform_impl::DeviceId::Kms( + super::DeviceId, + )), + phase: TouchPhase::Started, location: self.touch_location, force: None, id: e.slot().unwrap() as u64, @@ -218,15 +223,15 @@ impl EventSource for LibinputInputBackend { self.touch_location.y = e.y_transformed(self.screen_size.1); callback( - crate::event::Event::WindowEvent { - window_id: crate::window::WindowId( - crate::platform_impl::WindowId::Kms(super::WindowId), - ), - event: crate::event::WindowEvent::Touch(crate::event::Touch { - device_id: crate::event::DeviceId( - crate::platform_impl::DeviceId::Kms(super::DeviceId), - ), - phase: crate::event::TouchPhase::Moved, + Event::WindowEvent { + window_id: WindowId(platform_impl::WindowId::Kms( + super::WindowId, + )), + event: WindowEvent::Touch(Touch { + device_id: DeviceId(platform_impl::DeviceId::Kms( + super::DeviceId, + )), + phase: TouchPhase::Moved, location: self.touch_location, force: None, id: e.slot().unwrap() as u64, @@ -236,15 +241,13 @@ impl EventSource for LibinputInputBackend { ); } input::event::TouchEvent::Cancel(e) => callback( - crate::event::Event::WindowEvent { - window_id: crate::window::WindowId( - crate::platform_impl::WindowId::Kms(super::WindowId), - ), - event: crate::event::WindowEvent::Touch(crate::event::Touch { - device_id: crate::event::DeviceId( - crate::platform_impl::DeviceId::Kms(super::DeviceId), - ), - phase: crate::event::TouchPhase::Cancelled, + Event::WindowEvent { + window_id: WindowId(platform_impl::WindowId::Kms(super::WindowId)), + event: WindowEvent::Touch(Touch { + device_id: DeviceId(platform_impl::DeviceId::Kms( + super::DeviceId, + )), + phase: TouchPhase::Cancelled, location: self.touch_location, force: None, id: e.slot().unwrap() as u64, @@ -253,15 +256,13 @@ impl EventSource for LibinputInputBackend { &mut (), ), input::event::TouchEvent::Frame(_) => callback( - crate::event::Event::WindowEvent { - window_id: crate::window::WindowId( - crate::platform_impl::WindowId::Kms(super::WindowId), - ), - event: crate::event::WindowEvent::Touch(crate::event::Touch { - device_id: crate::event::DeviceId( - crate::platform_impl::DeviceId::Kms(super::DeviceId), - ), - phase: crate::event::TouchPhase::Ended, + Event::WindowEvent { + window_id: WindowId(platform_impl::WindowId::Kms(super::WindowId)), + event: WindowEvent::Touch(Touch { + device_id: DeviceId(platform_impl::DeviceId::Kms( + super::DeviceId, + )), + phase: TouchPhase::Ended, location: self.touch_location, force: None, id: 0, // e.slot().unwrap() as u64, @@ -273,17 +274,15 @@ impl EventSource for LibinputInputBackend { }, input::Event::Tablet(ev) => match ev { input::event::TabletToolEvent::Tip(e) => callback( - crate::event::Event::WindowEvent { - window_id: crate::window::WindowId( - crate::platform_impl::WindowId::Kms(super::WindowId), - ), - event: crate::event::WindowEvent::Touch(crate::event::Touch { - device_id: crate::event::DeviceId( - crate::platform_impl::DeviceId::Kms(super::DeviceId), - ), + Event::WindowEvent { + window_id: WindowId(platform_impl::WindowId::Kms(super::WindowId)), + event: WindowEvent::Touch(Touch { + device_id: DeviceId(platform_impl::DeviceId::Kms( + super::DeviceId, + )), phase: match e.tip_state() { - TipState::Down => crate::event::TouchPhase::Started, - TipState::Up => crate::event::TouchPhase::Ended, + TipState::Down => TouchPhase::Started, + TipState::Up => TouchPhase::Ended, }, location: PhysicalPosition::new( e.x_transformed(self.screen_size.0), @@ -301,26 +300,22 @@ impl EventSource for LibinputInputBackend { ), input::event::TabletToolEvent::Button(e) => { callback( - crate::event::Event::WindowEvent { - window_id: crate::window::WindowId( - crate::platform_impl::WindowId::Kms(super::WindowId), - ), - event: crate::event::WindowEvent::MouseInput { - device_id: crate::event::DeviceId( - crate::platform_impl::DeviceId::Kms(super::DeviceId), - ), + Event::WindowEvent { + window_id: WindowId(platform_impl::WindowId::Kms( + super::WindowId, + )), + event: WindowEvent::MouseInput { + device_id: DeviceId(platform_impl::DeviceId::Kms( + super::DeviceId, + )), state: match e.button_state() { - ButtonState::Pressed => { - crate::event::ElementState::Pressed - } - ButtonState::Released => { - crate::event::ElementState::Released - } + ButtonState::Pressed => ElementState::Pressed, + ButtonState::Released => ElementState::Released, }, button: match e.button() { - 1 => crate::event::MouseButton::Right, - 2 => crate::event::MouseButton::Middle, - _ => crate::event::MouseButton::Left, + 1 => MouseButton::Right, + 2 => MouseButton::Middle, + _ => MouseButton::Left, }, modifiers: self.modifiers, }, @@ -329,19 +324,15 @@ impl EventSource for LibinputInputBackend { ); callback( - crate::event::Event::DeviceEvent { - device_id: crate::event::DeviceId( - crate::platform_impl::DeviceId::Kms(super::DeviceId), - ), - event: crate::event::DeviceEvent::Button { + Event::DeviceEvent { + device_id: DeviceId(platform_impl::DeviceId::Kms( + super::DeviceId, + )), + event: DeviceEvent::Button { button: e.button(), state: match e.button_state() { - ButtonState::Pressed => { - crate::event::ElementState::Pressed - } - ButtonState::Released => { - crate::event::ElementState::Released - } + ButtonState::Pressed => ElementState::Pressed, + ButtonState::Released => ElementState::Released, }, }, }, @@ -361,14 +352,14 @@ impl EventSource for LibinputInputBackend { lock.y = lock.y.clamp(0.0, self.screen_size.1 as f64); callback( - crate::event::Event::WindowEvent { - window_id: crate::window::WindowId( - crate::platform_impl::WindowId::Kms(super::WindowId), - ), - event: crate::event::WindowEvent::CursorMoved { - device_id: crate::event::DeviceId( - crate::platform_impl::DeviceId::Kms(super::DeviceId), - ), + Event::WindowEvent { + window_id: WindowId(platform_impl::WindowId::Kms( + super::WindowId, + )), + event: WindowEvent::CursorMoved { + device_id: DeviceId(platform_impl::DeviceId::Kms( + super::DeviceId, + )), position: *lock, modifiers: self.modifiers, }, @@ -377,11 +368,11 @@ impl EventSource for LibinputInputBackend { ); callback( - crate::event::Event::DeviceEvent { - device_id: crate::event::DeviceId( - crate::platform_impl::DeviceId::Kms(super::DeviceId), - ), - event: crate::event::DeviceEvent::MouseMotion { + Event::DeviceEvent { + device_id: DeviceId(platform_impl::DeviceId::Kms( + super::DeviceId, + )), + event: DeviceEvent::MouseMotion { delta: (e.dx(), e.dy()), }, }, @@ -390,26 +381,22 @@ impl EventSource for LibinputInputBackend { } input::event::PointerEvent::Button(e) => { callback( - crate::event::Event::WindowEvent { - window_id: crate::window::WindowId( - crate::platform_impl::WindowId::Kms(super::WindowId), - ), - event: crate::event::WindowEvent::MouseInput { - device_id: crate::event::DeviceId( - crate::platform_impl::DeviceId::Kms(super::DeviceId), - ), + Event::WindowEvent { + window_id: WindowId(platform_impl::WindowId::Kms( + super::WindowId, + )), + event: WindowEvent::MouseInput { + device_id: DeviceId(platform_impl::DeviceId::Kms( + super::DeviceId, + )), state: match e.button_state() { - ButtonState::Pressed => { - crate::event::ElementState::Pressed - } - ButtonState::Released => { - crate::event::ElementState::Released - } + ButtonState::Pressed => ElementState::Pressed, + ButtonState::Released => ElementState::Released, }, button: match e.button() { - 1 => crate::event::MouseButton::Right, - 2 => crate::event::MouseButton::Middle, - _ => crate::event::MouseButton::Left, + 1 => MouseButton::Right, + 2 => MouseButton::Middle, + _ => MouseButton::Left, }, modifiers: self.modifiers, }, @@ -418,19 +405,15 @@ impl EventSource for LibinputInputBackend { ); callback( - crate::event::Event::DeviceEvent { - device_id: crate::event::DeviceId( - crate::platform_impl::DeviceId::Kms(super::DeviceId), - ), - event: crate::event::DeviceEvent::Button { + Event::DeviceEvent { + device_id: DeviceId(platform_impl::DeviceId::Kms( + super::DeviceId, + )), + event: DeviceEvent::Button { button: e.button(), state: match e.button_state() { - ButtonState::Pressed => { - crate::event::ElementState::Pressed - } - ButtonState::Released => { - crate::event::ElementState::Released - } + ButtonState::Pressed => ElementState::Pressed, + ButtonState::Released => ElementState::Released, }, }, }, @@ -438,34 +421,30 @@ impl EventSource for LibinputInputBackend { ); } input::event::PointerEvent::ScrollWheel(e) => { + use input::event::pointer::Axis; + callback( - crate::event::Event::WindowEvent { - window_id: crate::window::WindowId( - crate::platform_impl::WindowId::Kms(super::WindowId), - ), - event: crate::event::WindowEvent::MouseWheel { - device_id: crate::event::DeviceId( - crate::platform_impl::DeviceId::Kms(super::DeviceId), - ), + Event::WindowEvent { + window_id: WindowId(platform_impl::WindowId::Kms( + super::WindowId, + )), + event: WindowEvent::MouseWheel { + device_id: DeviceId(platform_impl::DeviceId::Kms( + super::DeviceId, + )), delta: MouseScrollDelta::LineDelta( - if e.has_axis(input::event::pointer::Axis::Horizontal) { - e.scroll_value( - input::event::pointer::Axis::Horizontal, - ) - as f32 + if e.has_axis(Axis::Horizontal) { + e.scroll_value(Axis::Horizontal) as f32 } else { 0.0 }, - if e.has_axis(input::event::pointer::Axis::Vertical) { - e.scroll_value( - input::event::pointer::Axis::Vertical, - ) - as f32 + if e.has_axis(Axis::Vertical) { + e.scroll_value(Axis::Vertical) as f32 } else { 0.0 }, ), - phase: crate::event::TouchPhase::Moved, + phase: TouchPhase::Moved, modifiers: self.modifiers, }, }, @@ -473,32 +452,30 @@ impl EventSource for LibinputInputBackend { ); } input::event::PointerEvent::ScrollFinger(e) => { + use input::event::pointer::Axis; + callback( - crate::event::Event::WindowEvent { - window_id: crate::window::WindowId( - crate::platform_impl::WindowId::Kms(super::WindowId), - ), - event: crate::event::WindowEvent::MouseWheel { - device_id: crate::event::DeviceId( - crate::platform_impl::DeviceId::Kms(super::DeviceId), - ), + Event::WindowEvent { + window_id: WindowId(platform_impl::WindowId::Kms( + super::WindowId, + )), + event: WindowEvent::MouseWheel { + device_id: DeviceId(platform_impl::DeviceId::Kms( + super::DeviceId, + )), delta: MouseScrollDelta::PixelDelta(PhysicalPosition::new( - if e.has_axis(input::event::pointer::Axis::Horizontal) { - e.scroll_value( - input::event::pointer::Axis::Horizontal, - ) + if e.has_axis(Axis::Horizontal) { + e.scroll_value(Axis::Horizontal) } else { 0.0 }, - if e.has_axis(input::event::pointer::Axis::Vertical) { - e.scroll_value( - input::event::pointer::Axis::Vertical, - ) + if e.has_axis(Axis::Vertical) { + e.scroll_value(Axis::Vertical) } else { 0.0 }, )), - phase: crate::event::TouchPhase::Moved, + phase: TouchPhase::Moved, modifiers: self.modifiers, }, }, @@ -513,14 +490,14 @@ impl EventSource for LibinputInputBackend { lock.y = e.absolute_y_transformed(self.screen_size.1); callback( - crate::event::Event::WindowEvent { - window_id: crate::window::WindowId( - crate::platform_impl::WindowId::Kms(super::WindowId), - ), - event: crate::event::WindowEvent::CursorMoved { - device_id: crate::event::DeviceId( - crate::platform_impl::DeviceId::Kms(super::DeviceId), - ), + Event::WindowEvent { + window_id: WindowId(platform_impl::WindowId::Kms( + super::WindowId, + )), + event: WindowEvent::CursorMoved { + device_id: DeviceId(platform_impl::DeviceId::Kms( + super::DeviceId, + )), position: *lock, modifiers: self.modifiers, }, @@ -532,8 +509,8 @@ impl EventSource for LibinputInputBackend { }, input::Event::Keyboard(ev) => { let state = match ev.key_state() { - KeyState::Pressed => crate::event::ElementState::Pressed, - KeyState::Released => crate::event::ElementState::Released, + KeyState::Pressed => ElementState::Pressed, + KeyState::Released => ElementState::Released, }; let k = if let input::event::KeyboardEvent::Key(key) = ev { @@ -564,14 +541,12 @@ impl EventSource for LibinputInputBackend { self.timer_handle.cancel_all_timeouts(); callback( - crate::event::Event::WindowEvent { - window_id: crate::window::WindowId( - crate::platform_impl::WindowId::Kms(super::WindowId), - ), - event: crate::event::WindowEvent::KeyboardInput { - device_id: crate::event::DeviceId( - crate::platform_impl::DeviceId::Kms(super::DeviceId), - ), + Event::WindowEvent { + window_id: WindowId(platform_impl::WindowId::Kms(super::WindowId)), + event: WindowEvent::KeyboardInput { + device_id: DeviceId(platform_impl::DeviceId::Kms( + super::DeviceId, + )), input, is_synthetic: false, }, @@ -579,7 +554,7 @@ impl EventSource for LibinputInputBackend { &mut (), ); - if let crate::event::ElementState::Pressed = state { + if let ElementState::Pressed = state { self.xkb_compose.feed(keysym); match self.xkb_compose.status() { @@ -588,15 +563,11 @@ impl EventSource for LibinputInputBackend { self.xkb_compose.utf8().and_then(|f| f.chars().next()) { callback( - crate::event::Event::WindowEvent { - window_id: crate::window::WindowId( - crate::platform_impl::WindowId::Kms( - super::WindowId, - ), - ), - event: crate::event::WindowEvent::ReceivedCharacter( - c, - ), + Event::WindowEvent { + window_id: WindowId(platform_impl::WindowId::Kms( + super::WindowId, + )), + event: WindowEvent::ReceivedCharacter(c), }, &mut (), ); @@ -615,15 +586,11 @@ impl EventSource for LibinputInputBackend { if let Some(c) = ch { callback( - crate::event::Event::WindowEvent { - window_id: crate::window::WindowId( - crate::platform_impl::WindowId::Kms( - super::WindowId, - ), - ), - event: crate::event::WindowEvent::ReceivedCharacter( - c, - ), + Event::WindowEvent { + window_id: WindowId(platform_impl::WindowId::Kms( + super::WindowId, + )), + event: WindowEvent::ReceivedCharacter(c), }, &mut (), ); @@ -640,15 +607,11 @@ impl EventSource for LibinputInputBackend { if let Some(c) = ch { callback( - crate::event::Event::WindowEvent { - window_id: crate::window::WindowId( - crate::platform_impl::WindowId::Kms( - super::WindowId, - ), - ), - event: crate::event::WindowEvent::ReceivedCharacter( - c, - ), + Event::WindowEvent { + window_id: WindowId(platform_impl::WindowId::Kms( + super::WindowId, + )), + event: WindowEvent::ReceivedCharacter(c), }, &mut (), ); @@ -658,67 +621,97 @@ impl EventSource for LibinputInputBackend { } } match keysym { - xkb_keymap::XKB_KEY_Alt_L - | xkb_keymap::XKB_KEY_Alt_R - => { - match state { - ElementState::Pressed => self.modifiers |= ModifiersState::ALT, - ElementState::Released => self.modifiers.remove(ModifiersState::ALT) - } - - callback(crate::event::Event::WindowEvent { - window_id: crate::window::WindowId(crate::platform_impl::WindowId::Kms(super::WindowId)), - event:crate::event::WindowEvent::ModifiersChanged(self.modifiers)}, &mut ()); - } - | xkb_keymap::XKB_KEY_Shift_L // LShift - | xkb_keymap::XKB_KEY_Shift_R // RShift - => { - match state { - ElementState::Pressed => self.modifiers |= ModifiersState::SHIFT, - ElementState::Released => self.modifiers.remove(ModifiersState::SHIFT) - } - - callback(crate::event::Event::WindowEvent { - window_id: crate::window::WindowId(crate::platform_impl::WindowId::Kms(super::WindowId)), - event:crate::event::WindowEvent::ModifiersChanged(self.modifiers)}, &mut ()); + xkb_keymap::XKB_KEY_Alt_L | xkb_keymap::XKB_KEY_Alt_R => { + match state { + ElementState::Pressed => self.modifiers |= ModifiersState::ALT, + ElementState::Released => { + self.modifiers.remove(ModifiersState::ALT) } + } - | xkb_keymap::XKB_KEY_Control_L // LCtrl - | xkb_keymap::XKB_KEY_Control_R // RCtrl - => { - match state { - ElementState::Pressed => self.modifiers |= ModifiersState::CTRL, - ElementState::Released => self.modifiers.remove(ModifiersState::CTRL) - } - - callback(crate::event::Event::WindowEvent { - window_id: crate::window::WindowId(crate::platform_impl::WindowId::Kms(super::WindowId)), - event:crate::event::WindowEvent::ModifiersChanged(self.modifiers)}, &mut ()); + callback( + Event::WindowEvent { + window_id: WindowId(platform_impl::WindowId::Kms( + super::WindowId, + )), + event: WindowEvent::ModifiersChanged(self.modifiers), + }, + &mut (), + ); + } + xkb_keymap::XKB_KEY_Shift_L | xkb_keymap::XKB_KEY_Shift_R => { + match state { + ElementState::Pressed => { + self.modifiers |= ModifiersState::SHIFT + } + ElementState::Released => { + self.modifiers.remove(ModifiersState::SHIFT) } + } + + callback( + Event::WindowEvent { + window_id: WindowId(platform_impl::WindowId::Kms( + super::WindowId, + )), + event: WindowEvent::ModifiersChanged(self.modifiers), + }, + &mut (), + ); + } - | xkb_keymap::XKB_KEY_Meta_L // LMeta - | xkb_keymap::XKB_KEY_Meta_R // RMeta - => { - match state { - ElementState::Pressed => self.modifiers |= ModifiersState::LOGO, - ElementState::Released => self.modifiers.remove(ModifiersState::LOGO) - } - - callback(crate::event::Event::WindowEvent { - window_id: crate::window::WindowId(crate::platform_impl::WindowId::Kms(super::WindowId)), - event: crate::event::WindowEvent::ModifiersChanged(self.modifiers)}, &mut ()); + xkb_keymap::XKB_KEY_Control_L | xkb_keymap::XKB_KEY_Control_R => { + match state { + ElementState::Pressed => self.modifiers |= ModifiersState::CTRL, + ElementState::Released => { + self.modifiers.remove(ModifiersState::CTRL) } - xkb_keymap::XKB_KEY_Sys_Req | xkb_keymap::XKB_KEY_Print - => { - if self.modifiers.is_empty() { - callback(crate::event::Event::WindowEvent { - window_id: crate::window::WindowId(crate::platform_impl::WindowId::Kms(super::WindowId)), - event: crate::event::WindowEvent::CloseRequested - }, &mut ()); - } + } + + callback( + Event::WindowEvent { + window_id: WindowId(platform_impl::WindowId::Kms( + super::WindowId, + )), + event: WindowEvent::ModifiersChanged(self.modifiers), + }, + &mut (), + ); + } + + xkb_keymap::XKB_KEY_Meta_L | xkb_keymap::XKB_KEY_Meta_R => { + match state { + ElementState::Pressed => self.modifiers |= ModifiersState::LOGO, + ElementState::Released => { + self.modifiers.remove(ModifiersState::LOGO) } - _ => {} + } + + callback( + Event::WindowEvent { + window_id: WindowId(platform_impl::WindowId::Kms( + super::WindowId, + )), + event: WindowEvent::ModifiersChanged(self.modifiers), + }, + &mut (), + ); } + xkb_keymap::XKB_KEY_Sys_Req | xkb_keymap::XKB_KEY_Print => { + if self.modifiers.is_empty() { + callback( + Event::WindowEvent { + window_id: WindowId(platform_impl::WindowId::Kms( + super::WindowId, + )), + event: WindowEvent::CloseRequested, + }, + &mut (), + ); + } + } + _ => {} + } } _ => {} } @@ -745,20 +738,20 @@ impl EventSource for LibinputInputBackend { /// An event loop's sink to deliver events from the Wayland event callbacks /// to the winit's user. -type EventSink = Vec>; +type EventSink = Vec>; pub struct EventLoopWindowTarget { /// Drm Connector - pub connector: drm::control::connector::Info, + pub connector: connector::Info, /// Drm crtc - pub crtc: drm::control::crtc::Info, + pub crtc: crtc::Info, /// Drm mode pub mode: drm::control::Mode, /// Drm plane - pub plane: drm::control::plane::Handle, + pub plane: plane::Handle, /// Allows window to edit cursor position pub(crate) cursor_arc: Arc>>, @@ -779,11 +772,9 @@ pub struct EventLoopWindowTarget { impl EventLoopWindowTarget { #[inline] - pub fn primary_monitor(&self) -> Option { - Some(crate::monitor::MonitorHandle { - inner: crate::platform_impl::MonitorHandle::Kms(super::MonitorHandle( - self.connector.clone(), - )), + pub fn primary_monitor(&self) -> Option { + Some(MonitorHandle { + inner: platform_impl::MonitorHandle::Kms(super::MonitorHandle(self.connector.clone())), }) } @@ -801,42 +792,36 @@ impl EventLoopWindowTarget { fn find_card_path(seat_name: &str) -> Result { let mut enumerator = Enumerator::new().map_err(|e| { - crate::error::OsError::new( + OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsError(format!( - "failed to open udev enumerator: {}", - e - )), + platform_impl::OsError::KmsError(format!("failed to open udev enumerator: {}", e)), ) })?; enumerator.match_subsystem("drm").map_err(|e| { - crate::error::OsError::new( + OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsError(format!( - "failed to enumerate drm subsystem: {}", - e - )), + platform_impl::OsError::KmsError(format!("failed to enumerate drm subsystem: {}", e)), ) })?; enumerator.match_sysname("card[0-9]*").map_err(|e| { - crate::error::OsError::new( + OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsError(format!("failed to find a valid card: {}", e)), + platform_impl::OsError::KmsError(format!("failed to find a valid card: {}", e)), ) })?; enumerator .scan_devices() .map_err(|e| { - crate::error::OsError::new( + OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsError(format!("failed to scan devices: {}", e)), + platform_impl::OsError::KmsError(format!("failed to scan devices: {}", e)), ) })? .filter(|device| { @@ -870,10 +855,10 @@ fn find_card_path(seat_name: &str) -> Result { .next() }) .ok_or_else(|| { - crate::error::OsError::new( + OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("failed to find suitable GPU"), + platform_impl::OsError::KmsMisc("failed to find suitable GPU"), ) }) } @@ -883,53 +868,48 @@ pub struct EventLoop { event_loop: calloop::EventLoop<'static, EventSink>, /// Pending user events. - pending_user_events: std::rc::Rc>>, + pending_user_events: Rc>>, /// Sender of user events. user_events_sender: calloop::channel::Sender, /// Window target. - window_target: crate::event_loop::EventLoopWindowTarget, + window_target: event_loop::EventLoopWindowTarget, } impl EventLoop { - pub fn new() -> Result, crate::error::OsError> { + pub fn new() -> Result, OsError> { #[cfg(feature = "kms-ext")] // When we create the seat here, we should probably wait for it to become active before we // use it. let mut seat = { + use std::sync::atomic::Ordering; // Allows us to know when the seat becomes active let active = Arc::new(AtomicBool::new(false)); let t_active = active.clone(); let mut s = libseat::Seat::open( move |_, event| { if let libseat::SeatEvent::Enable = event { - t_active.store(true, std::sync::atomic::Ordering::SeqCst); + t_active.store(true, Ordering::SeqCst); } }, None, ) .map_err(|e| { - crate::error::OsError::new( + OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsError(format!( - "failed to open libseat: {}", - e - )), + platform_impl::OsError::KmsError(format!("failed to open libseat: {}", e)), ) })?; // While our seat is not active dispatch it so that the seat will activate - while !active.load(std::sync::atomic::Ordering::SeqCst) { + while !active.load(Ordering::SeqCst) { s.dispatch(-1).map_err(|e| { - crate::error::OsError::new( + OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsError(format!( - "failed to dispatch seat: {}", - e - )), + platform_impl::OsError::KmsError(format!("failed to dispatch seat: {}", e)), ) })?; } @@ -956,13 +936,10 @@ impl EventLoop { let dev = seat .open_device(&card_path) .map_err(|e| { - crate::error::OsError::new( + OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsError(format!( - "failed to initialize DRM: {}", - e - )), + platform_impl::OsError::KmsError(format!("failed to initialize DRM: {}", e)), ) })? .1; @@ -976,10 +953,10 @@ impl EventLoop { .write(true) .open(&card_path) .map_err(|e| { - crate::error::OsError::new( + OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsError(format!( + platform_impl::OsError::KmsError(format!( "failed to initialize DRM: {}", e )), @@ -1012,10 +989,10 @@ impl EventLoop { xkb::KEYMAP_COMPILE_NO_FLAGS, ) .ok_or_else(|| { - crate::error::OsError::new( + OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("failed to compile XKB keymap"), + platform_impl::OsError::KmsMisc("failed to compile XKB keymap"), ) })?; @@ -1042,10 +1019,10 @@ impl EventLoop { ) .map_err(|_| { // e ^^^ would return () - crate::error::OsError::new( + OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("failed to compile XKB compose table"), + platform_impl::OsError::KmsMisc("failed to compile XKB compose table"), ) })?; let xkb_compose = xkb::compose::State::new(&compose_table, xkb::compose::STATE_NO_FLAGS); @@ -1053,10 +1030,10 @@ impl EventLoop { // Allows use to use the non-legacy atomic system drm::Device::set_client_capability(&drm, drm::ClientCapability::Atomic, true).map_err( |e| { - crate::error::OsError::new( + OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsError(format!( + platform_impl::OsError::KmsError(format!( "drm device does not support atomic modesetting :{}", e )), @@ -1066,10 +1043,10 @@ impl EventLoop { // Load the information. let res = drm.resource_handles().map_err(|e| { - crate::error::OsError::new( + OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsError(format!( + platform_impl::OsError::KmsError(format!( "could not load normal resource ids: {}", e )), @@ -1077,14 +1054,14 @@ impl EventLoop { })?; // Enumerate available connectors - let coninfo: Vec = res + let coninfo: Vec = res .connectors() .iter() .flat_map(|con| drm.get_connector(*con)) .collect(); // Enumerate available CRTCs - let crtcinfo: Vec = res + let crtcinfo: Vec = res .crtcs() .iter() .flat_map(|crtc| drm.get_crtc(*crtc)) @@ -1093,21 +1070,21 @@ impl EventLoop { // Filter each connector until we find one that's connected. let con = coninfo .iter() - .find(|&i| i.state() == drm::control::connector::State::Connected) + .find(|&i| i.state() == connector::State::Connected) .ok_or_else(|| { - crate::error::OsError::new( + OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("no connected connectors"), + platform_impl::OsError::KmsMisc("no connected connectors"), ) })?; // Get the first (usually perferred) CRTC let crtc = crtcinfo.get(0).ok_or_else(|| { - crate::error::OsError::new( + OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("no crtcs found"), + platform_impl::OsError::KmsMisc("no crtcs found"), ) })?; @@ -1118,27 +1095,27 @@ impl EventLoop { .find(|f| f.mode_type().contains(ModeTypeFlags::PREFERRED)) .or(con.modes().get(0)) .ok_or_else(|| { - crate::error::OsError::new( + OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("no modes found on connector"), + platform_impl::OsError::KmsMisc("no modes found on connector"), ) })?; // Enumerate available planes let planes = drm.plane_handles().map_err(|e| { - crate::error::OsError::new( + OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsError(format!("could not list planes: {}", e)), + platform_impl::OsError::KmsError(format!("could not list planes: {}", e)), ) })?; let (p_better_planes, p_compatible_planes): ( // The primary planes available to us - Vec, + Vec, // Other, not-ideal planes that are however useable - Vec, + Vec, ) = planes .planes() .iter() @@ -1161,7 +1138,7 @@ impl EventLoop { // Checks if the plane is a primary plane, and returns true if it is, // if not it returns false if info.name().to_str().map(|x| x == "type").unwrap_or(false) { - return val == (drm::control::PlaneType::Primary as u32).into(); + return val == (PlaneType::Primary as u32).into(); } } } @@ -1180,7 +1157,7 @@ impl EventLoop { let handle = event_loop.handle(); // A source of user events. - let pending_user_events = std::rc::Rc::new(std::cell::RefCell::new(Vec::new())); + let pending_user_events = Rc::new(RefCell::new(Vec::new())); let pending_user_events_clone = pending_user_events.clone(); let (user_events_sender, user_events_channel) = calloop::channel::channel(); @@ -1203,11 +1180,9 @@ impl EventLoop { .insert_source( event_loop_awakener_source, move |_event, _metadata, data| { - data.push(crate::event::Event::RedrawRequested( - crate::window::WindowId(crate::platform_impl::WindowId::Kms( - super::WindowId, - )), - )); + data.push(Event::RedrawRequested(WindowId( + platform_impl::WindowId::Kms(super::WindowId), + ))); }, ) .unwrap(); @@ -1225,25 +1200,19 @@ impl EventLoop { > = calloop::Dispatcher::new( repeat_handler, move |event, metadata, data: &mut EventSink| { - data.push(crate::event::Event::WindowEvent { - window_id: crate::window::WindowId(crate::platform_impl::WindowId::Kms( - super::WindowId, - )), - event: crate::event::WindowEvent::KeyboardInput { - device_id: crate::event::DeviceId(crate::platform_impl::DeviceId::Kms( - super::DeviceId, - )), + data.push(Event::WindowEvent { + window_id: WindowId(platform_impl::WindowId::Kms(super::WindowId)), + event: WindowEvent::KeyboardInput { + device_id: DeviceId(platform_impl::DeviceId::Kms(super::DeviceId)), input: event.0, is_synthetic: false, }, }); if let Some(c) = event.1 { - data.push(crate::event::Event::WindowEvent { - window_id: crate::window::WindowId(crate::platform_impl::WindowId::Kms( - super::WindowId, - )), - event: crate::event::WindowEvent::ReceivedCharacter(c), + data.push(Event::WindowEvent { + window_id: WindowId(platform_impl::WindowId::Kms(super::WindowId)), + event: WindowEvent::ReceivedCharacter(c), }); } @@ -1278,8 +1247,8 @@ impl EventLoop { handle.register_dispatcher(input_loop).unwrap(); handle.register_dispatcher(repeat_loop).unwrap(); - let window_target = crate::event_loop::EventLoopWindowTarget { - p: crate::platform_impl::EventLoopWindowTarget::Kms(EventLoopWindowTarget { + let window_target = event_loop::EventLoopWindowTarget { + p: platform_impl::EventLoopWindowTarget::Kms(EventLoopWindowTarget { connector: con.clone(), crtc: crtc.clone(), device: drm, @@ -1304,11 +1273,7 @@ impl EventLoop { pub fn run(mut self, callback: F) -> ! where - F: FnMut( - crate::event::Event<'_, T>, - &crate::event_loop::EventLoopWindowTarget, - &mut ControlFlow, - ) + 'static, + F: FnMut(Event<'_, T>, &event_loop::EventLoopWindowTarget, &mut ControlFlow) + 'static, { let exit_code = self.run_return(callback); std::process::exit(exit_code); @@ -1316,26 +1281,20 @@ impl EventLoop { pub fn run_return(&mut self, mut callback: F) -> i32 where - F: FnMut( - crate::event::Event<'_, T>, - &crate::event_loop::EventLoopWindowTarget, - &mut ControlFlow, - ), + F: FnMut(Event<'_, T>, &event_loop::EventLoopWindowTarget, &mut ControlFlow), { let mut control_flow = ControlFlow::Poll; let pending_user_events = self.pending_user_events.clone(); let mut event_sink_back_buffer = Vec::new(); callback( - crate::event::Event::NewEvents(StartCause::Init), + Event::NewEvents(StartCause::Init), &self.window_target, &mut control_flow, ); callback( - crate::event::Event::RedrawRequested(crate::window::WindowId( - crate::platform_impl::WindowId::Kms(super::WindowId), - )), + Event::RedrawRequested(WindowId(platform_impl::WindowId::Kms(super::WindowId))), &self.window_target, &mut control_flow, ); @@ -1351,7 +1310,7 @@ impl EventLoop { } callback( - crate::event::Event::NewEvents(StartCause::Poll), + Event::NewEvents(StartCause::Poll), &self.window_target, &mut control_flow, ); @@ -1362,7 +1321,7 @@ impl EventLoop { } callback( - crate::event::Event::NewEvents(StartCause::WaitCancelled { + Event::NewEvents(StartCause::WaitCancelled { start: Instant::now(), requested_resume: None, }), @@ -1388,7 +1347,7 @@ impl EventLoop { if now < deadline { callback( - crate::event::Event::NewEvents(StartCause::WaitCancelled { + Event::NewEvents(StartCause::WaitCancelled { start, requested_resume: Some(deadline), }), @@ -1397,7 +1356,7 @@ impl EventLoop { ) } else { callback( - crate::event::Event::NewEvents(StartCause::ResumeTimeReached { + Event::NewEvents(StartCause::ResumeTimeReached { start, requested_resume: deadline, }), @@ -1412,7 +1371,7 @@ impl EventLoop { // user events indirectly via callback to the user. for user_event in pending_user_events.borrow_mut().drain(..) { sticky_exit_callback( - crate::event::Event::UserEvent(user_event), + Event::UserEvent(user_event), &self.window_target, &mut control_flow, &mut callback, @@ -1424,10 +1383,7 @@ impl EventLoop { // to create a window in one of those callbacks. self.with_window_target(|window_target| { let state = &mut window_target.event_sink; - std::mem::swap::>>( - &mut event_sink_back_buffer, - state, - ); + std::mem::swap::>>(&mut event_sink_back_buffer, state); }); // Handle pending window events. @@ -1438,7 +1394,7 @@ impl EventLoop { // Send events cleared. sticky_exit_callback( - crate::event::Event::MainEventsCleared, + Event::MainEventsCleared, &self.window_target, &mut control_flow, &mut callback, @@ -1446,18 +1402,14 @@ impl EventLoop { // Send RedrawEventCleared. sticky_exit_callback( - crate::event::Event::RedrawEventsCleared, + Event::RedrawEventsCleared, &self.window_target, &mut control_flow, &mut callback, ); }; - callback( - crate::event::Event::LoopDestroyed, - &self.window_target, - &mut control_flow, - ); + callback(Event::LoopDestroyed, &self.window_target, &mut control_flow); exit_code } @@ -1467,13 +1419,13 @@ impl EventLoop { } #[inline] - pub fn window_target(&self) -> &crate::event_loop::EventLoopWindowTarget { + pub fn window_target(&self) -> &event_loop::EventLoopWindowTarget { &self.window_target } fn with_window_target) -> U>(&mut self, f: F) -> U { let state = match &mut self.window_target.p { - crate::platform_impl::EventLoopWindowTarget::Kms(window_target) => window_target, + platform_impl::EventLoopWindowTarget::Kms(window_target) => window_target, #[cfg(any(feature = "x11", feature = "wayland"))] _ => unreachable!(), }; @@ -1486,7 +1438,7 @@ impl EventLoop { timeout: D, ) -> std::io::Result<()> { let mut state = match &mut self.window_target.p { - crate::platform_impl::EventLoopWindowTarget::Kms(window_target) => { + platform_impl::EventLoopWindowTarget::Kms(window_target) => { &mut window_target.event_sink } #[cfg(any(feature = "x11", feature = "kms"))] diff --git a/src/platform_impl/linux/kms/mod.rs b/src/platform_impl/linux/kms/mod.rs index 54f52d223e..9cefb793ff 100644 --- a/src/platform_impl/linux/kms/mod.rs +++ b/src/platform_impl/linux/kms/mod.rs @@ -2,8 +2,12 @@ use crate::dpi::{PhysicalPosition, PhysicalSize}; pub mod event_loop; pub mod window; +use crate::{monitor, platform_impl}; pub use drm::SystemError; -use drm::{control::Device as ControlDevice, Device}; +use drm::{ + control::{Device as ControlDevice, *}, + Device, +}; pub use event_loop::EventLoop; pub use event_loop::EventLoopProxy; pub use event_loop::EventLoopWindowTarget; @@ -43,7 +47,7 @@ impl DeviceId { } #[derive(Debug, Clone, PartialEq, Eq)] -pub struct MonitorHandle(drm::control::connector::Info); +pub struct MonitorHandle(connector::Info); impl PartialOrd for MonitorHandle { fn partial_cmp(&self, other: &Self) -> Option { @@ -85,17 +89,17 @@ impl MonitorHandle { } #[inline] - pub fn video_modes(&self) -> impl Iterator { + pub fn video_modes(&self) -> impl Iterator { let modes = self.0.modes().to_vec(); let monitor = self.0.clone(); - modes.into_iter().map(move |f| crate::monitor::VideoMode { - video_mode: crate::platform_impl::VideoMode::Kms(VideoMode(f, monitor.clone())), + modes.into_iter().map(move |f| monitor::VideoMode { + video_mode: platform_impl::VideoMode::Kms(VideoMode(f, monitor.clone())), }) } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct VideoMode(drm::control::Mode, drm::control::connector::Info); +pub struct VideoMode(Mode, connector::Info); impl VideoMode { #[inline] @@ -115,9 +119,9 @@ impl VideoMode { } #[inline] - pub fn monitor(&self) -> crate::monitor::MonitorHandle { - crate::monitor::MonitorHandle { - inner: crate::platform_impl::MonitorHandle::Kms(MonitorHandle(self.1.clone())), + pub fn monitor(&self) -> monitor::MonitorHandle { + monitor::MonitorHandle { + inner: platform_impl::MonitorHandle::Kms(MonitorHandle(self.1.clone())), } } } diff --git a/src/platform_impl/linux/kms/window.rs b/src/platform_impl/linux/kms/window.rs index 00d9e1f6ca..5b95b5cc48 100644 --- a/src/platform_impl/linux/kms/window.rs +++ b/src/platform_impl/linux/kms/window.rs @@ -5,9 +5,11 @@ use parking_lot::Mutex; use crate::{ dpi::{PhysicalPosition, PhysicalSize, Position, Size}, - error::{ExternalError, NotSupportedError}, + error::{ExternalError, NotSupportedError, OsError}, + monitor::{MonitorHandle, VideoMode}, platform::unix::Card, - window::{CursorIcon, Fullscreen}, + platform_impl, + window::{CursorIcon, Fullscreen, WindowAttributes}, }; pub struct Window { @@ -37,9 +39,9 @@ fn find_prop_id( impl Window { pub fn new( event_loop_window_target: &super::event_loop::EventLoopWindowTarget, - _attributes: crate::window::WindowAttributes, - _platform_attributes: crate::platform_impl::PlatformSpecificWindowBuilderAttributes, - ) -> Result { + _attributes: WindowAttributes, + _platform_attributes: platform_impl::PlatformSpecificWindowBuilderAttributes, + ) -> Result { let mut atomic_req = atomic::AtomicModeReq::new(); atomic_req.add_property( @@ -50,10 +52,10 @@ impl Window { "CRTC_ID", ) .ok_or_else(|| { - crate::error::OsError::new( + OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("could not get CRTC_ID"), + platform_impl::OsError::KmsMisc("could not get CRTC_ID"), ) })?, property::Value::CRTC(Some(event_loop_window_target.crtc.handle())), @@ -63,10 +65,10 @@ impl Window { .device .create_property_blob(&event_loop_window_target.mode) .map_err(|_| { - crate::error::OsError::new( + OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("failed to create blob"), + platform_impl::OsError::KmsMisc("failed to create blob"), ) })?; @@ -78,10 +80,10 @@ impl Window { "MODE_ID", ) .ok_or_else(|| { - crate::error::OsError::new( + OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("could not get MODE_ID"), + platform_impl::OsError::KmsMisc("could not get MODE_ID"), ) })?, blob, @@ -95,10 +97,10 @@ impl Window { "ACTIVE", ) .ok_or_else(|| { - crate::error::OsError::new( + OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("could not get ACTIVE"), + platform_impl::OsError::KmsMisc("could not get ACTIVE"), ) })?, property::Value::Boolean(true), @@ -112,10 +114,10 @@ impl Window { "CRTC_ID", ) .ok_or_else(|| { - crate::error::OsError::new( + OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("could not get CRTC_ID"), + platform_impl::OsError::KmsMisc("could not get CRTC_ID"), ) })?, property::Value::CRTC(Some(event_loop_window_target.crtc.handle())), @@ -129,10 +131,10 @@ impl Window { "SRC_X", ) .ok_or_else(|| { - crate::error::OsError::new( + OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("could not get SRC_X"), + platform_impl::OsError::KmsMisc("could not get SRC_X"), ) })?, property::Value::UnsignedRange(0), @@ -146,10 +148,10 @@ impl Window { "SRC_Y", ) .ok_or_else(|| { - crate::error::OsError::new( + OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("could not get SRC_Y"), + platform_impl::OsError::KmsMisc("could not get SRC_Y"), ) })?, property::Value::UnsignedRange(0), @@ -163,10 +165,10 @@ impl Window { "SRC_W", ) .ok_or_else(|| { - crate::error::OsError::new( + OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("could not get SRC_W"), + platform_impl::OsError::KmsMisc("could not get SRC_W"), ) })?, property::Value::UnsignedRange((event_loop_window_target.mode.size().0 as u64) << 16), @@ -180,10 +182,10 @@ impl Window { "SRC_H", ) .ok_or_else(|| { - crate::error::OsError::new( + OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("could not get SRC_H"), + platform_impl::OsError::KmsMisc("could not get SRC_H"), ) })?, property::Value::UnsignedRange((event_loop_window_target.mode.size().1 as u64) << 16), @@ -197,10 +199,10 @@ impl Window { "CRTC_X", ) .ok_or_else(|| { - crate::error::OsError::new( + OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("could not get CRTC_X"), + platform_impl::OsError::KmsMisc("could not get CRTC_X"), ) })?, property::Value::SignedRange(0), @@ -214,10 +216,10 @@ impl Window { "CRTC_Y", ) .ok_or_else(|| { - crate::error::OsError::new( + OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("could not get CRTC_Y"), + platform_impl::OsError::KmsMisc("could not get CRTC_Y"), ) })?, property::Value::SignedRange(0), @@ -231,10 +233,10 @@ impl Window { "CRTC_W", ) .ok_or_else(|| { - crate::error::OsError::new( + OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("could not get CRTC_W"), + platform_impl::OsError::KmsMisc("could not get CRTC_W"), ) })?, property::Value::UnsignedRange(event_loop_window_target.mode.size().0 as u64), @@ -248,10 +250,10 @@ impl Window { "CRTC_H", ) .ok_or_else(|| { - crate::error::OsError::new( + OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsMisc("could not get CRTC_H"), + platform_impl::OsError::KmsMisc("could not get CRTC_H"), ) })?, property::Value::UnsignedRange(event_loop_window_target.mode.size().1 as u64), @@ -261,10 +263,10 @@ impl Window { .device .atomic_commit(AtomicCommitFlags::ALLOW_MODESET, atomic_req) .map_err(|e| { - crate::error::OsError::new( + OsError::new( line!(), file!(), - crate::platform_impl::OsError::KmsError(format!("failed to set mode: {}", e)), + platform_impl::OsError::KmsError(format!("failed to set mode: {}", e)), ) })?; @@ -382,8 +384,8 @@ impl Window { #[inline] pub fn fullscreen(&self) -> Option { - Some(Fullscreen::Exclusive(crate::monitor::VideoMode { - video_mode: crate::platform_impl::VideoMode::Kms(super::VideoMode( + Some(Fullscreen::Exclusive(VideoMode { + video_mode: platform_impl::VideoMode::Kms(super::VideoMode( self.mode, self.connector.clone(), )), @@ -436,11 +438,9 @@ impl Window { } #[inline] - pub fn primary_monitor(&self) -> Option { - Some(crate::monitor::MonitorHandle { - inner: crate::platform_impl::MonitorHandle::Kms(super::MonitorHandle( - self.connector.clone(), - )), + pub fn primary_monitor(&self) -> Option { + Some(MonitorHandle { + inner: platform_impl::MonitorHandle::Kms(super::MonitorHandle(self.connector.clone())), }) } } From 901c819f8455dd252439b74c91e4552e6c1c7025 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Mon, 9 May 2022 16:50:22 -0400 Subject: [PATCH 096/151] Fix 'card0' default name --- src/platform_impl/linux/kms/event_loop.rs | 10 ++++- src/platform_impl/linux/kms/mod.rs | 49 ++++++++++++++++------- src/platform_impl/linux/kms/window.rs | 23 +++++++---- 3 files changed, 58 insertions(+), 24 deletions(-) diff --git a/src/platform_impl/linux/kms/event_loop.rs b/src/platform_impl/linux/kms/event_loop.rs index 8a6ef6c95d..ea966c826f 100644 --- a/src/platform_impl/linux/kms/event_loop.rs +++ b/src/platform_impl/linux/kms/event_loop.rs @@ -774,7 +774,10 @@ impl EventLoopWindowTarget { #[inline] pub fn primary_monitor(&self) -> Option { Some(MonitorHandle { - inner: platform_impl::MonitorHandle::Kms(super::MonitorHandle(self.connector.clone())), + inner: platform_impl::MonitorHandle::Kms(super::MonitorHandle { + connector: self.connector.clone(), + name: self.mode.name().to_string_lossy().into_owned(), + }), }) } @@ -785,7 +788,10 @@ impl EventLoopWindowTarget { .unwrap() .connectors() .iter() - .map(|f| super::MonitorHandle(self.device.get_connector(*f).unwrap())) + .map(|f| super::MonitorHandle { + connector: self.device.get_connector(*f).unwrap(), + name: self.mode.name().to_string_lossy().into_owned(), + }) .collect() } } diff --git a/src/platform_impl/linux/kms/mod.rs b/src/platform_impl/linux/kms/mod.rs index 9cefb793ff..e10874d758 100644 --- a/src/platform_impl/linux/kms/mod.rs +++ b/src/platform_impl/linux/kms/mod.rs @@ -11,6 +11,7 @@ use drm::{ pub use event_loop::EventLoop; pub use event_loop::EventLoopProxy; pub use event_loop::EventLoopWindowTarget; +use std::os::unix; use std::os::unix::prelude::FromRawFd; use std::sync::Arc; pub use window::Window; @@ -21,8 +22,8 @@ pub struct Card(pub(crate) Arc); /// Implementing `AsRawFd` is a prerequisite to implementing the traits found /// in this crate. Here, we are just calling `as_raw_fd()` on the inner File. -impl std::os::unix::io::AsRawFd for Card { - fn as_raw_fd(&self) -> std::os::unix::io::RawFd { +impl unix::io::AsRawFd for Card { + fn as_raw_fd(&self) -> unix::io::RawFd { *self.0 } } @@ -47,34 +48,43 @@ impl DeviceId { } #[derive(Debug, Clone, PartialEq, Eq)] -pub struct MonitorHandle(connector::Info); +pub struct MonitorHandle { + connector: connector::Info, + name: String, +} impl PartialOrd for MonitorHandle { fn partial_cmp(&self, other: &Self) -> Option { - Some(self.0.interface_id().cmp(&other.0.interface_id())) + Some( + self.connector + .interface_id() + .cmp(&other.connector.interface_id()), + ) } } impl Ord for MonitorHandle { fn cmp(&self, other: &Self) -> std::cmp::Ordering { - self.0.interface_id().cmp(&other.0.interface_id()) + self.connector + .interface_id() + .cmp(&other.connector.interface_id()) } } impl MonitorHandle { #[inline] pub fn name(&self) -> Option { - Some(String::from("card0")) + Some(self.name.to_string()) } #[inline] pub fn native_identifier(&self) -> u32 { - self.0.interface_id() + self.connector.interface_id() } #[inline] pub fn size(&self) -> PhysicalSize { - let size = self.0.modes()[0].size(); + let size = self.connector.modes()[0].size(); PhysicalSize::new(size.0 as u32, size.1 as u32) } @@ -90,21 +100,27 @@ impl MonitorHandle { #[inline] pub fn video_modes(&self) -> impl Iterator { - let modes = self.0.modes().to_vec(); - let monitor = self.0.clone(); + let modes = self.connector.modes().to_vec(); + let monitor = self.connector.clone(); modes.into_iter().map(move |f| monitor::VideoMode { - video_mode: platform_impl::VideoMode::Kms(VideoMode(f, monitor.clone())), + video_mode: platform_impl::VideoMode::Kms(VideoMode { + mode: f, + connector: monitor.clone(), + }), }) } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct VideoMode(Mode, connector::Info); +pub struct VideoMode { + mode: Mode, + connector: connector::Info, +} impl VideoMode { #[inline] pub fn size(&self) -> PhysicalSize { - let size = self.0.size(); + let size = self.mode.size(); PhysicalSize::new(size.0 as u32, size.1 as u32) } @@ -115,13 +131,16 @@ impl VideoMode { #[inline] pub fn refresh_rate(&self) -> u16 { - self.0.vrefresh() as u16 + self.mode.vrefresh() as u16 } #[inline] pub fn monitor(&self) -> monitor::MonitorHandle { monitor::MonitorHandle { - inner: platform_impl::MonitorHandle::Kms(MonitorHandle(self.1.clone())), + inner: platform_impl::MonitorHandle::Kms(MonitorHandle { + connector: self.connector.clone(), + name: self.mode.name().to_string_lossy().into_owned(), + }), } } } diff --git a/src/platform_impl/linux/kms/window.rs b/src/platform_impl/linux/kms/window.rs index 5b95b5cc48..69ce025c41 100644 --- a/src/platform_impl/linux/kms/window.rs +++ b/src/platform_impl/linux/kms/window.rs @@ -385,10 +385,10 @@ impl Window { #[inline] pub fn fullscreen(&self) -> Option { Some(Fullscreen::Exclusive(VideoMode { - video_mode: platform_impl::VideoMode::Kms(super::VideoMode( - self.mode, - self.connector.clone(), - )), + video_mode: platform_impl::VideoMode::Kms(super::VideoMode { + mode: self.mode, + connector: self.connector.clone(), + }), })) } @@ -415,7 +415,10 @@ impl Window { #[inline] pub fn current_monitor(&self) -> Option { - Some(super::MonitorHandle(self.connector.clone())) + Some(super::MonitorHandle { + connector: self.connector.clone(), + name: self.mode.name().to_string_lossy().into_owned(), + }) } #[inline] @@ -425,7 +428,10 @@ impl Window { .unwrap() .connectors() .iter() - .map(|f| super::MonitorHandle(self.card.get_connector(*f).unwrap())) + .map(|f| super::MonitorHandle { + connector: self.card.get_connector(*f).unwrap(), + name: self.mode.name().to_string_lossy().into_owned(), + }) .collect() } @@ -440,7 +446,10 @@ impl Window { #[inline] pub fn primary_monitor(&self) -> Option { Some(MonitorHandle { - inner: platform_impl::MonitorHandle::Kms(super::MonitorHandle(self.connector.clone())), + inner: platform_impl::MonitorHandle::Kms(super::MonitorHandle { + connector: self.connector.clone(), + name: self.mode.name().to_string_lossy().into_owned(), + }), }) } } From 6f6654d5de4e156b3315741f4763297a8440c0eb Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Mon, 9 May 2022 17:09:45 -0400 Subject: [PATCH 097/151] Fix add atomic_req macro --- src/platform_impl/linux/kms/window.rs | 220 ++++++++------------------ 1 file changed, 64 insertions(+), 156 deletions(-) diff --git a/src/platform_impl/linux/kms/window.rs b/src/platform_impl/linux/kms/window.rs index 69ce025c41..45d3b52e3a 100644 --- a/src/platform_impl/linux/kms/window.rs +++ b/src/platform_impl/linux/kms/window.rs @@ -36,6 +36,22 @@ fn find_prop_id( .cloned() } +macro_rules! add_property { + ($atomic_req:expr,$handle:expr,$id_handle_1:expr,$prop_name:literal,$property:expr,) => { + $atomic_req.add_property( + $handle, + find_prop_id(&$id_handle_1, $handle, $prop_name).ok_or_else(|| { + OsError::new( + line!(), + file!(), + platform_impl::OsError::KmsMisc(concat!("could not get ", $prop_name)), + ) + })?, + $property, + ); + }; +} + impl Window { pub fn new( event_loop_window_target: &super::event_loop::EventLoopWindowTarget, @@ -44,20 +60,11 @@ impl Window { ) -> Result { let mut atomic_req = atomic::AtomicModeReq::new(); - atomic_req.add_property( + add_property!( + atomic_req, event_loop_window_target.connector.handle(), - find_prop_id( - &event_loop_window_target.device, - event_loop_window_target.connector.handle(), - "CRTC_ID", - ) - .ok_or_else(|| { - OsError::new( - line!(), - file!(), - platform_impl::OsError::KmsMisc("could not get CRTC_ID"), - ) - })?, + event_loop_window_target.device, + "CRTC_ID", property::Value::CRTC(Some(event_loop_window_target.crtc.handle())), ); @@ -72,190 +79,91 @@ impl Window { ) })?; - atomic_req.add_property( + add_property!( + atomic_req, event_loop_window_target.crtc.handle(), - find_prop_id( - &event_loop_window_target.device, - event_loop_window_target.crtc.handle(), - "MODE_ID", - ) - .ok_or_else(|| { - OsError::new( - line!(), - file!(), - platform_impl::OsError::KmsMisc("could not get MODE_ID"), - ) - })?, + event_loop_window_target.device, + "MODE_ID", blob, ); - atomic_req.add_property( + add_property!( + atomic_req, event_loop_window_target.crtc.handle(), - find_prop_id( - &event_loop_window_target.device, - event_loop_window_target.crtc.handle(), - "ACTIVE", - ) - .ok_or_else(|| { - OsError::new( - line!(), - file!(), - platform_impl::OsError::KmsMisc("could not get ACTIVE"), - ) - })?, + event_loop_window_target.device, + "ACTIVE", property::Value::Boolean(true), ); - atomic_req.add_property( + add_property!( + atomic_req, event_loop_window_target.plane, - find_prop_id( - &event_loop_window_target.device, - event_loop_window_target.plane, - "CRTC_ID", - ) - .ok_or_else(|| { - OsError::new( - line!(), - file!(), - platform_impl::OsError::KmsMisc("could not get CRTC_ID"), - ) - })?, + event_loop_window_target.device, + "CRTC_ID", property::Value::CRTC(Some(event_loop_window_target.crtc.handle())), ); - atomic_req.add_property( + add_property!( + atomic_req, event_loop_window_target.plane, - find_prop_id( - &event_loop_window_target.device, - event_loop_window_target.plane, - "SRC_X", - ) - .ok_or_else(|| { - OsError::new( - line!(), - file!(), - platform_impl::OsError::KmsMisc("could not get SRC_X"), - ) - })?, + event_loop_window_target.device, + "SRC_X", property::Value::UnsignedRange(0), ); - atomic_req.add_property( + add_property!( + atomic_req, event_loop_window_target.plane, - find_prop_id( - &event_loop_window_target.device, - event_loop_window_target.plane, - "SRC_Y", - ) - .ok_or_else(|| { - OsError::new( - line!(), - file!(), - platform_impl::OsError::KmsMisc("could not get SRC_Y"), - ) - })?, + event_loop_window_target.device, + "SRC_Y", property::Value::UnsignedRange(0), ); - atomic_req.add_property( + add_property!( + atomic_req, event_loop_window_target.plane, - find_prop_id( - &event_loop_window_target.device, - event_loop_window_target.plane, - "SRC_W", - ) - .ok_or_else(|| { - OsError::new( - line!(), - file!(), - platform_impl::OsError::KmsMisc("could not get SRC_W"), - ) - })?, + event_loop_window_target.device, + "SRC_W", property::Value::UnsignedRange((event_loop_window_target.mode.size().0 as u64) << 16), ); - atomic_req.add_property( + add_property!( + atomic_req, event_loop_window_target.plane, - find_prop_id( - &event_loop_window_target.device, - event_loop_window_target.plane, - "SRC_H", - ) - .ok_or_else(|| { - OsError::new( - line!(), - file!(), - platform_impl::OsError::KmsMisc("could not get SRC_H"), - ) - })?, + event_loop_window_target.device, + "SRC_H", property::Value::UnsignedRange((event_loop_window_target.mode.size().1 as u64) << 16), ); - atomic_req.add_property( + add_property!( + atomic_req, event_loop_window_target.plane, - find_prop_id( - &event_loop_window_target.device, - event_loop_window_target.plane, - "CRTC_X", - ) - .ok_or_else(|| { - OsError::new( - line!(), - file!(), - platform_impl::OsError::KmsMisc("could not get CRTC_X"), - ) - })?, + event_loop_window_target.device, + "CRTC_X", property::Value::SignedRange(0), ); - atomic_req.add_property( + add_property!( + atomic_req, event_loop_window_target.plane, - find_prop_id( - &event_loop_window_target.device, - event_loop_window_target.plane, - "CRTC_Y", - ) - .ok_or_else(|| { - OsError::new( - line!(), - file!(), - platform_impl::OsError::KmsMisc("could not get CRTC_Y"), - ) - })?, + event_loop_window_target.device, + "CRTC_Y", property::Value::SignedRange(0), ); - atomic_req.add_property( + add_property!( + atomic_req, event_loop_window_target.plane, - find_prop_id( - &event_loop_window_target.device, - event_loop_window_target.plane, - "CRTC_W", - ) - .ok_or_else(|| { - OsError::new( - line!(), - file!(), - platform_impl::OsError::KmsMisc("could not get CRTC_W"), - ) - })?, + event_loop_window_target.device, + "CRTC_W", property::Value::UnsignedRange(event_loop_window_target.mode.size().0 as u64), ); - atomic_req.add_property( + add_property!( + atomic_req, event_loop_window_target.plane, - find_prop_id( - &event_loop_window_target.device, - event_loop_window_target.plane, - "CRTC_H", - ) - .ok_or_else(|| { - OsError::new( - line!(), - file!(), - platform_impl::OsError::KmsMisc("could not get CRTC_H"), - ) - })?, + event_loop_window_target.device, + "CRTC_H", property::Value::UnsignedRange(event_loop_window_target.mode.size().1 as u64), ); From 5d5d1e4df6ef15ef19164b559fb35e4e5de65cba Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Mon, 9 May 2022 17:16:01 -0400 Subject: [PATCH 098/151] Add another macro --- src/platform_impl/linux/kms/event_loop.rs | 90 ++++++++--------------- 1 file changed, 31 insertions(+), 59 deletions(-) diff --git a/src/platform_impl/linux/kms/event_loop.rs b/src/platform_impl/linux/kms/event_loop.rs index ea966c826f..37d855cb6e 100644 --- a/src/platform_impl/linux/kms/event_loop.rs +++ b/src/platform_impl/linux/kms/event_loop.rs @@ -41,6 +41,12 @@ use crate::{ window::WindowId, }; +macro_rules! window_id { + () => { + WindowId(platform_impl::WindowId::Kms(super::WindowId)) + }; +} + const REPEAT_RATE: u64 = 25; const REPEAT_DELAY: u64 = 600; @@ -183,7 +189,7 @@ impl EventSource for LibinputInputBackend { input::Event::Touch(ev) => match ev { input::event::TouchEvent::Up(e) => callback( Event::WindowEvent { - window_id: WindowId(platform_impl::WindowId::Kms(super::WindowId)), + window_id: window_id!(), event: WindowEvent::Touch(Touch { device_id: DeviceId(platform_impl::DeviceId::Kms( super::DeviceId, @@ -202,9 +208,7 @@ impl EventSource for LibinputInputBackend { callback( Event::WindowEvent { - window_id: WindowId(platform_impl::WindowId::Kms( - super::WindowId, - )), + window_id: window_id!(), event: WindowEvent::Touch(Touch { device_id: DeviceId(platform_impl::DeviceId::Kms( super::DeviceId, @@ -224,9 +228,7 @@ impl EventSource for LibinputInputBackend { callback( Event::WindowEvent { - window_id: WindowId(platform_impl::WindowId::Kms( - super::WindowId, - )), + window_id: window_id!(), event: WindowEvent::Touch(Touch { device_id: DeviceId(platform_impl::DeviceId::Kms( super::DeviceId, @@ -242,7 +244,7 @@ impl EventSource for LibinputInputBackend { } input::event::TouchEvent::Cancel(e) => callback( Event::WindowEvent { - window_id: WindowId(platform_impl::WindowId::Kms(super::WindowId)), + window_id: window_id!(), event: WindowEvent::Touch(Touch { device_id: DeviceId(platform_impl::DeviceId::Kms( super::DeviceId, @@ -257,7 +259,7 @@ impl EventSource for LibinputInputBackend { ), input::event::TouchEvent::Frame(_) => callback( Event::WindowEvent { - window_id: WindowId(platform_impl::WindowId::Kms(super::WindowId)), + window_id: window_id!(), event: WindowEvent::Touch(Touch { device_id: DeviceId(platform_impl::DeviceId::Kms( super::DeviceId, @@ -275,7 +277,7 @@ impl EventSource for LibinputInputBackend { input::Event::Tablet(ev) => match ev { input::event::TabletToolEvent::Tip(e) => callback( Event::WindowEvent { - window_id: WindowId(platform_impl::WindowId::Kms(super::WindowId)), + window_id: window_id!(), event: WindowEvent::Touch(Touch { device_id: DeviceId(platform_impl::DeviceId::Kms( super::DeviceId, @@ -301,9 +303,7 @@ impl EventSource for LibinputInputBackend { input::event::TabletToolEvent::Button(e) => { callback( Event::WindowEvent { - window_id: WindowId(platform_impl::WindowId::Kms( - super::WindowId, - )), + window_id: window_id!(), event: WindowEvent::MouseInput { device_id: DeviceId(platform_impl::DeviceId::Kms( super::DeviceId, @@ -353,9 +353,7 @@ impl EventSource for LibinputInputBackend { callback( Event::WindowEvent { - window_id: WindowId(platform_impl::WindowId::Kms( - super::WindowId, - )), + window_id: window_id!(), event: WindowEvent::CursorMoved { device_id: DeviceId(platform_impl::DeviceId::Kms( super::DeviceId, @@ -382,9 +380,7 @@ impl EventSource for LibinputInputBackend { input::event::PointerEvent::Button(e) => { callback( Event::WindowEvent { - window_id: WindowId(platform_impl::WindowId::Kms( - super::WindowId, - )), + window_id: window_id!(), event: WindowEvent::MouseInput { device_id: DeviceId(platform_impl::DeviceId::Kms( super::DeviceId, @@ -425,9 +421,7 @@ impl EventSource for LibinputInputBackend { callback( Event::WindowEvent { - window_id: WindowId(platform_impl::WindowId::Kms( - super::WindowId, - )), + window_id: window_id!(), event: WindowEvent::MouseWheel { device_id: DeviceId(platform_impl::DeviceId::Kms( super::DeviceId, @@ -456,9 +450,7 @@ impl EventSource for LibinputInputBackend { callback( Event::WindowEvent { - window_id: WindowId(platform_impl::WindowId::Kms( - super::WindowId, - )), + window_id: window_id!(), event: WindowEvent::MouseWheel { device_id: DeviceId(platform_impl::DeviceId::Kms( super::DeviceId, @@ -491,9 +483,7 @@ impl EventSource for LibinputInputBackend { callback( Event::WindowEvent { - window_id: WindowId(platform_impl::WindowId::Kms( - super::WindowId, - )), + window_id: window_id!(), event: WindowEvent::CursorMoved { device_id: DeviceId(platform_impl::DeviceId::Kms( super::DeviceId, @@ -542,7 +532,7 @@ impl EventSource for LibinputInputBackend { callback( Event::WindowEvent { - window_id: WindowId(platform_impl::WindowId::Kms(super::WindowId)), + window_id: window_id!(), event: WindowEvent::KeyboardInput { device_id: DeviceId(platform_impl::DeviceId::Kms( super::DeviceId, @@ -564,9 +554,7 @@ impl EventSource for LibinputInputBackend { { callback( Event::WindowEvent { - window_id: WindowId(platform_impl::WindowId::Kms( - super::WindowId, - )), + window_id: window_id!(), event: WindowEvent::ReceivedCharacter(c), }, &mut (), @@ -587,9 +575,7 @@ impl EventSource for LibinputInputBackend { if let Some(c) = ch { callback( Event::WindowEvent { - window_id: WindowId(platform_impl::WindowId::Kms( - super::WindowId, - )), + window_id: window_id!(), event: WindowEvent::ReceivedCharacter(c), }, &mut (), @@ -608,9 +594,7 @@ impl EventSource for LibinputInputBackend { if let Some(c) = ch { callback( Event::WindowEvent { - window_id: WindowId(platform_impl::WindowId::Kms( - super::WindowId, - )), + window_id: window_id!(), event: WindowEvent::ReceivedCharacter(c), }, &mut (), @@ -631,9 +615,7 @@ impl EventSource for LibinputInputBackend { callback( Event::WindowEvent { - window_id: WindowId(platform_impl::WindowId::Kms( - super::WindowId, - )), + window_id: window_id!(), event: WindowEvent::ModifiersChanged(self.modifiers), }, &mut (), @@ -651,9 +633,7 @@ impl EventSource for LibinputInputBackend { callback( Event::WindowEvent { - window_id: WindowId(platform_impl::WindowId::Kms( - super::WindowId, - )), + window_id: window_id!(), event: WindowEvent::ModifiersChanged(self.modifiers), }, &mut (), @@ -670,9 +650,7 @@ impl EventSource for LibinputInputBackend { callback( Event::WindowEvent { - window_id: WindowId(platform_impl::WindowId::Kms( - super::WindowId, - )), + window_id: window_id!(), event: WindowEvent::ModifiersChanged(self.modifiers), }, &mut (), @@ -689,9 +667,7 @@ impl EventSource for LibinputInputBackend { callback( Event::WindowEvent { - window_id: WindowId(platform_impl::WindowId::Kms( - super::WindowId, - )), + window_id: window_id!(), event: WindowEvent::ModifiersChanged(self.modifiers), }, &mut (), @@ -701,9 +677,7 @@ impl EventSource for LibinputInputBackend { if self.modifiers.is_empty() { callback( Event::WindowEvent { - window_id: WindowId(platform_impl::WindowId::Kms( - super::WindowId, - )), + window_id: window_id!(), event: WindowEvent::CloseRequested, }, &mut (), @@ -1186,9 +1160,7 @@ impl EventLoop { .insert_source( event_loop_awakener_source, move |_event, _metadata, data| { - data.push(Event::RedrawRequested(WindowId( - platform_impl::WindowId::Kms(super::WindowId), - ))); + data.push(Event::RedrawRequested(window_id!())); }, ) .unwrap(); @@ -1207,7 +1179,7 @@ impl EventLoop { repeat_handler, move |event, metadata, data: &mut EventSink| { data.push(Event::WindowEvent { - window_id: WindowId(platform_impl::WindowId::Kms(super::WindowId)), + window_id: window_id!(), event: WindowEvent::KeyboardInput { device_id: DeviceId(platform_impl::DeviceId::Kms(super::DeviceId)), input: event.0, @@ -1217,7 +1189,7 @@ impl EventLoop { if let Some(c) = event.1 { data.push(Event::WindowEvent { - window_id: WindowId(platform_impl::WindowId::Kms(super::WindowId)), + window_id: window_id!(), event: WindowEvent::ReceivedCharacter(c), }); } @@ -1300,7 +1272,7 @@ impl EventLoop { ); callback( - Event::RedrawRequested(WindowId(platform_impl::WindowId::Kms(super::WindowId))), + Event::RedrawRequested(window_id!()), &self.window_target, &mut control_flow, ); From d3f09980f19aab465568e8f61843c6b341de4f31 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Mon, 9 May 2022 17:41:45 -0400 Subject: [PATCH 099/151] Remove wrong comment --- src/platform_impl/linux/kms/event_loop.rs | 1030 ++++++++++----------- src/platform_impl/linux/kms/window.rs | 5 +- 2 files changed, 512 insertions(+), 523 deletions(-) diff --git a/src/platform_impl/linux/kms/event_loop.rs b/src/platform_impl/linux/kms/event_loop.rs index 37d855cb6e..f9da86af2f 100644 --- a/src/platform_impl/linux/kms/event_loop.rs +++ b/src/platform_impl/linux/kms/event_loop.rs @@ -41,9 +41,21 @@ use crate::{ window::WindowId, }; +macro_rules! to_platform_impl { + ($p:ident, $params:expr) => { + $p(platform_impl::$p::Kms($params)) + }; +} + macro_rules! window_id { () => { - WindowId(platform_impl::WindowId::Kms(super::WindowId)) + to_platform_impl!(WindowId, super::WindowId) + }; +} + +macro_rules! device_id { + () => { + to_platform_impl!(DeviceId, super::DeviceId) }; } @@ -142,551 +154,531 @@ impl AsRawFd for LibinputInputBackend { } } -impl EventSource for LibinputInputBackend { - type Event = Event<'static, ()>; - type Metadata = (); - type Ret = (); +macro_rules! handle_device_event { + ($ev:expr,$callback:expr) => { + match $ev { + input::event::DeviceEvent::Added(_) => { + $callback( + Event::DeviceEvent { + device_id: device_id!(), + event: DeviceEvent::Added, + }, + &mut (), + ); + } + input::event::DeviceEvent::Removed(_) => { + $callback( + Event::DeviceEvent { + device_id: device_id!(), + event: DeviceEvent::Removed, + }, + &mut (), + ); + } + _ => {} + } + }; +} - fn process_events( - &mut self, - _: Readiness, - token: Token, - mut callback: F, - ) -> std::io::Result - where - F: FnMut(Self::Event, &mut ()) -> Self::Ret, - { - if token == self.token { - self.context.dispatch()?; +macro_rules! handle_touch_event { + ($self:expr,$ev:expr,$callback:expr) => { + match $ev { + input::event::TouchEvent::Up(e) => $callback( + Event::WindowEvent { + window_id: window_id!(), + event: WindowEvent::Touch(Touch { + device_id: device_id!(), + phase: TouchPhase::Ended, + location: $self.touch_location, + force: None, + id: e.slot().unwrap() as u64, + }), + }, + &mut (), + ), + input::event::TouchEvent::Down(e) => { + $self.touch_location.x = e.x_transformed($self.screen_size.0); + $self.touch_location.y = e.y_transformed($self.screen_size.1); + + $callback( + Event::WindowEvent { + window_id: window_id!(), + event: WindowEvent::Touch(Touch { + device_id: device_id!(), + phase: TouchPhase::Started, + location: $self.touch_location, + force: None, + id: e.slot().unwrap() as u64, + }), + }, + &mut (), + ) + } + input::event::TouchEvent::Motion(e) => { + $self.touch_location.x = e.x_transformed($self.screen_size.0); + $self.touch_location.y = e.y_transformed($self.screen_size.1); - for event in &mut self.context { - match event { - input::Event::Device(ev) => match ev { - input::event::DeviceEvent::Added(_) => { - callback( - Event::DeviceEvent { - device_id: DeviceId(platform_impl::DeviceId::Kms( - super::DeviceId, - )), - event: DeviceEvent::Added, + $callback( + Event::WindowEvent { + window_id: window_id!(), + event: WindowEvent::Touch(Touch { + device_id: device_id!(), + phase: TouchPhase::Moved, + location: $self.touch_location, + force: None, + id: e.slot().unwrap() as u64, + }), + }, + &mut (), + ); + } + input::event::TouchEvent::Cancel(e) => $callback( + Event::WindowEvent { + window_id: window_id!(), + event: WindowEvent::Touch(Touch { + device_id: device_id!(), + phase: TouchPhase::Cancelled, + location: $self.touch_location, + force: None, + id: e.slot().unwrap() as u64, + }), + }, + &mut (), + ), + input::event::TouchEvent::Frame(_) => $callback( + Event::WindowEvent { + window_id: window_id!(), + event: WindowEvent::Touch(Touch { + device_id: device_id!(), + phase: TouchPhase::Ended, + location: $self.touch_location, + force: None, + id: 0, // e.slot().unwrap() as u64, + }), + }, + &mut (), + ), + _ => {} + } + }; +} + +macro_rules! handle_tablet_tool_event { + ($self:expr,$ev:expr,$callback:expr) => { + match $ev { + input::event::TabletToolEvent::Tip(e) => $callback( + Event::WindowEvent { + window_id: window_id!(), + event: WindowEvent::Touch(Touch { + device_id: device_id!(), + phase: match e.tip_state() { + TipState::Down => TouchPhase::Started, + TipState::Up => TouchPhase::Ended, + }, + location: PhysicalPosition::new( + e.x_transformed($self.screen_size.0), + e.y_transformed($self.screen_size.1), + ), + force: Some(Force::Calibrated { + force: e.pressure(), + max_possible_force: 1.0, + altitude_angle: None, + }), + id: 0, + }), + }, + &mut (), + ), + input::event::TabletToolEvent::Button(e) => { + $callback( + Event::WindowEvent { + window_id: window_id!(), + event: WindowEvent::MouseInput { + device_id: device_id!(), + state: match e.button_state() { + ButtonState::Pressed => ElementState::Pressed, + ButtonState::Released => ElementState::Released, + }, + button: match e.button() { + 1 => MouseButton::Right, + 2 => MouseButton::Middle, + _ => MouseButton::Left, + }, + modifiers: $self.modifiers, + }, + }, + &mut (), + ); + + $callback( + Event::DeviceEvent { + device_id: device_id!(), + event: DeviceEvent::Button { + button: e.button(), + state: match e.button_state() { + ButtonState::Pressed => ElementState::Pressed, + ButtonState::Released => ElementState::Released, + }, + }, + }, + &mut (), + ); + } + _ => {} + } + }; +} + +macro_rules! handle_pointer_event { + ($self:expr,$ev:expr,$callback:expr) => { + match $ev { + input::event::PointerEvent::Motion(e) => { + let mut lock = $self.cursor_positon.lock(); + + lock.x += e.dx(); + lock.x = lock.x.clamp(0.0, $self.screen_size.0 as f64); + + lock.y += e.dy(); + lock.y = lock.y.clamp(0.0, $self.screen_size.1 as f64); + + $callback( + Event::WindowEvent { + window_id: window_id!(), + event: WindowEvent::CursorMoved { + device_id: device_id!(), + position: *lock, + modifiers: $self.modifiers, + }, + }, + &mut (), + ); + + $callback( + Event::DeviceEvent { + device_id: device_id!(), + event: DeviceEvent::MouseMotion { + delta: (e.dx(), e.dy()), + }, + }, + &mut (), + ); + } + input::event::PointerEvent::Button(e) => { + $callback( + Event::WindowEvent { + window_id: window_id!(), + event: WindowEvent::MouseInput { + device_id: device_id!(), + state: match e.button_state() { + ButtonState::Pressed => ElementState::Pressed, + ButtonState::Released => ElementState::Released, + }, + button: match e.button() { + 1 => MouseButton::Right, + 2 => MouseButton::Middle, + _ => MouseButton::Left, + }, + modifiers: $self.modifiers, + }, + }, + &mut (), + ); + + $callback( + Event::DeviceEvent { + device_id: device_id!(), + event: DeviceEvent::Button { + button: e.button(), + state: match e.button_state() { + ButtonState::Pressed => ElementState::Pressed, + ButtonState::Released => ElementState::Released, + }, + }, + }, + &mut (), + ); + } + input::event::PointerEvent::ScrollWheel(e) => { + use input::event::pointer::Axis; + + $callback( + Event::WindowEvent { + window_id: window_id!(), + event: WindowEvent::MouseWheel { + device_id: device_id!(), + delta: MouseScrollDelta::LineDelta( + if e.has_axis(Axis::Horizontal) { + e.scroll_value(Axis::Horizontal) as f32 + } else { + 0.0 }, - &mut (), - ); - } - input::event::DeviceEvent::Removed(_) => { - callback( - Event::DeviceEvent { - device_id: DeviceId(platform_impl::DeviceId::Kms( - super::DeviceId, - )), - event: DeviceEvent::Removed, + if e.has_axis(Axis::Vertical) { + e.scroll_value(Axis::Vertical) as f32 + } else { + 0.0 }, - &mut (), - ); - } - _ => {} + ), + phase: TouchPhase::Moved, + modifiers: $self.modifiers, + }, }, - input::Event::Touch(ev) => match ev { - input::event::TouchEvent::Up(e) => callback( - Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::Touch(Touch { - device_id: DeviceId(platform_impl::DeviceId::Kms( - super::DeviceId, - )), - phase: TouchPhase::Ended, - location: self.touch_location, - force: None, - id: e.slot().unwrap() as u64, - }), - }, - &mut (), - ), - input::event::TouchEvent::Down(e) => { - self.touch_location.x = e.x_transformed(self.screen_size.0); - self.touch_location.y = e.y_transformed(self.screen_size.1); - - callback( - Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::Touch(Touch { - device_id: DeviceId(platform_impl::DeviceId::Kms( - super::DeviceId, - )), - phase: TouchPhase::Started, - location: self.touch_location, - force: None, - id: e.slot().unwrap() as u64, - }), + &mut (), + ); + } + input::event::PointerEvent::ScrollFinger(e) => { + use input::event::pointer::Axis; + + $callback( + Event::WindowEvent { + window_id: window_id!(), + event: WindowEvent::MouseWheel { + device_id: device_id!(), + delta: MouseScrollDelta::PixelDelta(PhysicalPosition::new( + if e.has_axis(Axis::Horizontal) { + e.scroll_value(Axis::Horizontal) + } else { + 0.0 }, - &mut (), - ) - } - input::event::TouchEvent::Motion(e) => { - self.touch_location.x = e.x_transformed(self.screen_size.0); - self.touch_location.y = e.y_transformed(self.screen_size.1); - - callback( - Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::Touch(Touch { - device_id: DeviceId(platform_impl::DeviceId::Kms( - super::DeviceId, - )), - phase: TouchPhase::Moved, - location: self.touch_location, - force: None, - id: e.slot().unwrap() as u64, - }), + if e.has_axis(Axis::Vertical) { + e.scroll_value(Axis::Vertical) + } else { + 0.0 }, - &mut (), - ); - } - input::event::TouchEvent::Cancel(e) => callback( + )), + phase: TouchPhase::Moved, + modifiers: $self.modifiers, + }, + }, + &mut (), + ); + } + input::event::PointerEvent::MotionAbsolute(e) => { + let mut lock = $self.cursor_positon.lock(); + + lock.x = e.absolute_x_transformed($self.screen_size.0); + + lock.y = e.absolute_y_transformed($self.screen_size.1); + + $callback( + Event::WindowEvent { + window_id: window_id!(), + event: WindowEvent::CursorMoved { + device_id: device_id!(), + position: *lock, + modifiers: $self.modifiers, + }, + }, + &mut (), + ); + } + _ => {} + } + }; +} + +macro_rules! handle_keyboard_event { + ($self:expr,$ev:expr,$callback:expr) => {{ + let state = match $ev.key_state() { + KeyState::Pressed => ElementState::Pressed, + KeyState::Released => ElementState::Released, + }; + + let k = if let input::event::KeyboardEvent::Key(key) = $ev { + key.key() + } else { + unreachable!() + }; + + let key_offset = k + 8; + let keysym = $self.xkb_ctx.key_get_one_sym(key_offset); + let virtual_keycode = xkb_keymap::keysym_to_vkey(keysym); + + $self.xkb_ctx.update_key( + key_offset, + match state { + ElementState::Pressed => xkb::KeyDirection::Down, + ElementState::Released => xkb::KeyDirection::Up, + }, + ); + + let input = KeyboardInput { + scancode: k, + state: state.clone(), + virtual_keycode, + modifiers: $self.modifiers, + }; + + $self.timer_handle.cancel_all_timeouts(); + + $callback( + Event::WindowEvent { + window_id: window_id!(), + event: WindowEvent::KeyboardInput { + device_id: device_id!(), + input, + is_synthetic: false, + }, + }, + &mut (), + ); + + if let ElementState::Pressed = state { + $self.xkb_compose.feed(keysym); + + match $self.xkb_compose.status() { + xkb::compose::Status::Composed => { + if let Some(c) = $self.xkb_compose.utf8().and_then(|f| f.chars().next()) { + $callback( Event::WindowEvent { window_id: window_id!(), - event: WindowEvent::Touch(Touch { - device_id: DeviceId(platform_impl::DeviceId::Kms( - super::DeviceId, - )), - phase: TouchPhase::Cancelled, - location: self.touch_location, - force: None, - id: e.slot().unwrap() as u64, - }), + event: WindowEvent::ReceivedCharacter(c), }, &mut (), - ), - input::event::TouchEvent::Frame(_) => callback( + ); + } + } + xkb::compose::Status::Cancelled => { + let should_repeat = $self.xkb_keymap.key_repeats(key_offset); + let ch = $self.xkb_ctx.key_get_utf8(key_offset).chars().next(); + + if should_repeat { + $self + .timer_handle + .add_timeout(Duration::from_millis(REPEAT_DELAY), (input, ch)); + } + + if let Some(c) = ch { + $callback( Event::WindowEvent { window_id: window_id!(), - event: WindowEvent::Touch(Touch { - device_id: DeviceId(platform_impl::DeviceId::Kms( - super::DeviceId, - )), - phase: TouchPhase::Ended, - location: self.touch_location, - force: None, - id: 0, // e.slot().unwrap() as u64, - }), + event: WindowEvent::ReceivedCharacter(c), }, &mut (), - ), - _ => {} - }, - input::Event::Tablet(ev) => match ev { - input::event::TabletToolEvent::Tip(e) => callback( + ); + } + } + xkb::compose::Status::Nothing => { + let should_repeat = $self.xkb_keymap.key_repeats(key_offset); + let ch = $self.xkb_ctx.key_get_utf8(key_offset).chars().next(); + + if should_repeat { + $self + .timer_handle + .add_timeout(Duration::from_millis(600), (input, ch)); + } + + if let Some(c) = ch { + $callback( Event::WindowEvent { window_id: window_id!(), - event: WindowEvent::Touch(Touch { - device_id: DeviceId(platform_impl::DeviceId::Kms( - super::DeviceId, - )), - phase: match e.tip_state() { - TipState::Down => TouchPhase::Started, - TipState::Up => TouchPhase::Ended, - }, - location: PhysicalPosition::new( - e.x_transformed(self.screen_size.0), - e.y_transformed(self.screen_size.1), - ), - force: Some(Force::Calibrated { - force: e.pressure(), - max_possible_force: 1.0, - altitude_angle: None, - }), - id: 0, - }), + event: WindowEvent::ReceivedCharacter(c), }, &mut (), - ), - input::event::TabletToolEvent::Button(e) => { - callback( - Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::MouseInput { - device_id: DeviceId(platform_impl::DeviceId::Kms( - super::DeviceId, - )), - state: match e.button_state() { - ButtonState::Pressed => ElementState::Pressed, - ButtonState::Released => ElementState::Released, - }, - button: match e.button() { - 1 => MouseButton::Right, - 2 => MouseButton::Middle, - _ => MouseButton::Left, - }, - modifiers: self.modifiers, - }, - }, - &mut (), - ); - - callback( - Event::DeviceEvent { - device_id: DeviceId(platform_impl::DeviceId::Kms( - super::DeviceId, - )), - event: DeviceEvent::Button { - button: e.button(), - state: match e.button_state() { - ButtonState::Pressed => ElementState::Pressed, - ButtonState::Released => ElementState::Released, - }, - }, - }, - &mut (), - ); - } - _ => {} + ); + } + } + _ => {} + } + } + match keysym { + xkb_keymap::XKB_KEY_Alt_L | xkb_keymap::XKB_KEY_Alt_R => { + match state { + ElementState::Pressed => $self.modifiers |= ModifiersState::ALT, + ElementState::Released => $self.modifiers.remove(ModifiersState::ALT), + } + + $callback( + Event::WindowEvent { + window_id: window_id!(), + event: WindowEvent::ModifiersChanged($self.modifiers), }, - input::Event::Pointer(e) => match e { - input::event::PointerEvent::Motion(e) => { - let mut lock = self.cursor_positon.lock(); - - lock.x += e.dx(); - lock.x = lock.x.clamp(0.0, self.screen_size.0 as f64); - - lock.y += e.dy(); - lock.y = lock.y.clamp(0.0, self.screen_size.1 as f64); - - callback( - Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::CursorMoved { - device_id: DeviceId(platform_impl::DeviceId::Kms( - super::DeviceId, - )), - position: *lock, - modifiers: self.modifiers, - }, - }, - &mut (), - ); - - callback( - Event::DeviceEvent { - device_id: DeviceId(platform_impl::DeviceId::Kms( - super::DeviceId, - )), - event: DeviceEvent::MouseMotion { - delta: (e.dx(), e.dy()), - }, - }, - &mut (), - ); - } - input::event::PointerEvent::Button(e) => { - callback( - Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::MouseInput { - device_id: DeviceId(platform_impl::DeviceId::Kms( - super::DeviceId, - )), - state: match e.button_state() { - ButtonState::Pressed => ElementState::Pressed, - ButtonState::Released => ElementState::Released, - }, - button: match e.button() { - 1 => MouseButton::Right, - 2 => MouseButton::Middle, - _ => MouseButton::Left, - }, - modifiers: self.modifiers, - }, - }, - &mut (), - ); - - callback( - Event::DeviceEvent { - device_id: DeviceId(platform_impl::DeviceId::Kms( - super::DeviceId, - )), - event: DeviceEvent::Button { - button: e.button(), - state: match e.button_state() { - ButtonState::Pressed => ElementState::Pressed, - ButtonState::Released => ElementState::Released, - }, - }, - }, - &mut (), - ); - } - input::event::PointerEvent::ScrollWheel(e) => { - use input::event::pointer::Axis; - - callback( - Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::MouseWheel { - device_id: DeviceId(platform_impl::DeviceId::Kms( - super::DeviceId, - )), - delta: MouseScrollDelta::LineDelta( - if e.has_axis(Axis::Horizontal) { - e.scroll_value(Axis::Horizontal) as f32 - } else { - 0.0 - }, - if e.has_axis(Axis::Vertical) { - e.scroll_value(Axis::Vertical) as f32 - } else { - 0.0 - }, - ), - phase: TouchPhase::Moved, - modifiers: self.modifiers, - }, - }, - &mut (), - ); - } - input::event::PointerEvent::ScrollFinger(e) => { - use input::event::pointer::Axis; - - callback( - Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::MouseWheel { - device_id: DeviceId(platform_impl::DeviceId::Kms( - super::DeviceId, - )), - delta: MouseScrollDelta::PixelDelta(PhysicalPosition::new( - if e.has_axis(Axis::Horizontal) { - e.scroll_value(Axis::Horizontal) - } else { - 0.0 - }, - if e.has_axis(Axis::Vertical) { - e.scroll_value(Axis::Vertical) - } else { - 0.0 - }, - )), - phase: TouchPhase::Moved, - modifiers: self.modifiers, - }, - }, - &mut (), - ); - } - input::event::PointerEvent::MotionAbsolute(e) => { - let mut lock = self.cursor_positon.lock(); - - lock.x = e.absolute_x_transformed(self.screen_size.0); - - lock.y = e.absolute_y_transformed(self.screen_size.1); - - callback( - Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::CursorMoved { - device_id: DeviceId(platform_impl::DeviceId::Kms( - super::DeviceId, - )), - position: *lock, - modifiers: self.modifiers, - }, - }, - &mut (), - ); - } - _ => {} + &mut (), + ); + } + xkb_keymap::XKB_KEY_Shift_L | xkb_keymap::XKB_KEY_Shift_R => { + match state { + ElementState::Pressed => $self.modifiers |= ModifiersState::SHIFT, + ElementState::Released => $self.modifiers.remove(ModifiersState::SHIFT), + } + + $callback( + Event::WindowEvent { + window_id: window_id!(), + event: WindowEvent::ModifiersChanged($self.modifiers), }, - input::Event::Keyboard(ev) => { - let state = match ev.key_state() { - KeyState::Pressed => ElementState::Pressed, - KeyState::Released => ElementState::Released, - }; - - let k = if let input::event::KeyboardEvent::Key(key) = ev { - key.key() - } else { - unreachable!() - }; - - let key_offset = k + 8; - let keysym = self.xkb_ctx.key_get_one_sym(key_offset); - let virtual_keycode = xkb_keymap::keysym_to_vkey(keysym); - - self.xkb_ctx.update_key( - key_offset, - match state { - ElementState::Pressed => xkb::KeyDirection::Down, - ElementState::Released => xkb::KeyDirection::Up, - }, - ); + &mut (), + ); + } - let input = KeyboardInput { - scancode: k, - state: state.clone(), - virtual_keycode, - modifiers: self.modifiers, - }; + xkb_keymap::XKB_KEY_Control_L | xkb_keymap::XKB_KEY_Control_R => { + match state { + ElementState::Pressed => $self.modifiers |= ModifiersState::CTRL, + ElementState::Released => $self.modifiers.remove(ModifiersState::CTRL), + } - self.timer_handle.cancel_all_timeouts(); + $callback( + Event::WindowEvent { + window_id: window_id!(), + event: WindowEvent::ModifiersChanged($self.modifiers), + }, + &mut (), + ); + } - callback( - Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::KeyboardInput { - device_id: DeviceId(platform_impl::DeviceId::Kms( - super::DeviceId, - )), - input, - is_synthetic: false, - }, - }, - &mut (), - ); + xkb_keymap::XKB_KEY_Meta_L | xkb_keymap::XKB_KEY_Meta_R => { + match state { + ElementState::Pressed => $self.modifiers |= ModifiersState::LOGO, + ElementState::Released => $self.modifiers.remove(ModifiersState::LOGO), + } - if let ElementState::Pressed = state { - self.xkb_compose.feed(keysym); - - match self.xkb_compose.status() { - xkb::compose::Status::Composed => { - if let Some(c) = - self.xkb_compose.utf8().and_then(|f| f.chars().next()) - { - callback( - Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::ReceivedCharacter(c), - }, - &mut (), - ); - } - } - xkb::compose::Status::Cancelled => { - let should_repeat = self.xkb_keymap.key_repeats(key_offset); - let ch = self.xkb_ctx.key_get_utf8(key_offset).chars().next(); - - if should_repeat { - self.timer_handle.add_timeout( - Duration::from_millis(REPEAT_DELAY), - (input, ch), - ); - } - - if let Some(c) = ch { - callback( - Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::ReceivedCharacter(c), - }, - &mut (), - ); - } - } - xkb::compose::Status::Nothing => { - let should_repeat = self.xkb_keymap.key_repeats(key_offset); - let ch = self.xkb_ctx.key_get_utf8(key_offset).chars().next(); - - if should_repeat { - self.timer_handle - .add_timeout(Duration::from_millis(600), (input, ch)); - } - - if let Some(c) = ch { - callback( - Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::ReceivedCharacter(c), - }, - &mut (), - ); - } - } - _ => {} - } - } - match keysym { - xkb_keymap::XKB_KEY_Alt_L | xkb_keymap::XKB_KEY_Alt_R => { - match state { - ElementState::Pressed => self.modifiers |= ModifiersState::ALT, - ElementState::Released => { - self.modifiers.remove(ModifiersState::ALT) - } - } - - callback( - Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::ModifiersChanged(self.modifiers), - }, - &mut (), - ); - } - xkb_keymap::XKB_KEY_Shift_L | xkb_keymap::XKB_KEY_Shift_R => { - match state { - ElementState::Pressed => { - self.modifiers |= ModifiersState::SHIFT - } - ElementState::Released => { - self.modifiers.remove(ModifiersState::SHIFT) - } - } - - callback( - Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::ModifiersChanged(self.modifiers), - }, - &mut (), - ); - } + $callback( + Event::WindowEvent { + window_id: window_id!(), + event: WindowEvent::ModifiersChanged($self.modifiers), + }, + &mut (), + ); + } + xkb_keymap::XKB_KEY_Sys_Req | xkb_keymap::XKB_KEY_Print => { + if $self.modifiers.is_empty() { + $callback( + Event::WindowEvent { + window_id: window_id!(), + event: WindowEvent::CloseRequested, + }, + &mut (), + ); + } + } + _ => {} + } + }}; +} - xkb_keymap::XKB_KEY_Control_L | xkb_keymap::XKB_KEY_Control_R => { - match state { - ElementState::Pressed => self.modifiers |= ModifiersState::CTRL, - ElementState::Released => { - self.modifiers.remove(ModifiersState::CTRL) - } - } - - callback( - Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::ModifiersChanged(self.modifiers), - }, - &mut (), - ); - } +impl EventSource for LibinputInputBackend { + type Event = Event<'static, ()>; + type Metadata = (); + type Ret = (); - xkb_keymap::XKB_KEY_Meta_L | xkb_keymap::XKB_KEY_Meta_R => { - match state { - ElementState::Pressed => self.modifiers |= ModifiersState::LOGO, - ElementState::Released => { - self.modifiers.remove(ModifiersState::LOGO) - } - } - - callback( - Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::ModifiersChanged(self.modifiers), - }, - &mut (), - ); - } - xkb_keymap::XKB_KEY_Sys_Req | xkb_keymap::XKB_KEY_Print => { - if self.modifiers.is_empty() { - callback( - Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::CloseRequested, - }, - &mut (), - ); - } - } - _ => {} - } - } + fn process_events( + &mut self, + _: Readiness, + token: Token, + mut callback: F, + ) -> std::io::Result + where + F: FnMut(Self::Event, &mut ()) -> Self::Ret, + { + if token == self.token { + self.context.dispatch()?; + + for event in &mut self.context { + match event { + input::Event::Device(ev) => handle_device_event!(ev, callback), + input::Event::Touch(ev) => handle_touch_event!(self, ev, callback), + input::Event::Tablet(ev) => handle_tablet_tool_event!(self, ev, callback), + input::Event::Pointer(ev) => handle_pointer_event!(self, ev, callback), + input::Event::Keyboard(ev) => handle_keyboard_event!(self, ev, callback), _ => {} } } diff --git a/src/platform_impl/linux/kms/window.rs b/src/platform_impl/linux/kms/window.rs index 45d3b52e3a..9a7db94ec4 100644 --- a/src/platform_impl/linux/kms/window.rs +++ b/src/platform_impl/linux/kms/window.rs @@ -228,10 +228,7 @@ impl Window { } #[inline] - pub fn set_inner_size(&self, _size: Size) { - // It's technically possible to do this by changing video modes but that seems a little - // restrictive - } + pub fn set_inner_size(&self, _size: Size) {} #[inline] pub fn set_min_inner_size(&self, _dimensions: Option) {} From 3de76550a6cc2f7f8531c66a0ed3914857107bdc Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Mon, 9 May 2022 18:30:47 -0400 Subject: [PATCH 100/151] Add ability to change mode --- src/platform/unix.rs | 4 +- src/platform_impl/linux/kms/event_loop.rs | 32 ++--- src/platform_impl/linux/kms/mod.rs | 3 + src/platform_impl/linux/kms/window.rs | 136 +++++++++++++++++----- 4 files changed, 127 insertions(+), 48 deletions(-) diff --git a/src/platform/unix.rs b/src/platform/unix.rs index f741017d44..1589de3cef 100644 --- a/src/platform/unix.rs +++ b/src/platform/unix.rs @@ -155,7 +155,9 @@ impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { #[cfg(feature = "kms")] fn drm_mode(&self) -> Option { match self.p { - crate::platform_impl::EventLoopWindowTarget::Kms(ref window) => Some(window.mode), + crate::platform_impl::EventLoopWindowTarget::Kms(_) => { + crate::platform_impl::kms::MODE.lock().clone() + } #[cfg(any(feature = "x11", feature = "wayland"))] _ => None, } diff --git a/src/platform_impl/linux/kms/event_loop.rs b/src/platform_impl/linux/kms/event_loop.rs index f9da86af2f..e440a8a59b 100644 --- a/src/platform_impl/linux/kms/event_loop.rs +++ b/src/platform_impl/linux/kms/event_loop.rs @@ -41,6 +41,8 @@ use crate::{ window::WindowId, }; +use super::MODE; + macro_rules! to_platform_impl { ($p:ident, $params:expr) => { $p(platform_impl::$p::Kms($params)) @@ -713,9 +715,6 @@ pub struct EventLoopWindowTarget { /// Drm crtc pub crtc: crtc::Info, - /// Drm mode - pub mode: drm::control::Mode, - /// Drm plane pub plane: plane::Handle, @@ -742,23 +741,27 @@ impl EventLoopWindowTarget { Some(MonitorHandle { inner: platform_impl::MonitorHandle::Kms(super::MonitorHandle { connector: self.connector.clone(), - name: self.mode.name().to_string_lossy().into_owned(), + name: (*MODE.lock())?.name().to_string_lossy().into_owned(), }), }) } #[inline] pub fn available_monitors(&self) -> VecDeque { - self.device - .resource_handles() - .unwrap() - .connectors() - .iter() - .map(|f| super::MonitorHandle { - connector: self.device.get_connector(*f).unwrap(), - name: self.mode.name().to_string_lossy().into_owned(), - }) - .collect() + if let Some(mode) = *MODE.lock() { + self.device + .resource_handles() + .unwrap() + .connectors() + .iter() + .map(|f| super::MonitorHandle { + connector: self.device.get_connector(*f).unwrap(), + name: mode.name().to_string_lossy().into_owned(), + }) + .collect() + } else { + VecDeque::new() + } } } @@ -1224,7 +1227,6 @@ impl EventLoop { device: drm, plane: p_plane, cursor_arc, - mode, event_loop_handle: handle, event_sink, event_loop_awakener, diff --git a/src/platform_impl/linux/kms/mod.rs b/src/platform_impl/linux/kms/mod.rs index e10874d758..f3ea696293 100644 --- a/src/platform_impl/linux/kms/mod.rs +++ b/src/platform_impl/linux/kms/mod.rs @@ -11,11 +11,14 @@ use drm::{ pub use event_loop::EventLoop; pub use event_loop::EventLoopProxy; pub use event_loop::EventLoopWindowTarget; +use parking_lot::Mutex; use std::os::unix; use std::os::unix::prelude::FromRawFd; use std::sync::Arc; pub use window::Window; +pub static MODE: Mutex> = parking_lot::const_mutex(None); + #[derive(Debug, Clone)] /// A simple wrapper for a device node. pub struct Card(pub(crate) Arc); diff --git a/src/platform_impl/linux/kms/window.rs b/src/platform_impl/linux/kms/window.rs index 9a7db94ec4..a535550524 100644 --- a/src/platform_impl/linux/kms/window.rs +++ b/src/platform_impl/linux/kms/window.rs @@ -1,6 +1,7 @@ use std::{collections::VecDeque, os::unix::prelude::AsRawFd, sync::Arc}; -use drm::control::{atomic, property, AtomicCommitFlags, Device, ResourceHandle}; +use super::MODE; +use drm::control::*; use parking_lot::Mutex; use crate::{ @@ -13,10 +14,10 @@ use crate::{ }; pub struct Window { - mode: drm::control::Mode, - connector: drm::control::connector::Info, + connector: connector::Info, + crtc: crtc::Info, ping: calloop::ping::Ping, - plane: drm::control::plane::Handle, + plane: plane::Handle, cursor: Arc>>, card: Card, } @@ -36,17 +37,23 @@ fn find_prop_id( .cloned() } +macro_rules! find_prop_id { + ($id_handle_1:expr,$handle:expr,$prop_name:literal) => { + find_prop_id(&$id_handle_1, $handle, $prop_name).ok_or_else(|| { + OsError::new( + line!(), + file!(), + platform_impl::OsError::KmsMisc(concat!("could not get ", $prop_name)), + ) + }) + }; +} + macro_rules! add_property { ($atomic_req:expr,$handle:expr,$id_handle_1:expr,$prop_name:literal,$property:expr,) => { $atomic_req.add_property( $handle, - find_prop_id(&$id_handle_1, $handle, $prop_name).ok_or_else(|| { - OsError::new( - line!(), - file!(), - platform_impl::OsError::KmsMisc(concat!("could not get ", $prop_name)), - ) - })?, + find_prop_id!(&$id_handle_1, $handle, $prop_name)?, $property, ); }; @@ -68,9 +75,17 @@ impl Window { property::Value::CRTC(Some(event_loop_window_target.crtc.handle())), ); + let ref mode = MODE.lock().as_ref().ok_or_else(|| { + OsError::new( + line!(), + file!(), + platform_impl::OsError::KmsMisc("mode is not initialized"), + ) + })?; + let blob = event_loop_window_target .device - .create_property_blob(&event_loop_window_target.mode) + .create_property_blob(mode) .map_err(|_| { OsError::new( line!(), @@ -124,7 +139,7 @@ impl Window { event_loop_window_target.plane, event_loop_window_target.device, "SRC_W", - property::Value::UnsignedRange((event_loop_window_target.mode.size().0 as u64) << 16), + property::Value::UnsignedRange((mode.size().0 as u64) << 16), ); add_property!( @@ -132,7 +147,7 @@ impl Window { event_loop_window_target.plane, event_loop_window_target.device, "SRC_H", - property::Value::UnsignedRange((event_loop_window_target.mode.size().1 as u64) << 16), + property::Value::UnsignedRange((mode.size().1 as u64) << 16), ); add_property!( @@ -156,7 +171,7 @@ impl Window { event_loop_window_target.plane, event_loop_window_target.device, "CRTC_W", - property::Value::UnsignedRange(event_loop_window_target.mode.size().0 as u64), + property::Value::UnsignedRange(mode.size().0 as u64), ); add_property!( @@ -164,7 +179,7 @@ impl Window { event_loop_window_target.plane, event_loop_window_target.device, "CRTC_H", - property::Value::UnsignedRange(event_loop_window_target.mode.size().1 as u64), + property::Value::UnsignedRange(mode.size().1 as u64), ); event_loop_window_target @@ -179,8 +194,8 @@ impl Window { })?; Ok(Self { - mode: event_loop_window_target.mode.clone(), connector: event_loop_window_target.connector.clone(), + crtc: event_loop_window_target.crtc.clone(), plane: event_loop_window_target.plane.clone(), cursor: event_loop_window_target.cursor_arc.clone(), ping: event_loop_window_target.event_loop_awakener.clone(), @@ -218,7 +233,7 @@ impl Window { #[inline] pub fn inner_size(&self) -> PhysicalSize { - let size = self.mode.size(); + let size = MODE.lock().expect("mode is not initialized").size(); PhysicalSize::new(size.0 as u32, size.1 as u32) } @@ -291,14 +306,67 @@ impl Window { pub fn fullscreen(&self) -> Option { Some(Fullscreen::Exclusive(VideoMode { video_mode: platform_impl::VideoMode::Kms(super::VideoMode { - mode: self.mode, + mode: MODE.lock().expect("mode is not initialized"), connector: self.connector.clone(), }), })) } #[inline] - pub fn set_fullscreen(&self, _monitor: Option) {} + pub fn set_fullscreen(&self, monitor: Option) { + match monitor { + Some(Fullscreen::Exclusive(fullscreen)) => { + let modes = self.connector.modes().to_vec(); + let connector = self.connector.clone(); + if let Some(mo) = modes.into_iter().find(move |&f| { + VideoMode { + video_mode: platform_impl::VideoMode::Kms(super::VideoMode { + mode: f, + connector: connector.clone(), + }), + } == fullscreen + }) { + let mut atomic_req = atomic::AtomicModeReq::new(); + let blob = self.card.create_property_blob(&mo).unwrap(); + + atomic_req.add_property( + self.crtc.handle(), + find_prop_id!(&self.card, self.crtc.handle(), "MODE_ID").unwrap(), + blob, + ); + + atomic_req.add_property( + self.plane, + find_prop_id!(&self.card, self.plane, "SRC_W").unwrap(), + property::Value::UnsignedRange((mo.size().0 as u64) << 16), + ); + + atomic_req.add_property( + self.plane, + find_prop_id!(&self.card, self.plane, "SRC_H").unwrap(), + property::Value::UnsignedRange((mo.size().1 as u64) << 16), + ); + + atomic_req.add_property( + self.plane, + find_prop_id!(&self.card, self.plane, "CRTC_W").unwrap(), + property::Value::UnsignedRange(mo.size().0 as u64), + ); + + atomic_req.add_property( + self.plane, + find_prop_id!(&self.card, self.plane, "CRTC_H").unwrap(), + property::Value::UnsignedRange(mo.size().1 as u64), + ); + + self.card + .atomic_commit(AtomicCommitFlags::ALLOW_MODESET, atomic_req) + .unwrap(); + } + } + _ => {} + } + } #[inline] pub fn set_decorations(&self, _decorations: bool) {} @@ -322,22 +390,26 @@ impl Window { pub fn current_monitor(&self) -> Option { Some(super::MonitorHandle { connector: self.connector.clone(), - name: self.mode.name().to_string_lossy().into_owned(), + name: (*MODE.lock())?.name().to_string_lossy().into_owned(), }) } #[inline] pub fn available_monitors(&self) -> VecDeque { - self.card - .resource_handles() - .unwrap() - .connectors() - .iter() - .map(|f| super::MonitorHandle { - connector: self.card.get_connector(*f).unwrap(), - name: self.mode.name().to_string_lossy().into_owned(), - }) - .collect() + if let Some(mode) = *MODE.lock() { + self.card + .resource_handles() + .unwrap() + .connectors() + .iter() + .map(|f| super::MonitorHandle { + connector: self.card.get_connector(*f).unwrap(), + name: mode.name().to_string_lossy().into_owned(), + }) + .collect() + } else { + VecDeque::new() + } } #[inline] @@ -353,7 +425,7 @@ impl Window { Some(MonitorHandle { inner: platform_impl::MonitorHandle::Kms(super::MonitorHandle { connector: self.connector.clone(), - name: self.mode.name().to_string_lossy().into_owned(), + name: (*MODE.lock())?.name().to_string_lossy().into_owned(), }), }) } From 52a79c27c60c2dc6ad025ed17cae1aacc05022fb Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Mon, 9 May 2022 18:52:31 -0400 Subject: [PATCH 101/151] Adjust readability --- src/platform/unix.rs | 33 ++++++++++++----------- src/platform_impl/linux/kms/event_loop.rs | 1 + src/platform_impl/linux/kms/window.rs | 2 +- src/platform_impl/linux/mod.rs | 6 ++--- 4 files changed, 22 insertions(+), 20 deletions(-) diff --git a/src/platform/unix.rs b/src/platform/unix.rs index 1589de3cef..a1c6350602 100644 --- a/src/platform/unix.rs +++ b/src/platform/unix.rs @@ -24,7 +24,8 @@ use crate::dpi::Size; #[cfg(feature = "x11")] use crate::platform_impl::x11::{ffi::XVisualInfo, XConnection}; use crate::platform_impl::{ - ApplicationName, EventLoopWindowTarget as LinuxEventLoopWindowTarget, Window as LinuxWindow, + kms::MODE, ApplicationName, EventLoopWindowTarget as LinuxEventLoopWindowTarget, + Window as LinuxWindow, }; #[cfg(any(feature = "x11", feature = "wayland", feature = "kms"))] @@ -38,6 +39,8 @@ pub use crate::platform_impl::kms::Card; pub use crate::platform_impl::x11; #[cfg(feature = "x11")] pub use crate::platform_impl::{x11::util::WindowType as XWindowType, XNotSupported}; +#[cfg(feature = "kms")] +use drm::control::*; /// Additional methods on `EventLoopWindowTarget` that are specific to Unix. pub trait EventLoopWindowTargetExtUnix { @@ -61,31 +64,31 @@ pub trait EventLoopWindowTargetExtUnix { /// /// Returns `None` if the `EventLoop` doesn't use drm. #[cfg(feature = "kms")] - fn drm_device(&self) -> Option<&crate::platform::unix::Card>; + fn drm_device(&self) -> Option<&Card>; /// Returns the current crtc of the drm device /// /// Returns `None` if the `EventLoop` doesn't use drm. #[cfg(feature = "kms")] - fn drm_crtc(&self) -> Option<&drm::control::crtc::Info>; + fn drm_crtc(&self) -> Option<&crtc::Info>; /// Returns the current connector of the drm device /// /// Returns `None` if the `EventLoop` doesn't use drm. #[cfg(feature = "kms")] - fn drm_connector(&self) -> Option<&drm::control::connector::Info>; + fn drm_connector(&self) -> Option<&connector::Info>; /// Returns the current mode of the drm device /// /// Returns `None` if the `EventLoop` doesn't use drm. #[cfg(feature = "kms")] - fn drm_mode(&self) -> Option; + fn drm_mode(&self) -> Option; /// Returns the primary plane of the drm device /// /// Returns `None` if the `EventLoop` doesn't use drm. #[cfg(feature = "kms")] - fn drm_plane(&self) -> Option; + fn drm_plane(&self) -> Option; } impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { @@ -123,9 +126,9 @@ impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { #[inline] #[cfg(feature = "kms")] - fn drm_device(&self) -> Option<&crate::platform::unix::Card> { + fn drm_device(&self) -> Option<&Card> { match self.p { - crate::platform_impl::EventLoopWindowTarget::Kms(ref evlp) => Some(&evlp.device), + LinuxEventLoopWindowTarget::Kms(ref evlp) => Some(&evlp.device), #[cfg(any(feature = "x11", feature = "wayland"))] _ => None, } @@ -133,9 +136,9 @@ impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { #[inline] #[cfg(feature = "kms")] - fn drm_crtc(&self) -> Option<&drm::control::crtc::Info> { + fn drm_crtc(&self) -> Option<&crtc::Info> { match self.p { - crate::platform_impl::EventLoopWindowTarget::Kms(ref window) => Some(&window.crtc), + LinuxEventLoopWindowTarget::Kms(ref window) => Some(&window.crtc), #[cfg(any(feature = "x11", feature = "wayland"))] _ => None, } @@ -143,9 +146,9 @@ impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { #[inline] #[cfg(feature = "kms")] - fn drm_connector(&self) -> Option<&drm::control::connector::Info> { + fn drm_connector(&self) -> Option<&connector::Info> { match self.p { - crate::platform_impl::EventLoopWindowTarget::Kms(ref window) => Some(&window.connector), + LinuxEventLoopWindowTarget::Kms(ref window) => Some(&window.connector), #[cfg(any(feature = "x11", feature = "wayland"))] _ => None, } @@ -155,9 +158,7 @@ impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { #[cfg(feature = "kms")] fn drm_mode(&self) -> Option { match self.p { - crate::platform_impl::EventLoopWindowTarget::Kms(_) => { - crate::platform_impl::kms::MODE.lock().clone() - } + LinuxEventLoopWindowTarget::Kms(_) => MODE.lock().clone(), #[cfg(any(feature = "x11", feature = "wayland"))] _ => None, } @@ -167,7 +168,7 @@ impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { #[cfg(feature = "kms")] fn drm_plane(&self) -> Option { match self.p { - crate::platform_impl::EventLoopWindowTarget::Kms(ref window) => Some(window.plane), + LinuxEventLoopWindowTarget::Kms(ref window) => Some(window.plane), #[cfg(any(feature = "x11", feature = "wayland"))] _ => None, } diff --git a/src/platform_impl/linux/kms/event_loop.rs b/src/platform_impl/linux/kms/event_loop.rs index e440a8a59b..24c516b7f1 100644 --- a/src/platform_impl/linux/kms/event_loop.rs +++ b/src/platform_impl/linux/kms/event_loop.rs @@ -503,6 +503,7 @@ macro_rules! handle_keyboard_event { }, ); + #[allow(deprecated)] let input = KeyboardInput { scancode: k, state: state.clone(), diff --git a/src/platform_impl/linux/kms/window.rs b/src/platform_impl/linux/kms/window.rs index a535550524..efbd2034df 100644 --- a/src/platform_impl/linux/kms/window.rs +++ b/src/platform_impl/linux/kms/window.rs @@ -75,7 +75,7 @@ impl Window { property::Value::CRTC(Some(event_loop_window_target.crtc.handle())), ); - let ref mode = MODE.lock().as_ref().ok_or_else(|| { + let ref mode = MODE.lock().ok_or_else(|| { OsError::new( line!(), file!(), diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index e1f9c49e92..669c9fd2e0 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -802,19 +802,19 @@ impl EventLoop { pub fn run_return(&mut self, callback: F) -> i32 where - F: FnMut(crate::event::Event<'_, T>, &RootELW, &mut ControlFlow), + F: FnMut(Event<'_, T>, &RootELW, &mut ControlFlow), { x11_or_wayland_or_drm!(match self; EventLoop(evlp) => evlp.run_return(callback)) } pub fn run(self, callback: F) -> ! where - F: 'static + FnMut(crate::event::Event<'_, T>, &RootELW, &mut ControlFlow), + F: 'static + FnMut(Event<'_, T>, &RootELW, &mut ControlFlow), { x11_or_wayland_or_drm!(match self; EventLoop(evlp) => evlp.run(callback)) } - pub fn window_target(&self) -> &crate::event_loop::EventLoopWindowTarget { + pub fn window_target(&self) -> &RootELW { x11_or_wayland_or_drm!(match self; EventLoop(evl) => evl.window_target()) } } From 5a16458a0844defc02cef653203e753907f816ab Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Mon, 9 May 2022 19:19:44 -0400 Subject: [PATCH 102/151] Convert to plane function --- src/platform_impl/linux/kms/event_loop.rs | 83 +++++++++++++---------- 1 file changed, 46 insertions(+), 37 deletions(-) diff --git a/src/platform_impl/linux/kms/event_loop.rs b/src/platform_impl/linux/kms/event_loop.rs index 24c516b7f1..970ab37db1 100644 --- a/src/platform_impl/linux/kms/event_loop.rs +++ b/src/platform_impl/linux/kms/event_loop.rs @@ -766,6 +766,51 @@ impl EventLoopWindowTarget { } } +fn find_plane( + planes: PlaneResourceHandles, + res: ResourceHandles, + crtc: &crtc::Info, + drm: &Card, +) -> plane::Handle { + let (p_better_planes, p_compatible_planes): ( + // The primary planes available to us + Vec, + // Other, not-ideal planes that are however useable + Vec, + ) = planes + .planes() + .iter() + .filter(|&&plane| { + // Get the plane info from a handle + drm.get_plane(plane) + .map(|plane_info| { + let compatible_crtcs = res.filter_crtcs(plane_info.possible_crtcs()); + // Makes sure that the plane can be used with the CRTC we selected earlier + compatible_crtcs.contains(&crtc.handle()) + }) + .unwrap_or(false) + }) + .partition(|&&plane| { + // Get the plane properties from a handle + if let Ok(props) = drm.get_properties(plane) { + let (ids, vals) = props.as_props_and_values(); + for (&id, &val) in ids.iter().zip(vals.iter()) { + if let Ok(info) = drm.get_property(id) { + // Checks if the plane is a primary plane, and returns true if it is, + // if not it returns false + if info.name().to_str().map(|x| x == "type").unwrap_or(false) { + return val == (PlaneType::Primary as u32).into(); + } + } + } + } + false + }); + + // Get the first (best) plane we find, or the first compatibile plane + *p_better_planes.get(0).unwrap_or(&p_compatible_planes[0]) +} + fn find_card_path(seat_name: &str) -> Result { let mut enumerator = Enumerator::new().map_err(|e| { OsError::new( @@ -1087,43 +1132,7 @@ impl EventLoop { ) })?; - let (p_better_planes, p_compatible_planes): ( - // The primary planes available to us - Vec, - // Other, not-ideal planes that are however useable - Vec, - ) = planes - .planes() - .iter() - .filter(|&&plane| { - // Get the plane info from a handle - drm.get_plane(plane) - .map(|plane_info| { - let compatible_crtcs = res.filter_crtcs(plane_info.possible_crtcs()); - // Makes sure that the plane can be used with the CRTC we selected earlier - compatible_crtcs.contains(&crtc.handle()) - }) - .unwrap_or(false) - }) - .partition(|&&plane| { - // Get the plane properties from a handle - if let Ok(props) = drm.get_properties(plane) { - let (ids, vals) = props.as_props_and_values(); - for (&id, &val) in ids.iter().zip(vals.iter()) { - if let Ok(info) = drm.get_property(id) { - // Checks if the plane is a primary plane, and returns true if it is, - // if not it returns false - if info.name().to_str().map(|x| x == "type").unwrap_or(false) { - return val == (PlaneType::Primary as u32).into(); - } - } - } - } - false - }); - - // Get the first (best) plane we find, or the first compatibile plane - let p_plane = *p_better_planes.get(0).unwrap_or(&p_compatible_planes[0]); + let p_plane = find_plane(planes, res, crtc, &drm); let (disp_width, disp_height) = mode.size(); From 128724d17c7282f6bd8b1b917e610ca4bb78ec34 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Mon, 9 May 2022 19:34:27 -0400 Subject: [PATCH 103/151] Fix calloop reexport --- Cargo.toml | 148 +++++++++--------- src/platform/unix.rs | 8 +- src/platform_impl/linux/mod.rs | 2 +- .../linux/wayland/event_loop/mod.rs | 1 + .../linux/wayland/event_loop/proxy.rs | 2 +- .../linux/wayland/seat/keyboard/mod.rs | 2 +- src/platform_impl/linux/wayland/seat/mod.rs | 2 +- src/platform_impl/linux/wayland/window/mod.rs | 1 + src/platform_impl/linux/xkb_keymap.rs | 4 +- 9 files changed, 89 insertions(+), 81 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2a41dbf9aa..197af27f71 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ targets = ["i686-pc-windows-msvc", "x86_64-pc-windows-msvc", "i686-unknown-linux [features] default = ["x11", "wayland", "wayland-dlopen", "kms"] x11 = ["x11-dl", "mio", "percent-encoding", "parking_lot"] -wayland = ["wayland-client", "wayland-protocols", "sctk", "calloop"] +wayland = ["wayland-client", "wayland-protocols", "sctk"] wayland-dlopen = ["sctk/dlopen", "wayland-client/dlopen"] kms = ["drm", "input", "calloop", "xkbcommon", "udev"] kms-ext = ["libseat"] @@ -62,81 +62,81 @@ parking_lot = "0.12.0" [target.'cfg(target_os = "windows")'.dependencies.windows-sys] version = "0.36.1" features = [ - "Win32_Devices_HumanInterfaceDevice", - "Win32_Foundation", - "Win32_Globalization", - "Win32_Graphics_Dwm", - "Win32_Graphics_Gdi", - "Win32_Media", - "Win32_System_Com_StructuredStorage", - "Win32_System_Com", - "Win32_System_LibraryLoader", - "Win32_System_Ole", - "Win32_System_SystemInformation", - "Win32_System_SystemServices", - "Win32_System_Threading", - "Win32_System_WindowsProgramming", - "Win32_UI_Accessibility", - "Win32_UI_Controls", - "Win32_UI_HiDpi", - "Win32_UI_Input_Ime", - "Win32_UI_Input_KeyboardAndMouse", - "Win32_UI_Input_Pointer", - "Win32_UI_Input_Touch", - "Win32_UI_Shell", - "Win32_UI_TextServices", - "Win32_UI_WindowsAndMessaging", -] + "Win32_Devices_HumanInterfaceDevice", + "Win32_Foundation", + "Win32_Globalization", + "Win32_Graphics_Dwm", + "Win32_Graphics_Gdi", + "Win32_Media", + "Win32_System_Com_StructuredStorage", + "Win32_System_Com", + "Win32_System_LibraryLoader", + "Win32_System_Ole", + "Win32_System_SystemInformation", + "Win32_System_SystemServices", + "Win32_System_Threading", + "Win32_System_WindowsProgramming", + "Win32_UI_Accessibility", + "Win32_UI_Controls", + "Win32_UI_HiDpi", + "Win32_UI_Input_Ime", + "Win32_UI_Input_KeyboardAndMouse", + "Win32_UI_Input_Pointer", + "Win32_UI_Input_Touch", + "Win32_UI_Shell", + "Win32_UI_TextServices", + "Win32_UI_WindowsAndMessaging", + ] -[target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))'.dependencies] -wayland-client = { version = "0.29.4", default_features = false, features = ["use_system_lib"], optional = true } -wayland-protocols = { version = "0.29.4", features = [ "staging_protocols"], optional = true } -sctk = { package = "smithay-client-toolkit", version = "0.15.4", default_features = false, features = ["calloop"], optional = true } -mio = { version = "0.8", features = ["os-ext"], optional = true } -x11-dl = { version = "2.18.5", optional = true } -percent-encoding = { version = "2.0", optional = true } -parking_lot = { version = "0.12.0", optional = true } -libc = "0.2.64" -drm = { version = "0.6.2", optional = true } -input = { version = "0.7.1", optional = true } -libseat = { version = "0.1.4", optional = true } -udev = { version = "0.6.3", optional = true } -calloop = { version = "0.9.3", optional = true } -xkbcommon = { git = "https://github.com/StratusFearMe21/xkbcommon-rs", optional = true } + [target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))'.dependencies] + wayland-client = { version = "0.29.4", default_features = false, features = ["use_system_lib"], optional = true } + wayland-protocols = { version = "0.29.4", features = [ "staging_protocols"], optional = true } + sctk = { package = "smithay-client-toolkit", version = "0.15.4", default_features = false, features = ["calloop"], optional = true } + mio = { version = "0.8", features = ["os-ext"], optional = true } + x11-dl = { version = "2.18.5", optional = true } + percent-encoding = { version = "2.0", optional = true } + parking_lot = { version = "0.12.0", optional = true } + libc = "0.2.64" + drm = { version = "0.6.2", optional = true } + input = { version = "0.7.1", optional = true } + libseat = { version = "0.1.4", optional = true } + udev = { version = "0.6.3", optional = true } + calloop = { version = "0.9.3", optional = true } + xkbcommon = { git = "https://github.com/StratusFearMe21/xkbcommon-rs", optional = true } -[target.'cfg(target_arch = "wasm32")'.dependencies] -wasm-bindgen= "0.2.80" + [target.'cfg(target_arch = "wasm32")'.dependencies] + wasm-bindgen= "0.2.80" -[target.'cfg(target_arch = "wasm32")'.dependencies.web_sys] -package = "web-sys" -version = "0.3.57" -features = [ - 'console', - "AddEventListenerOptions", - 'CssStyleDeclaration', - 'BeforeUnloadEvent', - 'Document', - 'DomRect', - 'Element', - 'Event', - 'EventTarget', - 'FocusEvent', - 'HtmlCanvasElement', - 'HtmlElement', - 'KeyboardEvent', - 'MediaQueryList', - 'MediaQueryListEvent', - 'MouseEvent', - 'Node', - 'PointerEvent', - 'Window', - 'WheelEvent' -] + [target.'cfg(target_arch = "wasm32")'.dependencies.web_sys] + package = "web-sys" + version = "0.3.57" + features = [ + 'console', + "AddEventListenerOptions", + 'CssStyleDeclaration', + 'BeforeUnloadEvent', + 'Document', + 'DomRect', + 'Element', + 'Event', + 'EventTarget', + 'FocusEvent', + 'HtmlCanvasElement', + 'HtmlElement', + 'KeyboardEvent', + 'MediaQueryList', + 'MediaQueryListEvent', + 'MouseEvent', + 'Node', + 'PointerEvent', + 'Window', + 'WheelEvent' + ] -[target.'cfg(target_arch = "wasm32")'.dev-dependencies] -console_log = "0.2.0" + [target.'cfg(target_arch = "wasm32")'.dev-dependencies] + console_log = "0.2.0" -[workspace] -members = [ - "run-wasm", -] + [workspace] + members = [ + "run-wasm", + ] diff --git a/src/platform/unix.rs b/src/platform/unix.rs index a1c6350602..e1bf9f987d 100644 --- a/src/platform/unix.rs +++ b/src/platform/unix.rs @@ -21,11 +21,12 @@ use crate::{ #[cfg(feature = "x11")] use crate::dpi::Size; +#[cfg(feature = "kms")] +use crate::platform_impl::kms::MODE; #[cfg(feature = "x11")] use crate::platform_impl::x11::{ffi::XVisualInfo, XConnection}; use crate::platform_impl::{ - kms::MODE, ApplicationName, EventLoopWindowTarget as LinuxEventLoopWindowTarget, - Window as LinuxWindow, + ApplicationName, EventLoopWindowTarget as LinuxEventLoopWindowTarget, Window as LinuxWindow, }; #[cfg(any(feature = "x11", feature = "wayland", feature = "kms"))] @@ -95,8 +96,11 @@ impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { #[inline] fn unix_backend(&self) -> Backend { match self.p { + #[cfg(feature = "x11")] LinuxEventLoopWindowTarget::X(_) => Backend::X, + #[cfg(feature = "wayland")] LinuxEventLoopWindowTarget::Wayland(_) => Backend::Wayland, + #[cfg(feature = "kms")] LinuxEventLoopWindowTarget::Kms(_) => Backend::Kms, } } diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index 669c9fd2e0..efaf7e3a96 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -191,7 +191,7 @@ impl WindowId { pub const unsafe fn dummy() -> Self { #[cfg(feature = "wayland")] return WindowId::Wayland(wayland::WindowId::dummy()); - #[cfg(all(not(all(feature = "wayland", feature = "kms")), feature = "x11"))] + #[cfg(all(not(all(feature = "wayland")), feature = "x11"))] return WindowId::X(x11::WindowId::dummy()); #[cfg(all(not(all(feature = "wayland", feature = "x11")), feature = "kms"))] return WindowId::Kms(kms::WindowId::dummy()); diff --git a/src/platform_impl/linux/wayland/event_loop/mod.rs b/src/platform_impl/linux/wayland/event_loop/mod.rs index 5c5a9a5e50..1837849992 100644 --- a/src/platform_impl/linux/wayland/event_loop/mod.rs +++ b/src/platform_impl/linux/wayland/event_loop/mod.rs @@ -6,6 +6,7 @@ use std::process; use std::rc::Rc; use std::time::{Duration, Instant}; +use sctk::reexports::calloop; use sctk::reexports::client::protocol::wl_compositor::WlCompositor; use sctk::reexports::client::protocol::wl_shm::WlShm; use sctk::reexports::client::Display; diff --git a/src/platform_impl/linux/wayland/event_loop/proxy.rs b/src/platform_impl/linux/wayland/event_loop/proxy.rs index 0abd8cd7ca..dad64ef2c9 100644 --- a/src/platform_impl/linux/wayland/event_loop/proxy.rs +++ b/src/platform_impl/linux/wayland/event_loop/proxy.rs @@ -2,7 +2,7 @@ use std::sync::mpsc::SendError; -use calloop::channel::Sender; +use sctk::reexports::calloop::channel::Sender; use crate::event_loop::EventLoopClosed; diff --git a/src/platform_impl/linux/wayland/seat/keyboard/mod.rs b/src/platform_impl/linux/wayland/seat/keyboard/mod.rs index 77872208fd..a705d41d19 100644 --- a/src/platform_impl/linux/wayland/seat/keyboard/mod.rs +++ b/src/platform_impl/linux/wayland/seat/keyboard/mod.rs @@ -7,7 +7,7 @@ use sctk::reexports::client::protocol::wl_keyboard::WlKeyboard; use sctk::reexports::client::protocol::wl_seat::WlSeat; use sctk::reexports::client::Attached; -use calloop::{LoopHandle, RegistrationToken}; +use sctk::reexports::calloop::{LoopHandle, RegistrationToken}; use sctk::seat::keyboard; diff --git a/src/platform_impl/linux/wayland/seat/mod.rs b/src/platform_impl/linux/wayland/seat/mod.rs index 68c0cad27b..c6c4b02b61 100644 --- a/src/platform_impl/linux/wayland/seat/mod.rs +++ b/src/platform_impl/linux/wayland/seat/mod.rs @@ -6,11 +6,11 @@ use std::rc::Rc; use sctk::reexports::protocols::unstable::relative_pointer::v1::client::zwp_relative_pointer_manager_v1::ZwpRelativePointerManagerV1; use sctk::reexports::protocols::unstable::pointer_constraints::v1::client::zwp_pointer_constraints_v1::ZwpPointerConstraintsV1; use sctk::reexports::protocols::unstable::text_input::v3::client::zwp_text_input_manager_v3::ZwpTextInputManagerV3; +use sctk::reexports::calloop::LoopHandle; use sctk::reexports::client::protocol::wl_seat::WlSeat; use sctk::reexports::client::Attached; -use calloop::LoopHandle; use sctk::environment::Environment; use sctk::seat::pointer::ThemeManager; use sctk::seat::{SeatData, SeatListener}; diff --git a/src/platform_impl/linux/wayland/window/mod.rs b/src/platform_impl/linux/wayland/window/mod.rs index cc1074e845..ff1f5fd334 100644 --- a/src/platform_impl/linux/wayland/window/mod.rs +++ b/src/platform_impl/linux/wayland/window/mod.rs @@ -2,6 +2,7 @@ use std::collections::VecDeque; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, Mutex}; +use sctk::reexports::calloop; use sctk::reexports::client::protocol::wl_surface::WlSurface; use sctk::reexports::client::Display; diff --git a/src/platform_impl/linux/xkb_keymap.rs b/src/platform_impl/linux/xkb_keymap.rs index 09d5c32224..09f07b4473 100644 --- a/src/platform_impl/linux/xkb_keymap.rs +++ b/src/platform_impl/linux/xkb_keymap.rs @@ -290,6 +290,7 @@ pub fn keysym_to_vkey(keysym: u32) -> Option { // Flow control. XKB_KEY_Print => Some(VirtualKeyCode::Snapshot), XKB_KEY_Scroll_Lock => Some(VirtualKeyCode::Scroll), + XKB_KEY_Sys_Req => Some(VirtualKeyCode::Sysrq), XKB_KEY_Pause => Some(VirtualKeyCode::Pause), XKB_KEY_Insert => Some(VirtualKeyCode::Insert), XKB_KEY_Home => Some(VirtualKeyCode::Home), @@ -343,6 +344,7 @@ pub fn keysym_to_vkey(keysym: u32) -> Option { XKB_KEY_Alt_L => Some(VirtualKeyCode::LAlt), XKB_KEY_bracketleft => Some(VirtualKeyCode::LBracket), XKB_KEY_Control_L => Some(VirtualKeyCode::LControl), + XKB_KEY_Meta_L => Some(VirtualKeyCode::LWin), XKB_KEY_Shift_L => Some(VirtualKeyCode::LShift), XKB_KEY_Super_L => Some(VirtualKeyCode::LWin), XKB_KEY_XF86Mail => Some(VirtualKeyCode::Mail), @@ -378,13 +380,13 @@ pub fn keysym_to_vkey(keysym: u32) -> Option { XKB_KEY_Alt_R => Some(VirtualKeyCode::RAlt), XKB_KEY_bracketright => Some(VirtualKeyCode::RBracket), XKB_KEY_Control_R => Some(VirtualKeyCode::RControl), + XKB_KEY_Meta_R => Some(VirtualKeyCode::RWin), XKB_KEY_Shift_R => Some(VirtualKeyCode::RShift), XKB_KEY_Super_R => Some(VirtualKeyCode::RWin), XKB_KEY_semicolon => Some(VirtualKeyCode::Semicolon), XKB_KEY_slash => Some(VirtualKeyCode::Slash), XKB_KEY_XF86Sleep => Some(VirtualKeyCode::Sleep), // => Some(VirtualKeyCode::Stop), - // => Some(VirtualKeyCode::Sysrq), XKB_KEY_Tab => Some(VirtualKeyCode::Tab), XKB_KEY_ISO_Left_Tab => Some(VirtualKeyCode::Tab), XKB_KEY_underscore => Some(VirtualKeyCode::Underline), From d0e05fe53d2d8d595bcf31c05a76e6cafc4df531 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Mon, 9 May 2022 19:36:34 -0400 Subject: [PATCH 104/151] Fix calloop reexport --- src/platform_impl/linux/kms/event_loop.rs | 2 ++ src/platform_impl/linux/kms/window.rs | 3 +++ 2 files changed, 5 insertions(+) diff --git a/src/platform_impl/linux/kms/event_loop.rs b/src/platform_impl/linux/kms/event_loop.rs index 970ab37db1..6364d7f066 100644 --- a/src/platform_impl/linux/kms/event_loop.rs +++ b/src/platform_impl/linux/kms/event_loop.rs @@ -26,6 +26,8 @@ use input::{ }, LibinputInterface, }; +#[cfg(feature = "wayland")] +use sctk::reexports::calloop; use crate::{ dpi::PhysicalPosition, diff --git a/src/platform_impl/linux/kms/window.rs b/src/platform_impl/linux/kms/window.rs index efbd2034df..c7ea7c0df5 100644 --- a/src/platform_impl/linux/kms/window.rs +++ b/src/platform_impl/linux/kms/window.rs @@ -4,6 +4,9 @@ use super::MODE; use drm::control::*; use parking_lot::Mutex; +#[cfg(feature = "wayland")] +use sctk::reexports::calloop; + use crate::{ dpi::{PhysicalPosition, PhysicalSize, Position, Size}, error::{ExternalError, NotSupportedError, OsError}, From 491bfd0850f2df4c7b176bd3f19e4388a6cbcd57 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Mon, 9 May 2022 19:56:26 -0400 Subject: [PATCH 105/151] Add public documentation --- src/platform_impl/linux/kms/window.rs | 4 +-- src/window.rs | 40 +++++++++++++++------------ 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/src/platform_impl/linux/kms/window.rs b/src/platform_impl/linux/kms/window.rs index c7ea7c0df5..68b7fe9830 100644 --- a/src/platform_impl/linux/kms/window.rs +++ b/src/platform_impl/linux/kms/window.rs @@ -275,12 +275,12 @@ impl Window { #[inline] pub fn drag_window(&self) -> Result<(), ExternalError> { - Ok(()) + Err(ExternalError::NotSupported(NotSupportedError::new())) } #[inline] pub fn set_cursor_hittest(&self, _hittest: bool) -> Result<(), ExternalError> { - Ok(()) + Err(ExternalError::NotSupported(NotSupportedError::new())) } #[inline] diff --git a/src/window.rs b/src/window.rs index 96189872f8..1af7a9f1ff 100644 --- a/src/window.rs +++ b/src/window.rs @@ -632,7 +632,7 @@ impl Window { /// /// ## Platform-specific /// - /// - **iOS / Android:** Unsupported. + /// - **iOS / Android / DRM:** Unsupported. #[inline] pub fn set_title(&self, title: &str) { self.window.set_title(title) @@ -643,7 +643,7 @@ impl Window { /// If `false`, this will hide the window. If `true`, this will show the window. /// ## Platform-specific /// - /// - **Android / Wayland / Web:** Unsupported. + /// - **Android / Wayland / Web / DRM:** Unsupported. /// - **iOS:** Can only be called on the main thread. #[inline] pub fn set_visible(&self, visible: bool) { @@ -657,7 +657,7 @@ impl Window { /// ## Platform-specific /// /// - **X11:** Not implemented. - /// - **Wayland / iOS / Android / Web:** Unsupported. + /// - **Wayland / DRM / iOS / Android / Web:** Unsupported. #[inline] pub fn is_visible(&self) -> Option { self.window.is_visible() @@ -677,7 +677,7 @@ impl Window { /// /// ## Platform-specific /// - /// - **iOS / Android / Web:** Unsupported. + /// - **iOS / Android / Web / DRM:** Unsupported. #[inline] pub fn set_resizable(&self, resizable: bool) { self.window.set_resizable(resizable) @@ -698,7 +698,7 @@ impl Window { /// /// ## Platform-specific /// - /// - **iOS / Android / Web:** Unsupported. + /// - **DRM / iOS / Android / Web:** Unsupported. /// - **Wayland:** Un-minimize is unsupported. #[inline] pub fn set_minimized(&self, minimized: bool) { @@ -709,7 +709,7 @@ impl Window { /// /// ## Platform-specific /// - /// - **iOS / Android / Web:** Unsupported. + /// - **DRM / iOS / Android / Web:** Unsupported. #[inline] pub fn set_maximized(&self, maximized: bool) { self.window.set_maximized(maximized) @@ -744,6 +744,8 @@ impl Window { /// - **iOS:** Can only be called on the main thread. /// - **Wayland:** Does not support exclusive fullscreen mode and will no-op a request. /// - **Windows:** Screen saver is disabled in fullscreen mode. + /// - **DRM:** Fullscreen mode must be a valid exclusive fullscreen containing a video mode + /// from [`EventLoopWindowTarget::video_modes`] (will not panic if this condition is not met) /// - **Android:** Unsupported. #[inline] pub fn set_fullscreen(&self, fullscreen: Option) { @@ -757,6 +759,7 @@ impl Window { /// - **iOS:** Can only be called on the main thread. /// - **Android:** Will always return `None`. /// - **Wayland:** Can return `Borderless(None)` when there are no monitors. + /// - **DRM:** Always returns the current video mode containing the current [`VideoMode`] #[inline] pub fn fullscreen(&self) -> Option { self.window.fullscreen() @@ -766,7 +769,7 @@ impl Window { /// /// ## Platform-specific /// - /// - **iOS / Android / Web:** Unsupported. + /// - **DRM / iOS / Android / Web:** Unsupported. /// /// [`setPrefersStatusBarHidden`]: https://developer.apple.com/documentation/uikit/uiviewcontroller/1621440-prefersstatusbarhidden?language=objc #[inline] @@ -779,7 +782,7 @@ impl Window { /// ## Platform-specific /// /// - **X11:** Not implemented. - /// - **iOS / Android / Web:** Unsupported. + /// - **DRM / iOS / Android / Web:** Unsupported. #[inline] pub fn is_decorated(&self) -> bool { self.window.is_decorated() @@ -789,7 +792,7 @@ impl Window { /// /// ## Platform-specific /// - /// - **iOS / Android / Web / Wayland:** Unsupported. + /// - **DRM / iOS / Android / Web / Wayland:** Unsupported. #[inline] pub fn set_always_on_top(&self, always_on_top: bool) { self.window.set_always_on_top(always_on_top) @@ -800,7 +803,7 @@ impl Window { /// /// ## Platform-specific /// - /// - **iOS / Android / Web / Wayland / macOS:** Unsupported. + /// - **iOS / Android / Web / Wayland / DRM / macOS:** Unsupported. /// /// On Windows, this sets `ICON_SMALL`. The base size for a window icon is 16x16, but it's /// recommended to account for screen scaling and pick a multiple of that, i.e. 32x32. @@ -836,7 +839,7 @@ impl Window { /// /// ## Platform-specific /// - /// - **iOS / Android / Web:** Unsupported. + /// - **DRM / iOS / Android / Web:** Unsupported. /// /// [chinese]: https://support.apple.com/guide/chinese-input-method/use-the-candidate-window-cim12992/104/mac/12.0 /// [japanese]: https://support.apple.com/guide/japanese-input-method/use-the-candidate-window-jpim10262/6.3/mac/12.0 @@ -862,7 +865,7 @@ impl Window { /// ## Platform-specific /// /// - **macOS:** IME must be enabled to receive text-input where dead-key sequences are combined. - /// - ** iOS / Android / Web :** Unsupported. + /// - **DRM / iOS / Android / Web :** Unsupported. /// /// [`Ime`]: crate::event::WindowEvent::Ime /// [`KeyboardInput`]: crate::event::WindowEvent::KeyboardInput @@ -881,7 +884,7 @@ impl Window { /// /// ## Platform-specific /// - /// - **iOS / Android / Web / Wayland:** Unsupported. + /// - **DRM / iOS / Android / Web / Wayland:** Unsupported. #[inline] pub fn focus_window(&self) { self.window.focus_window() @@ -896,7 +899,7 @@ impl Window { /// /// ## Platform-specific /// - /// - **iOS / Android / Web :** Unsupported. + /// - **DRM / iOS / Android / Web :** Unsupported. /// - **macOS:** `None` has no effect. /// - **X11:** Requests for user attention must be manually cleared. /// - **Wayland:** Requires `xdg_activation_v1` protocol, `None` has no effect. @@ -912,7 +915,7 @@ impl Window { /// /// ## Platform-specific /// - /// - **iOS / Android:** Unsupported. + /// - **DRM / iOS / Android:** Unsupported. #[inline] pub fn set_cursor_icon(&self, cursor: CursorIcon) { self.window.set_cursor_icon(cursor); @@ -949,6 +952,7 @@ impl Window { /// ## Platform-specific /// /// - **macOS:** This locks the cursor in a fixed location, which looks visually awkward. + /// - **DRM:** Has no effect /// - **iOS / Android:** Always returns an [`ExternalError::NotSupported`]. #[inline] pub fn set_cursor_grab(&self, grab: bool) -> Result<(), ExternalError> { @@ -966,7 +970,7 @@ impl Window { /// - **Wayland:** The cursor is only hidden within the confines of the window. /// - **macOS:** The cursor is hidden as long as the window has input focus, even if the cursor is /// outside of the window. - /// - **iOS / Android:** Unsupported. + /// - **DRM / iOS / Android:** Unsupported. #[inline] pub fn set_cursor_visible(&self, visible: bool) { self.window.set_cursor_visible(visible) @@ -982,7 +986,7 @@ impl Window { /// - **X11:** Un-grabs the cursor. /// - **Wayland:** Requires the cursor to be inside the window to be dragged. /// - **macOS:** May prevent the button release event to be triggered. - /// - **iOS / Android / Web:** Always returns an [`ExternalError::NotSupported`]. + /// - **DRM / iOS / Android / Web:** Always returns an [`ExternalError::NotSupported`]. #[inline] pub fn drag_window(&self) -> Result<(), ExternalError> { self.window.drag_window() @@ -995,7 +999,7 @@ impl Window { /// /// ## Platform-specific /// - /// - **iOS / Android / Web / X11:** Always returns an [`ExternalError::NotSupported`]. + /// - **DRM / iOS / Android / Web / X11:** Always returns an [`ExternalError::NotSupported`]. #[inline] pub fn set_cursor_hittest(&self, hittest: bool) -> Result<(), ExternalError> { self.window.set_cursor_hittest(hittest) From a0cc057d8102400930e22abe7d75fe80540f1b3c Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Mon, 9 May 2022 19:58:01 -0400 Subject: [PATCH 106/151] Add public documentation --- src/window.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/window.rs b/src/window.rs index 1af7a9f1ff..87d5184733 100644 --- a/src/window.rs +++ b/src/window.rs @@ -745,7 +745,7 @@ impl Window { /// - **Wayland:** Does not support exclusive fullscreen mode and will no-op a request. /// - **Windows:** Screen saver is disabled in fullscreen mode. /// - **DRM:** Fullscreen mode must be a valid exclusive fullscreen containing a video mode - /// from [`EventLoopWindowTarget::video_modes`] (will not panic if this condition is not met) + /// from [`MonitorHandle::video_modes`] (will not panic if this condition is not met) /// - **Android:** Unsupported. #[inline] pub fn set_fullscreen(&self, fullscreen: Option) { From 2c75f5a299711b08dec27b590ed7fa1965142d90 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Mon, 9 May 2022 20:07:16 -0400 Subject: [PATCH 107/151] Fix modesetting --- src/platform_impl/linux/kms/event_loop.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/platform_impl/linux/kms/event_loop.rs b/src/platform_impl/linux/kms/event_loop.rs index 6364d7f066..f7a10f1061 100644 --- a/src/platform_impl/linux/kms/event_loop.rs +++ b/src/platform_impl/linux/kms/event_loop.rs @@ -1125,6 +1125,8 @@ impl EventLoop { ) })?; + *MODE.lock() = Some(mode); + // Enumerate available planes let planes = drm.plane_handles().map_err(|e| { OsError::new( From f39d00ba9d99b5396c58c48c0f84ee738659a2d5 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Mon, 9 May 2022 20:21:04 -0400 Subject: [PATCH 108/151] Fix clippy on kms end --- src/platform/unix.rs | 2 +- src/platform_impl/linux/kms/event_loop.rs | 10 +-- src/platform_impl/linux/kms/window.rs | 105 +++++++++++----------- 3 files changed, 57 insertions(+), 60 deletions(-) diff --git a/src/platform/unix.rs b/src/platform/unix.rs index e1bf9f987d..28e8d65722 100644 --- a/src/platform/unix.rs +++ b/src/platform/unix.rs @@ -162,7 +162,7 @@ impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { #[cfg(feature = "kms")] fn drm_mode(&self) -> Option { match self.p { - LinuxEventLoopWindowTarget::Kms(_) => MODE.lock().clone(), + LinuxEventLoopWindowTarget::Kms(_) => *MODE.lock(), #[cfg(any(feature = "x11", feature = "wayland"))] _ => None, } diff --git a/src/platform_impl/linux/kms/event_loop.rs b/src/platform_impl/linux/kms/event_loop.rs index f7a10f1061..1f9ecfb5ce 100644 --- a/src/platform_impl/linux/kms/event_loop.rs +++ b/src/platform_impl/linux/kms/event_loop.rs @@ -99,7 +99,7 @@ impl LibinputInterface for Interface { std::fs::OpenOptions::new() .custom_flags(flags) - .read((flags & libc::O_RDONLY != 0) | (flags & libc::O_RDWR != 0)) + .read(flags & libc::O_RDWR != 0) .write((flags & libc::O_WRONLY != 0) | (flags & libc::O_RDWR != 0)) .open(path) .map(|file| file.into_raw_fd()) @@ -1116,7 +1116,7 @@ impl EventLoop { .modes() .iter() .find(|f| f.mode_type().contains(ModeTypeFlags::PREFERRED)) - .or(con.modes().get(0)) + .or_else(|| con.modes().get(0)) .ok_or_else(|| { OsError::new( line!(), @@ -1237,7 +1237,7 @@ impl EventLoop { let window_target = event_loop::EventLoopWindowTarget { p: platform_impl::EventLoopWindowTarget::Kms(EventLoopWindowTarget { connector: con.clone(), - crtc: crtc.clone(), + crtc: *crtc, device: drm, plane: p_plane, cursor_arc, @@ -1423,7 +1423,7 @@ impl EventLoop { &mut self, timeout: D, ) -> std::io::Result<()> { - let mut state = match &mut self.window_target.p { + let state = match &mut self.window_target.p { platform_impl::EventLoopWindowTarget::Kms(window_target) => { &mut window_target.event_sink } @@ -1431,7 +1431,7 @@ impl EventLoop { _ => unreachable!(), }; - self.event_loop.dispatch(timeout, &mut state) + self.event_loop.dispatch(timeout, state) } } diff --git a/src/platform_impl/linux/kms/window.rs b/src/platform_impl/linux/kms/window.rs index 68b7fe9830..9439f4194e 100644 --- a/src/platform_impl/linux/kms/window.rs +++ b/src/platform_impl/linux/kms/window.rs @@ -78,13 +78,13 @@ impl Window { property::Value::CRTC(Some(event_loop_window_target.crtc.handle())), ); - let ref mode = MODE.lock().ok_or_else(|| { + let mode = &(MODE.lock().ok_or_else(|| { OsError::new( line!(), file!(), platform_impl::OsError::KmsMisc("mode is not initialized"), ) - })?; + })?); let blob = event_loop_window_target .device @@ -198,8 +198,8 @@ impl Window { Ok(Self { connector: event_loop_window_target.connector.clone(), - crtc: event_loop_window_target.crtc.clone(), - plane: event_loop_window_target.plane.clone(), + crtc: event_loop_window_target.crtc, + plane: event_loop_window_target.plane, cursor: event_loop_window_target.cursor_arc.clone(), ping: event_loop_window_target.event_loop_awakener.clone(), card: event_loop_window_target.device.clone(), @@ -317,57 +317,54 @@ impl Window { #[inline] pub fn set_fullscreen(&self, monitor: Option) { - match monitor { - Some(Fullscreen::Exclusive(fullscreen)) => { - let modes = self.connector.modes().to_vec(); - let connector = self.connector.clone(); - if let Some(mo) = modes.into_iter().find(move |&f| { - VideoMode { - video_mode: platform_impl::VideoMode::Kms(super::VideoMode { - mode: f, - connector: connector.clone(), - }), - } == fullscreen - }) { - let mut atomic_req = atomic::AtomicModeReq::new(); - let blob = self.card.create_property_blob(&mo).unwrap(); - - atomic_req.add_property( - self.crtc.handle(), - find_prop_id!(&self.card, self.crtc.handle(), "MODE_ID").unwrap(), - blob, - ); - - atomic_req.add_property( - self.plane, - find_prop_id!(&self.card, self.plane, "SRC_W").unwrap(), - property::Value::UnsignedRange((mo.size().0 as u64) << 16), - ); - - atomic_req.add_property( - self.plane, - find_prop_id!(&self.card, self.plane, "SRC_H").unwrap(), - property::Value::UnsignedRange((mo.size().1 as u64) << 16), - ); - - atomic_req.add_property( - self.plane, - find_prop_id!(&self.card, self.plane, "CRTC_W").unwrap(), - property::Value::UnsignedRange(mo.size().0 as u64), - ); - - atomic_req.add_property( - self.plane, - find_prop_id!(&self.card, self.plane, "CRTC_H").unwrap(), - property::Value::UnsignedRange(mo.size().1 as u64), - ); - - self.card - .atomic_commit(AtomicCommitFlags::ALLOW_MODESET, atomic_req) - .unwrap(); - } + if let Some(Fullscreen::Exclusive(fullscreen)) = monitor { + let modes = self.connector.modes().to_vec(); + let connector = self.connector.clone(); + if let Some(mo) = modes.into_iter().find(move |&f| { + VideoMode { + video_mode: platform_impl::VideoMode::Kms(super::VideoMode { + mode: f, + connector: connector.clone(), + }), + } == fullscreen + }) { + let mut atomic_req = atomic::AtomicModeReq::new(); + let blob = self.card.create_property_blob(&mo).unwrap(); + + atomic_req.add_property( + self.crtc.handle(), + find_prop_id!(&self.card, self.crtc.handle(), "MODE_ID").unwrap(), + blob, + ); + + atomic_req.add_property( + self.plane, + find_prop_id!(&self.card, self.plane, "SRC_W").unwrap(), + property::Value::UnsignedRange((mo.size().0 as u64) << 16), + ); + + atomic_req.add_property( + self.plane, + find_prop_id!(&self.card, self.plane, "SRC_H").unwrap(), + property::Value::UnsignedRange((mo.size().1 as u64) << 16), + ); + + atomic_req.add_property( + self.plane, + find_prop_id!(&self.card, self.plane, "CRTC_W").unwrap(), + property::Value::UnsignedRange(mo.size().0 as u64), + ); + + atomic_req.add_property( + self.plane, + find_prop_id!(&self.card, self.plane, "CRTC_H").unwrap(), + property::Value::UnsignedRange(mo.size().1 as u64), + ); + + self.card + .atomic_commit(AtomicCommitFlags::ALLOW_MODESET, atomic_req) + .unwrap(); } - _ => {} } } From 285a715217da73b87af7b7c129e3e230d7c40a77 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Mon, 9 May 2022 21:22:01 -0400 Subject: [PATCH 109/151] Fix Add known XKB keysyms --- src/platform_impl/linux/xkb_keymap.rs | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/platform_impl/linux/xkb_keymap.rs b/src/platform_impl/linux/xkb_keymap.rs index 09f07b4473..a1a38d394f 100644 --- a/src/platform_impl/linux/xkb_keymap.rs +++ b/src/platform_impl/linux/xkb_keymap.rs @@ -15,6 +15,7 @@ pub const XKB_KEY_Scroll_Lock: u32 = 0xff14; pub const XKB_KEY_Sys_Req: u32 = 0xff15; pub const XKB_KEY_Escape: u32 = 0xff1b; pub const XKB_KEY_Delete: u32 = 0xffff; // Delete, rubout +pub const XKB_KEY_Caps_Lock: u32 = 0xffe5; // International & multi-key character composition @@ -219,6 +220,13 @@ pub const XKB_KEY_XF86Sleep: u32 = 0x1008FF2F; // Put system to sleep pub const XKB_KEY_XF86Copy: u32 = 0x1008FF57; // Copy selection pub const XKB_KEY_XF86Cut: u32 = 0x1008FF58; // Cut selection pub const XKB_KEY_XF86Paste: u32 = 0x1008FF6D; // Paste +pub const XKB_KEY_XF86AudioStop: u32 = 0x1008FF15; +pub const XKB_KEY_XF86MyComputer: u32 = 0x1008FF33; +pub const XKB_KEY_XF86Stop: u32 = 0x1008FF28; +pub const XKB_KEY_XF86WakeUp: u32 = 0x1008FF2B; +pub const XKB_KEY_XF86Favorites: u32 = 0x1008FF30; +pub const XKB_KEY_XF86HomePage: u32 = 0x1008FF18; +pub const XKB_KEY_XF86Refresh: u32 = 0x1008FF29; pub fn keysym_to_vkey(keysym: u32) -> Option { match keysym { @@ -333,7 +341,7 @@ pub fn keysym_to_vkey(keysym: u32) -> Option { // => Some(VirtualKeyCode::Ax), XKB_KEY_backslash => Some(VirtualKeyCode::Backslash), XKB_KEY_XF86Calculator => Some(VirtualKeyCode::Calculator), - // => Some(VirtualKeyCode::Capital), + XKB_KEY_Caps_Lock => Some(VirtualKeyCode::Capital), XKB_KEY_colon => Some(VirtualKeyCode::Colon), XKB_KEY_comma => Some(VirtualKeyCode::Comma), // => Some(VirtualKeyCode::Convert), @@ -348,12 +356,12 @@ pub fn keysym_to_vkey(keysym: u32) -> Option { XKB_KEY_Shift_L => Some(VirtualKeyCode::LShift), XKB_KEY_Super_L => Some(VirtualKeyCode::LWin), XKB_KEY_XF86Mail => Some(VirtualKeyCode::Mail), + XKB_KEY_XF86AudioStop => Some(VirtualKeyCode::MediaStop), // => Some(VirtualKeyCode::MediaSelect), - // => Some(VirtualKeyCode::MediaStop), XKB_KEY_minus => Some(VirtualKeyCode::Minus), XKB_KEY_asterisk => Some(VirtualKeyCode::Asterisk), XKB_KEY_XF86AudioMute => Some(VirtualKeyCode::Mute), - // => Some(VirtualKeyCode::MyComputer), + XKB_KEY_XF86MyComputer => Some(VirtualKeyCode::MyComputer), XKB_KEY_XF86AudioNext => Some(VirtualKeyCode::NextTrack), // => Some(VirtualKeyCode::NoConvert), XKB_KEY_KP_Separator => Some(VirtualKeyCode::NumpadComma), @@ -386,19 +394,19 @@ pub fn keysym_to_vkey(keysym: u32) -> Option { XKB_KEY_semicolon => Some(VirtualKeyCode::Semicolon), XKB_KEY_slash => Some(VirtualKeyCode::Slash), XKB_KEY_XF86Sleep => Some(VirtualKeyCode::Sleep), - // => Some(VirtualKeyCode::Stop), + XKB_KEY_XF86Stop => Some(VirtualKeyCode::Stop), XKB_KEY_Tab => Some(VirtualKeyCode::Tab), XKB_KEY_ISO_Left_Tab => Some(VirtualKeyCode::Tab), XKB_KEY_underscore => Some(VirtualKeyCode::Underline), // => Some(VirtualKeyCode::Unlabeled), XKB_KEY_XF86AudioLowerVolume => Some(VirtualKeyCode::VolumeDown), XKB_KEY_XF86AudioRaiseVolume => Some(VirtualKeyCode::VolumeUp), - // => Some(VirtualKeyCode::Wake), + XKB_KEY_XF86WakeUp => Some(VirtualKeyCode::Wake), // => Some(VirtualKeyCode::Webback), - // => Some(VirtualKeyCode::WebFavorites), + XKB_KEY_XF86Favorites => Some(VirtualKeyCode::WebFavorites), // => Some(VirtualKeyCode::WebForward), - // => Some(VirtualKeyCode::WebHome), - // => Some(VirtualKeyCode::WebRefresh), + XKB_KEY_XF86HomePage => Some(VirtualKeyCode::WebHome), + XKB_KEY_XF86Refresh => Some(VirtualKeyCode::WebRefresh), // => Some(VirtualKeyCode::WebSearch), // => Some(VirtualKeyCode::WebStop), XKB_KEY_yen => Some(VirtualKeyCode::Yen), From 76aaea0415f4d9f7fe12004b854179a5a51c0f56 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Mon, 9 May 2022 21:27:32 -0400 Subject: [PATCH 110/151] Fix formatting --- Cargo.toml | 146 ++++++++++++++++++++++++++--------------------------- 1 file changed, 73 insertions(+), 73 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 197af27f71..a9efd6d096 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,81 +62,81 @@ parking_lot = "0.12.0" [target.'cfg(target_os = "windows")'.dependencies.windows-sys] version = "0.36.1" features = [ - "Win32_Devices_HumanInterfaceDevice", - "Win32_Foundation", - "Win32_Globalization", - "Win32_Graphics_Dwm", - "Win32_Graphics_Gdi", - "Win32_Media", - "Win32_System_Com_StructuredStorage", - "Win32_System_Com", - "Win32_System_LibraryLoader", - "Win32_System_Ole", - "Win32_System_SystemInformation", - "Win32_System_SystemServices", - "Win32_System_Threading", - "Win32_System_WindowsProgramming", - "Win32_UI_Accessibility", - "Win32_UI_Controls", - "Win32_UI_HiDpi", - "Win32_UI_Input_Ime", - "Win32_UI_Input_KeyboardAndMouse", - "Win32_UI_Input_Pointer", - "Win32_UI_Input_Touch", - "Win32_UI_Shell", - "Win32_UI_TextServices", - "Win32_UI_WindowsAndMessaging", - ] + "Win32_Devices_HumanInterfaceDevice", + "Win32_Foundation", + "Win32_Globalization", + "Win32_Graphics_Dwm", + "Win32_Graphics_Gdi", + "Win32_Media", + "Win32_System_Com_StructuredStorage", + "Win32_System_Com", + "Win32_System_LibraryLoader", + "Win32_System_Ole", + "Win32_System_SystemInformation", + "Win32_System_SystemServices", + "Win32_System_Threading", + "Win32_System_WindowsProgramming", + "Win32_UI_Accessibility", + "Win32_UI_Controls", + "Win32_UI_HiDpi", + "Win32_UI_Input_Ime", + "Win32_UI_Input_KeyboardAndMouse", + "Win32_UI_Input_Pointer", + "Win32_UI_Input_Touch", + "Win32_UI_Shell", + "Win32_UI_TextServices", + "Win32_UI_WindowsAndMessaging", +] - [target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))'.dependencies] - wayland-client = { version = "0.29.4", default_features = false, features = ["use_system_lib"], optional = true } - wayland-protocols = { version = "0.29.4", features = [ "staging_protocols"], optional = true } - sctk = { package = "smithay-client-toolkit", version = "0.15.4", default_features = false, features = ["calloop"], optional = true } - mio = { version = "0.8", features = ["os-ext"], optional = true } - x11-dl = { version = "2.18.5", optional = true } - percent-encoding = { version = "2.0", optional = true } - parking_lot = { version = "0.12.0", optional = true } - libc = "0.2.64" - drm = { version = "0.6.2", optional = true } - input = { version = "0.7.1", optional = true } - libseat = { version = "0.1.4", optional = true } - udev = { version = "0.6.3", optional = true } - calloop = { version = "0.9.3", optional = true } - xkbcommon = { git = "https://github.com/StratusFearMe21/xkbcommon-rs", optional = true } +[target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))'.dependencies] +wayland-client = { version = "0.29.4", default_features = false, features = ["use_system_lib"], optional = true } +wayland-protocols = { version = "0.29.4", features = [ "staging_protocols"], optional = true } +sctk = { package = "smithay-client-toolkit", version = "0.15.4", default_features = false, features = ["calloop"], optional = true } +mio = { version = "0.8.3", features = ["os-ext"], optional = true } +x11-dl = { version = "2.19.1", optional = true } +percent-encoding = { version = "2.1.0", optional = true } +parking_lot = { version = "0.12.0", optional = true } +libc = "0.2.125" +drm = { version = "0.6.2", optional = true } +input = { version = "0.7.1", optional = true } +libseat = { version = "0.1.4", optional = true } +udev = { version = "0.6.3", optional = true } +calloop = { version = "0.9.3", optional = true } +xkbcommon = { git = "https://github.com/StratusFearMe21/xkbcommon-rs", optional = true } - [target.'cfg(target_arch = "wasm32")'.dependencies] - wasm-bindgen= "0.2.80" +[target.'cfg(target_arch = "wasm32")'.dependencies] +wasm-bindgen= "0.2.80" - [target.'cfg(target_arch = "wasm32")'.dependencies.web_sys] - package = "web-sys" - version = "0.3.57" - features = [ - 'console', - "AddEventListenerOptions", - 'CssStyleDeclaration', - 'BeforeUnloadEvent', - 'Document', - 'DomRect', - 'Element', - 'Event', - 'EventTarget', - 'FocusEvent', - 'HtmlCanvasElement', - 'HtmlElement', - 'KeyboardEvent', - 'MediaQueryList', - 'MediaQueryListEvent', - 'MouseEvent', - 'Node', - 'PointerEvent', - 'Window', - 'WheelEvent' - ] +[target.'cfg(target_arch = "wasm32")'.dependencies.web_sys] +package = "web-sys" +version = "0.3.57" +features = [ + 'console', + "AddEventListenerOptions", + 'CssStyleDeclaration', + 'BeforeUnloadEvent', + 'Document', + 'DomRect', + 'Element', + 'Event', + 'EventTarget', + 'FocusEvent', + 'HtmlCanvasElement', + 'HtmlElement', + 'KeyboardEvent', + 'MediaQueryList', + 'MediaQueryListEvent', + 'MouseEvent', + 'Node', + 'PointerEvent', + 'Window', + 'WheelEvent' +] - [target.'cfg(target_arch = "wasm32")'.dev-dependencies] - console_log = "0.2.0" +[target.'cfg(target_arch = "wasm32")'.dev-dependencies] +console_log = "0.2.0" - [workspace] - members = [ - "run-wasm", - ] +[workspace] +members = [ + "run-wasm", +] From cfe89aec81b5643ff2cad57aa574d37a0f9346ea Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 10 May 2022 08:14:01 -0400 Subject: [PATCH 111/151] Fix CI --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1076aa5655..48c11392de 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -65,6 +65,9 @@ jobs: - name: Install GCC Multilib if: (matrix.platform.os == 'ubuntu-latest') && contains(matrix.platform.target, 'i686') run: sudo apt-get update && sudo apt-get install gcc-multilib + - name: Install C Dependencies + if: (matrix.platform.os == 'ubuntu-latest') + run: sudo apt-get update && sudo apt-get install libudev-dev libinput-dev - name: Install cargo-apk if: contains(matrix.platform.target, 'android') run: cargo install cargo-apk From b5caf34276370ea147db43eb49659d9a65a3b90d Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 10 May 2022 09:10:19 -0400 Subject: [PATCH 112/151] Fix CI --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 48c11392de..c403dd18e6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,6 +31,7 @@ jobs: - { target: x86_64-unknown-linux-gnu, os: ubuntu-latest, } - { target: x86_64-unknown-linux-gnu, os: ubuntu-latest, options: --no-default-features, features: x11 } - { target: x86_64-unknown-linux-gnu, os: ubuntu-latest, options: --no-default-features, features: "wayland,wayland-dlopen" } + - { target: x86_64-unknown-linux-gnu, os: ubuntu-latest, options: --no-default-features, features: "kms,kms-ext" } - { target: aarch64-linux-android, os: ubuntu-latest, cmd: 'apk --' } - { target: x86_64-apple-darwin, os: macos-latest, } - { target: x86_64-apple-ios, os: macos-latest, } From cb1e893324d5fa849f9f88700235ed80541e5744 Mon Sep 17 00:00:00 2001 From: StratusFearMe21 <57533634+StratusFearMe21@users.noreply.github.com> Date: Tue, 10 May 2022 16:25:39 -0400 Subject: [PATCH 113/151] Update README.md Co-authored-by: Kirill Chibisov --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ec5fee5141..41811da541 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ Winit provides the following features, which can be enabled in your `Cargo.toml` * `serde`: Enables serialization/deserialization of certain types with [Serde](https://crates.io/crates/serde). * `x11` (enabled by default): On Unix platform, compiles with the X11 backend * `wayland` (enabled by default): On Unix platform, compiles with the Wayland backend -* `kmsdrm` (enabled by default): On Unix platform, compiles with the kmsdrm backend +* `kms` (enabled by default): On Unix platform, compiles with the kmsdrm backend * `mint`: Enables mint (math interoperability standard types) conversions. ### Platform-specific usage From 7e6dbda9e07aa0591817d4601d9901a55ef26095 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 10 May 2022 17:15:43 -0400 Subject: [PATCH 114/151] Fix OsError creation --- src/platform_impl/linux/kms/event_loop.rs | 834 ++-------------------- src/platform_impl/linux/kms/input.rs | 700 ++++++++++++++++++ src/platform_impl/linux/kms/mod.rs | 3 + src/platform_impl/linux/kms/window.rs | 38 +- 4 files changed, 770 insertions(+), 805 deletions(-) create mode 100644 src/platform_impl/linux/kms/input.rs diff --git a/src/platform_impl/linux/kms/event_loop.rs b/src/platform_impl/linux/kms/event_loop.rs index 1f9ecfb5ce..5ee5cf26c5 100644 --- a/src/platform_impl/linux/kms/event_loop.rs +++ b/src/platform_impl/linux/kms/event_loop.rs @@ -3,7 +3,6 @@ use std::{ cell::RefCell, collections::VecDeque, marker::PhantomData, - os::unix::prelude::{AsRawFd, FromRawFd, RawFd}, path::{Path, PathBuf}, rc::Rc, sync::{mpsc::SendError, Arc}, @@ -14,36 +13,27 @@ use std::{collections::HashMap, sync::atomic::AtomicBool}; use udev::Enumerator; use xkbcommon::xkb; -use calloop::{EventSource, Interest, Mode, Poll, PostAction, Readiness, Token, TokenFactory}; use drm::control::*; -use input::{ - event::{ - keyboard::KeyboardEventTrait, - pointer::PointerScrollEvent, - tablet_pad::{ButtonState, KeyState}, - tablet_tool::{TabletToolEventTrait, TipState}, - touch::{TouchEventPosition, TouchEventSlot}, - }, - LibinputInterface, -}; + #[cfg(feature = "wayland")] use sctk::reexports::calloop; +use crate::error; + use crate::{ dpi::PhysicalPosition, - error::OsError, - event::{ - DeviceEvent, DeviceId, ElementState, Event, Force, KeyboardInput, ModifiersState, - MouseButton, MouseScrollDelta, StartCause, Touch, TouchPhase, WindowEvent, - }, + event::{DeviceId, Event, KeyboardInput, StartCause, WindowEvent}, event_loop::{self, ControlFlow, EventLoopClosed}, monitor::MonitorHandle, platform::unix::Card, - platform_impl::{self, platform::sticky_exit_callback, xkb_keymap}, + platform_impl::{self, platform::sticky_exit_callback, OsError}, window::WindowId, }; -use super::MODE; +use super::{ + input::{Interface, LibinputInputBackend, REPEAT_RATE}, + MODE, +}; macro_rules! to_platform_impl { ($p:ident, $params:expr) => { @@ -57,656 +47,6 @@ macro_rules! window_id { }; } -macro_rules! device_id { - () => { - to_platform_impl!(DeviceId, super::DeviceId) - }; -} - -const REPEAT_RATE: u64 = 25; -const REPEAT_DELAY: u64 = 600; - -#[cfg(feature = "kms-ext")] -struct Interface(libseat::Seat, HashMap); -#[cfg(not(feature = "kms-ext"))] -struct Interface; - -#[cfg(feature = "kms-ext")] -impl LibinputInterface for Interface { - fn open_restricted(&mut self, path: &Path, _flags: i32) -> Result { - self.0 - .open_device(&path) - .map(|(id, file)| { - self.1.insert(file, id); - file - }) - .map_err(|err| err.into()) - } - - fn close_restricted(&mut self, fd: RawFd) { - if let Some(dev) = self.1.get(&fd).copied() { - self.0.close_device(dev).unwrap(); - } - - unsafe { std::fs::File::from_raw_fd(fd) }; - } -} - -#[cfg(not(feature = "kms-ext"))] -impl LibinputInterface for Interface { - fn open_restricted(&mut self, path: &Path, flags: i32) -> Result { - use std::os::unix::prelude::*; - - std::fs::OpenOptions::new() - .custom_flags(flags) - .read(flags & libc::O_RDWR != 0) - .write((flags & libc::O_WRONLY != 0) | (flags & libc::O_RDWR != 0)) - .open(path) - .map(|file| file.into_raw_fd()) - .map_err(|err| err.raw_os_error().unwrap()) - } - fn close_restricted(&mut self, fd: RawFd) { - unsafe { - std::fs::File::from_raw_fd(fd); - } - } -} - -pub struct LibinputInputBackend { - context: input::Libinput, - xkb_ctx: xkb::State, - xkb_keymap: xkb::Keymap, - xkb_compose: xkb::compose::State, - token: Token, - touch_location: PhysicalPosition, - screen_size: (u32, u32), - modifiers: ModifiersState, - cursor_positon: Arc>>, - timer_handle: calloop::timer::TimerHandle<(KeyboardInput, Option)>, -} - -impl LibinputInputBackend { - /// Initialize a new [`LibinputInputBackend`] from a given already initialized - /// [libinput context](input::Libinput). - pub fn new( - context: input::Libinput, - screen_size: (u32, u32), - timer_handle: calloop::timer::TimerHandle<(KeyboardInput, Option)>, - xkb_ctx: xkb::State, - xkb_keymap: xkb::Keymap, - xkb_compose: xkb::compose::State, - cursor_positon: Arc>>, - ) -> Self { - LibinputInputBackend { - context, - token: Token::invalid(), - touch_location: PhysicalPosition::new(0.0, 0.0), - modifiers: ModifiersState::empty(), - cursor_positon, - screen_size, - timer_handle, - xkb_ctx, - xkb_keymap, - xkb_compose, - } - } -} - -impl AsRawFd for LibinputInputBackend { - fn as_raw_fd(&self) -> RawFd { - self.context.as_raw_fd() - } -} - -macro_rules! handle_device_event { - ($ev:expr,$callback:expr) => { - match $ev { - input::event::DeviceEvent::Added(_) => { - $callback( - Event::DeviceEvent { - device_id: device_id!(), - event: DeviceEvent::Added, - }, - &mut (), - ); - } - input::event::DeviceEvent::Removed(_) => { - $callback( - Event::DeviceEvent { - device_id: device_id!(), - event: DeviceEvent::Removed, - }, - &mut (), - ); - } - _ => {} - } - }; -} - -macro_rules! handle_touch_event { - ($self:expr,$ev:expr,$callback:expr) => { - match $ev { - input::event::TouchEvent::Up(e) => $callback( - Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::Touch(Touch { - device_id: device_id!(), - phase: TouchPhase::Ended, - location: $self.touch_location, - force: None, - id: e.slot().unwrap() as u64, - }), - }, - &mut (), - ), - input::event::TouchEvent::Down(e) => { - $self.touch_location.x = e.x_transformed($self.screen_size.0); - $self.touch_location.y = e.y_transformed($self.screen_size.1); - - $callback( - Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::Touch(Touch { - device_id: device_id!(), - phase: TouchPhase::Started, - location: $self.touch_location, - force: None, - id: e.slot().unwrap() as u64, - }), - }, - &mut (), - ) - } - input::event::TouchEvent::Motion(e) => { - $self.touch_location.x = e.x_transformed($self.screen_size.0); - $self.touch_location.y = e.y_transformed($self.screen_size.1); - - $callback( - Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::Touch(Touch { - device_id: device_id!(), - phase: TouchPhase::Moved, - location: $self.touch_location, - force: None, - id: e.slot().unwrap() as u64, - }), - }, - &mut (), - ); - } - input::event::TouchEvent::Cancel(e) => $callback( - Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::Touch(Touch { - device_id: device_id!(), - phase: TouchPhase::Cancelled, - location: $self.touch_location, - force: None, - id: e.slot().unwrap() as u64, - }), - }, - &mut (), - ), - input::event::TouchEvent::Frame(_) => $callback( - Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::Touch(Touch { - device_id: device_id!(), - phase: TouchPhase::Ended, - location: $self.touch_location, - force: None, - id: 0, // e.slot().unwrap() as u64, - }), - }, - &mut (), - ), - _ => {} - } - }; -} - -macro_rules! handle_tablet_tool_event { - ($self:expr,$ev:expr,$callback:expr) => { - match $ev { - input::event::TabletToolEvent::Tip(e) => $callback( - Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::Touch(Touch { - device_id: device_id!(), - phase: match e.tip_state() { - TipState::Down => TouchPhase::Started, - TipState::Up => TouchPhase::Ended, - }, - location: PhysicalPosition::new( - e.x_transformed($self.screen_size.0), - e.y_transformed($self.screen_size.1), - ), - force: Some(Force::Calibrated { - force: e.pressure(), - max_possible_force: 1.0, - altitude_angle: None, - }), - id: 0, - }), - }, - &mut (), - ), - input::event::TabletToolEvent::Button(e) => { - $callback( - Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::MouseInput { - device_id: device_id!(), - state: match e.button_state() { - ButtonState::Pressed => ElementState::Pressed, - ButtonState::Released => ElementState::Released, - }, - button: match e.button() { - 1 => MouseButton::Right, - 2 => MouseButton::Middle, - _ => MouseButton::Left, - }, - modifiers: $self.modifiers, - }, - }, - &mut (), - ); - - $callback( - Event::DeviceEvent { - device_id: device_id!(), - event: DeviceEvent::Button { - button: e.button(), - state: match e.button_state() { - ButtonState::Pressed => ElementState::Pressed, - ButtonState::Released => ElementState::Released, - }, - }, - }, - &mut (), - ); - } - _ => {} - } - }; -} - -macro_rules! handle_pointer_event { - ($self:expr,$ev:expr,$callback:expr) => { - match $ev { - input::event::PointerEvent::Motion(e) => { - let mut lock = $self.cursor_positon.lock(); - - lock.x += e.dx(); - lock.x = lock.x.clamp(0.0, $self.screen_size.0 as f64); - - lock.y += e.dy(); - lock.y = lock.y.clamp(0.0, $self.screen_size.1 as f64); - - $callback( - Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::CursorMoved { - device_id: device_id!(), - position: *lock, - modifiers: $self.modifiers, - }, - }, - &mut (), - ); - - $callback( - Event::DeviceEvent { - device_id: device_id!(), - event: DeviceEvent::MouseMotion { - delta: (e.dx(), e.dy()), - }, - }, - &mut (), - ); - } - input::event::PointerEvent::Button(e) => { - $callback( - Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::MouseInput { - device_id: device_id!(), - state: match e.button_state() { - ButtonState::Pressed => ElementState::Pressed, - ButtonState::Released => ElementState::Released, - }, - button: match e.button() { - 1 => MouseButton::Right, - 2 => MouseButton::Middle, - _ => MouseButton::Left, - }, - modifiers: $self.modifiers, - }, - }, - &mut (), - ); - - $callback( - Event::DeviceEvent { - device_id: device_id!(), - event: DeviceEvent::Button { - button: e.button(), - state: match e.button_state() { - ButtonState::Pressed => ElementState::Pressed, - ButtonState::Released => ElementState::Released, - }, - }, - }, - &mut (), - ); - } - input::event::PointerEvent::ScrollWheel(e) => { - use input::event::pointer::Axis; - - $callback( - Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::MouseWheel { - device_id: device_id!(), - delta: MouseScrollDelta::LineDelta( - if e.has_axis(Axis::Horizontal) { - e.scroll_value(Axis::Horizontal) as f32 - } else { - 0.0 - }, - if e.has_axis(Axis::Vertical) { - e.scroll_value(Axis::Vertical) as f32 - } else { - 0.0 - }, - ), - phase: TouchPhase::Moved, - modifiers: $self.modifiers, - }, - }, - &mut (), - ); - } - input::event::PointerEvent::ScrollFinger(e) => { - use input::event::pointer::Axis; - - $callback( - Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::MouseWheel { - device_id: device_id!(), - delta: MouseScrollDelta::PixelDelta(PhysicalPosition::new( - if e.has_axis(Axis::Horizontal) { - e.scroll_value(Axis::Horizontal) - } else { - 0.0 - }, - if e.has_axis(Axis::Vertical) { - e.scroll_value(Axis::Vertical) - } else { - 0.0 - }, - )), - phase: TouchPhase::Moved, - modifiers: $self.modifiers, - }, - }, - &mut (), - ); - } - input::event::PointerEvent::MotionAbsolute(e) => { - let mut lock = $self.cursor_positon.lock(); - - lock.x = e.absolute_x_transformed($self.screen_size.0); - - lock.y = e.absolute_y_transformed($self.screen_size.1); - - $callback( - Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::CursorMoved { - device_id: device_id!(), - position: *lock, - modifiers: $self.modifiers, - }, - }, - &mut (), - ); - } - _ => {} - } - }; -} - -macro_rules! handle_keyboard_event { - ($self:expr,$ev:expr,$callback:expr) => {{ - let state = match $ev.key_state() { - KeyState::Pressed => ElementState::Pressed, - KeyState::Released => ElementState::Released, - }; - - let k = if let input::event::KeyboardEvent::Key(key) = $ev { - key.key() - } else { - unreachable!() - }; - - let key_offset = k + 8; - let keysym = $self.xkb_ctx.key_get_one_sym(key_offset); - let virtual_keycode = xkb_keymap::keysym_to_vkey(keysym); - - $self.xkb_ctx.update_key( - key_offset, - match state { - ElementState::Pressed => xkb::KeyDirection::Down, - ElementState::Released => xkb::KeyDirection::Up, - }, - ); - - #[allow(deprecated)] - let input = KeyboardInput { - scancode: k, - state: state.clone(), - virtual_keycode, - modifiers: $self.modifiers, - }; - - $self.timer_handle.cancel_all_timeouts(); - - $callback( - Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::KeyboardInput { - device_id: device_id!(), - input, - is_synthetic: false, - }, - }, - &mut (), - ); - - if let ElementState::Pressed = state { - $self.xkb_compose.feed(keysym); - - match $self.xkb_compose.status() { - xkb::compose::Status::Composed => { - if let Some(c) = $self.xkb_compose.utf8().and_then(|f| f.chars().next()) { - $callback( - Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::ReceivedCharacter(c), - }, - &mut (), - ); - } - } - xkb::compose::Status::Cancelled => { - let should_repeat = $self.xkb_keymap.key_repeats(key_offset); - let ch = $self.xkb_ctx.key_get_utf8(key_offset).chars().next(); - - if should_repeat { - $self - .timer_handle - .add_timeout(Duration::from_millis(REPEAT_DELAY), (input, ch)); - } - - if let Some(c) = ch { - $callback( - Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::ReceivedCharacter(c), - }, - &mut (), - ); - } - } - xkb::compose::Status::Nothing => { - let should_repeat = $self.xkb_keymap.key_repeats(key_offset); - let ch = $self.xkb_ctx.key_get_utf8(key_offset).chars().next(); - - if should_repeat { - $self - .timer_handle - .add_timeout(Duration::from_millis(600), (input, ch)); - } - - if let Some(c) = ch { - $callback( - Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::ReceivedCharacter(c), - }, - &mut (), - ); - } - } - _ => {} - } - } - match keysym { - xkb_keymap::XKB_KEY_Alt_L | xkb_keymap::XKB_KEY_Alt_R => { - match state { - ElementState::Pressed => $self.modifiers |= ModifiersState::ALT, - ElementState::Released => $self.modifiers.remove(ModifiersState::ALT), - } - - $callback( - Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::ModifiersChanged($self.modifiers), - }, - &mut (), - ); - } - xkb_keymap::XKB_KEY_Shift_L | xkb_keymap::XKB_KEY_Shift_R => { - match state { - ElementState::Pressed => $self.modifiers |= ModifiersState::SHIFT, - ElementState::Released => $self.modifiers.remove(ModifiersState::SHIFT), - } - - $callback( - Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::ModifiersChanged($self.modifiers), - }, - &mut (), - ); - } - - xkb_keymap::XKB_KEY_Control_L | xkb_keymap::XKB_KEY_Control_R => { - match state { - ElementState::Pressed => $self.modifiers |= ModifiersState::CTRL, - ElementState::Released => $self.modifiers.remove(ModifiersState::CTRL), - } - - $callback( - Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::ModifiersChanged($self.modifiers), - }, - &mut (), - ); - } - - xkb_keymap::XKB_KEY_Meta_L | xkb_keymap::XKB_KEY_Meta_R => { - match state { - ElementState::Pressed => $self.modifiers |= ModifiersState::LOGO, - ElementState::Released => $self.modifiers.remove(ModifiersState::LOGO), - } - - $callback( - Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::ModifiersChanged($self.modifiers), - }, - &mut (), - ); - } - xkb_keymap::XKB_KEY_Sys_Req | xkb_keymap::XKB_KEY_Print => { - if $self.modifiers.is_empty() { - $callback( - Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::CloseRequested, - }, - &mut (), - ); - } - } - _ => {} - } - }}; -} - -impl EventSource for LibinputInputBackend { - type Event = Event<'static, ()>; - type Metadata = (); - type Ret = (); - - fn process_events( - &mut self, - _: Readiness, - token: Token, - mut callback: F, - ) -> std::io::Result - where - F: FnMut(Self::Event, &mut ()) -> Self::Ret, - { - if token == self.token { - self.context.dispatch()?; - - for event in &mut self.context { - match event { - input::Event::Device(ev) => handle_device_event!(ev, callback), - input::Event::Touch(ev) => handle_touch_event!(self, ev, callback), - input::Event::Tablet(ev) => handle_tablet_tool_event!(self, ev, callback), - input::Event::Pointer(ev) => handle_pointer_event!(self, ev, callback), - input::Event::Keyboard(ev) => handle_keyboard_event!(self, ev, callback), - _ => {} - } - } - } - Ok(PostAction::Continue) - } - - fn register(&mut self, poll: &mut Poll, factory: &mut TokenFactory) -> std::io::Result<()> { - self.token = factory.token(); - poll.register(self.as_raw_fd(), Interest::READ, Mode::Level, self.token) - } - - fn reregister(&mut self, poll: &mut Poll, factory: &mut TokenFactory) -> std::io::Result<()> { - self.token = factory.token(); - poll.reregister(self.as_raw_fd(), Interest::READ, Mode::Level, self.token) - } - - fn unregister(&mut self, poll: &mut Poll) -> std::io::Result<()> { - self.token = Token::invalid(); - poll.unregister(self.as_raw_fd()) - } -} - /// An event loop's sink to deliver events from the Wayland event callbacks /// to the winit's user. type EventSink = Vec>; @@ -813,40 +153,31 @@ fn find_plane( *p_better_planes.get(0).unwrap_or(&p_compatible_planes[0]) } -fn find_card_path(seat_name: &str) -> Result { +fn find_card_path(seat_name: &str) -> Result { let mut enumerator = Enumerator::new().map_err(|e| { - OsError::new( - line!(), - file!(), - platform_impl::OsError::KmsError(format!("failed to open udev enumerator: {}", e)), - ) + os_error!(OsError::KmsError(format!( + "failed to open udev enumerator: {}", + e + ))) })?; enumerator.match_subsystem("drm").map_err(|e| { - OsError::new( - line!(), - file!(), - platform_impl::OsError::KmsError(format!("failed to enumerate drm subsystem: {}", e)), - ) + os_error!(OsError::KmsError(format!( + "failed to enumerate drm subsystem: {}", + e + ))) })?; enumerator.match_sysname("card[0-9]*").map_err(|e| { - OsError::new( - line!(), - file!(), - platform_impl::OsError::KmsError(format!("failed to find a valid card: {}", e)), - ) + os_error!(OsError::KmsError(format!( + "failed to find a valid card: {}", + e + ))) })?; enumerator .scan_devices() - .map_err(|e| { - OsError::new( - line!(), - file!(), - platform_impl::OsError::KmsError(format!("failed to scan devices: {}", e)), - ) - })? + .map_err(|e| os_error!(OsError::KmsError(format!("failed to scan devices: {}", e))))? .filter(|device| { let dev_seat_name = device .property_value("ID_SEAT") @@ -877,13 +208,7 @@ fn find_card_path(seat_name: &str) -> Result { .flat_map(|device| device.devnode().map(std::path::PathBuf::from)) .next() }) - .ok_or_else(|| { - OsError::new( - line!(), - file!(), - platform_impl::OsError::KmsMisc("failed to find suitable GPU"), - ) - }) + .ok_or_else(|| os_error!(OsError::KmsMisc("failed to find suitable GPU"))) } pub struct EventLoop { @@ -901,7 +226,7 @@ pub struct EventLoop { } impl EventLoop { - pub fn new() -> Result, OsError> { + pub fn new() -> Result, error::OsError> { #[cfg(feature = "kms-ext")] // When we create the seat here, we should probably wait for it to become active before we // use it. @@ -918,22 +243,12 @@ impl EventLoop { }, None, ) - .map_err(|e| { - OsError::new( - line!(), - file!(), - platform_impl::OsError::KmsError(format!("failed to open libseat: {}", e)), - ) - })?; + .map_err(|e| os_error!(OsError::KmsError(format!("failed to open libseat: {}", e))))?; // While our seat is not active dispatch it so that the seat will activate while !active.load(Ordering::SeqCst) { s.dispatch(-1).map_err(|e| { - OsError::new( - line!(), - file!(), - platform_impl::OsError::KmsError(format!("failed to dispatch seat: {}", e)), - ) + os_error!(OsError::KmsError(format!("failed to dispatch seat: {}", e))) })?; } s @@ -959,11 +274,10 @@ impl EventLoop { let dev = seat .open_device(&card_path) .map_err(|e| { - OsError::new( - line!(), - file!(), - platform_impl::OsError::KmsError(format!("failed to initialize DRM: {}", e)), - ) + os_error!(OsError::KmsError(format!( + "failed to initialize DRM: {}", + e + ))) })? .1; @@ -976,14 +290,10 @@ impl EventLoop { .write(true) .open(&card_path) .map_err(|e| { - OsError::new( - line!(), - file!(), - platform_impl::OsError::KmsError(format!( - "failed to initialize DRM: {}", - e - )), - ) + os_error!(OsError::KmsError(format!( + "failed to initialize DRM: {}", + e + ))) })?, ); let drm = Card(std::sync::Arc::new(dev)); @@ -1011,13 +321,7 @@ impl EventLoop { std::env::var("WINIT_XKB_OPTIONS").ok(), xkb::KEYMAP_COMPILE_NO_FLAGS, ) - .ok_or_else(|| { - OsError::new( - line!(), - file!(), - platform_impl::OsError::KmsMisc("failed to compile XKB keymap"), - ) - })?; + .ok_or_else(|| os_error!(OsError::KmsMisc("failed to compile XKB keymap")))?; let state = xkb::State::new(&keymap); @@ -1042,38 +346,26 @@ impl EventLoop { ) .map_err(|_| { // e ^^^ would return () - OsError::new( - line!(), - file!(), - platform_impl::OsError::KmsMisc("failed to compile XKB compose table"), - ) + os_error!(OsError::KmsMisc("failed to compile XKB compose table")) })?; let xkb_compose = xkb::compose::State::new(&compose_table, xkb::compose::STATE_NO_FLAGS); // Allows use to use the non-legacy atomic system drm::Device::set_client_capability(&drm, drm::ClientCapability::Atomic, true).map_err( |e| { - OsError::new( - line!(), - file!(), - platform_impl::OsError::KmsError(format!( - "drm device does not support atomic modesetting :{}", - e - )), - ) + os_error!(OsError::KmsError(format!( + "drm device does not support atomic modesetting :{}", + e + ))) }, )?; // Load the information. let res = drm.resource_handles().map_err(|e| { - OsError::new( - line!(), - file!(), - platform_impl::OsError::KmsError(format!( - "could not load normal resource ids: {}", - e - )), - ) + os_error!(OsError::KmsError(format!( + "could not load normal resource ids: {}", + e + ))) })?; // Enumerate available connectors @@ -1094,22 +386,12 @@ impl EventLoop { let con = coninfo .iter() .find(|&i| i.state() == connector::State::Connected) - .ok_or_else(|| { - OsError::new( - line!(), - file!(), - platform_impl::OsError::KmsMisc("no connected connectors"), - ) - })?; + .ok_or_else(|| os_error!(OsError::KmsMisc("no connected connectors")))?; // Get the first (usually perferred) CRTC - let crtc = crtcinfo.get(0).ok_or_else(|| { - OsError::new( - line!(), - file!(), - platform_impl::OsError::KmsMisc("no crtcs found"), - ) - })?; + let crtc = crtcinfo + .get(0) + .ok_or_else(|| os_error!(OsError::KmsMisc("no crtcs found")))?; // Get the perferred (or first) mode let &mode = con @@ -1117,24 +399,14 @@ impl EventLoop { .iter() .find(|f| f.mode_type().contains(ModeTypeFlags::PREFERRED)) .or_else(|| con.modes().get(0)) - .ok_or_else(|| { - OsError::new( - line!(), - file!(), - platform_impl::OsError::KmsMisc("no modes found on connector"), - ) - })?; + .ok_or_else(|| os_error!(OsError::KmsMisc("no modes found on connector")))?; *MODE.lock() = Some(mode); // Enumerate available planes - let planes = drm.plane_handles().map_err(|e| { - OsError::new( - line!(), - file!(), - platform_impl::OsError::KmsError(format!("could not list planes: {}", e)), - ) - })?; + let planes = drm + .plane_handles() + .map_err(|e| os_error!(OsError::KmsError(format!("could not list planes: {}", e))))?; let p_plane = find_plane(planes, res, crtc, &drm); diff --git a/src/platform_impl/linux/kms/input.rs b/src/platform_impl/linux/kms/input.rs new file mode 100644 index 0000000000..c9eafa0e31 --- /dev/null +++ b/src/platform_impl/linux/kms/input.rs @@ -0,0 +1,700 @@ +use crate::{ + dpi::PhysicalPosition, + event::DeviceId, + event::{ + DeviceEvent, ElementState, Event, Force, KeyboardInput, ModifiersState, MouseButton, + MouseScrollDelta, Touch, TouchPhase, WindowEvent, + }, + platform_impl::{self, xkb_keymap}, + window::WindowId, +}; +use input::{ + event::{ + keyboard::KeyboardEventTrait, + pointer::PointerScrollEvent, + tablet_pad::{ButtonState, KeyState}, + tablet_tool::{TabletToolEventTrait, TipState}, + touch::{TouchEventPosition, TouchEventSlot}, + }, + LibinputInterface, +}; +use parking_lot::Mutex; +#[cfg(feature = "kms-ext")] +use std::collections::HashMap; +use std::{ + os::unix::prelude::{AsRawFd, FromRawFd, RawFd}, + path::Path, + sync::Arc, + time::Duration, +}; + +use calloop::{EventSource, Interest, Mode, Poll, PostAction, Readiness, Token, TokenFactory}; +use xkbcommon::xkb; + +pub const REPEAT_RATE: u64 = 25; +pub const REPEAT_DELAY: u64 = 600; + +macro_rules! to_platform_impl { + ($p:ident, $params:expr) => { + $p(platform_impl::$p::Kms($params)) + }; +} + +macro_rules! window_id { + () => { + to_platform_impl!(WindowId, super::WindowId) + }; +} + +macro_rules! device_id { + () => { + to_platform_impl!(DeviceId, super::DeviceId) + }; +} + +#[cfg(feature = "kms-ext")] +struct Interface(libseat::Seat, HashMap); +#[cfg(not(feature = "kms-ext"))] +pub struct Interface; + +#[cfg(feature = "kms-ext")] +impl LibinputInterface for Interface { + fn open_restricted(&mut self, path: &Path, _flags: i32) -> Result { + self.0 + .open_device(&path) + .map(|(id, file)| { + self.1.insert(file, id); + file + }) + .map_err(|err| err.into()) + } + + fn close_restricted(&mut self, fd: RawFd) { + if let Some(dev) = self.1.get(&fd).copied() { + self.0.close_device(dev).unwrap(); + } + + unsafe { std::fs::File::from_raw_fd(fd) }; + } +} + +#[cfg(not(feature = "kms-ext"))] +impl LibinputInterface for Interface { + fn open_restricted(&mut self, path: &Path, flags: i32) -> Result { + use std::os::unix::prelude::*; + + std::fs::OpenOptions::new() + .custom_flags(flags) + .read(flags & libc::O_RDWR != 0) + .write((flags & libc::O_WRONLY != 0) | (flags & libc::O_RDWR != 0)) + .open(path) + .map(|file| file.into_raw_fd()) + .map_err(|err| err.raw_os_error().unwrap()) + } + fn close_restricted(&mut self, fd: RawFd) { + unsafe { + std::fs::File::from_raw_fd(fd); + } + } +} + +pub struct LibinputInputBackend { + context: input::Libinput, + xkb_ctx: xkb::State, + xkb_keymap: xkb::Keymap, + xkb_compose: xkb::compose::State, + token: Token, + touch_location: PhysicalPosition, + screen_size: (u32, u32), + modifiers: ModifiersState, + cursor_positon: Arc>>, + timer_handle: calloop::timer::TimerHandle<(KeyboardInput, Option)>, +} + +impl LibinputInputBackend { + /// Initialize a new [`LibinputInputBackend`] from a given already initialized + /// [libinput context](input::Libinput). + pub fn new( + context: input::Libinput, + screen_size: (u32, u32), + timer_handle: calloop::timer::TimerHandle<(KeyboardInput, Option)>, + xkb_ctx: xkb::State, + xkb_keymap: xkb::Keymap, + xkb_compose: xkb::compose::State, + cursor_positon: Arc>>, + ) -> Self { + LibinputInputBackend { + context, + token: Token::invalid(), + touch_location: PhysicalPosition::new(0.0, 0.0), + modifiers: ModifiersState::empty(), + cursor_positon, + screen_size, + timer_handle, + xkb_ctx, + xkb_keymap, + xkb_compose, + } + } +} + +impl AsRawFd for LibinputInputBackend { + fn as_raw_fd(&self) -> RawFd { + self.context.as_raw_fd() + } +} + +macro_rules! handle_device_event { + ($ev:expr,$callback:expr) => { + match $ev { + input::event::DeviceEvent::Added(_) => { + $callback( + Event::DeviceEvent { + device_id: device_id!(), + event: DeviceEvent::Added, + }, + &mut (), + ); + } + input::event::DeviceEvent::Removed(_) => { + $callback( + Event::DeviceEvent { + device_id: device_id!(), + event: DeviceEvent::Removed, + }, + &mut (), + ); + } + _ => {} + } + }; +} + +macro_rules! handle_touch_event { + ($self:expr,$ev:expr,$callback:expr) => { + match $ev { + input::event::TouchEvent::Up(e) => $callback( + Event::WindowEvent { + window_id: window_id!(), + event: WindowEvent::Touch(Touch { + device_id: device_id!(), + phase: TouchPhase::Ended, + location: $self.touch_location, + force: None, + id: e.slot().unwrap() as u64, + }), + }, + &mut (), + ), + input::event::TouchEvent::Down(e) => { + $self.touch_location.x = e.x_transformed($self.screen_size.0); + $self.touch_location.y = e.y_transformed($self.screen_size.1); + + $callback( + Event::WindowEvent { + window_id: window_id!(), + event: WindowEvent::Touch(Touch { + device_id: device_id!(), + phase: TouchPhase::Started, + location: $self.touch_location, + force: None, + id: e.slot().unwrap() as u64, + }), + }, + &mut (), + ) + } + input::event::TouchEvent::Motion(e) => { + $self.touch_location.x = e.x_transformed($self.screen_size.0); + $self.touch_location.y = e.y_transformed($self.screen_size.1); + + $callback( + Event::WindowEvent { + window_id: window_id!(), + event: WindowEvent::Touch(Touch { + device_id: device_id!(), + phase: TouchPhase::Moved, + location: $self.touch_location, + force: None, + id: e.slot().unwrap() as u64, + }), + }, + &mut (), + ); + } + input::event::TouchEvent::Cancel(e) => $callback( + Event::WindowEvent { + window_id: window_id!(), + event: WindowEvent::Touch(Touch { + device_id: device_id!(), + phase: TouchPhase::Cancelled, + location: $self.touch_location, + force: None, + id: e.slot().unwrap() as u64, + }), + }, + &mut (), + ), + input::event::TouchEvent::Frame(_) => $callback( + Event::WindowEvent { + window_id: window_id!(), + event: WindowEvent::Touch(Touch { + device_id: device_id!(), + phase: TouchPhase::Ended, + location: $self.touch_location, + force: None, + id: 0, // e.slot().unwrap() as u64, + }), + }, + &mut (), + ), + _ => {} + } + }; +} + +macro_rules! handle_tablet_tool_event { + ($self:expr,$ev:expr,$callback:expr) => { + match $ev { + input::event::TabletToolEvent::Tip(e) => $callback( + Event::WindowEvent { + window_id: window_id!(), + event: WindowEvent::Touch(Touch { + device_id: device_id!(), + phase: match e.tip_state() { + TipState::Down => TouchPhase::Started, + TipState::Up => TouchPhase::Ended, + }, + location: PhysicalPosition::new( + e.x_transformed($self.screen_size.0), + e.y_transformed($self.screen_size.1), + ), + force: Some(Force::Calibrated { + force: e.pressure(), + max_possible_force: 1.0, + altitude_angle: None, + }), + id: 0, + }), + }, + &mut (), + ), + input::event::TabletToolEvent::Button(e) => { + $callback( + Event::WindowEvent { + window_id: window_id!(), + event: WindowEvent::MouseInput { + device_id: device_id!(), + state: match e.button_state() { + ButtonState::Pressed => ElementState::Pressed, + ButtonState::Released => ElementState::Released, + }, + button: match e.button() { + 1 => MouseButton::Right, + 2 => MouseButton::Middle, + _ => MouseButton::Left, + }, + modifiers: $self.modifiers, + }, + }, + &mut (), + ); + + $callback( + Event::DeviceEvent { + device_id: device_id!(), + event: DeviceEvent::Button { + button: e.button(), + state: match e.button_state() { + ButtonState::Pressed => ElementState::Pressed, + ButtonState::Released => ElementState::Released, + }, + }, + }, + &mut (), + ); + } + _ => {} + } + }; +} + +macro_rules! handle_pointer_event { + ($self:expr,$ev:expr,$callback:expr) => { + match $ev { + input::event::PointerEvent::Motion(e) => { + let mut lock = $self.cursor_positon.lock(); + + lock.x += e.dx(); + lock.x = lock.x.clamp(0.0, $self.screen_size.0 as f64); + + lock.y += e.dy(); + lock.y = lock.y.clamp(0.0, $self.screen_size.1 as f64); + + $callback( + Event::WindowEvent { + window_id: window_id!(), + event: WindowEvent::CursorMoved { + device_id: device_id!(), + position: *lock, + modifiers: $self.modifiers, + }, + }, + &mut (), + ); + + $callback( + Event::DeviceEvent { + device_id: device_id!(), + event: DeviceEvent::MouseMotion { + delta: (e.dx(), e.dy()), + }, + }, + &mut (), + ); + } + + input::event::PointerEvent::Button(e) => { + $callback( + Event::WindowEvent { + window_id: window_id!(), + event: WindowEvent::MouseInput { + device_id: device_id!(), + state: match e.button_state() { + ButtonState::Pressed => ElementState::Pressed, + ButtonState::Released => ElementState::Released, + }, + button: match e.button() { + 1 => MouseButton::Right, + 2 => MouseButton::Middle, + _ => MouseButton::Left, + }, + modifiers: $self.modifiers, + }, + }, + &mut (), + ); + + $callback( + Event::DeviceEvent { + device_id: device_id!(), + event: DeviceEvent::Button { + button: e.button(), + state: match e.button_state() { + ButtonState::Pressed => ElementState::Pressed, + ButtonState::Released => ElementState::Released, + }, + }, + }, + &mut (), + ); + } + + input::event::PointerEvent::ScrollWheel(e) => { + use input::event::pointer::Axis; + + $callback( + Event::WindowEvent { + window_id: window_id!(), + event: WindowEvent::MouseWheel { + device_id: device_id!(), + delta: MouseScrollDelta::LineDelta( + if e.has_axis(Axis::Horizontal) { + e.scroll_value(Axis::Horizontal) as f32 + } else { + 0.0 + }, + if e.has_axis(Axis::Vertical) { + e.scroll_value(Axis::Vertical) as f32 + } else { + 0.0 + }, + ), + phase: TouchPhase::Moved, + modifiers: $self.modifiers, + }, + }, + &mut (), + ); + } + + input::event::PointerEvent::ScrollFinger(e) => { + use input::event::pointer::Axis; + + $callback( + Event::WindowEvent { + window_id: window_id!(), + event: WindowEvent::MouseWheel { + device_id: device_id!(), + delta: MouseScrollDelta::PixelDelta(PhysicalPosition::new( + if e.has_axis(Axis::Horizontal) { + e.scroll_value(Axis::Horizontal) + } else { + 0.0 + }, + if e.has_axis(Axis::Vertical) { + e.scroll_value(Axis::Vertical) + } else { + 0.0 + }, + )), + phase: TouchPhase::Moved, + modifiers: $self.modifiers, + }, + }, + &mut (), + ); + } + + input::event::PointerEvent::MotionAbsolute(e) => { + let mut lock = $self.cursor_positon.lock(); + + lock.x = e.absolute_x_transformed($self.screen_size.0); + + lock.y = e.absolute_y_transformed($self.screen_size.1); + + $callback( + Event::WindowEvent { + window_id: window_id!(), + event: WindowEvent::CursorMoved { + device_id: device_id!(), + position: *lock, + modifiers: $self.modifiers, + }, + }, + &mut (), + ); + } + _ => {} + } + }; +} + +macro_rules! handle_keyboard_event { + ($self:expr,$ev:expr,$callback:expr) => {{ + let state = match $ev.key_state() { + KeyState::Pressed => ElementState::Pressed, + KeyState::Released => ElementState::Released, + }; + + let k = if let input::event::KeyboardEvent::Key(key) = $ev { + key.key() + } else { + unreachable!() + }; + + let key_offset = k + 8; + let keysym = $self.xkb_ctx.key_get_one_sym(key_offset); + let virtual_keycode = xkb_keymap::keysym_to_vkey(keysym); + + $self.xkb_ctx.update_key( + key_offset, + match state { + ElementState::Pressed => xkb::KeyDirection::Down, + ElementState::Released => xkb::KeyDirection::Up, + }, + ); + + #[allow(deprecated)] + let input = KeyboardInput { + scancode: k, + state: state.clone(), + virtual_keycode, + modifiers: $self.modifiers, + }; + + $self.timer_handle.cancel_all_timeouts(); + + $callback( + Event::WindowEvent { + window_id: window_id!(), + event: WindowEvent::KeyboardInput { + device_id: device_id!(), + input, + is_synthetic: false, + }, + }, + &mut (), + ); + + if let ElementState::Pressed = state { + $self.xkb_compose.feed(keysym); + + match $self.xkb_compose.status() { + xkb::compose::Status::Composed => { + if let Some(c) = $self.xkb_compose.utf8().and_then(|f| f.chars().next()) { + $callback( + Event::WindowEvent { + window_id: window_id!(), + event: WindowEvent::ReceivedCharacter(c), + }, + &mut (), + ); + } + } + xkb::compose::Status::Cancelled => { + let should_repeat = $self.xkb_keymap.key_repeats(key_offset); + let ch = $self.xkb_ctx.key_get_utf8(key_offset).chars().next(); + + if should_repeat { + $self + .timer_handle + .add_timeout(Duration::from_millis(REPEAT_DELAY), (input, ch)); + } + + if let Some(c) = ch { + $callback( + Event::WindowEvent { + window_id: window_id!(), + event: WindowEvent::ReceivedCharacter(c), + }, + &mut (), + ); + } + } + xkb::compose::Status::Nothing => { + let should_repeat = $self.xkb_keymap.key_repeats(key_offset); + let ch = $self.xkb_ctx.key_get_utf8(key_offset).chars().next(); + + if should_repeat { + $self + .timer_handle + .add_timeout(Duration::from_millis(600), (input, ch)); + } + + if let Some(c) = ch { + $callback( + Event::WindowEvent { + window_id: window_id!(), + event: WindowEvent::ReceivedCharacter(c), + }, + &mut (), + ); + } + } + _ => {} + } + } + match keysym { + xkb_keymap::XKB_KEY_Alt_L | xkb_keymap::XKB_KEY_Alt_R => { + match state { + ElementState::Pressed => $self.modifiers |= ModifiersState::ALT, + ElementState::Released => $self.modifiers.remove(ModifiersState::ALT), + } + + $callback( + Event::WindowEvent { + window_id: window_id!(), + event: WindowEvent::ModifiersChanged($self.modifiers), + }, + &mut (), + ); + } + + xkb_keymap::XKB_KEY_Shift_L | xkb_keymap::XKB_KEY_Shift_R => { + match state { + ElementState::Pressed => $self.modifiers |= ModifiersState::SHIFT, + ElementState::Released => $self.modifiers.remove(ModifiersState::SHIFT), + } + + $callback( + Event::WindowEvent { + window_id: window_id!(), + event: WindowEvent::ModifiersChanged($self.modifiers), + }, + &mut (), + ); + } + + xkb_keymap::XKB_KEY_Control_L | xkb_keymap::XKB_KEY_Control_R => { + match state { + ElementState::Pressed => $self.modifiers |= ModifiersState::CTRL, + ElementState::Released => $self.modifiers.remove(ModifiersState::CTRL), + } + + $callback( + Event::WindowEvent { + window_id: window_id!(), + event: WindowEvent::ModifiersChanged($self.modifiers), + }, + &mut (), + ); + } + + xkb_keymap::XKB_KEY_Meta_L | xkb_keymap::XKB_KEY_Meta_R => { + match state { + ElementState::Pressed => $self.modifiers |= ModifiersState::LOGO, + ElementState::Released => $self.modifiers.remove(ModifiersState::LOGO), + } + + $callback( + Event::WindowEvent { + window_id: window_id!(), + event: WindowEvent::ModifiersChanged($self.modifiers), + }, + &mut (), + ); + } + + xkb_keymap::XKB_KEY_Sys_Req | xkb_keymap::XKB_KEY_Print => { + if $self.modifiers.is_empty() { + $callback( + Event::WindowEvent { + window_id: window_id!(), + event: WindowEvent::CloseRequested, + }, + &mut (), + ); + } + } + _ => {} + } + }}; +} + +impl EventSource for LibinputInputBackend { + type Event = Event<'static, ()>; + type Metadata = (); + type Ret = (); + + fn process_events( + &mut self, + _: Readiness, + token: Token, + mut callback: F, + ) -> std::io::Result + where + F: FnMut(Self::Event, &mut ()) -> Self::Ret, + { + if token == self.token { + self.context.dispatch()?; + + for event in &mut self.context { + match event { + input::Event::Device(ev) => handle_device_event!(ev, callback), + input::Event::Touch(ev) => handle_touch_event!(self, ev, callback), + input::Event::Tablet(ev) => handle_tablet_tool_event!(self, ev, callback), + input::Event::Pointer(ev) => handle_pointer_event!(self, ev, callback), + input::Event::Keyboard(ev) => handle_keyboard_event!(self, ev, callback), + _ => {} + } + } + } + Ok(PostAction::Continue) + } + + fn register(&mut self, poll: &mut Poll, factory: &mut TokenFactory) -> std::io::Result<()> { + self.token = factory.token(); + poll.register(self.as_raw_fd(), Interest::READ, Mode::Level, self.token) + } + + fn reregister(&mut self, poll: &mut Poll, factory: &mut TokenFactory) -> std::io::Result<()> { + self.token = factory.token(); + poll.reregister(self.as_raw_fd(), Interest::READ, Mode::Level, self.token) + } + + fn unregister(&mut self, poll: &mut Poll) -> std::io::Result<()> { + self.token = Token::invalid(); + poll.unregister(self.as_raw_fd()) + } +} diff --git a/src/platform_impl/linux/kms/mod.rs b/src/platform_impl/linux/kms/mod.rs index f3ea696293..5ecddf114c 100644 --- a/src/platform_impl/linux/kms/mod.rs +++ b/src/platform_impl/linux/kms/mod.rs @@ -1,6 +1,7 @@ use crate::dpi::{PhysicalPosition, PhysicalSize}; pub mod event_loop; +pub mod input; pub mod window; use crate::{monitor, platform_impl}; pub use drm::SystemError; @@ -44,6 +45,7 @@ impl ControlDevice for Card {} #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct DeviceId; +#[allow(dead_code)] impl DeviceId { pub const unsafe fn dummy() -> Self { DeviceId @@ -151,6 +153,7 @@ impl VideoMode { #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct WindowId; +#[allow(dead_code)] impl WindowId { pub const unsafe fn dummy() -> Self { Self diff --git a/src/platform_impl/linux/kms/window.rs b/src/platform_impl/linux/kms/window.rs index 9439f4194e..3b0051c77d 100644 --- a/src/platform_impl/linux/kms/window.rs +++ b/src/platform_impl/linux/kms/window.rs @@ -7,9 +7,11 @@ use parking_lot::Mutex; #[cfg(feature = "wayland")] use sctk::reexports::calloop; +use crate::error; + use crate::{ dpi::{PhysicalPosition, PhysicalSize, Position, Size}, - error::{ExternalError, NotSupportedError, OsError}, + error::{ExternalError, NotSupportedError}, monitor::{MonitorHandle, VideoMode}, platform::unix::Card, platform_impl, @@ -43,11 +45,10 @@ fn find_prop_id( macro_rules! find_prop_id { ($id_handle_1:expr,$handle:expr,$prop_name:literal) => { find_prop_id(&$id_handle_1, $handle, $prop_name).ok_or_else(|| { - OsError::new( - line!(), - file!(), - platform_impl::OsError::KmsMisc(concat!("could not get ", $prop_name)), - ) + os_error!(platform_impl::OsError::KmsMisc(concat!( + "could not get ", + $prop_name + ))) }) }; } @@ -67,7 +68,7 @@ impl Window { event_loop_window_target: &super::event_loop::EventLoopWindowTarget, _attributes: WindowAttributes, _platform_attributes: platform_impl::PlatformSpecificWindowBuilderAttributes, - ) -> Result { + ) -> Result { let mut atomic_req = atomic::AtomicModeReq::new(); add_property!( @@ -79,23 +80,13 @@ impl Window { ); let mode = &(MODE.lock().ok_or_else(|| { - OsError::new( - line!(), - file!(), - platform_impl::OsError::KmsMisc("mode is not initialized"), - ) + os_error!(platform_impl::OsError::KmsMisc("mode is not initialized")) })?); let blob = event_loop_window_target .device .create_property_blob(mode) - .map_err(|_| { - OsError::new( - line!(), - file!(), - platform_impl::OsError::KmsMisc("failed to create blob"), - ) - })?; + .map_err(|_| os_error!(platform_impl::OsError::KmsMisc("failed to create blob")))?; add_property!( atomic_req, @@ -189,11 +180,10 @@ impl Window { .device .atomic_commit(AtomicCommitFlags::ALLOW_MODESET, atomic_req) .map_err(|e| { - OsError::new( - line!(), - file!(), - platform_impl::OsError::KmsError(format!("failed to set mode: {}", e)), - ) + os_error!(platform_impl::OsError::KmsError(format!( + "failed to set mode: {}", + e + ))) })?; Ok(Self { From 046f1a0bf6628e217c5c3f10c19d4eb33d677de7 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 10 May 2022 18:11:59 -0400 Subject: [PATCH 115/151] Fix CI --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c403dd18e6..42fdb4dcfc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -68,7 +68,7 @@ jobs: run: sudo apt-get update && sudo apt-get install gcc-multilib - name: Install C Dependencies if: (matrix.platform.os == 'ubuntu-latest') - run: sudo apt-get update && sudo apt-get install libudev-dev libinput-dev + run: sudo apt-get update && sudo apt-get install libudev-dev libinput-dev libxkbcommon-dev - name: Install cargo-apk if: contains(matrix.platform.target, 'android') run: cargo install cargo-apk From 5359a00a0053468efedf9a224e77985a25521bda Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 10 May 2022 18:20:53 -0400 Subject: [PATCH 116/151] Fix CI --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 42fdb4dcfc..81b21588a7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -68,7 +68,7 @@ jobs: run: sudo apt-get update && sudo apt-get install gcc-multilib - name: Install C Dependencies if: (matrix.platform.os == 'ubuntu-latest') - run: sudo apt-get update && sudo apt-get install libudev-dev libinput-dev libxkbcommon-dev + run: sudo apt-get update && sudo apt-get install libudev-dev libinput-dev libxkbcommon-dev libseat-dev - name: Install cargo-apk if: contains(matrix.platform.target, 'android') run: cargo install cargo-apk From e3ade8483e0b90e0ce32ebda9b078aa03a8d9cb5 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 10 May 2022 18:28:47 -0400 Subject: [PATCH 117/151] Fix CI --- .github/workflows/ci.yml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 81b21588a7..022ed49663 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -68,7 +68,18 @@ jobs: run: sudo apt-get update && sudo apt-get install gcc-multilib - name: Install C Dependencies if: (matrix.platform.os == 'ubuntu-latest') - run: sudo apt-get update && sudo apt-get install libudev-dev libinput-dev libxkbcommon-dev libseat-dev + run: sudo apt-get update && sudo apt-get install libudev-dev libinput-dev libxkbcommon-dev meson ninja-build + - name: Build libseat + if: (matrix.platform.os == 'ubuntu-latest') + run: | + sudo apt-get install meson ninja-build + wget https://git.sr.ht/~kennylevinsen/seatd/archive/0.5.0.tar.gz -O libseat-source.tar.gz + tar xf libseat-source.tar.gz + cd seatd-0.5.0 + meson -Dbuiltin=enabled -Dserver=disabled -Dexamples=disabled -Dman-pages=disabled build . + ninja -C build + sudo meson install -C build + - name: Install cargo-apk if: contains(matrix.platform.target, 'android') run: cargo install cargo-apk From a2856589dc21ef9511e5bb33a2d89b316ba2a1eb Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 10 May 2022 18:37:23 -0400 Subject: [PATCH 118/151] Fix CI --- Cargo.toml | 2 +- src/platform_impl/linux/kms/input.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a9efd6d096..57927ef123 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ default = ["x11", "wayland", "wayland-dlopen", "kms"] x11 = ["x11-dl", "mio", "percent-encoding", "parking_lot"] wayland = ["wayland-client", "wayland-protocols", "sctk"] wayland-dlopen = ["sctk/dlopen", "wayland-client/dlopen"] -kms = ["drm", "input", "calloop", "xkbcommon", "udev"] +kms = ["drm", "input", "calloop", "xkbcommon", "udev", "parking_lot"] kms-ext = ["libseat"] [dependencies] diff --git a/src/platform_impl/linux/kms/input.rs b/src/platform_impl/linux/kms/input.rs index c9eafa0e31..43cc23e3cc 100644 --- a/src/platform_impl/linux/kms/input.rs +++ b/src/platform_impl/linux/kms/input.rs @@ -53,7 +53,7 @@ macro_rules! device_id { } #[cfg(feature = "kms-ext")] -struct Interface(libseat::Seat, HashMap); +pub struct Interface(libseat::Seat, HashMap); #[cfg(not(feature = "kms-ext"))] pub struct Interface; From 680be41fca80f2431736f947d42883fc9dd46802 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 10 May 2022 18:38:54 -0400 Subject: [PATCH 119/151] Fix CI --- src/platform_impl/linux/kms/input.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform_impl/linux/kms/input.rs b/src/platform_impl/linux/kms/input.rs index 43cc23e3cc..4997110667 100644 --- a/src/platform_impl/linux/kms/input.rs +++ b/src/platform_impl/linux/kms/input.rs @@ -53,7 +53,7 @@ macro_rules! device_id { } #[cfg(feature = "kms-ext")] -pub struct Interface(libseat::Seat, HashMap); +pub struct Interface(pub libseat::Seat, pub HashMap); #[cfg(not(feature = "kms-ext"))] pub struct Interface; From a8727fafd5833fb0956b19388ded2f0cf240f2ef Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 10 May 2022 19:03:03 -0400 Subject: [PATCH 120/151] Fix CI --- src/platform/unix.rs | 7 ++++--- src/platform_impl/linux/kms/event_loop.rs | 2 +- src/platform_impl/linux/mod.rs | 6 +++--- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/platform/unix.rs b/src/platform/unix.rs index 28e8d65722..a9f6217a1e 100644 --- a/src/platform/unix.rs +++ b/src/platform/unix.rs @@ -6,6 +6,7 @@ target_os = "openbsd" ))] +#[cfg(any(feature = "x11", feature = "wayland"))] use std::os::raw; #[cfg(feature = "x11")] use std::ptr; @@ -25,9 +26,9 @@ use crate::dpi::Size; use crate::platform_impl::kms::MODE; #[cfg(feature = "x11")] use crate::platform_impl::x11::{ffi::XVisualInfo, XConnection}; -use crate::platform_impl::{ - ApplicationName, EventLoopWindowTarget as LinuxEventLoopWindowTarget, Window as LinuxWindow, -}; +#[cfg(any(feature = "x11", feature = "wayland"))] +use crate::platform_impl::Window as LinuxWindow; +use crate::platform_impl::{ApplicationName, EventLoopWindowTarget as LinuxEventLoopWindowTarget}; #[cfg(any(feature = "x11", feature = "wayland", feature = "kms"))] pub use crate::platform_impl::Backend; diff --git a/src/platform_impl/linux/kms/event_loop.rs b/src/platform_impl/linux/kms/event_loop.rs index 5ee5cf26c5..a7b68f70bf 100644 --- a/src/platform_impl/linux/kms/event_loop.rs +++ b/src/platform_impl/linux/kms/event_loop.rs @@ -699,7 +699,7 @@ impl EventLoop { platform_impl::EventLoopWindowTarget::Kms(window_target) => { &mut window_target.event_sink } - #[cfg(any(feature = "x11", feature = "kms"))] + #[cfg(any(feature = "x11", feature = "wayland"))] _ => unreachable!(), }; diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index efaf7e3a96..c63d0c1ec8 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -532,12 +532,12 @@ impl Window { Window::Kms(_) => (), } } - pub fn request_user_attention(&self, request_type: Option) { + pub fn request_user_attention(&self, _request_type: Option) { match self { #[cfg(feature = "x11")] - Window::X(ref w) => w.request_user_attention(request_type), + Window::X(ref w) => w.request_user_attention(_request_type), #[cfg(feature = "wayland")] - Window::Wayland(ref w) => w.request_user_attention(request_type), + Window::Wayland(ref w) => w.request_user_attention(_request_type), #[cfg(feature = "kms")] Window::Kms(_) => (), } From 2f45711d83e5b7c9991101dcd8bf88e4b21a409a Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 10 May 2022 19:18:16 -0400 Subject: [PATCH 121/151] Fix CI --- .github/workflows/ci.yml | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 022ed49663..47c5f2df01 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -62,6 +62,40 @@ jobs: with: rust-version: ${{ matrix.rust_version }}${{ matrix.platform.host }} targets: ${{ matrix.platform.target }} + - name: Setup cross linux toolchain + if: contains(matrix.target, '-linux-') && !startsWith(matrix.target, 'x86_64-') + run: | + case "${{ matrix.target }}" in + i686-*) SYSTEM_ARCH=i386 ;; + arm*) SYSTEM_ARCH=armhf ;; + aarch64*) SYSTEM_ARCH=arm64 ;; + esac + GCC_TARGET=$(printf "${{ matrix.target }}" | sed 's/-unknown-/-/' | sed 's/arm[^-]*/arm/g') + ENV_TARGET=$(printf "${{ matrix.target }}" | tr '-' '_') + ENV_TARGET_UC=$(printf "${ENV_TARGET}" | tr '[[:lower:]]' '[[:upper:]]') + sudo rm -f /etc/apt/sources.list.d/*.list + case "${{ matrix.target }}" in + arm* | aarch64*) + sudo tee /etc/apt/sources.list << EOF + deb [arch=i386,amd64] http://archive.ubuntu.com/ubuntu/ focal main universe + deb [arch=i386,amd64] http://archive.ubuntu.com/ubuntu/ focal-updates main universe + deb [arch=i386,amd64] http://security.ubuntu.com/ubuntu/ focal-security main universe + deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports/ focal main universe + deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports/ focal-updates main universe + deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports/ focal-security main universe + EOF + ;; + esac + sudo dpkg --add-architecture ${SYSTEM_ARCH} + dpkg --print-foreign-architectures + sudo apt-get update -qqy + sudo apt-get dist-upgrade -qqy --fix-broken + sudo apt-get install -qqy --fix-broken -o Debug::pkgProblemResolver=yes libinput-dev:${SYSTEM_ARCH} gcc-${GCC_TARGET} pkg-config-${GCC_TARGET} + echo "CARGO_TARGET_${ENV_TARGET_UC}_LINKER=${GCC_TARGET}-gcc" >> $GITHUB_ENV + echo "PKG_CONFIG_ALLOW_CROSS=1" >> $GITHUB_ENV + echo "PKG_CONFIG_${ENV_TARGET}=${GCC_TARGET}-pkg-config" >> $GITHUB_ENV + echo "PKG_CONFIG=${GCC_TARGET}-pkg-config" >> $GITHUB_ENV + echo "BINDGEN_EXTRA_CLANG_ARGS=\"-L/usr/lib/${GCC_TARGET} -L/lib/${GCC_TARGET}\"" >> $GITHUB_ENV - name: Install GCC Multilib if: (matrix.platform.os == 'ubuntu-latest') && contains(matrix.platform.target, 'i686') From 1cf79c260e6a6b1691fb36c5f09e275756f4d702 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 10 May 2022 19:21:18 -0400 Subject: [PATCH 122/151] Fix CI --- .github/workflows/ci.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 47c5f2df01..f93b0c7863 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -84,7 +84,7 @@ jobs: deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports/ focal-updates main universe deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports/ focal-security main universe EOF - ;; + ;; esac sudo dpkg --add-architecture ${SYSTEM_ARCH} dpkg --print-foreign-architectures @@ -99,14 +99,13 @@ jobs: - name: Install GCC Multilib if: (matrix.platform.os == 'ubuntu-latest') && contains(matrix.platform.target, 'i686') - run: sudo apt-get update && sudo apt-get install gcc-multilib + run: sudo apt-get install gcc-multilib - name: Install C Dependencies if: (matrix.platform.os == 'ubuntu-latest') - run: sudo apt-get update && sudo apt-get install libudev-dev libinput-dev libxkbcommon-dev meson ninja-build + run: sudo apt-get install libudev-dev libinput-dev libxkbcommon-dev meson ninja-build - name: Build libseat if: (matrix.platform.os == 'ubuntu-latest') run: | - sudo apt-get install meson ninja-build wget https://git.sr.ht/~kennylevinsen/seatd/archive/0.5.0.tar.gz -O libseat-source.tar.gz tar xf libseat-source.tar.gz cd seatd-0.5.0 From 35d762d5d57f922348719fdd630728a4c0373d0a Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 10 May 2022 19:24:54 -0400 Subject: [PATCH 123/151] Fix CI --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f93b0c7863..62ef78cafc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -99,10 +99,10 @@ jobs: - name: Install GCC Multilib if: (matrix.platform.os == 'ubuntu-latest') && contains(matrix.platform.target, 'i686') - run: sudo apt-get install gcc-multilib + run: sudo apt-get install -qqy gcc-multilib - name: Install C Dependencies if: (matrix.platform.os == 'ubuntu-latest') - run: sudo apt-get install libudev-dev libinput-dev libxkbcommon-dev meson ninja-build + run: sudo apt-get install -qqy libudev-dev libinput-dev libxkbcommon-dev meson ninja-build - name: Build libseat if: (matrix.platform.os == 'ubuntu-latest') run: | From 0bca5403c549fcecb566ef91347e6af32fa35212 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 10 May 2022 19:26:05 -0400 Subject: [PATCH 124/151] Fix CI --- .github/workflows/ci.yml | 34 ---------------------------------- 1 file changed, 34 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 62ef78cafc..254629d832 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -62,40 +62,6 @@ jobs: with: rust-version: ${{ matrix.rust_version }}${{ matrix.platform.host }} targets: ${{ matrix.platform.target }} - - name: Setup cross linux toolchain - if: contains(matrix.target, '-linux-') && !startsWith(matrix.target, 'x86_64-') - run: | - case "${{ matrix.target }}" in - i686-*) SYSTEM_ARCH=i386 ;; - arm*) SYSTEM_ARCH=armhf ;; - aarch64*) SYSTEM_ARCH=arm64 ;; - esac - GCC_TARGET=$(printf "${{ matrix.target }}" | sed 's/-unknown-/-/' | sed 's/arm[^-]*/arm/g') - ENV_TARGET=$(printf "${{ matrix.target }}" | tr '-' '_') - ENV_TARGET_UC=$(printf "${ENV_TARGET}" | tr '[[:lower:]]' '[[:upper:]]') - sudo rm -f /etc/apt/sources.list.d/*.list - case "${{ matrix.target }}" in - arm* | aarch64*) - sudo tee /etc/apt/sources.list << EOF - deb [arch=i386,amd64] http://archive.ubuntu.com/ubuntu/ focal main universe - deb [arch=i386,amd64] http://archive.ubuntu.com/ubuntu/ focal-updates main universe - deb [arch=i386,amd64] http://security.ubuntu.com/ubuntu/ focal-security main universe - deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports/ focal main universe - deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports/ focal-updates main universe - deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports/ focal-security main universe - EOF - ;; - esac - sudo dpkg --add-architecture ${SYSTEM_ARCH} - dpkg --print-foreign-architectures - sudo apt-get update -qqy - sudo apt-get dist-upgrade -qqy --fix-broken - sudo apt-get install -qqy --fix-broken -o Debug::pkgProblemResolver=yes libinput-dev:${SYSTEM_ARCH} gcc-${GCC_TARGET} pkg-config-${GCC_TARGET} - echo "CARGO_TARGET_${ENV_TARGET_UC}_LINKER=${GCC_TARGET}-gcc" >> $GITHUB_ENV - echo "PKG_CONFIG_ALLOW_CROSS=1" >> $GITHUB_ENV - echo "PKG_CONFIG_${ENV_TARGET}=${GCC_TARGET}-pkg-config" >> $GITHUB_ENV - echo "PKG_CONFIG=${GCC_TARGET}-pkg-config" >> $GITHUB_ENV - echo "BINDGEN_EXTRA_CLANG_ARGS=\"-L/usr/lib/${GCC_TARGET} -L/lib/${GCC_TARGET}\"" >> $GITHUB_ENV - name: Install GCC Multilib if: (matrix.platform.os == 'ubuntu-latest') && contains(matrix.platform.target, 'i686') From b86fdb162b831c30b269b37bc0fd4d5760c7da46 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 10 May 2022 19:28:17 -0400 Subject: [PATCH 125/151] Fix CI --- .github/workflows/ci.yml | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 254629d832..e7a7714ad6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -62,6 +62,40 @@ jobs: with: rust-version: ${{ matrix.rust_version }}${{ matrix.platform.host }} targets: ${{ matrix.platform.target }} + - name: Setup cross linux toolchain + if: contains(matrix.target, '-linux-') && !startsWith(matrix.target, 'x86_64-') + run: | + case "${{ matrix.target }}" in + i686-*) SYSTEM_ARCH=i386 ;; + arm*) SYSTEM_ARCH=armhf ;; + aarch64*) SYSTEM_ARCH=arm64 ;; + esac + GCC_TARGET=$(printf "${{ matrix.target }}" | sed 's/-unknown-/-/' | sed 's/arm[^-]*/arm/g') + ENV_TARGET=$(printf "${{ matrix.target }}" | tr '-' '_') + ENV_TARGET_UC=$(printf "${ENV_TARGET}" | tr '[[:lower:]]' '[[:upper:]]') + sudo rm -f /etc/apt/sources.list.d/*.list + case "${{ matrix.target }}" in + arm* | aarch64*) + sudo tee /etc/apt/sources.list << EOF + deb [arch=i386,amd64] http://archive.ubuntu.com/ubuntu/ focal main universe + deb [arch=i386,amd64] http://archive.ubuntu.com/ubuntu/ focal-updates main universe + deb [arch=i386,amd64] http://security.ubuntu.com/ubuntu/ focal-security main universe + deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports/ focal main universe + deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports/ focal-updates main universe + deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports/ focal-security main universe + EOF + ;; + esac + sudo dpkg --add-architecture ${SYSTEM_ARCH} + dpkg --print-foreign-architectures + sudo apt-get update -qqy + sudo apt-get dist-upgrade -qqy --fix-broken + sudo apt-get install -qqy --fix-broken -o Debug::pkgProblemResolver=yes libinput-dev:${SYSTEM_ARCH} gcc-${GCC_TARGET} pkg-config-${GCC_TARGET} + echo "CARGO_TARGET_${ENV_TARGET_UC}_LINKER=${GCC_TARGET}-gcc" >> $GITHUB_ENV + echo "PKG_CONFIG_ALLOW_CROSS=1" >> $GITHUB_ENV + echo "PKG_CONFIG_${ENV_TARGET}=${GCC_TARGET}-pkg-config" >> $GITHUB_ENV + echo "PKG_CONFIG=${GCC_TARGET}-pkg-config" >> $GITHUB_ENV + echo "BINDGEN_EXTRA_CLANG_ARGS=\"-L/usr/lib/${GCC_TARGET} -L/lib/${GCC_TARGET}\"" >> $GITHUB_ENV - name: Install GCC Multilib if: (matrix.platform.os == 'ubuntu-latest') && contains(matrix.platform.target, 'i686') From 3db2879890bc76bbe1f9f1a5c9dbd3f4a9bce778 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 10 May 2022 19:42:46 -0400 Subject: [PATCH 126/151] Fix CI --- .github/workflows/ci.yml | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e7a7714ad6..c9ca30d955 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -62,8 +62,16 @@ jobs: with: rust-version: ${{ matrix.rust_version }}${{ matrix.platform.host }} targets: ${{ matrix.platform.target }} + - name: Install C Dependencies + if: (matrix.platform.os == 'ubuntu-latest') && contains(matrix.platform.target, 'x86_64') + run: | + TZ=Etc/UTC + ln -snf /usr/share/zoneinfo/${TZ} /etc/localtime + echo ${TZ} > /etc/timezone + sudo apt-get update -qqy + sudo apt-get install -qqy libudev-dev libinput-dev libxkbcommon-dev meson ninja-build - name: Setup cross linux toolchain - if: contains(matrix.target, '-linux-') && !startsWith(matrix.target, 'x86_64-') + if: (matrix.platform.os == 'ubuntu-latest') && contains(matrix.platform.target, 'i686') run: | case "${{ matrix.target }}" in i686-*) SYSTEM_ARCH=i386 ;; @@ -100,9 +108,6 @@ jobs: - name: Install GCC Multilib if: (matrix.platform.os == 'ubuntu-latest') && contains(matrix.platform.target, 'i686') run: sudo apt-get install -qqy gcc-multilib - - name: Install C Dependencies - if: (matrix.platform.os == 'ubuntu-latest') - run: sudo apt-get install -qqy libudev-dev libinput-dev libxkbcommon-dev meson ninja-build - name: Build libseat if: (matrix.platform.os == 'ubuntu-latest') run: | From 75d11a29e0ce0ecb8bcb9d9130c4b0eff868adb5 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 10 May 2022 19:46:47 -0400 Subject: [PATCH 127/151] Fix CI --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c9ca30d955..8ad5da74b5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -73,16 +73,16 @@ jobs: - name: Setup cross linux toolchain if: (matrix.platform.os == 'ubuntu-latest') && contains(matrix.platform.target, 'i686') run: | - case "${{ matrix.target }}" in + case "${{ matrix.platform.target }}" in i686-*) SYSTEM_ARCH=i386 ;; arm*) SYSTEM_ARCH=armhf ;; aarch64*) SYSTEM_ARCH=arm64 ;; esac - GCC_TARGET=$(printf "${{ matrix.target }}" | sed 's/-unknown-/-/' | sed 's/arm[^-]*/arm/g') - ENV_TARGET=$(printf "${{ matrix.target }}" | tr '-' '_') + GCC_TARGET=$(printf "${{ matrix.platform.target }}" | sed 's/-unknown-/-/' | sed 's/arm[^-]*/arm/g') + ENV_TARGET=$(printf "${{ matrix.platform.target }}" | tr '-' '_') ENV_TARGET_UC=$(printf "${ENV_TARGET}" | tr '[[:lower:]]' '[[:upper:]]') sudo rm -f /etc/apt/sources.list.d/*.list - case "${{ matrix.target }}" in + case "${{ matrix.platform.target }}" in arm* | aarch64*) sudo tee /etc/apt/sources.list << EOF deb [arch=i386,amd64] http://archive.ubuntu.com/ubuntu/ focal main universe From 03fe6144fef4ea007a2420d620ce6c4707f3f7db Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 10 May 2022 19:52:12 -0400 Subject: [PATCH 128/151] Fix CI --- .github/workflows/ci.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8ad5da74b5..20385af76f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -62,14 +62,16 @@ jobs: with: rust-version: ${{ matrix.rust_version }}${{ matrix.platform.host }} targets: ${{ matrix.platform.target }} - - name: Install C Dependencies - if: (matrix.platform.os == 'ubuntu-latest') && contains(matrix.platform.target, 'x86_64') + - name: Update TZ run: | TZ=Etc/UTC ln -snf /usr/share/zoneinfo/${TZ} /etc/localtime echo ${TZ} > /etc/timezone sudo apt-get update -qqy - sudo apt-get install -qqy libudev-dev libinput-dev libxkbcommon-dev meson ninja-build + sudo apt-get install -qqy curl gcc pkg-config libclang-dev dpkg-dev + - name: Update TZ + if: (matrix.platform.os == 'ubuntu-latest') && contains(matrix.platform.target, 'x86_64') + run: sudo apt-get install -qqy libudev-dev libinput-dev libxkbcommon-dev meson ninja-build - name: Setup cross linux toolchain if: (matrix.platform.os == 'ubuntu-latest') && contains(matrix.platform.target, 'i686') run: | From f1e966913f683c411fbbe503944a04675592b1c1 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 10 May 2022 19:54:53 -0400 Subject: [PATCH 129/151] Fix CI --- .github/workflows/ci.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 20385af76f..5497cd6fbe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -62,11 +62,8 @@ jobs: with: rust-version: ${{ matrix.rust_version }}${{ matrix.platform.host }} targets: ${{ matrix.platform.target }} - - name: Update TZ + - name: Install Build Deps run: | - TZ=Etc/UTC - ln -snf /usr/share/zoneinfo/${TZ} /etc/localtime - echo ${TZ} > /etc/timezone sudo apt-get update -qqy sudo apt-get install -qqy curl gcc pkg-config libclang-dev dpkg-dev - name: Update TZ From 11a48f410a5d187183cb1c3af3ade6ecc3703e26 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 10 May 2022 19:57:37 -0400 Subject: [PATCH 130/151] Fix CI --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5497cd6fbe..679e5008f5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -63,6 +63,7 @@ jobs: rust-version: ${{ matrix.rust_version }}${{ matrix.platform.host }} targets: ${{ matrix.platform.target }} - name: Install Build Deps + if: (matrix.platform.os == 'ubuntu-latest') run: | sudo apt-get update -qqy sudo apt-get install -qqy curl gcc pkg-config libclang-dev dpkg-dev From c1711c716b25654770c55ee02354b69b31e7a4a3 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 10 May 2022 20:00:54 -0400 Subject: [PATCH 131/151] Fix CI --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 679e5008f5..433c860c24 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -109,7 +109,7 @@ jobs: if: (matrix.platform.os == 'ubuntu-latest') && contains(matrix.platform.target, 'i686') run: sudo apt-get install -qqy gcc-multilib - name: Build libseat - if: (matrix.platform.os == 'ubuntu-latest') + if: (matrix.platform.os == 'ubuntu-latest') && !contains(matrix.platform.target, 'android') run: | wget https://git.sr.ht/~kennylevinsen/seatd/archive/0.5.0.tar.gz -O libseat-source.tar.gz tar xf libseat-source.tar.gz From a5c2f70ef529b02453d28c0ad9cad356eb38b617 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 10 May 2022 20:14:06 -0400 Subject: [PATCH 132/151] Fix CI --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 433c860c24..f00bf351bf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -98,7 +98,7 @@ jobs: dpkg --print-foreign-architectures sudo apt-get update -qqy sudo apt-get dist-upgrade -qqy --fix-broken - sudo apt-get install -qqy --fix-broken -o Debug::pkgProblemResolver=yes libinput-dev:${SYSTEM_ARCH} gcc-${GCC_TARGET} pkg-config-${GCC_TARGET} + sudo apt-get install -qqy --fix-broken -o Debug::pkgProblemResolver=yes libinput-dev gcc-${GCC_TARGET} pkg-config-${GCC_TARGET} echo "CARGO_TARGET_${ENV_TARGET_UC}_LINKER=${GCC_TARGET}-gcc" >> $GITHUB_ENV echo "PKG_CONFIG_ALLOW_CROSS=1" >> $GITHUB_ENV echo "PKG_CONFIG_${ENV_TARGET}=${GCC_TARGET}-pkg-config" >> $GITHUB_ENV From 690b0fb2d44d80472626c26fdcb6af1f7c9b4e7a Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 10 May 2022 20:18:39 -0400 Subject: [PATCH 133/151] Fix CI --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f00bf351bf..c0d9387897 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -111,6 +111,7 @@ jobs: - name: Build libseat if: (matrix.platform.os == 'ubuntu-latest') && !contains(matrix.platform.target, 'android') run: | + sudo apt-get install meson ninja-build wget https://git.sr.ht/~kennylevinsen/seatd/archive/0.5.0.tar.gz -O libseat-source.tar.gz tar xf libseat-source.tar.gz cd seatd-0.5.0 From dfac034e277626a5ee4e9857b851f692b7f245bf Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 10 May 2022 20:26:46 -0400 Subject: [PATCH 134/151] Fix CI --- .github/workflows/ci.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c0d9387897..64a98cda1c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -98,20 +98,16 @@ jobs: dpkg --print-foreign-architectures sudo apt-get update -qqy sudo apt-get dist-upgrade -qqy --fix-broken - sudo apt-get install -qqy --fix-broken -o Debug::pkgProblemResolver=yes libinput-dev gcc-${GCC_TARGET} pkg-config-${GCC_TARGET} + sudo apt-get install -qqy --fix-broken -o Debug::pkgProblemResolver=yes libinput-dev libudev-dev gcc-${GCC_TARGET} gcc-multilib libudev-dev libinput-dev libxkbcommon-dev meson ninja-build pkg-config-${GCC_TARGET} echo "CARGO_TARGET_${ENV_TARGET_UC}_LINKER=${GCC_TARGET}-gcc" >> $GITHUB_ENV echo "PKG_CONFIG_ALLOW_CROSS=1" >> $GITHUB_ENV echo "PKG_CONFIG_${ENV_TARGET}=${GCC_TARGET}-pkg-config" >> $GITHUB_ENV echo "PKG_CONFIG=${GCC_TARGET}-pkg-config" >> $GITHUB_ENV echo "BINDGEN_EXTRA_CLANG_ARGS=\"-L/usr/lib/${GCC_TARGET} -L/lib/${GCC_TARGET}\"" >> $GITHUB_ENV - - name: Install GCC Multilib - if: (matrix.platform.os == 'ubuntu-latest') && contains(matrix.platform.target, 'i686') - run: sudo apt-get install -qqy gcc-multilib - name: Build libseat if: (matrix.platform.os == 'ubuntu-latest') && !contains(matrix.platform.target, 'android') run: | - sudo apt-get install meson ninja-build wget https://git.sr.ht/~kennylevinsen/seatd/archive/0.5.0.tar.gz -O libseat-source.tar.gz tar xf libseat-source.tar.gz cd seatd-0.5.0 From af6a6ba34cd9743298f855a96f06de33905a48b5 Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 10 May 2022 20:34:09 -0400 Subject: [PATCH 135/151] Fix CI --- .github/workflows/ci.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 64a98cda1c..4f44460dc6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -62,11 +62,6 @@ jobs: with: rust-version: ${{ matrix.rust_version }}${{ matrix.platform.host }} targets: ${{ matrix.platform.target }} - - name: Install Build Deps - if: (matrix.platform.os == 'ubuntu-latest') - run: | - sudo apt-get update -qqy - sudo apt-get install -qqy curl gcc pkg-config libclang-dev dpkg-dev - name: Update TZ if: (matrix.platform.os == 'ubuntu-latest') && contains(matrix.platform.target, 'x86_64') run: sudo apt-get install -qqy libudev-dev libinput-dev libxkbcommon-dev meson ninja-build @@ -98,13 +93,18 @@ jobs: dpkg --print-foreign-architectures sudo apt-get update -qqy sudo apt-get dist-upgrade -qqy --fix-broken - sudo apt-get install -qqy --fix-broken -o Debug::pkgProblemResolver=yes libinput-dev libudev-dev gcc-${GCC_TARGET} gcc-multilib libudev-dev libinput-dev libxkbcommon-dev meson ninja-build pkg-config-${GCC_TARGET} + sudo apt-get install -qqy --fix-broken -o Debug::pkgProblemResolver=yes gcc-${GCC_TARGET} pkg-config-${GCC_TARGET} echo "CARGO_TARGET_${ENV_TARGET_UC}_LINKER=${GCC_TARGET}-gcc" >> $GITHUB_ENV echo "PKG_CONFIG_ALLOW_CROSS=1" >> $GITHUB_ENV echo "PKG_CONFIG_${ENV_TARGET}=${GCC_TARGET}-pkg-config" >> $GITHUB_ENV echo "PKG_CONFIG=${GCC_TARGET}-pkg-config" >> $GITHUB_ENV echo "BINDGEN_EXTRA_CLANG_ARGS=\"-L/usr/lib/${GCC_TARGET} -L/lib/${GCC_TARGET}\"" >> $GITHUB_ENV + - name: Install Build Deps + if: (matrix.platform.os == 'ubuntu-latest') + run: | + sudo apt-get update -qqy + sudo apt-get install -qqy --fix-broken -o Debug::pkgProblemResolver=yes curl gcc pkg-config libclang-dev dpkg-dev libinput-dev libudev-dev libxkbcommon-dev gcc-multilib meson ninja-build - name: Build libseat if: (matrix.platform.os == 'ubuntu-latest') && !contains(matrix.platform.target, 'android') run: | From 161c8c9c5060f3915d0f72fca5d46e939e6cec8d Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 10 May 2022 20:41:36 -0400 Subject: [PATCH 136/151] Fix CI --- .github/workflows/ci.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4f44460dc6..d6a58d412e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -93,7 +93,8 @@ jobs: dpkg --print-foreign-architectures sudo apt-get update -qqy sudo apt-get dist-upgrade -qqy --fix-broken - sudo apt-get install -qqy --fix-broken -o Debug::pkgProblemResolver=yes gcc-${GCC_TARGET} pkg-config-${GCC_TARGET} + sudo apt-get install -qqy --fix-broken -o Debug::pkgProblemResolver=yes gcc-${GCC_TARGET} pkg-config-${GCC_TARGET} meson ninja-build + sudo apt-get install -qqy --fix-broken -o Debug::pkgProblemResolver=yes libinput-dev:${SYSTEM_ARCH} libudev-dev:${SYSTEM_ARCH} libxkbcommon-dev:${SYSTEM_ARCH} gcc-multilib echo "CARGO_TARGET_${ENV_TARGET_UC}_LINKER=${GCC_TARGET}-gcc" >> $GITHUB_ENV echo "PKG_CONFIG_ALLOW_CROSS=1" >> $GITHUB_ENV echo "PKG_CONFIG_${ENV_TARGET}=${GCC_TARGET}-pkg-config" >> $GITHUB_ENV @@ -104,7 +105,7 @@ jobs: if: (matrix.platform.os == 'ubuntu-latest') run: | sudo apt-get update -qqy - sudo apt-get install -qqy --fix-broken -o Debug::pkgProblemResolver=yes curl gcc pkg-config libclang-dev dpkg-dev libinput-dev libudev-dev libxkbcommon-dev gcc-multilib meson ninja-build + sudo apt-get install -qqy --fix-broken -o Debug::pkgProblemResolver=yes curl gcc pkg-config libclang-dev dpkg-dev - name: Build libseat if: (matrix.platform.os == 'ubuntu-latest') && !contains(matrix.platform.target, 'android') run: | From 12d005809e7cdf1c44674038e24a0b3adc60a25b Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 10 May 2022 20:46:58 -0400 Subject: [PATCH 137/151] Fix CI --- src/platform/unix.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/platform/unix.rs b/src/platform/unix.rs index a9f6217a1e..14cc97eb66 100644 --- a/src/platform/unix.rs +++ b/src/platform/unix.rs @@ -106,9 +106,9 @@ impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { } } + #[cfg(feature = "x11")] #[inline] #[doc(hidden)] - #[cfg(feature = "x11")] fn xlib_xconnection(&self) -> Option> { match self.p { LinuxEventLoopWindowTarget::X(ref e) => Some(e.x_connection().clone()), @@ -318,9 +318,9 @@ impl WindowExtUnix for Window { } } + #[cfg(feature = "x11")] #[inline] #[doc(hidden)] - #[cfg(feature = "x11")] fn xlib_xconnection(&self) -> Option> { match self.window { LinuxWindow::X(ref w) => Some(w.xlib_xconnection()), From aa5041ed96f1054f398317ffab3ebe4765bea22d Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 10 May 2022 20:53:06 -0400 Subject: [PATCH 138/151] Fix CI --- src/platform/unix.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/platform/unix.rs b/src/platform/unix.rs index 14cc97eb66..5adbca61d3 100644 --- a/src/platform/unix.rs +++ b/src/platform/unix.rs @@ -108,7 +108,6 @@ impl EventLoopWindowTargetExtUnix for EventLoopWindowTarget { #[cfg(feature = "x11")] #[inline] - #[doc(hidden)] fn xlib_xconnection(&self) -> Option> { match self.p { LinuxEventLoopWindowTarget::X(ref e) => Some(e.x_connection().clone()), @@ -320,7 +319,6 @@ impl WindowExtUnix for Window { #[cfg(feature = "x11")] #[inline] - #[doc(hidden)] fn xlib_xconnection(&self) -> Option> { match self.window { LinuxWindow::X(ref w) => Some(w.xlib_xconnection()), From 9ee4d9556c493b63520e6fb92c4570e90223fc1f Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 10 May 2022 22:05:25 -0400 Subject: [PATCH 139/151] Fix code duplication --- src/platform_impl/linux/kms/input.rs | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/src/platform_impl/linux/kms/input.rs b/src/platform_impl/linux/kms/input.rs index 4997110667..9e03a488b8 100644 --- a/src/platform_impl/linux/kms/input.rs +++ b/src/platform_impl/linux/kms/input.rs @@ -531,8 +531,9 @@ macro_rules! handle_keyboard_event { &mut (), ); } + $self.xkb_compose.reset(); } - xkb::compose::Status::Cancelled => { + xkb::compose::Status::Cancelled | xkb::compose::Status::Nothing => { let should_repeat = $self.xkb_keymap.key_repeats(key_offset); let ch = $self.xkb_ctx.key_get_utf8(key_offset).chars().next(); @@ -552,26 +553,6 @@ macro_rules! handle_keyboard_event { ); } } - xkb::compose::Status::Nothing => { - let should_repeat = $self.xkb_keymap.key_repeats(key_offset); - let ch = $self.xkb_ctx.key_get_utf8(key_offset).chars().next(); - - if should_repeat { - $self - .timer_handle - .add_timeout(Duration::from_millis(600), (input, ch)); - } - - if let Some(c) = ch { - $callback( - Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::ReceivedCharacter(c), - }, - &mut (), - ); - } - } _ => {} } } From 4a7b46e92516be37d79160864505cb9f2fb6eff9 Mon Sep 17 00:00:00 2001 From: mraerino Date: Sun, 7 May 2023 17:03:54 +0000 Subject: [PATCH 140/151] Fixup feature attributes to use the alias --- src/platform_impl/linux/kms/event_loop.rs | 4 +- src/platform_impl/linux/mod.rs | 52 +++++++++++------------ 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/platform_impl/linux/kms/event_loop.rs b/src/platform_impl/linux/kms/event_loop.rs index a7b68f70bf..4b6c978477 100644 --- a/src/platform_impl/linux/kms/event_loop.rs +++ b/src/platform_impl/linux/kms/event_loop.rs @@ -684,7 +684,7 @@ impl EventLoop { fn with_window_target) -> U>(&mut self, f: F) -> U { let state = match &mut self.window_target.p { platform_impl::EventLoopWindowTarget::Kms(window_target) => window_target, - #[cfg(any(feature = "x11", feature = "wayland"))] + #[cfg(any(x11_platform, wayland_platform))] _ => unreachable!(), }; @@ -699,7 +699,7 @@ impl EventLoop { platform_impl::EventLoopWindowTarget::Kms(window_target) => { &mut window_target.event_sink } - #[cfg(any(feature = "x11", feature = "wayland"))] + #[cfg(any(x11_platform, wayland_platform))] _ => unreachable!(), }; diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index 4faad6e5d4..d3638f5a55 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -133,9 +133,9 @@ pub enum OsError { XMisc(&'static str), #[cfg(wayland_platform)] WaylandMisc(&'static str), - #[cfg(feature = "kms")] + #[cfg(drm_platform)] KmsError(String), - #[cfg(feature = "kms")] + #[cfg(drm_platform)] KmsMisc(&'static str), } @@ -148,9 +148,9 @@ impl fmt::Display for OsError { OsError::XMisc(e) => _f.pad(e), #[cfg(wayland_platform)] OsError::WaylandMisc(e) => _f.pad(e), - #[cfg(feature = "kms")] + #[cfg(drm_platform)] OsError::KmsError(ref e) => _f.pad(e), - #[cfg(feature = "kms")] + #[cfg(drm_platform)] OsError::KmsMisc(e) => _f.pad(e), } } @@ -161,7 +161,7 @@ pub(crate) enum Window { X(x11::Window), #[cfg(wayland_platform)] Wayland(wayland::Window), - #[cfg(feature = "kms")] + #[cfg(drm_platform)] Kms(kms::Window), } @@ -192,7 +192,7 @@ pub enum DeviceId { X(x11::DeviceId), #[cfg(wayland_platform)] Wayland(wayland::DeviceId), - #[cfg(feature = "kms")] + #[cfg(drm_platform)] Kms(kms::DeviceId), } @@ -202,7 +202,7 @@ impl DeviceId { return DeviceId::Wayland(wayland::DeviceId::dummy()); #[cfg(all(not(wayland_platform), x11_platform))] return DeviceId::X(x11::DeviceId::dummy()); - #[cfg(all(not(all(feature = "wayland", feature = "x11")), feature = "kms"))] + #[cfg(all(not(all(wayland_platform, x11_platform)), drm_platform))] return DeviceId::Kms(kms::DeviceId::dummy()); } } @@ -213,7 +213,7 @@ pub enum MonitorHandle { X(x11::MonitorHandle), #[cfg(wayland_platform)] Wayland(wayland::MonitorHandle), - #[cfg(feature = "kms")] + #[cfg(drm_platform)] Kms(kms::MonitorHandle), } @@ -233,7 +233,7 @@ macro_rules! x11_or_wayland_or_drm { $enum::X($($c1)*) => $enum2::X($x), #[cfg(wayland_platform)] $enum::Wayland($($c1)*) => $enum2::Wayland($x), - #[cfg(feature = "kms")] + #[cfg(drm_platform)] $enum::Kms($($c1)*) => $enum2::Kms($x) } }; @@ -292,7 +292,7 @@ pub enum VideoMode { X(x11::VideoMode), #[cfg(wayland_platform)] Wayland(wayland::VideoMode), - #[cfg(feature = "kms")] + #[cfg(drm_platform)] Kms(kms::VideoMode), } @@ -334,7 +334,7 @@ impl Window { EventLoopWindowTarget::X(ref window_target) => { x11::Window::new(window_target, attribs, pl_attribs).map(Window::X) } - #[cfg(feature = "kms")] + #[cfg(drm_platform)] EventLoopWindowTarget::Kms(ref window_target) => { kms::Window::new(window_target, attribs, pl_attribs).map(Window::Kms) } @@ -530,7 +530,7 @@ impl Window { Window::X(ref w) => w.set_window_level(_level), #[cfg(wayland_platform)] Window::Wayland(_) => (), - #[cfg(feature = "kms")] + #[cfg(drm_platform)] Window::Kms(_) => (), } } @@ -542,7 +542,7 @@ impl Window { Window::X(ref w) => w.set_window_icon(_window_icon), #[cfg(wayland_platform)] Window::Wayland(_) => (), - #[cfg(feature = "kms")] + #[cfg(drm_platform)] Window::Kms(_) => (), } } @@ -569,7 +569,7 @@ impl Window { Window::X(ref w) => w.focus_window(), #[cfg(wayland_platform)] Window::Wayland(_) => (), - #[cfg(feature = "kms")] + #[cfg(drm_platform)] Window::Kms(_) => (), } } @@ -602,7 +602,7 @@ impl Window { let current_monitor = MonitorHandle::Wayland(window.current_monitor()?); Some(current_monitor) } - #[cfg(feature = "kms")] + #[cfg(drm_platform)] Window::Kms(ref window) => { let current_monitor = MonitorHandle::Kms(window.current_monitor()?); Some(RootMonitorHandle { @@ -627,7 +627,7 @@ impl Window { .into_iter() .map(MonitorHandle::Wayland) .collect(), - #[cfg(feature = "kms")] + #[cfg(drm_platform)] Window::Kms(ref window) => window .available_monitors() .into_iter() @@ -646,7 +646,7 @@ impl Window { } #[cfg(wayland_platform)] Window::Wayland(ref window) => window.primary_monitor(), - #[cfg(feature = "kms")] + #[cfg(drm_platform)] Window::Kms(ref window) => window.primary_monitor(), } } @@ -733,7 +733,7 @@ pub enum EventLoop { Wayland(Box>), #[cfg(x11_platform)] X(x11::EventLoop), - #[cfg(feature = "kms")] + #[cfg(drm_platform)] Kms(kms::EventLoop), } @@ -742,7 +742,7 @@ pub enum EventLoopProxy { X(x11::EventLoopProxy), #[cfg(wayland_platform)] Wayland(wayland::EventLoopProxy), - #[cfg(feature = "kms")] + #[cfg(drm_platform)] Kms(kms::EventLoopProxy), } @@ -775,7 +775,7 @@ impl EventLoop { return EventLoop::new_wayland_any_thread().expect("failed to open Wayland connection"); } - #[cfg(feature = "kms")] + #[cfg(drm_platform)] if attributes.forced_backend == Some(Backend::Kms) { // TODO: Propagate return EventLoop::new_drm_any_thread().expect("failed to open drm connection"); @@ -799,10 +799,10 @@ impl EventLoop { panic!("wayland feature is not enabled"); } "drm" | "kms" | "gbm" | "tty" => { - #[cfg(feature = "kms")] + #[cfg(drm_platform)] return EventLoop::new_drm_any_thread() .expect("Failed to initialize drm backend"); - #[cfg(not(feature = "kms"))] + #[cfg(not(drm_platform))] panic!("kms feature is not enabled"); } _ => panic!( @@ -856,7 +856,7 @@ impl EventLoop { Ok(EventLoop::X(x11::EventLoop::new(xconn))) } - #[cfg(feature = "kms")] + #[cfg(drm_platform)] fn new_drm_any_thread() -> Result, RootOsError> { kms::EventLoop::new().map(EventLoop::Kms) } @@ -895,7 +895,7 @@ pub enum EventLoopWindowTarget { Wayland(wayland::EventLoopWindowTarget), #[cfg(x11_platform)] X(x11::EventLoopWindowTarget), - #[cfg(feature = "kms")] + #[cfg(drm_platform)] Kms(kms::EventLoopWindowTarget), } @@ -926,7 +926,7 @@ impl EventLoopWindowTarget { .into_iter() .map(MonitorHandle::X) .collect(), - #[cfg(feature = "kms")] + #[cfg(drm_platform)] EventLoopWindowTarget::Kms(ref evlp) => evlp .available_monitors() .into_iter() @@ -945,7 +945,7 @@ impl EventLoopWindowTarget { let primary_monitor = MonitorHandle::X(evlp.x_connection().primary_monitor()); Some(primary_monitor) } - #[cfg(feature = "kms")] + #[cfg(drm_platform)] EventLoopWindowTarget::Kms(ref evlp) => evlp.primary_monitor(), } } From 0c2223a3c5b084a183980d59a24ac810b0b93ec9 Mon Sep 17 00:00:00 2001 From: mraerino Date: Sun, 7 May 2023 17:20:10 +0000 Subject: [PATCH 141/151] Fixup input handling --- src/platform_impl/linux/kms/event_loop.rs | 46 ++----------------- src/platform_impl/linux/kms/input.rs | 55 +++++++++++++++++++---- 2 files changed, 51 insertions(+), 50 deletions(-) diff --git a/src/platform_impl/linux/kms/event_loop.rs b/src/platform_impl/linux/kms/event_loop.rs index 4b6c978477..9bd08774fe 100644 --- a/src/platform_impl/linux/kms/event_loop.rs +++ b/src/platform_impl/linux/kms/event_loop.rs @@ -15,14 +15,11 @@ use xkbcommon::xkb; use drm::control::*; -#[cfg(feature = "wayland")] -use sctk::reexports::calloop; - use crate::error; use crate::{ dpi::PhysicalPosition, - event::{DeviceId, Event, KeyboardInput, StartCause, WindowEvent}, + event::{Event, StartCause}, event_loop::{self, ControlFlow, EventLoopClosed}, monitor::MonitorHandle, platform::unix::Card, @@ -31,7 +28,7 @@ use crate::{ }; use super::{ - input::{Interface, LibinputInputBackend, REPEAT_RATE}, + input::{Interface, LibinputInputBackend}, MODE, }; @@ -49,7 +46,7 @@ macro_rules! window_id { /// An event loop's sink to deliver events from the Wayland event callbacks /// to the winit's user. -type EventSink = Vec>; +pub type EventSink = Vec>; pub struct EventLoopWindowTarget { /// Drm Connector @@ -446,40 +443,6 @@ impl EventLoop { ) .unwrap(); - // This is used so that when you hold down a key, the same `KeyboardInput` event will be - // repeated until the key is released or another key is pressed down - let repeat_handler = calloop::timer::Timer::new().unwrap(); - - let repeat_handle = repeat_handler.handle(); - - let repeat_loop: calloop::Dispatcher< - 'static, - calloop::timer::Timer<(KeyboardInput, Option)>, - EventSink, - > = calloop::Dispatcher::new( - repeat_handler, - move |event, metadata, data: &mut EventSink| { - data.push(Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::KeyboardInput { - device_id: DeviceId(platform_impl::DeviceId::Kms(super::DeviceId)), - input: event.0, - is_synthetic: false, - }, - }); - - if let Some(c) = event.1 { - data.push(Event::WindowEvent { - window_id: window_id!(), - event: WindowEvent::ReceivedCharacter(c), - }); - } - - // Repeat the key with the same key event as was input from the LibinputInterface - metadata.add_timeout(Duration::from_millis(REPEAT_RATE), event); - }, - ); - // It is an Arc> so that windows can change the cursor position let cursor_arc = Arc::new(Mutex::new(PhysicalPosition::new(0.0, 0.0))); @@ -487,7 +450,7 @@ impl EventLoop { let input_backend: LibinputInputBackend = LibinputInputBackend::new( input, (disp_width.into(), disp_height.into()), // plane, fb - repeat_handle, + event_loop.handle(), state, keymap, xkb_compose, @@ -504,7 +467,6 @@ impl EventLoop { ); handle.register_dispatcher(input_loop).unwrap(); - handle.register_dispatcher(repeat_loop).unwrap(); let window_target = event_loop::EventLoopWindowTarget { p: platform_impl::EventLoopWindowTarget::Kms(EventLoopWindowTarget { diff --git a/src/platform_impl/linux/kms/input.rs b/src/platform_impl/linux/kms/input.rs index 9e03a488b8..928f6279af 100644 --- a/src/platform_impl/linux/kms/input.rs +++ b/src/platform_impl/linux/kms/input.rs @@ -28,9 +28,14 @@ use std::{ time::Duration, }; -use calloop::{EventSource, Interest, Mode, Poll, PostAction, Readiness, Token, TokenFactory}; +use calloop::{ + timer::TimeoutAction, EventSource, Interest, LoopHandle, Mode, Poll, PostAction, Readiness, + RegistrationToken, Token, TokenFactory, +}; use xkbcommon::xkb; +use super::event_loop::EventSink; + pub const REPEAT_RATE: u64 = 25; pub const REPEAT_DELAY: u64 = 600; @@ -108,7 +113,8 @@ pub struct LibinputInputBackend { screen_size: (u32, u32), modifiers: ModifiersState, cursor_positon: Arc>>, - timer_handle: calloop::timer::TimerHandle<(KeyboardInput, Option)>, + ev_handle: calloop::LoopHandle<'static, EventSink>, + current_repeat: Option, } impl LibinputInputBackend { @@ -117,7 +123,7 @@ impl LibinputInputBackend { pub fn new( context: input::Libinput, screen_size: (u32, u32), - timer_handle: calloop::timer::TimerHandle<(KeyboardInput, Option)>, + ev_handle: calloop::LoopHandle<'static, EventSink>, xkb_ctx: xkb::State, xkb_keymap: xkb::Keymap, xkb_compose: xkb::compose::State, @@ -130,7 +136,8 @@ impl LibinputInputBackend { modifiers: ModifiersState::empty(), cursor_positon, screen_size, - timer_handle, + ev_handle, + current_repeat: None, xkb_ctx, xkb_keymap, xkb_compose, @@ -470,6 +477,37 @@ macro_rules! handle_pointer_event { }; } +// This is used so that when you hold down a key, the same `KeyboardInput` event will be +// repeated until the key is released or another key is pressed down +fn repeat_keyboard_event( + event: (KeyboardInput, Option), + loop_handle: &LoopHandle<'static, EventSink>, +) -> calloop::Result { + let timer = calloop::timer::Timer::immediate(); + let window_id = winid(); + loop_handle + .insert_source(timer, move |_, _, data| { + data.push(Event::WindowEvent { + window_id, + event: WindowEvent::KeyboardInput { + device_id: DeviceId(platform_impl::DeviceId::Kms(super::DeviceId)), + input: event.0, + is_synthetic: false, + }, + }); + + if let Some(c) = event.1 { + data.push(Event::WindowEvent { + window_id, + event: WindowEvent::ReceivedCharacter(c), + }); + } + + TimeoutAction::ToDuration(Duration::from_millis(REPEAT_RATE)) + }) + .map_err(Into::into) +} + macro_rules! handle_keyboard_event { ($self:expr,$ev:expr,$callback:expr) => {{ let state = match $ev.key_state() { @@ -503,7 +541,9 @@ macro_rules! handle_keyboard_event { modifiers: $self.modifiers, }; - $self.timer_handle.cancel_all_timeouts(); + if let Some(repeat) = $self.current_repeat.take() { + $self.ev_handle.remove(repeat); + } $callback( Event::WindowEvent { @@ -538,9 +578,8 @@ macro_rules! handle_keyboard_event { let ch = $self.xkb_ctx.key_get_utf8(key_offset).chars().next(); if should_repeat { - $self - .timer_handle - .add_timeout(Duration::from_millis(REPEAT_DELAY), (input, ch)); + $self.current_repeat = + Some(repeat_keyboard_event((input, ch), &$self.ev_handle)?); } if let Some(c) = ch { From 3de800ef9753420200e104a5dd9d3e57d4eb0067 Mon Sep 17 00:00:00 2001 From: mraerino Date: Sun, 7 May 2023 17:25:23 +0000 Subject: [PATCH 142/151] Fix event source to adhere to event loop library --- src/platform_impl/linux/kms/event_loop.rs | 17 ++++++++++---- src/platform_impl/linux/kms/input.rs | 27 +++++++++++++---------- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/src/platform_impl/linux/kms/event_loop.rs b/src/platform_impl/linux/kms/event_loop.rs index 9bd08774fe..92970a2617 100644 --- a/src/platform_impl/linux/kms/event_loop.rs +++ b/src/platform_impl/linux/kms/event_loop.rs @@ -526,7 +526,7 @@ impl EventLoop { // Non-blocking dispatch. let timeout = Duration::from_millis(0); if let Err(error) = self.loop_dispatch(Some(timeout)) { - break error.raw_os_error().unwrap_or(1); + break exit_code(error); } callback( @@ -537,7 +537,7 @@ impl EventLoop { } ControlFlow::Wait => { if let Err(error) = self.loop_dispatch(None) { - break error.raw_os_error().unwrap_or(1); + break exit_code(error); } callback( @@ -560,7 +560,7 @@ impl EventLoop { }; if let Err(error) = self.loop_dispatch(Some(duration)) { - break error.raw_os_error().unwrap_or(1); + break exit_code(error); } let now = Instant::now(); @@ -656,7 +656,7 @@ impl EventLoop { fn loop_dispatch>>( &mut self, timeout: D, - ) -> std::io::Result<()> { + ) -> calloop::Result<()> { let state = match &mut self.window_target.p { platform_impl::EventLoopWindowTarget::Kms(window_target) => { &mut window_target.event_sink @@ -669,6 +669,15 @@ impl EventLoop { } } +fn exit_code(err: calloop::Error) -> i32 { + if let calloop::Error::IoError(io_err) = err { + if let Some(raw_os) = io_err.raw_os_error() { + return raw_os; + } + } + 1 +} + /// A handle that can be sent across the threads and used to wake up the `EventLoop`. pub struct EventLoopProxy { user_events_sender: calloop::channel::Sender, diff --git a/src/platform_impl/linux/kms/input.rs b/src/platform_impl/linux/kms/input.rs index 928f6279af..b9b5027e26 100644 --- a/src/platform_impl/linux/kms/input.rs +++ b/src/platform_impl/linux/kms/input.rs @@ -108,7 +108,7 @@ pub struct LibinputInputBackend { xkb_ctx: xkb::State, xkb_keymap: xkb::Keymap, xkb_compose: xkb::compose::State, - token: Token, + token: Option, touch_location: PhysicalPosition, screen_size: (u32, u32), modifiers: ModifiersState, @@ -131,7 +131,7 @@ impl LibinputInputBackend { ) -> Self { LibinputInputBackend { context, - token: Token::invalid(), + token: None, touch_location: PhysicalPosition::new(0.0, 0.0), modifiers: ModifiersState::empty(), cursor_positon, @@ -676,17 +676,18 @@ impl EventSource for LibinputInputBackend { type Event = Event<'static, ()>; type Metadata = (); type Ret = (); + type Error = calloop::Error; fn process_events( &mut self, _: Readiness, token: Token, mut callback: F, - ) -> std::io::Result + ) -> calloop::Result where F: FnMut(Self::Event, &mut ()) -> Self::Ret, { - if token == self.token { + if self.token.filter(|t| *t == token).is_some() { self.context.dispatch()?; for event in &mut self.context { @@ -703,18 +704,20 @@ impl EventSource for LibinputInputBackend { Ok(PostAction::Continue) } - fn register(&mut self, poll: &mut Poll, factory: &mut TokenFactory) -> std::io::Result<()> { - self.token = factory.token(); - poll.register(self.as_raw_fd(), Interest::READ, Mode::Level, self.token) + fn register(&mut self, poll: &mut Poll, factory: &mut TokenFactory) -> calloop::Result<()> { + let token = factory.token(); + self.token = Some(token); + poll.register(self.as_raw_fd(), Interest::READ, Mode::Level, token) } - fn reregister(&mut self, poll: &mut Poll, factory: &mut TokenFactory) -> std::io::Result<()> { - self.token = factory.token(); - poll.reregister(self.as_raw_fd(), Interest::READ, Mode::Level, self.token) + fn reregister(&mut self, poll: &mut Poll, factory: &mut TokenFactory) -> calloop::Result<()> { + let token = factory.token(); + self.token = Some(token); + poll.reregister(self.as_raw_fd(), Interest::READ, Mode::Level, token) } - fn unregister(&mut self, poll: &mut Poll) -> std::io::Result<()> { - self.token = Token::invalid(); + fn unregister(&mut self, poll: &mut Poll) -> calloop::Result<()> { + self.token = None; poll.unregister(self.as_raw_fd()) } } From 46d511dd4c0ef82ddc5c8fe8afc4ba1c2adccf17 Mon Sep 17 00:00:00 2001 From: mraerino Date: Sun, 7 May 2023 17:28:55 +0000 Subject: [PATCH 143/151] Fix generation of window id --- src/platform_impl/linux/kms/event_loop.rs | 19 ++------- src/platform_impl/linux/kms/input.rs | 49 ++++++++++------------- src/platform_impl/linux/kms/window.rs | 12 ++++-- 3 files changed, 34 insertions(+), 46 deletions(-) diff --git a/src/platform_impl/linux/kms/event_loop.rs b/src/platform_impl/linux/kms/event_loop.rs index 92970a2617..f671ae8e84 100644 --- a/src/platform_impl/linux/kms/event_loop.rs +++ b/src/platform_impl/linux/kms/event_loop.rs @@ -24,26 +24,14 @@ use crate::{ monitor::MonitorHandle, platform::unix::Card, platform_impl::{self, platform::sticky_exit_callback, OsError}, - window::WindowId, }; use super::{ input::{Interface, LibinputInputBackend}, + window::winid, MODE, }; -macro_rules! to_platform_impl { - ($p:ident, $params:expr) => { - $p(platform_impl::$p::Kms($params)) - }; -} - -macro_rules! window_id { - () => { - to_platform_impl!(WindowId, super::WindowId) - }; -} - /// An event loop's sink to deliver events from the Wayland event callbacks /// to the winit's user. pub type EventSink = Vec>; @@ -406,6 +394,7 @@ impl EventLoop { .map_err(|e| os_error!(OsError::KmsError(format!("could not list planes: {}", e))))?; let p_plane = find_plane(planes, res, crtc, &drm); + let window_id = winid(); let (disp_width, disp_height) = mode.size(); @@ -438,7 +427,7 @@ impl EventLoop { .insert_source( event_loop_awakener_source, move |_event, _metadata, data| { - data.push(Event::RedrawRequested(window_id!())); + data.push(Event::RedrawRequested(window_id)); }, ) .unwrap(); @@ -514,7 +503,7 @@ impl EventLoop { ); callback( - Event::RedrawRequested(window_id!()), + Event::RedrawRequested(winid()), &self.window_target, &mut control_flow, ); diff --git a/src/platform_impl/linux/kms/input.rs b/src/platform_impl/linux/kms/input.rs index b9b5027e26..f494d88c9d 100644 --- a/src/platform_impl/linux/kms/input.rs +++ b/src/platform_impl/linux/kms/input.rs @@ -6,7 +6,6 @@ use crate::{ MouseScrollDelta, Touch, TouchPhase, WindowEvent, }, platform_impl::{self, xkb_keymap}, - window::WindowId, }; use input::{ event::{ @@ -34,7 +33,7 @@ use calloop::{ }; use xkbcommon::xkb; -use super::event_loop::EventSink; +use super::{event_loop::EventSink, window::winid}; pub const REPEAT_RATE: u64 = 25; pub const REPEAT_DELAY: u64 = 600; @@ -45,12 +44,6 @@ macro_rules! to_platform_impl { }; } -macro_rules! window_id { - () => { - to_platform_impl!(WindowId, super::WindowId) - }; -} - macro_rules! device_id { () => { to_platform_impl!(DeviceId, super::DeviceId) @@ -182,7 +175,7 @@ macro_rules! handle_touch_event { match $ev { input::event::TouchEvent::Up(e) => $callback( Event::WindowEvent { - window_id: window_id!(), + window_id: winid(), event: WindowEvent::Touch(Touch { device_id: device_id!(), phase: TouchPhase::Ended, @@ -199,7 +192,7 @@ macro_rules! handle_touch_event { $callback( Event::WindowEvent { - window_id: window_id!(), + window_id: winid(), event: WindowEvent::Touch(Touch { device_id: device_id!(), phase: TouchPhase::Started, @@ -217,7 +210,7 @@ macro_rules! handle_touch_event { $callback( Event::WindowEvent { - window_id: window_id!(), + window_id: winid(), event: WindowEvent::Touch(Touch { device_id: device_id!(), phase: TouchPhase::Moved, @@ -231,7 +224,7 @@ macro_rules! handle_touch_event { } input::event::TouchEvent::Cancel(e) => $callback( Event::WindowEvent { - window_id: window_id!(), + window_id: winid(), event: WindowEvent::Touch(Touch { device_id: device_id!(), phase: TouchPhase::Cancelled, @@ -244,7 +237,7 @@ macro_rules! handle_touch_event { ), input::event::TouchEvent::Frame(_) => $callback( Event::WindowEvent { - window_id: window_id!(), + window_id: winid(), event: WindowEvent::Touch(Touch { device_id: device_id!(), phase: TouchPhase::Ended, @@ -265,7 +258,7 @@ macro_rules! handle_tablet_tool_event { match $ev { input::event::TabletToolEvent::Tip(e) => $callback( Event::WindowEvent { - window_id: window_id!(), + window_id: winid(), event: WindowEvent::Touch(Touch { device_id: device_id!(), phase: match e.tip_state() { @@ -289,7 +282,7 @@ macro_rules! handle_tablet_tool_event { input::event::TabletToolEvent::Button(e) => { $callback( Event::WindowEvent { - window_id: window_id!(), + window_id: winid(), event: WindowEvent::MouseInput { device_id: device_id!(), state: match e.button_state() { @@ -340,7 +333,7 @@ macro_rules! handle_pointer_event { $callback( Event::WindowEvent { - window_id: window_id!(), + window_id: winid(), event: WindowEvent::CursorMoved { device_id: device_id!(), position: *lock, @@ -364,7 +357,7 @@ macro_rules! handle_pointer_event { input::event::PointerEvent::Button(e) => { $callback( Event::WindowEvent { - window_id: window_id!(), + window_id: winid(), event: WindowEvent::MouseInput { device_id: device_id!(), state: match e.button_state() { @@ -402,7 +395,7 @@ macro_rules! handle_pointer_event { $callback( Event::WindowEvent { - window_id: window_id!(), + window_id: winid(), event: WindowEvent::MouseWheel { device_id: device_id!(), delta: MouseScrollDelta::LineDelta( @@ -430,7 +423,7 @@ macro_rules! handle_pointer_event { $callback( Event::WindowEvent { - window_id: window_id!(), + window_id: winid(), event: WindowEvent::MouseWheel { device_id: device_id!(), delta: MouseScrollDelta::PixelDelta(PhysicalPosition::new( @@ -462,7 +455,7 @@ macro_rules! handle_pointer_event { $callback( Event::WindowEvent { - window_id: window_id!(), + window_id: winid(), event: WindowEvent::CursorMoved { device_id: device_id!(), position: *lock, @@ -547,7 +540,7 @@ macro_rules! handle_keyboard_event { $callback( Event::WindowEvent { - window_id: window_id!(), + window_id: winid(), event: WindowEvent::KeyboardInput { device_id: device_id!(), input, @@ -565,7 +558,7 @@ macro_rules! handle_keyboard_event { if let Some(c) = $self.xkb_compose.utf8().and_then(|f| f.chars().next()) { $callback( Event::WindowEvent { - window_id: window_id!(), + window_id: winid(), event: WindowEvent::ReceivedCharacter(c), }, &mut (), @@ -585,7 +578,7 @@ macro_rules! handle_keyboard_event { if let Some(c) = ch { $callback( Event::WindowEvent { - window_id: window_id!(), + window_id: winid(), event: WindowEvent::ReceivedCharacter(c), }, &mut (), @@ -604,7 +597,7 @@ macro_rules! handle_keyboard_event { $callback( Event::WindowEvent { - window_id: window_id!(), + window_id: winid(), event: WindowEvent::ModifiersChanged($self.modifiers), }, &mut (), @@ -619,7 +612,7 @@ macro_rules! handle_keyboard_event { $callback( Event::WindowEvent { - window_id: window_id!(), + window_id: winid(), event: WindowEvent::ModifiersChanged($self.modifiers), }, &mut (), @@ -634,7 +627,7 @@ macro_rules! handle_keyboard_event { $callback( Event::WindowEvent { - window_id: window_id!(), + window_id: winid(), event: WindowEvent::ModifiersChanged($self.modifiers), }, &mut (), @@ -649,7 +642,7 @@ macro_rules! handle_keyboard_event { $callback( Event::WindowEvent { - window_id: window_id!(), + window_id: winid(), event: WindowEvent::ModifiersChanged($self.modifiers), }, &mut (), @@ -660,7 +653,7 @@ macro_rules! handle_keyboard_event { if $self.modifiers.is_empty() { $callback( Event::WindowEvent { - window_id: window_id!(), + window_id: winid(), event: WindowEvent::CloseRequested, }, &mut (), diff --git a/src/platform_impl/linux/kms/window.rs b/src/platform_impl/linux/kms/window.rs index 3b0051c77d..e7a0a64d80 100644 --- a/src/platform_impl/linux/kms/window.rs +++ b/src/platform_impl/linux/kms/window.rs @@ -15,7 +15,7 @@ use crate::{ monitor::{MonitorHandle, VideoMode}, platform::unix::Card, platform_impl, - window::{CursorIcon, Fullscreen, WindowAttributes}, + window::{CursorIcon, Fullscreen, WindowAttributes, WindowId}, }; pub struct Window { @@ -63,6 +63,11 @@ macro_rules! add_property { }; } +pub(crate) fn winid() -> WindowId { + // there is only one window + 0.into() +} + impl Window { pub fn new( event_loop_window_target: &super::event_loop::EventLoopWindowTarget, @@ -195,9 +200,10 @@ impl Window { card: event_loop_window_target.device.clone(), }) } + #[inline] - pub fn id(&self) -> super::WindowId { - super::WindowId + pub fn id(&self) -> platform_impl::WindowId { + winid().0 } #[inline] From d1e258076f6b3745037ba985540dac99f287aa62 Mon Sep 17 00:00:00 2001 From: mraerino Date: Sun, 7 May 2023 17:36:18 +0000 Subject: [PATCH 144/151] Fix monitor handle implementation --- src/platform_impl/linux/kms/event_loop.rs | 16 +++++------ src/platform_impl/linux/kms/mod.rs | 35 +++++++++++++---------- src/platform_impl/linux/kms/window.rs | 20 +++++++------ src/platform_impl/linux/mod.rs | 4 +-- 4 files changed, 40 insertions(+), 35 deletions(-) diff --git a/src/platform_impl/linux/kms/event_loop.rs b/src/platform_impl/linux/kms/event_loop.rs index f671ae8e84..ea230fc303 100644 --- a/src/platform_impl/linux/kms/event_loop.rs +++ b/src/platform_impl/linux/kms/event_loop.rs @@ -21,9 +21,8 @@ use crate::{ dpi::PhysicalPosition, event::{Event, StartCause}, event_loop::{self, ControlFlow, EventLoopClosed}, - monitor::MonitorHandle, platform::unix::Card, - platform_impl::{self, platform::sticky_exit_callback, OsError}, + platform_impl::{self, platform::sticky_exit_callback, MonitorHandle, OsError}, }; use super::{ @@ -66,12 +65,12 @@ pub struct EventLoopWindowTarget { impl EventLoopWindowTarget { #[inline] pub fn primary_monitor(&self) -> Option { - Some(MonitorHandle { - inner: platform_impl::MonitorHandle::Kms(super::MonitorHandle { - connector: self.connector.clone(), - name: (*MODE.lock())?.name().to_string_lossy().into_owned(), - }), - }) + let mode = (*MODE.lock())?; + Some(MonitorHandle::Kms(super::MonitorHandle { + connector: self.connector.clone(), + mode, + name: mode.name().to_string_lossy().into_owned(), + })) } #[inline] @@ -84,6 +83,7 @@ impl EventLoopWindowTarget { .iter() .map(|f| super::MonitorHandle { connector: self.device.get_connector(*f).unwrap(), + mode, name: mode.name().to_string_lossy().into_owned(), }) .collect() diff --git a/src/platform_impl/linux/kms/mod.rs b/src/platform_impl/linux/kms/mod.rs index 5ecddf114c..f6fc19cecc 100644 --- a/src/platform_impl/linux/kms/mod.rs +++ b/src/platform_impl/linux/kms/mod.rs @@ -3,7 +3,7 @@ use crate::dpi::{PhysicalPosition, PhysicalSize}; pub mod event_loop; pub mod input; pub mod window; -use crate::{monitor, platform_impl}; +use crate::platform_impl; pub use drm::SystemError; use drm::{ control::{Device as ControlDevice, *}, @@ -55,6 +55,7 @@ impl DeviceId { #[derive(Debug, Clone, PartialEq, Eq)] pub struct MonitorHandle { connector: connector::Info, + mode: Mode, name: String, } @@ -89,7 +90,7 @@ impl MonitorHandle { #[inline] pub fn size(&self) -> PhysicalSize { - let size = self.connector.modes()[0].size(); + let size = self.mode.size(); PhysicalSize::new(size.0 as u32, size.1 as u32) } @@ -98,20 +99,25 @@ impl MonitorHandle { PhysicalPosition::new(0, 0) } + #[inline] + pub fn refresh_rate_millihertz(&self) -> Option { + Some(self.mode.vrefresh() * 1000) + } + #[inline] pub fn scale_factor(&self) -> f64 { 1.0 } #[inline] - pub fn video_modes(&self) -> impl Iterator { + pub fn video_modes(&self) -> impl Iterator { let modes = self.connector.modes().to_vec(); let monitor = self.connector.clone(); - modes.into_iter().map(move |f| monitor::VideoMode { - video_mode: platform_impl::VideoMode::Kms(VideoMode { + modes.into_iter().map(move |f| { + platform_impl::VideoMode::Kms(VideoMode { mode: f, connector: monitor.clone(), - }), + }) }) } } @@ -135,18 +141,17 @@ impl VideoMode { } #[inline] - pub fn refresh_rate(&self) -> u16 { - self.mode.vrefresh() as u16 + pub fn refresh_rate_millihertz(&self) -> u32 { + self.mode.vrefresh() * 1000 } #[inline] - pub fn monitor(&self) -> monitor::MonitorHandle { - monitor::MonitorHandle { - inner: platform_impl::MonitorHandle::Kms(MonitorHandle { - connector: self.connector.clone(), - name: self.mode.name().to_string_lossy().into_owned(), - }), - } + pub fn monitor(&self) -> platform_impl::MonitorHandle { + platform_impl::MonitorHandle::Kms(MonitorHandle { + connector: self.connector.clone(), + mode: self.mode, + name: self.mode.name().to_string_lossy().into_owned(), + }) } } diff --git a/src/platform_impl/linux/kms/window.rs b/src/platform_impl/linux/kms/window.rs index e7a0a64d80..a0ae7781cb 100644 --- a/src/platform_impl/linux/kms/window.rs +++ b/src/platform_impl/linux/kms/window.rs @@ -12,9 +12,8 @@ use crate::error; use crate::{ dpi::{PhysicalPosition, PhysicalSize, Position, Size}, error::{ExternalError, NotSupportedError}, - monitor::{MonitorHandle, VideoMode}, platform::unix::Card, - platform_impl, + platform_impl::{self, MonitorHandle, VideoMode}, window::{CursorIcon, Fullscreen, WindowAttributes, WindowId}, }; @@ -384,9 +383,11 @@ impl Window { #[inline] pub fn current_monitor(&self) -> Option { + let mode = (*MODE.lock())?; Some(super::MonitorHandle { connector: self.connector.clone(), - name: (*MODE.lock())?.name().to_string_lossy().into_owned(), + mode, + name: mode.name().to_string_lossy().into_owned(), }) } @@ -400,6 +401,7 @@ impl Window { .iter() .map(|f| super::MonitorHandle { connector: self.card.get_connector(*f).unwrap(), + mode, name: mode.name().to_string_lossy().into_owned(), }) .collect() @@ -418,11 +420,11 @@ impl Window { #[inline] pub fn primary_monitor(&self) -> Option { - Some(MonitorHandle { - inner: platform_impl::MonitorHandle::Kms(super::MonitorHandle { - connector: self.connector.clone(), - name: (*MODE.lock())?.name().to_string_lossy().into_owned(), - }), - }) + let mode = (*MODE.lock())?; + Some(MonitorHandle::Kms(super::MonitorHandle { + connector: self.connector.clone(), + mode, + name: mode.name().to_string_lossy().into_owned(), + })) } } diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index d3638f5a55..700ae1751c 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -605,9 +605,7 @@ impl Window { #[cfg(drm_platform)] Window::Kms(ref window) => { let current_monitor = MonitorHandle::Kms(window.current_monitor()?); - Some(RootMonitorHandle { - inner: current_monitor, - }) + Some(current_monitor) } } } From 2f0ec0d1990cc4af1090ecc041b716bc7eb8bb98 Mon Sep 17 00:00:00 2001 From: mraerino Date: Sun, 7 May 2023 17:41:04 +0000 Subject: [PATCH 145/151] Fix raw window/display handle getters --- src/platform_impl/linux/kms/event_loop.rs | 9 +++++++++ src/platform_impl/linux/kms/window.rs | 16 ++++++++++++---- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/platform_impl/linux/kms/event_loop.rs b/src/platform_impl/linux/kms/event_loop.rs index ea230fc303..6c9f4f060b 100644 --- a/src/platform_impl/linux/kms/event_loop.rs +++ b/src/platform_impl/linux/kms/event_loop.rs @@ -1,8 +1,10 @@ use parking_lot::Mutex; +use raw_window_handle::{DrmDisplayHandle, RawDisplayHandle}; use std::{ cell::RefCell, collections::VecDeque, marker::PhantomData, + os::fd::AsRawFd, path::{Path, PathBuf}, rc::Rc, sync::{mpsc::SendError, Arc}, @@ -91,6 +93,13 @@ impl EventLoopWindowTarget { VecDeque::new() } } + + #[inline] + pub fn raw_display_handle(&self) -> RawDisplayHandle { + let mut dh = DrmDisplayHandle::empty(); + dh.fd = self.device.as_raw_fd(); + dh.into() + } } fn find_plane( diff --git a/src/platform_impl/linux/kms/window.rs b/src/platform_impl/linux/kms/window.rs index a0ae7781cb..a3ed12250e 100644 --- a/src/platform_impl/linux/kms/window.rs +++ b/src/platform_impl/linux/kms/window.rs @@ -7,6 +7,8 @@ use parking_lot::Mutex; #[cfg(feature = "wayland")] use sctk::reexports::calloop; +use raw_window_handle::{DrmDisplayHandle, RawDisplayHandle, RawWindowHandle}; + use crate::error; use crate::{ @@ -411,11 +413,17 @@ impl Window { } #[inline] - pub fn raw_window_handle(&self) -> raw_window_handle::DrmHandle { - let mut rwh = raw_window_handle::DrmHandle::empty(); - rwh.fd = self.card.as_raw_fd(); + pub fn raw_window_handle(&self) -> RawWindowHandle { + let mut rwh = raw_window_handle::DrmWindowHandle::empty(); rwh.plane = self.plane.into(); - rwh + rwh.into() + } + + #[inline] + pub fn raw_display_handle(&self) -> RawDisplayHandle { + let mut dh = DrmDisplayHandle::empty(); + dh.fd = self.card.as_raw_fd(); + dh.into() } #[inline] From c9712f4a218280e2db3c53f1899c55872ac5c2e7 Mon Sep 17 00:00:00 2001 From: mraerino Date: Sun, 7 May 2023 17:41:36 +0000 Subject: [PATCH 146/151] Fix imports --- src/platform_impl/linux/kms/event_loop.rs | 3 +-- src/platform_impl/linux/kms/window.rs | 6 +----- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/platform_impl/linux/kms/event_loop.rs b/src/platform_impl/linux/kms/event_loop.rs index 6c9f4f060b..e08379e8e3 100644 --- a/src/platform_impl/linux/kms/event_loop.rs +++ b/src/platform_impl/linux/kms/event_loop.rs @@ -23,14 +23,13 @@ use crate::{ dpi::PhysicalPosition, event::{Event, StartCause}, event_loop::{self, ControlFlow, EventLoopClosed}, - platform::unix::Card, platform_impl::{self, platform::sticky_exit_callback, MonitorHandle, OsError}, }; use super::{ input::{Interface, LibinputInputBackend}, window::winid, - MODE, + Card, MODE, }; /// An event loop's sink to deliver events from the Wayland event callbacks diff --git a/src/platform_impl/linux/kms/window.rs b/src/platform_impl/linux/kms/window.rs index a3ed12250e..fd59f226cd 100644 --- a/src/platform_impl/linux/kms/window.rs +++ b/src/platform_impl/linux/kms/window.rs @@ -1,12 +1,9 @@ use std::{collections::VecDeque, os::unix::prelude::AsRawFd, sync::Arc}; -use super::MODE; +use super::{Card, MODE}; use drm::control::*; use parking_lot::Mutex; -#[cfg(feature = "wayland")] -use sctk::reexports::calloop; - use raw_window_handle::{DrmDisplayHandle, RawDisplayHandle, RawWindowHandle}; use crate::error; @@ -14,7 +11,6 @@ use crate::error; use crate::{ dpi::{PhysicalPosition, PhysicalSize, Position, Size}, error::{ExternalError, NotSupportedError}, - platform::unix::Card, platform_impl::{self, MonitorHandle, VideoMode}, window::{CursorIcon, Fullscreen, WindowAttributes, WindowId}, }; From 3b0ccf273bf45a5778be27a13ff3d05e8f2769a0 Mon Sep 17 00:00:00 2001 From: mraerino Date: Sun, 7 May 2023 17:44:05 +0000 Subject: [PATCH 147/151] Fix fullscreen methods --- src/platform_impl/linux/kms/window.rs | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/src/platform_impl/linux/kms/window.rs b/src/platform_impl/linux/kms/window.rs index fd59f226cd..9582b29399 100644 --- a/src/platform_impl/linux/kms/window.rs +++ b/src/platform_impl/linux/kms/window.rs @@ -11,7 +11,7 @@ use crate::error; use crate::{ dpi::{PhysicalPosition, PhysicalSize, Position, Size}, error::{ExternalError, NotSupportedError}, - platform_impl::{self, MonitorHandle, VideoMode}, + platform_impl::{self, Fullscreen, MonitorHandle, VideoMode}, window::{CursorIcon, Fullscreen, WindowAttributes, WindowId}, }; @@ -299,27 +299,23 @@ impl Window { pub fn set_minimized(&self, _minimized: bool) {} #[inline] - pub fn fullscreen(&self) -> Option { - Some(Fullscreen::Exclusive(VideoMode { - video_mode: platform_impl::VideoMode::Kms(super::VideoMode { - mode: MODE.lock().expect("mode is not initialized"), - connector: self.connector.clone(), - }), - })) + pub(crate) fn fullscreen(&self) -> Option { + Some(Fullscreen::Exclusive(VideoMode::Kms(super::VideoMode { + mode: MODE.lock().expect("mode is not initialized"), + connector: self.connector.clone(), + }))) } #[inline] - pub fn set_fullscreen(&self, monitor: Option) { + pub(crate) fn set_fullscreen(&self, monitor: Option) { if let Some(Fullscreen::Exclusive(fullscreen)) = monitor { let modes = self.connector.modes().to_vec(); let connector = self.connector.clone(); if let Some(mo) = modes.into_iter().find(move |&f| { - VideoMode { - video_mode: platform_impl::VideoMode::Kms(super::VideoMode { - mode: f, - connector: connector.clone(), - }), - } == fullscreen + VideoMode::Kms(super::VideoMode { + mode: f, + connector: connector.clone(), + }) == fullscreen }) { let mut atomic_req = atomic::AtomicModeReq::new(); let blob = self.card.create_property_blob(&mo).unwrap(); From 971a669d52351cf57f559f519d621be5a107332b Mon Sep 17 00:00:00 2001 From: mraerino Date: Sun, 7 May 2023 17:44:40 +0000 Subject: [PATCH 148/151] Implement missing window functions --- src/platform_impl/linux/kms/window.rs | 62 ++++++++++++++++++++++++++- src/platform_impl/linux/mod.rs | 14 +++--- 2 files changed, 67 insertions(+), 9 deletions(-) diff --git a/src/platform_impl/linux/kms/window.rs b/src/platform_impl/linux/kms/window.rs index 9582b29399..6db2e38ea0 100644 --- a/src/platform_impl/linux/kms/window.rs +++ b/src/platform_impl/linux/kms/window.rs @@ -12,7 +12,10 @@ use crate::{ dpi::{PhysicalPosition, PhysicalSize, Position, Size}, error::{ExternalError, NotSupportedError}, platform_impl::{self, Fullscreen, MonitorHandle, VideoMode}, - window::{CursorIcon, Fullscreen, WindowAttributes, WindowId}, + window::{ + CursorGrabMode, CursorIcon, ImePurpose, ResizeDirection, Theme, WindowAttributes, + WindowButtons, WindowId, + }, }; pub struct Window { @@ -206,6 +209,14 @@ impl Window { #[inline] pub fn set_title(&self, _title: &str) {} + #[inline] + pub fn title(&self) -> String { + String::new() + } + + #[inline] + pub fn set_transparent(&self, _transparent: bool) {} + #[inline] pub fn set_visible(&self, _visible: bool) {} @@ -247,6 +258,16 @@ impl Window { #[inline] pub fn set_max_inner_size(&self, _dimensions: Option) {} + #[inline] + pub fn resize_increments(&self) -> Option> { + None + } + + #[inline] + pub fn set_resize_increments(&self, _increments: Option) { + warn!("`set_resize_increments` is not implemented for DRM"); + } + #[inline] pub fn set_resizable(&self, _resizable: bool) {} @@ -255,11 +276,27 @@ impl Window { false } + #[inline] + pub fn set_enabled_buttons(&self, _buttons: WindowButtons) {} + + #[inline] + pub fn enabled_buttons(&self) -> WindowButtons { + WindowButtons::all() + } + + #[inline] + pub fn set_theme(&self, _theme: Option) {} + + #[inline] + pub fn theme(&self) -> Option { + None + } + #[inline] pub fn set_cursor_icon(&self, _cursor: CursorIcon) {} #[inline] - pub fn set_cursor_grab(&self, _grab: bool) -> Result<(), ExternalError> { + pub fn set_cursor_grab(&self, _mode: CursorGrabMode) -> Result<(), ExternalError> { Ok(()) } @@ -271,6 +308,14 @@ impl Window { Err(ExternalError::NotSupported(NotSupportedError::new())) } + #[inline] + pub fn drag_resize_window( + &self, + _direction: ResizeDirection, + ) -> Result<(), error::ExternalError> { + Err(ExternalError::NotSupported(NotSupportedError::new())) + } + #[inline] pub fn set_cursor_hittest(&self, _hittest: bool) -> Result<(), ExternalError> { Err(ExternalError::NotSupported(NotSupportedError::new())) @@ -298,6 +343,11 @@ impl Window { #[inline] pub fn set_minimized(&self, _minimized: bool) {} + #[inline] + pub fn is_minimized(&self) -> Option { + None + } + #[inline] pub(crate) fn fullscreen(&self) -> Option { Some(Fullscreen::Exclusive(VideoMode::Kms(super::VideoMode { @@ -370,6 +420,9 @@ impl Window { #[inline] pub fn set_ime_allowed(&self, _allowed: bool) {} + #[inline] + pub fn set_ime_purpose(&self, _purpose: ImePurpose) {} + #[inline] pub fn request_redraw(&self) { self.ping.ping(); @@ -427,4 +480,9 @@ impl Window { name: mode.name().to_string_lossy().into_owned(), })) } + + #[inline] + pub fn has_focus(&self) -> bool { + false + } } diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index 700ae1751c..c81fd20d5b 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -360,7 +360,7 @@ impl Window { #[inline] pub fn set_transparent(&self, transparent: bool) { - x11_or_wayland!(match self; Window(w) => w.set_transparent(transparent)); + x11_or_wayland_or_drm!(match self; Window(w) => w.set_transparent(transparent)); } #[inline] @@ -415,12 +415,12 @@ impl Window { #[inline] pub fn resize_increments(&self) -> Option> { - x11_or_wayland!(match self; Window(w) => w.resize_increments()) + x11_or_wayland_or_drm!(match self; Window(w) => w.resize_increments()) } #[inline] pub fn set_resize_increments(&self, increments: Option) { - x11_or_wayland!(match self; Window(w) => w.set_resize_increments(increments)) + x11_or_wayland_or_drm!(match self; Window(w) => w.set_resize_increments(increments)) } #[inline] @@ -435,12 +435,12 @@ impl Window { #[inline] pub fn set_enabled_buttons(&self, buttons: WindowButtons) { - x11_or_wayland!(match self; Window(w) => w.set_enabled_buttons(buttons)) + x11_or_wayland_or_drm!(match self; Window(w) => w.set_enabled_buttons(buttons)) } #[inline] pub fn enabled_buttons(&self) -> WindowButtons { - x11_or_wayland!(match self; Window(w) => w.enabled_buttons()) + x11_or_wayland_or_drm!(match self; Window(w) => w.enabled_buttons()) } #[inline] @@ -559,7 +559,7 @@ impl Window { #[inline] pub fn set_ime_purpose(&self, purpose: ImePurpose) { - x11_or_wayland!(match self; Window(w) => w.set_ime_purpose(purpose)) + x11_or_wayland_or_drm!(match self; Window(w) => w.set_ime_purpose(purpose)) } #[inline] @@ -961,7 +961,7 @@ impl EventLoopWindowTarget { } pub fn raw_display_handle(&self) -> raw_window_handle::RawDisplayHandle { - x11_or_wayland!(match self; Self(evlp) => evlp.raw_display_handle()) + x11_or_wayland_or_drm!(match self; Self(evlp) => evlp.raw_display_handle()) } } From 31bf479c2ca3faa5df46090b37e390a6a4819c8c Mon Sep 17 00:00:00 2001 From: mraerino Date: Sun, 7 May 2023 17:44:50 +0000 Subject: [PATCH 149/151] Fix argument pass --- src/platform_impl/linux/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index c81fd20d5b..5a258e50c2 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -576,9 +576,9 @@ impl Window { pub fn request_user_attention(&self, _request_type: Option) { match self { #[cfg(x11_platform)] - Window::X(ref w) => w.request_user_attention(request_type), + Window::X(ref w) => w.request_user_attention(_request_type), #[cfg(wayland_platform)] - Window::Wayland(ref w) => w.request_user_attention(request_type), + Window::Wayland(ref w) => w.request_user_attention(_request_type), #[cfg(drm_platform)] Window::Kms(_) => (), } From 75105d4de91f65bdb51c1c3da334ed9406ea31c3 Mon Sep 17 00:00:00 2001 From: mraerino Date: Sun, 7 May 2023 17:55:28 +0000 Subject: [PATCH 150/151] Replace git dependency with released version --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index ef313c3c8c..442d52c65c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -121,7 +121,7 @@ drm = { version = "0.6.2", optional = true } input = { version = "0.7.1", optional = true } libseat = { version = "0.1.4", optional = true } udev = { version = "0.6.3", optional = true } -xkbcommon = { git = "https://github.com/StratusFearMe21/xkbcommon-rs", optional = true } +xkbcommon = { version = "0.5.0", optional = true } parking_lot = { version = "0.12.0", optional = true } [target.'cfg(target_os = "redox")'.dependencies] From 115bfe9e391a321fe42e1bf42a8e5a4b39882c14 Mon Sep 17 00:00:00 2001 From: mraerino Date: Sun, 7 May 2023 18:34:58 +0000 Subject: [PATCH 151/151] Add missing config attributes --- src/platform_impl/linux/mod.rs | 2 +- src/platform_impl/mod.rs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index 5a258e50c2..f7f93be4d9 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -903,7 +903,7 @@ impl EventLoopWindowTarget { match *self { #[cfg(wayland_platform)] EventLoopWindowTarget::Wayland(_) => true, - #[cfg(x11_platform)] + #[cfg(any(x11_platform, drm_platform))] _ => false, } } diff --git a/src/platform_impl/mod.rs b/src/platform_impl/mod.rs index 3b2b261344..af03fd3371 100644 --- a/src/platform_impl/mod.rs +++ b/src/platform_impl/mod.rs @@ -4,7 +4,7 @@ use crate::window::Fullscreen as RootFullscreen; #[cfg(windows_platform)] #[path = "windows/mod.rs"] mod platform; -#[cfg(any(x11_platform, wayland_platform))] +#[cfg(any(x11_platform, wayland_platform, drm_platform))] #[path = "linux/mod.rs"] mod platform; #[cfg(macos_platform)] @@ -61,6 +61,7 @@ impl From for RootFullscreen { not(android_platform), not(x11_platform), not(wayland_platform), + not(drm_platform), not(wasm_platform), not(orbital_platform), ))]