From 1002f30b067c6931d83fc91dd855512eb1af2e2c Mon Sep 17 00:00:00 2001 From: daxpedda Date: Tue, 26 Jan 2021 20:20:27 +0100 Subject: [PATCH 01/23] X11 implementation. --- CHANGELOG.md | 1 + FEATURES.md | 1 + src/platform_impl/android/mod.rs | 6 +++ src/platform_impl/ios/window.rs | 4 ++ src/platform_impl/linux/mod.rs | 5 +++ src/platform_impl/linux/wayland/window/mod.rs | 5 +++ src/platform_impl/linux/x11/window.rs | 40 +++++++++++++++++++ src/platform_impl/macos/window.rs | 5 +++ src/platform_impl/web/window.rs | 5 +++ src/platform_impl/windows/window.rs | 5 +++ src/window.rs | 15 +++++++ 11 files changed, 92 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e57ea66bed..228c4105b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ - On Android, bump `ndk` and `ndk-glue` to 0.3: use predefined constants for event `ident`. - 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 `Window::set_drag_window`. Implemented on Windows, macOS, X11 and Wayland. # 0.24.0 (2020-12-09) diff --git a/FEATURES.md b/FEATURES.md index 4ebb64291a..8bea2043fb 100644 --- a/FEATURES.md +++ b/FEATURES.md @@ -209,6 +209,7 @@ Legend: |Raw Device Events |▢[#750] |▢[#750] |▢[#750] |❌ |❌ |❌ |❓ | |Gamepad/Joystick events |❌[#804] |❌ |❌ |❌ |❌ |❌ |❓ | |Device movement events |❓ |❓ |❓ |❓ |❌ |❌ |❓ | +|Drag window with cursor |✔️ |✔️ |✔️ |✔️ |**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. diff --git a/src/platform_impl/android/mod.rs b/src/platform_impl/android/mod.rs index 0365a40e5e..f9124064db 100644 --- a/src/platform_impl/android/mod.rs +++ b/src/platform_impl/android/mod.rs @@ -556,6 +556,12 @@ impl Window { pub fn set_cursor_visible(&self, _: bool) {} + pub fn set_drag_window(&self) -> Result<(), error::ExternalError> { + Err(error::ExternalError::NotSupported( + error::NotSupportedError::new(), + )) + } + pub fn raw_window_handle(&self) -> raw_window_handle::RawWindowHandle { let a_native_window = if let Some(native_window) = ndk_glue::native_window().as_ref() { unsafe { native_window.ptr().as_mut() as *mut _ as *mut _ } diff --git a/src/platform_impl/ios/window.rs b/src/platform_impl/ios/window.rs index 7a3665a2b9..0721f27076 100644 --- a/src/platform_impl/ios/window.rs +++ b/src/platform_impl/ios/window.rs @@ -182,6 +182,10 @@ impl Inner { debug!("`Window::set_cursor_visible` is ignored on iOS") } + pub fn set_drag_window(&self) -> Result<(), ExternalError> { + Err(ExternalError::NotSupported(NotSupportedError::new())) + } + pub fn set_minimized(&self, _minimized: bool) { warn!("`Window::set_minimized` is ignored on iOS") } diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index e845b83be3..e5bb4e089f 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -358,6 +358,11 @@ impl Window { x11_or_wayland!(match self; Window(window) => window.set_cursor_visible(visible)) } + #[inline] + pub fn set_drag_window(&self) -> Result<(), ExternalError> { + x11_or_wayland!(match self; Window(window) => window.set_drag_window()) + } + #[inline] pub fn scale_factor(&self) -> f64 { x11_or_wayland!(match self; Window(w) => w.scale_factor() as f64) diff --git a/src/platform_impl/linux/wayland/window/mod.rs b/src/platform_impl/linux/wayland/window/mod.rs index d51f47a7a2..55333a059c 100644 --- a/src/platform_impl/linux/wayland/window/mod.rs +++ b/src/platform_impl/linux/wayland/window/mod.rs @@ -586,6 +586,11 @@ impl Window { Err(ExternalError::NotSupported(NotSupportedError::new())) } + #[inline] + pub fn set_drag_window(&self) -> Result<(), ExternalError> { + Err(ExternalError::NotSupported(NotSupportedError::new())) + } + #[inline] pub fn set_ime_position(&self, position: Position) { let scale_factor = self.scale_factor() as f64; diff --git a/src/platform_impl/linux/x11/window.rs b/src/platform_impl/linux/x11/window.rs index 0fa64cf164..6324378300 100644 --- a/src/platform_impl/linux/x11/window.rs +++ b/src/platform_impl/linux/x11/window.rs @@ -1276,6 +1276,46 @@ impl UnownedWindow { self.set_cursor_position_physical(x, y) } + pub fn set_drag_window(&self) -> Result<(), ExternalError> { + let pointer = self + .xconn + .query_pointer(self.xwindow, util::VIRTUAL_CORE_POINTER) + .map_err(|err| ExternalError::Os(os_error!(OsError::XError(err))))?; + + let window = self.inner_position().map_err(ExternalError::NotSupported)?; + + let message = unsafe { self.xconn.get_atom_unchecked(b"_NET_WM_MOVERESIZE\0") }; + + // we can't use `set_cursor_grab(false)` here because it doesn't run `XUngrabPointer` + // if the cursor isn't currently grabbed + let mut grabbed_lock = self.cursor_grabbed.lock(); + unsafe { + (self.xconn.xlib.XUngrabPointer)(self.xconn.display, ffi::CurrentTime); + } + self.xconn + .flush_requests() + .map_err(|err| ExternalError::Os(os_error!(OsError::XError(err))))?; + *grabbed_lock = false; + + // we keep the lock until we are done + self.xconn + .send_client_msg( + self.xwindow, + self.root, + message, + Some(ffi::SubstructureRedirectMask | ffi::SubstructureNotifyMask), + [ + (window.x as c_long + pointer.win_x as c_long), + (window.y as c_long + pointer.win_y as c_long), + 8, // _NET_WM_MOVERESIZE_MOVE + ffi::Button1 as c_long, + 1, + ], + ) + .flush() + .map_err(|err| ExternalError::Os(os_error!(OsError::XError(err)))) + } + pub(crate) fn set_ime_position_physical(&self, x: i32, y: i32) { let _ = self .ime_sender diff --git a/src/platform_impl/macos/window.rs b/src/platform_impl/macos/window.rs index 94a2f541cf..0453acbcae 100644 --- a/src/platform_impl/macos/window.rs +++ b/src/platform_impl/macos/window.rs @@ -636,6 +636,11 @@ impl UnownedWindow { Ok(()) } + #[inline] + pub fn set_drag_window(&self) -> Result<(), ExternalError> { + Err(ExternalError::NotSupported(NotSupportedError::new())) + } + pub(crate) fn is_zoomed(&self) -> bool { // because `isZoomed` doesn't work if the window's borderless, // we make it resizable temporalily. diff --git a/src/platform_impl/web/window.rs b/src/platform_impl/web/window.rs index 63e3948128..d886711db3 100644 --- a/src/platform_impl/web/window.rs +++ b/src/platform_impl/web/window.rs @@ -222,6 +222,11 @@ impl Window { } } + #[inline] + pub fn set_drag_window(&self) -> Result<(), ExternalError> { + Err(ExternalError::NotSupported(NotSupportedError::new())) + } + #[inline] pub fn set_minimized(&self, _minimized: bool) { // Intentionally a no-op, as canvases cannot be 'minimized' diff --git a/src/platform_impl/windows/window.rs b/src/platform_impl/windows/window.rs index cc04b8f790..c2bf155d77 100644 --- a/src/platform_impl/windows/window.rs +++ b/src/platform_impl/windows/window.rs @@ -357,6 +357,11 @@ impl Window { Ok(()) } + #[inline] + pub fn set_drag_window(&self) -> Result<(), ExternalError> { + Err(ExternalError::NotSupported(NotSupportedError::new())) + } + #[inline] pub fn id(&self) -> WindowId { WindowId(self.window.0) diff --git a/src/window.rs b/src/window.rs index 052f5746e0..2acf0196a4 100644 --- a/src/window.rs +++ b/src/window.rs @@ -764,6 +764,21 @@ impl Window { pub fn set_cursor_visible(&self, visible: bool) { self.window.set_cursor_visible(visible) } + + /// Moves the window with the left mouse button until the button is released. + /// + /// There's no guarantee that this will work unless the left mouse button was pressed + /// immediately before this function is called. + /// + /// ## Platform-specific + /// + /// - **X11:** Un-grabs the cursor. + /// - **macOS:** May prevent the button release event to be triggered. + /// - **iOS / Android / Web:** Always returns an [`ExternalError::NotSupported`]. + #[inline] + pub fn set_drag_window(&self) -> Result<(), ExternalError> { + self.window.set_drag_window() + } } /// Monitor info functions. From a6a536d72be91e8c247fd17f415ecdc89c4a6db0 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Tue, 26 Jan 2021 20:31:08 +0100 Subject: [PATCH 02/23] Introduce example. --- examples/drag_window.rs | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 examples/drag_window.rs diff --git a/examples/drag_window.rs b/examples/drag_window.rs new file mode 100644 index 0000000000..d4af3e9ebd --- /dev/null +++ b/examples/drag_window.rs @@ -0,0 +1,34 @@ +use simple_logger::SimpleLogger; +use winit::{ + event::{ElementState, Event, MouseButton, WindowEvent}, + event_loop::{ControlFlow, EventLoop}, + window::WindowBuilder, +}; + +fn main() { + SimpleLogger::new().init().unwrap(); + let event_loop = EventLoop::new(); + + let window = WindowBuilder::new().build(&event_loop).unwrap(); + + event_loop.run(move |event, _, control_flow| { + println!("{:?}", event); + + match event { + Event::WindowEvent { + event: WindowEvent::CloseRequested, + .. + } => *control_flow = ControlFlow::Exit, + Event::WindowEvent { + event: + WindowEvent::MouseInput { + state: ElementState::Pressed, + button: MouseButton::Left, + .. + }, + .. + } => window.set_drag_window().unwrap(), + _ => (), + } + }); +} From 838d9ba12e842899068a2ab4e6c67f1c8c7ba0f5 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Wed, 27 Jan 2021 11:53:10 +0100 Subject: [PATCH 03/23] Wayland implementation. --- Cargo.toml | 3 +++ .../linux/wayland/seat/pointer/handlers.rs | 5 +++++ .../linux/wayland/seat/pointer/mod.rs | 18 +++++++++++++++++- src/platform_impl/linux/wayland/window/mod.rs | 9 ++++++++- src/platform_impl/linux/wayland/window/shim.rs | 12 ++++++++++++ 5 files changed, 45 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 64b1bee10e..eac565ce22 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -131,3 +131,6 @@ features = ["experimental_features_which_may_break_on_minor_version_bumps"] [target.'cfg(target_arch = "wasm32")'.dev-dependencies] console_log = "0.2" + +[patch.crates-io] +smithay-client-toolkit = { git = "https://github.com/daxpedda/client-toolkit", branch = "start-interactive-move" } diff --git a/src/platform_impl/linux/wayland/seat/pointer/handlers.rs b/src/platform_impl/linux/wayland/seat/pointer/handlers.rs index 7d291713fa..147b0e745e 100644 --- a/src/platform_impl/linux/wayland/seat/pointer/handlers.rs +++ b/src/platform_impl/linux/wayland/seat/pointer/handlers.rs @@ -4,6 +4,8 @@ use std::cell::RefCell; use std::rc::Rc; use sctk::reexports::client::protocol::wl_pointer::{self, Event as PointerEvent}; +use sctk::reexports::client::protocol::wl_seat::WlSeat; +use sctk::reexports::client::Attached; use sctk::reexports::protocols::unstable::relative_pointer::v1::client::zwp_relative_pointer_v1::Event as RelativePointerEvent; use sctk::seat::pointer::ThemedPointer; @@ -28,6 +30,7 @@ pub(super) fn handle_pointer( event: PointerEvent, pointer_data: &Rc>, winit_state: &mut WinitState, + seat: Attached, ) { let event_sink = &mut winit_state.event_sink; let mut pointer_data = pointer_data.borrow_mut(); @@ -59,6 +62,7 @@ pub(super) fn handle_pointer( confined_pointer: Rc::downgrade(&pointer_data.confined_pointer), pointer_constraints: pointer_data.pointer_constraints.clone(), latest_serial: pointer_data.latest_serial.clone(), + seat, }; window_handle.pointer_entered(winit_pointer); @@ -101,6 +105,7 @@ pub(super) fn handle_pointer( confined_pointer: Rc::downgrade(&pointer_data.confined_pointer), pointer_constraints: pointer_data.pointer_constraints.clone(), latest_serial: pointer_data.latest_serial.clone(), + seat, }; window_handle.pointer_left(winit_pointer); diff --git a/src/platform_impl/linux/wayland/seat/pointer/mod.rs b/src/platform_impl/linux/wayland/seat/pointer/mod.rs index 5debc8cbcf..2a9cbcb4c7 100644 --- a/src/platform_impl/linux/wayland/seat/pointer/mod.rs +++ b/src/platform_impl/linux/wayland/seat/pointer/mod.rs @@ -13,6 +13,7 @@ use sctk::reexports::protocols::unstable::pointer_constraints::v1::client::zwp_p use sctk::reexports::protocols::unstable::pointer_constraints::v1::client::zwp_confined_pointer_v1::ZwpConfinedPointerV1; use sctk::seat::pointer::{ThemeManager, ThemedPointer}; +use sctk::window::{ConceptFrame, Window}; use crate::event::ModifiersState; use crate::platform_impl::wayland::event_loop::WinitState; @@ -35,6 +36,9 @@ pub struct WinitPointer { /// Latest observed serial in pointer events. latest_serial: Rc>, + + /// Seat. + seat: Attached, } impl PartialEq for WinitPointer { @@ -144,6 +148,11 @@ impl WinitPointer { confined_pointer.destroy(); } } + + /// Tries to unconfine the pointer if the current pointer is confined. + pub fn set_drag_window(&self, window: &Window) { + window.start_interactive_move(&self.seat, self.latest_serial.get()); + } } /// A pointer wrapper for easy releasing and managing pointers. @@ -172,11 +181,18 @@ impl Pointers { pointer_constraints.clone(), modifiers_state, ))); + let seat_clone = seat.clone(); let pointer = theme_manager.theme_pointer_with_impl( seat, move |event, pointer, mut dispatch_data| { let winit_state = dispatch_data.get::().unwrap(); - handlers::handle_pointer(pointer, event, &pointer_data, winit_state); + handlers::handle_pointer( + pointer, + event, + &pointer_data, + winit_state, + seat_clone.clone(), + ); }, ); diff --git a/src/platform_impl/linux/wayland/window/mod.rs b/src/platform_impl/linux/wayland/window/mod.rs index 55333a059c..5f25e6ce87 100644 --- a/src/platform_impl/linux/wayland/window/mod.rs +++ b/src/platform_impl/linux/wayland/window/mod.rs @@ -588,7 +588,14 @@ impl Window { #[inline] pub fn set_drag_window(&self) -> Result<(), ExternalError> { - Err(ExternalError::NotSupported(NotSupportedError::new())) + let drag_window_request = WindowRequest::DragWindow; + self.window_requests + .lock() + .unwrap() + .push(drag_window_request); + self.event_loop_awakener.ping(); + + Ok(()) } #[inline] diff --git a/src/platform_impl/linux/wayland/window/shim.rs b/src/platform_impl/linux/wayland/window/shim.rs index 59cf921a59..61db034172 100644 --- a/src/platform_impl/linux/wayland/window/shim.rs +++ b/src/platform_impl/linux/wayland/window/shim.rs @@ -34,6 +34,9 @@ pub enum WindowRequest { /// Grab cursor. GrabCursor(bool), + /// Drag window. + DragWindow, + /// Maximize the window. Maximize(bool), @@ -268,6 +271,12 @@ impl WindowHandle { pointer.set_cursor(Some(cursor_icon)); } } + + pub fn set_drag_window(&self) { + for pointer in self.pointers.iter() { + pointer.set_drag_window(&self.window); + } + } } #[inline] @@ -299,6 +308,9 @@ pub fn handle_window_requests(winit_state: &mut WinitState) { WindowRequest::GrabCursor(grab) => { window_handle.set_cursor_grab(grab); } + WindowRequest::DragWindow => { + window_handle.set_drag_window(); + } WindowRequest::Maximize(maximize) => { if maximize { window_handle.window.set_maximized(); From a24038aac5f503111b94b28bc40a1496d162faed Mon Sep 17 00:00:00 2001 From: daxpedda Date: Wed, 27 Jan 2021 12:31:06 +0100 Subject: [PATCH 04/23] Windows implementation. --- src/platform_impl/windows/window.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/platform_impl/windows/window.rs b/src/platform_impl/windows/window.rs index c2bf155d77..0f33081be0 100644 --- a/src/platform_impl/windows/window.rs +++ b/src/platform_impl/windows/window.rs @@ -14,7 +14,7 @@ use std::{ use winapi::{ ctypes::c_int, shared::{ - minwindef::{HINSTANCE, UINT}, + minwindef::{HINSTANCE, UINT, WPARAM}, windef::{HWND, POINT, RECT}, }, um::{ @@ -359,7 +359,17 @@ impl Window { #[inline] pub fn set_drag_window(&self) -> Result<(), ExternalError> { - Err(ExternalError::NotSupported(NotSupportedError::new())) + unsafe { + winuser::ReleaseCapture(); + winuser::SendMessageW( + self.window.0, + winuser::WM_NCLBUTTONDOWN, + winuser::HTCAPTION as WPARAM, + 0, + ); + } + + Ok(()) } #[inline] From 8b268a0b325f345e7fd6021df0ed1ba49e8e314f Mon Sep 17 00:00:00 2001 From: daxpedda Date: Wed, 27 Jan 2021 12:52:17 +0100 Subject: [PATCH 05/23] Improve Wayland seat passing. --- src/platform_impl/linux/wayland/seat/pointer/handlers.rs | 3 +-- src/platform_impl/linux/wayland/seat/pointer/mod.rs | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/platform_impl/linux/wayland/seat/pointer/handlers.rs b/src/platform_impl/linux/wayland/seat/pointer/handlers.rs index 147b0e745e..62b2114321 100644 --- a/src/platform_impl/linux/wayland/seat/pointer/handlers.rs +++ b/src/platform_impl/linux/wayland/seat/pointer/handlers.rs @@ -5,7 +5,6 @@ use std::rc::Rc; use sctk::reexports::client::protocol::wl_pointer::{self, Event as PointerEvent}; use sctk::reexports::client::protocol::wl_seat::WlSeat; -use sctk::reexports::client::Attached; use sctk::reexports::protocols::unstable::relative_pointer::v1::client::zwp_relative_pointer_v1::Event as RelativePointerEvent; use sctk::seat::pointer::ThemedPointer; @@ -30,7 +29,7 @@ pub(super) fn handle_pointer( event: PointerEvent, pointer_data: &Rc>, winit_state: &mut WinitState, - seat: Attached, + seat: WlSeat, ) { let event_sink = &mut winit_state.event_sink; let mut pointer_data = pointer_data.borrow_mut(); diff --git a/src/platform_impl/linux/wayland/seat/pointer/mod.rs b/src/platform_impl/linux/wayland/seat/pointer/mod.rs index 2a9cbcb4c7..bc4d152f08 100644 --- a/src/platform_impl/linux/wayland/seat/pointer/mod.rs +++ b/src/platform_impl/linux/wayland/seat/pointer/mod.rs @@ -38,7 +38,7 @@ pub struct WinitPointer { latest_serial: Rc>, /// Seat. - seat: Attached, + seat: WlSeat, } impl PartialEq for WinitPointer { @@ -181,7 +181,7 @@ impl Pointers { pointer_constraints.clone(), modifiers_state, ))); - let seat_clone = seat.clone(); + let pointer_seat = seat.detach(); let pointer = theme_manager.theme_pointer_with_impl( seat, move |event, pointer, mut dispatch_data| { @@ -191,7 +191,7 @@ impl Pointers { event, &pointer_data, winit_state, - seat_clone.clone(), + pointer_seat.clone(), ); }, ); From b7e96ea7ba1a4ae1bea4cf8d7a8aac8061cfc60d Mon Sep 17 00:00:00 2001 From: daxpedda Date: Wed, 27 Jan 2021 14:41:42 +0100 Subject: [PATCH 06/23] MacOS implementation. --- src/platform_impl/macos/window.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/platform_impl/macos/window.rs b/src/platform_impl/macos/window.rs index 0453acbcae..a633935694 100644 --- a/src/platform_impl/macos/window.rs +++ b/src/platform_impl/macos/window.rs @@ -638,7 +638,12 @@ impl UnownedWindow { #[inline] pub fn set_drag_window(&self) -> Result<(), ExternalError> { - Err(ExternalError::NotSupported(NotSupportedError::new())) + unsafe { + let event: id = msg_send![NSApp(), currentEvent]; + let _: () = msg_send![*self.ns_window, performWindowDragWithEvent: event]; + } + + Ok(()) } pub(crate) fn is_zoomed(&self) -> bool { From 6072a468dddfd7a32be38ebd89551ddb91960d79 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Wed, 27 Jan 2021 22:12:44 +0100 Subject: [PATCH 07/23] Correct windows implementation per specification. --- src/platform_impl/windows/window.rs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/platform_impl/windows/window.rs b/src/platform_impl/windows/window.rs index 0f33081be0..8eac5c6e9b 100644 --- a/src/platform_impl/windows/window.rs +++ b/src/platform_impl/windows/window.rs @@ -14,8 +14,8 @@ use std::{ use winapi::{ ctypes::c_int, shared::{ - minwindef::{HINSTANCE, UINT, WPARAM}, - windef::{HWND, POINT, RECT}, + minwindef::{HINSTANCE, LPARAM, UINT, WPARAM}, + windef::{HWND, POINT, POINTS, RECT}, }, um::{ combaseapi, dwmapi, @@ -26,7 +26,7 @@ use winapi::{ oleidl::LPDROPTARGET, shobjidl_core::{CLSID_TaskbarList, ITaskbarList2}, wingdi::{CreateRectRgn, DeleteObject}, - winnt::LPCWSTR, + winnt::{LPCWSTR, SHORT}, winuser, }, }; @@ -360,12 +360,21 @@ impl Window { #[inline] pub fn set_drag_window(&self) -> Result<(), ExternalError> { unsafe { + let points = { + let mut pos = mem::zeroed(); + winuser::GetCursorPos(&mut pos); + pos + }; + let points = POINTS { + x: points.x as SHORT, + y: points.y as SHORT, + }; winuser::ReleaseCapture(); winuser::SendMessageW( self.window.0, winuser::WM_NCLBUTTONDOWN, winuser::HTCAPTION as WPARAM, - 0, + &points as *const _ as LPARAM, ); } From 35aa76f41def341e6a945f74ef000e20fbc7abbd Mon Sep 17 00:00:00 2001 From: daxpedda Date: Wed, 27 Jan 2021 22:13:22 +0100 Subject: [PATCH 08/23] Update dependency smithay-client-toolkit from branch to master. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index eac565ce22..1e4cc1bdd1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -133,4 +133,4 @@ features = ["experimental_features_which_may_break_on_minor_version_bumps"] console_log = "0.2" [patch.crates-io] -smithay-client-toolkit = { git = "https://github.com/daxpedda/client-toolkit", branch = "start-interactive-move" } +smithay-client-toolkit = { git = "https://github.com/smithay/client-toolkit" } From c8f703045487016cd0ecbda5ddb752b1f0a52623 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Thu, 28 Jan 2021 20:41:54 +0100 Subject: [PATCH 09/23] Fixed blocking thread in windows implementation. --- src/platform_impl/windows/window.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform_impl/windows/window.rs b/src/platform_impl/windows/window.rs index 8eac5c6e9b..eaeef5cde7 100644 --- a/src/platform_impl/windows/window.rs +++ b/src/platform_impl/windows/window.rs @@ -370,7 +370,7 @@ impl Window { y: points.y as SHORT, }; winuser::ReleaseCapture(); - winuser::SendMessageW( + winuser::PostMessageW( self.window.0, winuser::WM_NCLBUTTONDOWN, winuser::HTCAPTION as WPARAM, From b58ca0df56385732739933780de25760d76046f8 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Sun, 7 Feb 2021 17:53:42 +0100 Subject: [PATCH 10/23] Add multi-window example. --- examples/drag_window.rs | 52 +++++++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 15 deletions(-) diff --git a/examples/drag_window.rs b/examples/drag_window.rs index d4af3e9ebd..4f2654abdc 100644 --- a/examples/drag_window.rs +++ b/examples/drag_window.rs @@ -1,6 +1,8 @@ use simple_logger::SimpleLogger; use winit::{ - event::{ElementState, Event, MouseButton, WindowEvent}, + event::{ + ElementState, Event, KeyboardInput, MouseButton, StartCause, VirtualKeyCode, WindowEvent, + }, event_loop::{ControlFlow, EventLoop}, window::WindowBuilder, }; @@ -9,26 +11,46 @@ fn main() { SimpleLogger::new().init().unwrap(); let event_loop = EventLoop::new(); - let window = WindowBuilder::new().build(&event_loop).unwrap(); + let window_1 = WindowBuilder::new().build(&event_loop).unwrap(); + let window_2 = WindowBuilder::new().build(&event_loop).unwrap(); - event_loop.run(move |event, _, control_flow| { - println!("{:?}", event); + let mut switched = false; - match event { - Event::WindowEvent { - event: WindowEvent::CloseRequested, + event_loop.run(move |event, _, control_flow| match event { + Event::NewEvents(StartCause::Init) => { + eprintln!("Switch which window is to be dragged by pressing \"x\".") + } + Event::WindowEvent { event, window_id } => match event { + WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit, + WindowEvent::MouseInput { + state: ElementState::Pressed, + button: MouseButton::Left, .. - } => *control_flow = ControlFlow::Exit, - Event::WindowEvent { - event: - WindowEvent::MouseInput { - state: ElementState::Pressed, - button: MouseButton::Left, + } => { + let window = if (window_id == window_1.id() && switched) + || (window_id == window_2.id() && !switched) + { + &window_2 + } else { + &window_1 + }; + + window.set_drag_window().unwrap() + } + WindowEvent::KeyboardInput { + input: + KeyboardInput { + state: ElementState::Released, + virtual_keycode: Some(VirtualKeyCode::X), .. }, .. - } => window.set_drag_window().unwrap(), + } => { + switched = !switched; + println!("Switched!") + } _ => (), - } + }, + _ => (), }); } From 213af5036e31aa78d46681b94d2849b901ae6d22 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Sun, 7 Feb 2021 18:04:55 +0100 Subject: [PATCH 11/23] Move Wayland to a different PR. --- Cargo.toml | 3 --- FEATURES.md | 2 +- src/platform_impl/linux/mod.rs | 7 ++++++- .../linux/wayland/seat/pointer/handlers.rs | 4 ---- .../linux/wayland/seat/pointer/mod.rs | 18 +----------------- src/platform_impl/linux/wayland/window/mod.rs | 12 ------------ src/platform_impl/linux/wayland/window/shim.rs | 12 ------------ src/window.rs | 2 +- 8 files changed, 9 insertions(+), 51 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1e4cc1bdd1..64b1bee10e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -131,6 +131,3 @@ features = ["experimental_features_which_may_break_on_minor_version_bumps"] [target.'cfg(target_arch = "wasm32")'.dev-dependencies] console_log = "0.2" - -[patch.crates-io] -smithay-client-toolkit = { git = "https://github.com/smithay/client-toolkit" } diff --git a/FEATURES.md b/FEATURES.md index 8bea2043fb..8d9c1e4a43 100644 --- a/FEATURES.md +++ b/FEATURES.md @@ -209,7 +209,7 @@ Legend: |Raw Device Events |▢[#750] |▢[#750] |▢[#750] |❌ |❌ |❌ |❓ | |Gamepad/Joystick events |❌[#804] |❌ |❌ |❌ |❌ |❌ |❓ | |Device movement events |❓ |❓ |❓ |❓ |❌ |❌ |❓ | -|Drag window with cursor |✔️ |✔️ |✔️ |✔️ |**N/A**|**N/A**|**N/A** | +|Drag window with cursor |✔️ |✔️ |✔️ |❌ |**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. diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index e5bb4e089f..ca7964b0d6 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -360,7 +360,12 @@ impl Window { #[inline] pub fn set_drag_window(&self) -> Result<(), ExternalError> { - x11_or_wayland!(match self; Window(window) => window.set_drag_window()) + match self { + #[cfg(feature = "x11")] + &Window::X(ref w) => w.set_drag_window(), + #[cfg(feature = "wayland")] + _ => Err(ExternalError::NotSupported(NotSupportedError::new())), + } } #[inline] diff --git a/src/platform_impl/linux/wayland/seat/pointer/handlers.rs b/src/platform_impl/linux/wayland/seat/pointer/handlers.rs index 62b2114321..7d291713fa 100644 --- a/src/platform_impl/linux/wayland/seat/pointer/handlers.rs +++ b/src/platform_impl/linux/wayland/seat/pointer/handlers.rs @@ -4,7 +4,6 @@ use std::cell::RefCell; use std::rc::Rc; use sctk::reexports::client::protocol::wl_pointer::{self, Event as PointerEvent}; -use sctk::reexports::client::protocol::wl_seat::WlSeat; use sctk::reexports::protocols::unstable::relative_pointer::v1::client::zwp_relative_pointer_v1::Event as RelativePointerEvent; use sctk::seat::pointer::ThemedPointer; @@ -29,7 +28,6 @@ pub(super) fn handle_pointer( event: PointerEvent, pointer_data: &Rc>, winit_state: &mut WinitState, - seat: WlSeat, ) { let event_sink = &mut winit_state.event_sink; let mut pointer_data = pointer_data.borrow_mut(); @@ -61,7 +59,6 @@ pub(super) fn handle_pointer( confined_pointer: Rc::downgrade(&pointer_data.confined_pointer), pointer_constraints: pointer_data.pointer_constraints.clone(), latest_serial: pointer_data.latest_serial.clone(), - seat, }; window_handle.pointer_entered(winit_pointer); @@ -104,7 +101,6 @@ pub(super) fn handle_pointer( confined_pointer: Rc::downgrade(&pointer_data.confined_pointer), pointer_constraints: pointer_data.pointer_constraints.clone(), latest_serial: pointer_data.latest_serial.clone(), - seat, }; window_handle.pointer_left(winit_pointer); diff --git a/src/platform_impl/linux/wayland/seat/pointer/mod.rs b/src/platform_impl/linux/wayland/seat/pointer/mod.rs index bc4d152f08..5debc8cbcf 100644 --- a/src/platform_impl/linux/wayland/seat/pointer/mod.rs +++ b/src/platform_impl/linux/wayland/seat/pointer/mod.rs @@ -13,7 +13,6 @@ use sctk::reexports::protocols::unstable::pointer_constraints::v1::client::zwp_p use sctk::reexports::protocols::unstable::pointer_constraints::v1::client::zwp_confined_pointer_v1::ZwpConfinedPointerV1; use sctk::seat::pointer::{ThemeManager, ThemedPointer}; -use sctk::window::{ConceptFrame, Window}; use crate::event::ModifiersState; use crate::platform_impl::wayland::event_loop::WinitState; @@ -36,9 +35,6 @@ pub struct WinitPointer { /// Latest observed serial in pointer events. latest_serial: Rc>, - - /// Seat. - seat: WlSeat, } impl PartialEq for WinitPointer { @@ -148,11 +144,6 @@ impl WinitPointer { confined_pointer.destroy(); } } - - /// Tries to unconfine the pointer if the current pointer is confined. - pub fn set_drag_window(&self, window: &Window) { - window.start_interactive_move(&self.seat, self.latest_serial.get()); - } } /// A pointer wrapper for easy releasing and managing pointers. @@ -181,18 +172,11 @@ impl Pointers { pointer_constraints.clone(), modifiers_state, ))); - let pointer_seat = seat.detach(); let pointer = theme_manager.theme_pointer_with_impl( seat, move |event, pointer, mut dispatch_data| { let winit_state = dispatch_data.get::().unwrap(); - handlers::handle_pointer( - pointer, - event, - &pointer_data, - winit_state, - pointer_seat.clone(), - ); + handlers::handle_pointer(pointer, event, &pointer_data, winit_state); }, ); diff --git a/src/platform_impl/linux/wayland/window/mod.rs b/src/platform_impl/linux/wayland/window/mod.rs index 5f25e6ce87..d51f47a7a2 100644 --- a/src/platform_impl/linux/wayland/window/mod.rs +++ b/src/platform_impl/linux/wayland/window/mod.rs @@ -586,18 +586,6 @@ impl Window { Err(ExternalError::NotSupported(NotSupportedError::new())) } - #[inline] - pub fn set_drag_window(&self) -> Result<(), ExternalError> { - let drag_window_request = WindowRequest::DragWindow; - self.window_requests - .lock() - .unwrap() - .push(drag_window_request); - self.event_loop_awakener.ping(); - - Ok(()) - } - #[inline] pub fn set_ime_position(&self, position: Position) { let scale_factor = self.scale_factor() as f64; diff --git a/src/platform_impl/linux/wayland/window/shim.rs b/src/platform_impl/linux/wayland/window/shim.rs index 61db034172..59cf921a59 100644 --- a/src/platform_impl/linux/wayland/window/shim.rs +++ b/src/platform_impl/linux/wayland/window/shim.rs @@ -34,9 +34,6 @@ pub enum WindowRequest { /// Grab cursor. GrabCursor(bool), - /// Drag window. - DragWindow, - /// Maximize the window. Maximize(bool), @@ -271,12 +268,6 @@ impl WindowHandle { pointer.set_cursor(Some(cursor_icon)); } } - - pub fn set_drag_window(&self) { - for pointer in self.pointers.iter() { - pointer.set_drag_window(&self.window); - } - } } #[inline] @@ -308,9 +299,6 @@ pub fn handle_window_requests(winit_state: &mut WinitState) { WindowRequest::GrabCursor(grab) => { window_handle.set_cursor_grab(grab); } - WindowRequest::DragWindow => { - window_handle.set_drag_window(); - } WindowRequest::Maximize(maximize) => { if maximize { window_handle.window.set_maximized(); diff --git a/src/window.rs b/src/window.rs index 2acf0196a4..b57e2cc897 100644 --- a/src/window.rs +++ b/src/window.rs @@ -774,7 +774,7 @@ impl Window { /// /// - **X11:** Un-grabs the cursor. /// - **macOS:** May prevent the button release event to be triggered. - /// - **iOS / Android / Web:** Always returns an [`ExternalError::NotSupported`]. + /// - **Wayland / iOS / Android / Web:** Always returns an [`ExternalError::NotSupported`]. #[inline] pub fn set_drag_window(&self) -> Result<(), ExternalError> { self.window.set_drag_window() From 47b223c092a343041dfa359e272e9273f5ed7c1e Mon Sep 17 00:00:00 2001 From: daxpedda Date: Sun, 7 Feb 2021 18:38:12 +0100 Subject: [PATCH 12/23] Fix CHANGELOG. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 228c4105b3..2f463c05ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ - 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 `Window::set_drag_window`. Implemented on Windows, macOS, X11 and Wayland. +- Added `Window::set_drag_window`. Implemented on Windows, macOS and X11. # 0.24.0 (2020-12-09) From a6694f892cd7e23af105b60ebe5fae8d8c2d1707 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Sun, 7 Feb 2021 19:54:57 +0100 Subject: [PATCH 13/23] Improve example. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Markus Røyset --- examples/drag_window.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/examples/drag_window.rs b/examples/drag_window.rs index 4f2654abdc..e8def87b54 100644 --- a/examples/drag_window.rs +++ b/examples/drag_window.rs @@ -37,6 +37,17 @@ fn main() { window.set_drag_window().unwrap() } + WindowEvent::CursorEntered { .. } => { + let (drag_target, other) = if (window_id == window_1.id() && switched) + || (window_id == window_2.id() && !switched) + { + (&window_2, &window_1) + } else { + (&window_1, &window_2) + }; + drag_target.set_title("drag target"); + other.set_title("winit window"); + } WindowEvent::KeyboardInput { input: KeyboardInput { From 487014ffa85771f1093777cc8c7515d5140f34f9 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Sun, 7 Feb 2021 20:00:25 +0100 Subject: [PATCH 14/23] Rename `set_drag_window` to `begin_drag`. --- CHANGELOG.md | 1 + examples/drag_window.rs | 2 +- src/platform_impl/android/mod.rs | 2 +- src/platform_impl/ios/window.rs | 2 +- src/platform_impl/linux/mod.rs | 4 ++-- src/platform_impl/linux/x11/window.rs | 2 +- src/platform_impl/macos/window.rs | 2 +- src/platform_impl/web/window.rs | 2 +- src/platform_impl/windows/window.rs | 2 +- src/window.rs | 4 ++-- 10 files changed, 12 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f463c05ed..82e0d7ffcb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ - On Web, added support for `DeviceEvent::MouseMotion` to listen for relative mouse movements. - Added `Window::set_drag_window`. Implemented on Windows, macOS, X11 and Wayland. - Added `Window::set_drag_window`. Implemented on Windows, macOS and X11. +- Added `Window::begin_drag`. Implemented on Windows, macOS and X11. # 0.24.0 (2020-12-09) diff --git a/examples/drag_window.rs b/examples/drag_window.rs index e8def87b54..c72304dde9 100644 --- a/examples/drag_window.rs +++ b/examples/drag_window.rs @@ -35,7 +35,7 @@ fn main() { &window_1 }; - window.set_drag_window().unwrap() + window.begin_drag().unwrap() } WindowEvent::CursorEntered { .. } => { let (drag_target, other) = if (window_id == window_1.id() && switched) diff --git a/src/platform_impl/android/mod.rs b/src/platform_impl/android/mod.rs index f9124064db..87beb40e6f 100644 --- a/src/platform_impl/android/mod.rs +++ b/src/platform_impl/android/mod.rs @@ -556,7 +556,7 @@ impl Window { pub fn set_cursor_visible(&self, _: bool) {} - pub fn set_drag_window(&self) -> Result<(), error::ExternalError> { + pub fn begin_drag(&self) -> Result<(), error::ExternalError> { Err(error::ExternalError::NotSupported( error::NotSupportedError::new(), )) diff --git a/src/platform_impl/ios/window.rs b/src/platform_impl/ios/window.rs index 0721f27076..036340ac54 100644 --- a/src/platform_impl/ios/window.rs +++ b/src/platform_impl/ios/window.rs @@ -182,7 +182,7 @@ impl Inner { debug!("`Window::set_cursor_visible` is ignored on iOS") } - pub fn set_drag_window(&self) -> Result<(), ExternalError> { + pub fn begin_drag(&self) -> Result<(), ExternalError> { Err(ExternalError::NotSupported(NotSupportedError::new())) } diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index ca7964b0d6..9f90ea0426 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -359,10 +359,10 @@ impl Window { } #[inline] - pub fn set_drag_window(&self) -> Result<(), ExternalError> { + pub fn begin_drag(&self) -> Result<(), ExternalError> { match self { #[cfg(feature = "x11")] - &Window::X(ref w) => w.set_drag_window(), + &Window::X(ref w) => w.begin_drag(), #[cfg(feature = "wayland")] _ => Err(ExternalError::NotSupported(NotSupportedError::new())), } diff --git a/src/platform_impl/linux/x11/window.rs b/src/platform_impl/linux/x11/window.rs index 6324378300..fe694a22e0 100644 --- a/src/platform_impl/linux/x11/window.rs +++ b/src/platform_impl/linux/x11/window.rs @@ -1276,7 +1276,7 @@ impl UnownedWindow { self.set_cursor_position_physical(x, y) } - pub fn set_drag_window(&self) -> Result<(), ExternalError> { + pub fn begin_drag(&self) -> Result<(), ExternalError> { let pointer = self .xconn .query_pointer(self.xwindow, util::VIRTUAL_CORE_POINTER) diff --git a/src/platform_impl/macos/window.rs b/src/platform_impl/macos/window.rs index a633935694..2ccd4be3b9 100644 --- a/src/platform_impl/macos/window.rs +++ b/src/platform_impl/macos/window.rs @@ -637,7 +637,7 @@ impl UnownedWindow { } #[inline] - pub fn set_drag_window(&self) -> Result<(), ExternalError> { + pub fn begin_drag(&self) -> Result<(), ExternalError> { unsafe { let event: id = msg_send![NSApp(), currentEvent]; let _: () = msg_send![*self.ns_window, performWindowDragWithEvent: event]; diff --git a/src/platform_impl/web/window.rs b/src/platform_impl/web/window.rs index d886711db3..9bbf5d81cc 100644 --- a/src/platform_impl/web/window.rs +++ b/src/platform_impl/web/window.rs @@ -223,7 +223,7 @@ impl Window { } #[inline] - pub fn set_drag_window(&self) -> Result<(), ExternalError> { + pub fn begin_drag(&self) -> Result<(), ExternalError> { Err(ExternalError::NotSupported(NotSupportedError::new())) } diff --git a/src/platform_impl/windows/window.rs b/src/platform_impl/windows/window.rs index eaeef5cde7..fc5710540b 100644 --- a/src/platform_impl/windows/window.rs +++ b/src/platform_impl/windows/window.rs @@ -358,7 +358,7 @@ impl Window { } #[inline] - pub fn set_drag_window(&self) -> Result<(), ExternalError> { + pub fn begin_drag(&self) -> Result<(), ExternalError> { unsafe { let points = { let mut pos = mem::zeroed(); diff --git a/src/window.rs b/src/window.rs index b57e2cc897..3e19e11dfa 100644 --- a/src/window.rs +++ b/src/window.rs @@ -776,8 +776,8 @@ impl Window { /// - **macOS:** May prevent the button release event to be triggered. /// - **Wayland / iOS / Android / Web:** Always returns an [`ExternalError::NotSupported`]. #[inline] - pub fn set_drag_window(&self) -> Result<(), ExternalError> { - self.window.set_drag_window() + pub fn begin_drag(&self) -> Result<(), ExternalError> { + self.window.begin_drag() } } From bd7d4c8fed185e9be04554113c6b72308508b7c0 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Sun, 7 Feb 2021 20:12:31 +0100 Subject: [PATCH 15/23] Improve example. --- examples/drag_window.rs | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/examples/drag_window.rs b/examples/drag_window.rs index c72304dde9..a38e40a789 100644 --- a/examples/drag_window.rs +++ b/examples/drag_window.rs @@ -4,7 +4,7 @@ use winit::{ ElementState, Event, KeyboardInput, MouseButton, StartCause, VirtualKeyCode, WindowEvent, }, event_loop::{ControlFlow, EventLoop}, - window::WindowBuilder, + window::{Window, WindowBuilder, WindowId}, }; fn main() { @@ -15,6 +15,7 @@ fn main() { let window_2 = WindowBuilder::new().build(&event_loop).unwrap(); let mut switched = false; + let mut entered_id = window_2.id(); event_loop.run(move |event, _, control_flow| match event { Event::NewEvents(StartCause::Init) => { @@ -38,15 +39,8 @@ fn main() { window.begin_drag().unwrap() } WindowEvent::CursorEntered { .. } => { - let (drag_target, other) = if (window_id == window_1.id() && switched) - || (window_id == window_2.id() && !switched) - { - (&window_2, &window_1) - } else { - (&window_1, &window_2) - }; - drag_target.set_title("drag target"); - other.set_title("winit window"); + entered_id = window_id; + name_windows(entered_id, switched, &window_1, &window_2) } WindowEvent::KeyboardInput { input: @@ -58,6 +52,7 @@ fn main() { .. } => { switched = !switched; + name_windows(entered_id, switched, &window_1, &window_2); println!("Switched!") } _ => (), @@ -65,3 +60,14 @@ fn main() { _ => (), }); } + +fn name_windows(window_id: WindowId, switched: bool, window_1: &Window, window_2: &Window) { + let (drag_target, other) = + if (window_id == window_1.id() && switched) || (window_id == window_2.id() && !switched) { + (&window_2, &window_1) + } else { + (&window_1, &window_2) + }; + drag_target.set_title("drag target"); + other.set_title("winit window"); +} From aae5d18a1bdbf0788d5285f8147bac0585b68810 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Wed, 24 Feb 2021 17:11:48 +0100 Subject: [PATCH 16/23] Fix CHANGELOG. --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 82e0d7ffcb..8a8ffa93df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,6 @@ - On Android, bump `ndk` and `ndk-glue` to 0.3: use predefined constants for event `ident`. - 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 `Window::set_drag_window`. Implemented on Windows, macOS, X11 and Wayland. - Added `Window::set_drag_window`. Implemented on Windows, macOS and X11. - Added `Window::begin_drag`. Implemented on Windows, macOS and X11. From 6e2083902ba7be0507a77670ea79ee7cdc407eea Mon Sep 17 00:00:00 2001 From: daxpedda Date: Wed, 3 Mar 2021 20:15:30 +0100 Subject: [PATCH 17/23] Fix CHANGELOG. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Markus Røyset --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a8ffa93df..a5c2e78e60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,6 @@ - On Android, bump `ndk` and `ndk-glue` to 0.3: use predefined constants for event `ident`. - 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 `Window::set_drag_window`. Implemented on Windows, macOS and X11. - Added `Window::begin_drag`. Implemented on Windows, macOS and X11. # 0.24.0 (2020-12-09) From 5ec7722cb5228c4181a5013844c7b8aa2e8ce8aa Mon Sep 17 00:00:00 2001 From: daxpedda Date: Thu, 4 Mar 2021 20:38:33 +0100 Subject: [PATCH 18/23] Rename to `drag_window`. --- CHANGELOG.md | 2 +- examples/drag_window.rs | 2 +- src/platform_impl/android/mod.rs | 2 +- src/platform_impl/ios/window.rs | 2 +- src/platform_impl/linux/mod.rs | 2 +- src/platform_impl/linux/x11/window.rs | 2 +- src/platform_impl/macos/window.rs | 2 +- src/platform_impl/web/window.rs | 2 +- src/platform_impl/windows/window.rs | 2 +- src/window.rs | 4 ++-- 10 files changed, 11 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a5c2e78e60..bae416e7dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ - On Android, bump `ndk` and `ndk-glue` to 0.3: use predefined constants for event `ident`. - 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 `Window::begin_drag`. Implemented on Windows, macOS and X11. +- Added `Window::drag_window`. Implemented on Windows, macOS and X11. # 0.24.0 (2020-12-09) diff --git a/examples/drag_window.rs b/examples/drag_window.rs index a38e40a789..a408c7c722 100644 --- a/examples/drag_window.rs +++ b/examples/drag_window.rs @@ -36,7 +36,7 @@ fn main() { &window_1 }; - window.begin_drag().unwrap() + window.drag_window().unwrap() } WindowEvent::CursorEntered { .. } => { entered_id = window_id; diff --git a/src/platform_impl/android/mod.rs b/src/platform_impl/android/mod.rs index 87beb40e6f..543bca1b03 100644 --- a/src/platform_impl/android/mod.rs +++ b/src/platform_impl/android/mod.rs @@ -556,7 +556,7 @@ impl Window { pub fn set_cursor_visible(&self, _: bool) {} - pub fn begin_drag(&self) -> Result<(), error::ExternalError> { + pub fn drag_window(&self) -> Result<(), error::ExternalError> { Err(error::ExternalError::NotSupported( error::NotSupportedError::new(), )) diff --git a/src/platform_impl/ios/window.rs b/src/platform_impl/ios/window.rs index 036340ac54..1f6e559169 100644 --- a/src/platform_impl/ios/window.rs +++ b/src/platform_impl/ios/window.rs @@ -182,7 +182,7 @@ impl Inner { debug!("`Window::set_cursor_visible` is ignored on iOS") } - pub fn begin_drag(&self) -> Result<(), ExternalError> { + pub fn drag_window(&self) -> Result<(), ExternalError> { Err(ExternalError::NotSupported(NotSupportedError::new())) } diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index 9f90ea0426..746b563a92 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -359,7 +359,7 @@ impl Window { } #[inline] - pub fn begin_drag(&self) -> Result<(), ExternalError> { + pub fn drag_window(&self) -> Result<(), ExternalError> { match self { #[cfg(feature = "x11")] &Window::X(ref w) => w.begin_drag(), diff --git a/src/platform_impl/linux/x11/window.rs b/src/platform_impl/linux/x11/window.rs index fe694a22e0..b4ca7c409c 100644 --- a/src/platform_impl/linux/x11/window.rs +++ b/src/platform_impl/linux/x11/window.rs @@ -1276,7 +1276,7 @@ impl UnownedWindow { self.set_cursor_position_physical(x, y) } - pub fn begin_drag(&self) -> Result<(), ExternalError> { + pub fn drag_window(&self) -> Result<(), ExternalError> { let pointer = self .xconn .query_pointer(self.xwindow, util::VIRTUAL_CORE_POINTER) diff --git a/src/platform_impl/macos/window.rs b/src/platform_impl/macos/window.rs index 2ccd4be3b9..86bc0acae3 100644 --- a/src/platform_impl/macos/window.rs +++ b/src/platform_impl/macos/window.rs @@ -637,7 +637,7 @@ impl UnownedWindow { } #[inline] - pub fn begin_drag(&self) -> Result<(), ExternalError> { + pub fn drag_window(&self) -> Result<(), ExternalError> { unsafe { let event: id = msg_send![NSApp(), currentEvent]; let _: () = msg_send![*self.ns_window, performWindowDragWithEvent: event]; diff --git a/src/platform_impl/web/window.rs b/src/platform_impl/web/window.rs index 9bbf5d81cc..a51210caa6 100644 --- a/src/platform_impl/web/window.rs +++ b/src/platform_impl/web/window.rs @@ -223,7 +223,7 @@ impl Window { } #[inline] - pub fn begin_drag(&self) -> Result<(), ExternalError> { + pub fn drag_window(&self) -> Result<(), ExternalError> { Err(ExternalError::NotSupported(NotSupportedError::new())) } diff --git a/src/platform_impl/windows/window.rs b/src/platform_impl/windows/window.rs index fc5710540b..775fa7b402 100644 --- a/src/platform_impl/windows/window.rs +++ b/src/platform_impl/windows/window.rs @@ -358,7 +358,7 @@ impl Window { } #[inline] - pub fn begin_drag(&self) -> Result<(), ExternalError> { + pub fn drag_window(&self) -> Result<(), ExternalError> { unsafe { let points = { let mut pos = mem::zeroed(); diff --git a/src/window.rs b/src/window.rs index 3e19e11dfa..0e7fb22dce 100644 --- a/src/window.rs +++ b/src/window.rs @@ -776,8 +776,8 @@ impl Window { /// - **macOS:** May prevent the button release event to be triggered. /// - **Wayland / iOS / Android / Web:** Always returns an [`ExternalError::NotSupported`]. #[inline] - pub fn begin_drag(&self) -> Result<(), ExternalError> { - self.window.begin_drag() + pub fn drag_window(&self) -> Result<(), ExternalError> { + self.window.drag_window() } } From 8f49e379a38a05d000f56c3d803f084ae15f93b5 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Thu, 4 Mar 2021 20:43:00 +0100 Subject: [PATCH 19/23] Fix typo. --- src/platform_impl/linux/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index 746b563a92..a5f153898d 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -362,7 +362,7 @@ impl Window { pub fn drag_window(&self) -> Result<(), ExternalError> { match self { #[cfg(feature = "x11")] - &Window::X(ref w) => w.begin_drag(), + &Window::X(ref w) => w.drag_window(), #[cfg(feature = "wayland")] _ => Err(ExternalError::NotSupported(NotSupportedError::new())), } From cf90ed540bc784772b1499fb777929b549f66856 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Thu, 4 Mar 2021 22:20:47 +0100 Subject: [PATCH 20/23] Re-introduce Wayland implementation. --- CHANGELOG.md | 2 +- Cargo.toml | 2 +- FEATURES.md | 2 +- src/platform_impl/linux/mod.rs | 7 +------ .../linux/wayland/seat/pointer/handlers.rs | 4 ++++ .../linux/wayland/seat/pointer/mod.rs | 17 ++++++++++++++++- src/platform_impl/linux/wayland/window/mod.rs | 12 ++++++++++++ src/platform_impl/linux/wayland/window/shim.rs | 12 ++++++++++++ src/window.rs | 3 ++- 9 files changed, 50 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bae416e7dd..b9896f9b08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ - On Android, bump `ndk` and `ndk-glue` to 0.3: use predefined constants for event `ident`. - 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 `Window::drag_window`. Implemented on Windows, macOS and X11. +- Added `Window::drag_window`. Implemented on Windows, macOS, X11 and Wayland. # 0.24.0 (2020-12-09) diff --git a/Cargo.toml b/Cargo.toml index 64b1bee10e..930aeb464a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -85,7 +85,7 @@ features = [ [target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))'.dependencies] wayland-client = { version = "0.28", features = [ "dlopen"] , optional = true } -sctk = { package = "smithay-client-toolkit", version = "0.12", optional = true } +sctk = { package = "smithay-client-toolkit", version = "0.13", optional = true } mio = { version = "0.6", optional = true } mio-extras = { version = "2.0", optional = true } x11-dl = { version = "2.18.5", optional = true } diff --git a/FEATURES.md b/FEATURES.md index 8d9c1e4a43..8bea2043fb 100644 --- a/FEATURES.md +++ b/FEATURES.md @@ -209,7 +209,7 @@ Legend: |Raw Device Events |▢[#750] |▢[#750] |▢[#750] |❌ |❌ |❌ |❓ | |Gamepad/Joystick events |❌[#804] |❌ |❌ |❌ |❌ |❌ |❓ | |Device movement events |❓ |❓ |❓ |❓ |❌ |❌ |❓ | -|Drag window with cursor |✔️ |✔️ |✔️ |❌ |**N/A**|**N/A**|**N/A** | +|Drag window with cursor |✔️ |✔️ |✔️ |✔️ |**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. diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index a5f153898d..480fc8af84 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -360,12 +360,7 @@ impl Window { #[inline] pub fn drag_window(&self) -> Result<(), ExternalError> { - match self { - #[cfg(feature = "x11")] - &Window::X(ref w) => w.drag_window(), - #[cfg(feature = "wayland")] - _ => Err(ExternalError::NotSupported(NotSupportedError::new())), - } + x11_or_wayland!(match self; Window(window) => window.drag_window()) } #[inline] diff --git a/src/platform_impl/linux/wayland/seat/pointer/handlers.rs b/src/platform_impl/linux/wayland/seat/pointer/handlers.rs index 7d291713fa..62b2114321 100644 --- a/src/platform_impl/linux/wayland/seat/pointer/handlers.rs +++ b/src/platform_impl/linux/wayland/seat/pointer/handlers.rs @@ -4,6 +4,7 @@ use std::cell::RefCell; use std::rc::Rc; use sctk::reexports::client::protocol::wl_pointer::{self, Event as PointerEvent}; +use sctk::reexports::client::protocol::wl_seat::WlSeat; use sctk::reexports::protocols::unstable::relative_pointer::v1::client::zwp_relative_pointer_v1::Event as RelativePointerEvent; use sctk::seat::pointer::ThemedPointer; @@ -28,6 +29,7 @@ pub(super) fn handle_pointer( event: PointerEvent, pointer_data: &Rc>, winit_state: &mut WinitState, + seat: WlSeat, ) { let event_sink = &mut winit_state.event_sink; let mut pointer_data = pointer_data.borrow_mut(); @@ -59,6 +61,7 @@ pub(super) fn handle_pointer( confined_pointer: Rc::downgrade(&pointer_data.confined_pointer), pointer_constraints: pointer_data.pointer_constraints.clone(), latest_serial: pointer_data.latest_serial.clone(), + seat, }; window_handle.pointer_entered(winit_pointer); @@ -101,6 +104,7 @@ pub(super) fn handle_pointer( confined_pointer: Rc::downgrade(&pointer_data.confined_pointer), pointer_constraints: pointer_data.pointer_constraints.clone(), latest_serial: pointer_data.latest_serial.clone(), + seat, }; window_handle.pointer_left(winit_pointer); diff --git a/src/platform_impl/linux/wayland/seat/pointer/mod.rs b/src/platform_impl/linux/wayland/seat/pointer/mod.rs index 5debc8cbcf..7ae1f251b3 100644 --- a/src/platform_impl/linux/wayland/seat/pointer/mod.rs +++ b/src/platform_impl/linux/wayland/seat/pointer/mod.rs @@ -13,6 +13,7 @@ use sctk::reexports::protocols::unstable::pointer_constraints::v1::client::zwp_p use sctk::reexports::protocols::unstable::pointer_constraints::v1::client::zwp_confined_pointer_v1::ZwpConfinedPointerV1; use sctk::seat::pointer::{ThemeManager, ThemedPointer}; +use sctk::window::{ConceptFrame, Window}; use crate::event::ModifiersState; use crate::platform_impl::wayland::event_loop::WinitState; @@ -35,6 +36,9 @@ pub struct WinitPointer { /// Latest observed serial in pointer events. latest_serial: Rc>, + + /// Seat. + seat: WlSeat, } impl PartialEq for WinitPointer { @@ -144,6 +148,10 @@ impl WinitPointer { confined_pointer.destroy(); } } + + pub fn drag_window(&self, window: &Window) { + window.start_interactive_move(&self.seat, self.latest_serial.get()); + } } /// A pointer wrapper for easy releasing and managing pointers. @@ -172,11 +180,18 @@ impl Pointers { pointer_constraints.clone(), modifiers_state, ))); + let pointer_seat = seat.detach(); let pointer = theme_manager.theme_pointer_with_impl( seat, move |event, pointer, mut dispatch_data| { let winit_state = dispatch_data.get::().unwrap(); - handlers::handle_pointer(pointer, event, &pointer_data, winit_state); + handlers::handle_pointer( + pointer, + event, + &pointer_data, + winit_state, + pointer_seat.clone(), + ); }, ); diff --git a/src/platform_impl/linux/wayland/window/mod.rs b/src/platform_impl/linux/wayland/window/mod.rs index d51f47a7a2..5f59651edb 100644 --- a/src/platform_impl/linux/wayland/window/mod.rs +++ b/src/platform_impl/linux/wayland/window/mod.rs @@ -586,6 +586,18 @@ impl Window { Err(ExternalError::NotSupported(NotSupportedError::new())) } + #[inline] + pub fn drag_window(&self) -> Result<(), ExternalError> { + let drag_window_request = WindowRequest::DragWindow; + self.window_requests + .lock() + .unwrap() + .push(drag_window_request); + self.event_loop_awakener.ping(); + + Ok(()) + } + #[inline] pub fn set_ime_position(&self, position: Position) { let scale_factor = self.scale_factor() as f64; diff --git a/src/platform_impl/linux/wayland/window/shim.rs b/src/platform_impl/linux/wayland/window/shim.rs index 59cf921a59..9397559fa1 100644 --- a/src/platform_impl/linux/wayland/window/shim.rs +++ b/src/platform_impl/linux/wayland/window/shim.rs @@ -34,6 +34,9 @@ pub enum WindowRequest { /// Grab cursor. GrabCursor(bool), + /// Drag window. + DragWindow, + /// Maximize the window. Maximize(bool), @@ -268,6 +271,12 @@ impl WindowHandle { pointer.set_cursor(Some(cursor_icon)); } } + + pub fn drag_window(&self) { + for pointer in self.pointers.iter() { + pointer.drag_window(&self.window); + } + } } #[inline] @@ -299,6 +308,9 @@ pub fn handle_window_requests(winit_state: &mut WinitState) { WindowRequest::GrabCursor(grab) => { window_handle.set_cursor_grab(grab); } + WindowRequest::DragWindow => { + window_handle.drag_window(); + } WindowRequest::Maximize(maximize) => { if maximize { window_handle.window.set_maximized(); diff --git a/src/window.rs b/src/window.rs index 0e7fb22dce..b96f3f7329 100644 --- a/src/window.rs +++ b/src/window.rs @@ -773,8 +773,9 @@ impl Window { /// ## Platform-specific /// /// - **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. - /// - **Wayland / iOS / Android / Web:** Always returns an [`ExternalError::NotSupported`]. + /// - **iOS / Android / Web:** Always returns an [`ExternalError::NotSupported`]. #[inline] pub fn drag_window(&self) -> Result<(), ExternalError> { self.window.drag_window() From 834057256a457758fd540c900fcf1873cb0c8f04 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Thu, 4 Mar 2021 23:06:45 +0100 Subject: [PATCH 21/23] Fixing Wayland build. --- .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 1c35451427..962c7c27e7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -71,9 +71,9 @@ jobs: rust-version: ${{ matrix.rust_version }}${{ matrix.platform.host }} targets: ${{ matrix.platform.target }} - - name: Install GCC Multilib + - name: Install GCC Multilib & fontconfig 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 update && sudo apt-get install gcc-multilib libfontconfig-dev - name: Install cargo-apk if: contains(matrix.platform.target, 'android') run: cargo install cargo-apk From 1b79efd8ebc43a8f4fa5f143d830799b1009e080 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Fri, 5 Mar 2021 10:46:09 +0100 Subject: [PATCH 22/23] Fixing Wayland build. --- .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 962c7c27e7..f69ff143ad 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -73,7 +73,7 @@ jobs: - name: Install GCC Multilib & fontconfig if: (matrix.platform.os == 'ubuntu-latest') && contains(matrix.platform.target, 'i686') - run: sudo apt-get update && sudo apt-get install gcc-multilib libfontconfig-dev + run: sudo apt-get update && sudo apt-get install gcc-multilib g++-multilib - name: Install cargo-apk if: contains(matrix.platform.target, 'android') run: cargo install cargo-apk From 65c5e066a2a45098e6efc79f018a504dcfaf9c8b Mon Sep 17 00:00:00 2001 From: daxpedda Date: Fri, 5 Mar 2021 18:46:34 +0100 Subject: [PATCH 23/23] Move SCTK to 0.12.3. --- .github/workflows/ci.yml | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f69ff143ad..1c35451427 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -71,9 +71,9 @@ jobs: rust-version: ${{ matrix.rust_version }}${{ matrix.platform.host }} targets: ${{ matrix.platform.target }} - - name: Install GCC Multilib & fontconfig + - 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 g++-multilib + run: sudo apt-get update && sudo apt-get install gcc-multilib - name: Install cargo-apk if: contains(matrix.platform.target, 'android') run: cargo install cargo-apk diff --git a/Cargo.toml b/Cargo.toml index 930aeb464a..2db7219d41 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -85,7 +85,7 @@ features = [ [target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))'.dependencies] wayland-client = { version = "0.28", features = [ "dlopen"] , optional = true } -sctk = { package = "smithay-client-toolkit", version = "0.13", optional = true } +sctk = { package = "smithay-client-toolkit", version = "0.12.3", optional = true } mio = { version = "0.6", optional = true } mio-extras = { version = "2.0", optional = true } x11-dl = { version = "2.18.5", optional = true }