Add dragging window with cursor feature (#1840)
* X11 implementation. * Introduce example. * Wayland implementation. * Windows implementation. * Improve Wayland seat passing. * MacOS implementation. * Correct windows implementation per specification. * Update dependency smithay-client-toolkit from branch to master. * Fixed blocking thread in windows implementation. * Add multi-window example. * Move Wayland to a different PR. * Fix CHANGELOG. * Improve example. Co-authored-by: Markus Røyset <maroider@protonmail.com> * Rename `set_drag_window` to `begin_drag`. * Improve example. * Fix CHANGELOG. * Fix CHANGELOG. Co-authored-by: Markus Røyset <maroider@protonmail.com> * Rename to `drag_window`. * Fix typo. * Re-introduce Wayland implementation. * Fixing Wayland build. * Fixing Wayland build. * Move SCTK to 0.12.3. Co-authored-by: Markus Røyset <maroider@protonmail.com>
This commit is contained in:
parent
4192d04a53
commit
98470393d1
16 changed files with 233 additions and 5 deletions
|
|
@ -358,6 +358,11 @@ impl Window {
|
|||
x11_or_wayland!(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())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn scale_factor(&self) -> f64 {
|
||||
x11_or_wayland!(match self; Window(w) => w.scale_factor() as f64)
|
||||
|
|
|
|||
|
|
@ -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<RefCell<PointerData>>,
|
||||
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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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<Cell<u32>>,
|
||||
|
||||
/// Seat.
|
||||
seat: WlSeat,
|
||||
}
|
||||
|
||||
impl PartialEq for WinitPointer {
|
||||
|
|
@ -144,6 +148,10 @@ impl WinitPointer {
|
|||
confined_pointer.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn drag_window(&self, window: &Window<ConceptFrame>) {
|
||||
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::<WinitState>().unwrap();
|
||||
handlers::handle_pointer(pointer, event, &pointer_data, winit_state);
|
||||
handlers::handle_pointer(
|
||||
pointer,
|
||||
event,
|
||||
&pointer_data,
|
||||
winit_state,
|
||||
pointer_seat.clone(),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -1276,6 +1276,46 @@ impl UnownedWindow {
|
|||
self.set_cursor_position_physical(x, y)
|
||||
}
|
||||
|
||||
pub fn 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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue