commit
719295931b
|
@ -8,14 +8,14 @@ use rand;
|
||||||
|
|
||||||
use smithay::{
|
use smithay::{
|
||||||
reexports::wayland_server::{
|
reexports::wayland_server::{
|
||||||
protocol::{wl_buffer, wl_shell_surface, wl_surface},
|
protocol::{wl_buffer, wl_pointer::ButtonState, wl_shell_surface, wl_surface},
|
||||||
Display,
|
Display,
|
||||||
},
|
},
|
||||||
utils::Rectangle,
|
utils::Rectangle,
|
||||||
wayland::{
|
wayland::{
|
||||||
compositor::{compositor_init, CompositorToken, RegionAttributes, SurfaceAttributes, SurfaceEvent},
|
compositor::{compositor_init, CompositorToken, RegionAttributes, SurfaceAttributes, SurfaceEvent},
|
||||||
data_device::DnDIconRole,
|
data_device::DnDIconRole,
|
||||||
seat::CursorImageRole,
|
seat::{AxisFrame, CursorImageRole, GrabStartData, PointerGrab, PointerInnerHandle, Seat},
|
||||||
shell::{
|
shell::{
|
||||||
legacy::{
|
legacy::{
|
||||||
wl_shell_init, ShellRequest, ShellState as WlShellState, ShellSurfaceKind, ShellSurfaceRole,
|
wl_shell_init, ShellRequest, ShellState as WlShellState, ShellSurfaceKind, ShellSurfaceRole,
|
||||||
|
@ -25,6 +25,7 @@ use smithay::{
|
||||||
XdgSurfaceRole,
|
XdgSurfaceRole,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
SERIAL_COUNTER as SCOUNTER,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -45,6 +46,56 @@ pub type MyWindowMap = WindowMap<
|
||||||
|
|
||||||
pub type MyCompositorToken = CompositorToken<Roles>;
|
pub type MyCompositorToken = CompositorToken<Roles>;
|
||||||
|
|
||||||
|
struct MoveSurfaceGrab {
|
||||||
|
start_data: GrabStartData,
|
||||||
|
window_map: Rc<RefCell<MyWindowMap>>,
|
||||||
|
toplevel: SurfaceKind<Roles>,
|
||||||
|
initial_window_location: (i32, i32),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PointerGrab for MoveSurfaceGrab {
|
||||||
|
fn motion(
|
||||||
|
&mut self,
|
||||||
|
_handle: &mut PointerInnerHandle<'_>,
|
||||||
|
location: (f64, f64),
|
||||||
|
_focus: Option<(wl_surface::WlSurface, (f64, f64))>,
|
||||||
|
_serial: u32,
|
||||||
|
_time: u32,
|
||||||
|
) {
|
||||||
|
let dx = location.0 - self.start_data.location.0;
|
||||||
|
let dy = location.1 - self.start_data.location.1;
|
||||||
|
let new_window_x = (self.initial_window_location.0 as f64 + dx) as i32;
|
||||||
|
let new_window_y = (self.initial_window_location.1 as f64 + dy) as i32;
|
||||||
|
|
||||||
|
self.window_map
|
||||||
|
.borrow_mut()
|
||||||
|
.set_location(&self.toplevel, (new_window_x, new_window_y));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn button(
|
||||||
|
&mut self,
|
||||||
|
handle: &mut PointerInnerHandle<'_>,
|
||||||
|
button: u32,
|
||||||
|
state: ButtonState,
|
||||||
|
serial: u32,
|
||||||
|
time: u32,
|
||||||
|
) {
|
||||||
|
handle.button(button, state, serial, time);
|
||||||
|
if handle.current_pressed().is_empty() {
|
||||||
|
// No more buttons are pressed, release the grab.
|
||||||
|
handle.unset_grab(serial, time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn axis(&mut self, handle: &mut PointerInnerHandle<'_>, details: AxisFrame) {
|
||||||
|
handle.axis(details)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn start_data(&self) -> &GrabStartData {
|
||||||
|
&self.start_data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn init_shell(
|
pub fn init_shell(
|
||||||
display: &mut Display,
|
display: &mut Display,
|
||||||
log: ::slog::Logger,
|
log: ::slog::Logger,
|
||||||
|
@ -100,6 +151,47 @@ pub fn init_shell(
|
||||||
position: (10, 10),
|
position: (10, 10),
|
||||||
serial: 42,
|
serial: 42,
|
||||||
}),
|
}),
|
||||||
|
XdgRequest::Move {
|
||||||
|
surface,
|
||||||
|
seat,
|
||||||
|
serial,
|
||||||
|
} => {
|
||||||
|
let seat = Seat::from_resource(&seat).unwrap();
|
||||||
|
// TODO: touch move.
|
||||||
|
let pointer = seat.get_pointer().unwrap();
|
||||||
|
|
||||||
|
// Check that this surface has a click grab.
|
||||||
|
if !pointer.has_grab(serial) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let start_data = pointer.grab_start_data().unwrap();
|
||||||
|
|
||||||
|
// If the focus was for a different surface, ignore the request.
|
||||||
|
if start_data.focus.is_none()
|
||||||
|
|| !start_data
|
||||||
|
.focus
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.0
|
||||||
|
.as_ref()
|
||||||
|
.same_client_as(surface.get_surface().unwrap().as_ref())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let toplevel = SurfaceKind::Xdg(surface);
|
||||||
|
let initial_window_location = xdg_window_map.borrow().location(&toplevel).unwrap();
|
||||||
|
|
||||||
|
let grab = MoveSurfaceGrab {
|
||||||
|
start_data,
|
||||||
|
window_map: xdg_window_map.clone(),
|
||||||
|
toplevel,
|
||||||
|
initial_window_location,
|
||||||
|
};
|
||||||
|
|
||||||
|
pointer.set_grab(grab, serial);
|
||||||
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
log.clone(),
|
log.clone(),
|
||||||
|
@ -111,11 +203,11 @@ pub fn init_shell(
|
||||||
display,
|
display,
|
||||||
compositor_token,
|
compositor_token,
|
||||||
move |req: ShellRequest<_>| {
|
move |req: ShellRequest<_>| {
|
||||||
if let ShellRequest::SetKind {
|
match req {
|
||||||
|
ShellRequest::SetKind {
|
||||||
surface,
|
surface,
|
||||||
kind: ShellSurfaceKind::Toplevel,
|
kind: ShellSurfaceKind::Toplevel,
|
||||||
} = req
|
} => {
|
||||||
{
|
|
||||||
// place the window at a random location in the [0;800]x[0;800] square
|
// place the window at a random location in the [0;800]x[0;800] square
|
||||||
use rand::distributions::{Distribution, Uniform};
|
use rand::distributions::{Distribution, Uniform};
|
||||||
let range = Uniform::new(0, 800);
|
let range = Uniform::new(0, 800);
|
||||||
|
@ -127,6 +219,49 @@ pub fn init_shell(
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.insert(SurfaceKind::Wl(surface), (x, y));
|
.insert(SurfaceKind::Wl(surface), (x, y));
|
||||||
}
|
}
|
||||||
|
ShellRequest::Move {
|
||||||
|
surface,
|
||||||
|
seat,
|
||||||
|
serial,
|
||||||
|
} => {
|
||||||
|
let seat = Seat::from_resource(&seat).unwrap();
|
||||||
|
// TODO: touch move.
|
||||||
|
let pointer = seat.get_pointer().unwrap();
|
||||||
|
|
||||||
|
// Check that this surface has a click grab.
|
||||||
|
if !pointer.has_grab(serial) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let start_data = pointer.grab_start_data().unwrap();
|
||||||
|
|
||||||
|
// If the focus was for a different surface, ignore the request.
|
||||||
|
if start_data.focus.is_none()
|
||||||
|
|| !start_data
|
||||||
|
.focus
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.0
|
||||||
|
.as_ref()
|
||||||
|
.same_client_as(surface.get_surface().unwrap().as_ref())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let toplevel = SurfaceKind::Wl(surface);
|
||||||
|
let initial_window_location = shell_window_map.borrow().location(&toplevel).unwrap();
|
||||||
|
|
||||||
|
let grab = MoveSurfaceGrab {
|
||||||
|
start_data,
|
||||||
|
window_map: shell_window_map.clone(),
|
||||||
|
toplevel,
|
||||||
|
initial_window_location,
|
||||||
|
};
|
||||||
|
|
||||||
|
pointer.set_grab(grab, serial);
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
},
|
},
|
||||||
log.clone(),
|
log.clone(),
|
||||||
);
|
);
|
||||||
|
|
|
@ -33,6 +33,15 @@ where
|
||||||
Kind::Wl(ref t) => t.get_surface(),
|
Kind::Wl(ref t) => t.get_surface(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Do this handle and the other one actually refer to the same toplevel surface?
|
||||||
|
pub fn equals(&self, other: &Self) -> bool {
|
||||||
|
match (self, other) {
|
||||||
|
(Kind::Xdg(a), Kind::Xdg(b)) => a.equals(b),
|
||||||
|
(Kind::Wl(a), Kind::Wl(b)) => a.equals(b),
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Window<R> {
|
struct Window<R> {
|
||||||
|
@ -225,4 +234,20 @@ where
|
||||||
pub fn clear(&mut self) {
|
pub fn clear(&mut self) {
|
||||||
self.windows.clear();
|
self.windows.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the location of the toplevel, if it exists.
|
||||||
|
pub fn location(&self, toplevel: &Kind<R>) -> Option<(i32, i32)> {
|
||||||
|
self.windows
|
||||||
|
.iter()
|
||||||
|
.find(|w| w.toplevel.equals(toplevel))
|
||||||
|
.map(|w| w.location)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the location of the toplevel, if it exists.
|
||||||
|
pub fn set_location(&mut self, toplevel: &Kind<R>, location: (i32, i32)) {
|
||||||
|
if let Some(w) = self.windows.iter_mut().find(|w| w.toplevel.equals(toplevel)) {
|
||||||
|
w.location = location;
|
||||||
|
w.self_update(self.ctoken, &self.get_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,12 +8,13 @@ use wayland_server::{
|
||||||
|
|
||||||
use crate::wayland::{
|
use crate::wayland::{
|
||||||
compositor::{roles::Role, CompositorToken},
|
compositor::{roles::Role, CompositorToken},
|
||||||
seat::{AxisFrame, PointerGrab, PointerInnerHandle, Seat},
|
seat::{AxisFrame, GrabStartData, PointerGrab, PointerInnerHandle, Seat},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{with_source_metadata, DataDeviceData, DnDIconRole, SeatData};
|
use super::{with_source_metadata, DataDeviceData, DnDIconRole, SeatData};
|
||||||
|
|
||||||
pub(crate) struct DnDGrab<R> {
|
pub(crate) struct DnDGrab<R> {
|
||||||
|
start_data: GrabStartData,
|
||||||
data_source: Option<wl_data_source::WlDataSource>,
|
data_source: Option<wl_data_source::WlDataSource>,
|
||||||
current_focus: Option<wl_surface::WlSurface>,
|
current_focus: Option<wl_surface::WlSurface>,
|
||||||
pending_offers: Vec<wl_data_offer::WlDataOffer>,
|
pending_offers: Vec<wl_data_offer::WlDataOffer>,
|
||||||
|
@ -27,6 +28,7 @@ pub(crate) struct DnDGrab<R> {
|
||||||
|
|
||||||
impl<R: Role<DnDIconRole> + 'static> DnDGrab<R> {
|
impl<R: Role<DnDIconRole> + 'static> DnDGrab<R> {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
|
start_data: GrabStartData,
|
||||||
source: Option<wl_data_source::WlDataSource>,
|
source: Option<wl_data_source::WlDataSource>,
|
||||||
origin: wl_surface::WlSurface,
|
origin: wl_surface::WlSurface,
|
||||||
seat: Seat,
|
seat: Seat,
|
||||||
|
@ -35,6 +37,7 @@ impl<R: Role<DnDIconRole> + 'static> DnDGrab<R> {
|
||||||
callback: Rc<RefCell<dyn FnMut(super::DataDeviceEvent)>>,
|
callback: Rc<RefCell<dyn FnMut(super::DataDeviceEvent)>>,
|
||||||
) -> DnDGrab<R> {
|
) -> DnDGrab<R> {
|
||||||
DnDGrab {
|
DnDGrab {
|
||||||
|
start_data,
|
||||||
data_source: source,
|
data_source: source,
|
||||||
current_focus: None,
|
current_focus: None,
|
||||||
pending_offers: Vec::with_capacity(1),
|
pending_offers: Vec::with_capacity(1),
|
||||||
|
@ -222,6 +225,10 @@ impl<R: Role<DnDIconRole> + 'static> PointerGrab for DnDGrab<R> {
|
||||||
// we just forward the axis events as is
|
// we just forward the axis events as is
|
||||||
handle.axis(details);
|
handle.axis(details);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn start_data(&self) -> &GrabStartData {
|
||||||
|
&self.start_data
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct OfferData {
|
struct OfferData {
|
||||||
|
|
|
@ -69,7 +69,7 @@ use wayland_server::{
|
||||||
|
|
||||||
use crate::wayland::{
|
use crate::wayland::{
|
||||||
compositor::{roles::Role, CompositorToken},
|
compositor::{roles::Role, CompositorToken},
|
||||||
seat::Seat,
|
seat::{GrabStartData, Seat},
|
||||||
};
|
};
|
||||||
|
|
||||||
mod data_source;
|
mod data_source;
|
||||||
|
@ -354,8 +354,13 @@ pub fn set_data_device_selection(seat: &Seat, mime_types: Vec<String>) {
|
||||||
/// You'll receive events generated by the interaction of clients with your
|
/// You'll receive events generated by the interaction of clients with your
|
||||||
/// drag'n'drop in the provided callback. See [`ServerDndEvent`] for details about
|
/// drag'n'drop in the provided callback. See [`ServerDndEvent`] for details about
|
||||||
/// which events can be generated and what response is expected from you to them.
|
/// which events can be generated and what response is expected from you to them.
|
||||||
pub fn start_dnd<C>(seat: &Seat, serial: u32, metadata: SourceMetadata, callback: C)
|
pub fn start_dnd<C>(
|
||||||
where
|
seat: &Seat,
|
||||||
|
serial: u32,
|
||||||
|
start_data: GrabStartData,
|
||||||
|
metadata: SourceMetadata,
|
||||||
|
callback: C,
|
||||||
|
) where
|
||||||
C: FnMut(ServerDndEvent) + 'static,
|
C: FnMut(ServerDndEvent) + 'static,
|
||||||
{
|
{
|
||||||
// TODO: same question as in set_data_device_focus
|
// TODO: same question as in set_data_device_focus
|
||||||
|
@ -366,7 +371,12 @@ where
|
||||||
});
|
});
|
||||||
if let Some(pointer) = seat.get_pointer() {
|
if let Some(pointer) = seat.get_pointer() {
|
||||||
pointer.set_grab(
|
pointer.set_grab(
|
||||||
server_dnd_grab::ServerDnDGrab::new(metadata, seat.clone(), Rc::new(RefCell::new(callback))),
|
server_dnd_grab::ServerDnDGrab::new(
|
||||||
|
start_data,
|
||||||
|
metadata,
|
||||||
|
seat.clone(),
|
||||||
|
Rc::new(RefCell::new(callback)),
|
||||||
|
),
|
||||||
serial,
|
serial,
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
|
@ -466,8 +476,10 @@ where
|
||||||
source: source.clone(),
|
source: source.clone(),
|
||||||
icon: icon.clone(),
|
icon: icon.clone(),
|
||||||
});
|
});
|
||||||
|
let start_data = pointer.grab_start_data().unwrap();
|
||||||
pointer.set_grab(
|
pointer.set_grab(
|
||||||
dnd_grab::DnDGrab::new(
|
dnd_grab::DnDGrab::new(
|
||||||
|
start_data,
|
||||||
source,
|
source,
|
||||||
origin,
|
origin,
|
||||||
seat.clone(),
|
seat.clone(),
|
||||||
|
|
|
@ -7,7 +7,7 @@ use wayland_server::{
|
||||||
NewResource,
|
NewResource,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::wayland::seat::{AxisFrame, PointerGrab, PointerInnerHandle, Seat};
|
use crate::wayland::seat::{AxisFrame, GrabStartData, PointerGrab, PointerInnerHandle, Seat};
|
||||||
|
|
||||||
use super::{DataDeviceData, SeatData};
|
use super::{DataDeviceData, SeatData};
|
||||||
|
|
||||||
|
@ -37,6 +37,7 @@ pub enum ServerDndEvent {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct ServerDnDGrab<C: 'static> {
|
pub(crate) struct ServerDnDGrab<C: 'static> {
|
||||||
|
start_data: GrabStartData,
|
||||||
metadata: super::SourceMetadata,
|
metadata: super::SourceMetadata,
|
||||||
current_focus: Option<wl_surface::WlSurface>,
|
current_focus: Option<wl_surface::WlSurface>,
|
||||||
pending_offers: Vec<wl_data_offer::WlDataOffer>,
|
pending_offers: Vec<wl_data_offer::WlDataOffer>,
|
||||||
|
@ -47,11 +48,13 @@ pub(crate) struct ServerDnDGrab<C: 'static> {
|
||||||
|
|
||||||
impl<C: 'static> ServerDnDGrab<C> {
|
impl<C: 'static> ServerDnDGrab<C> {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
|
start_data: GrabStartData,
|
||||||
metadata: super::SourceMetadata,
|
metadata: super::SourceMetadata,
|
||||||
seat: Seat,
|
seat: Seat,
|
||||||
callback: Rc<RefCell<C>>,
|
callback: Rc<RefCell<C>>,
|
||||||
) -> ServerDnDGrab<C> {
|
) -> ServerDnDGrab<C> {
|
||||||
ServerDnDGrab {
|
ServerDnDGrab {
|
||||||
|
start_data,
|
||||||
metadata,
|
metadata,
|
||||||
current_focus: None,
|
current_focus: None,
|
||||||
pending_offers: Vec::with_capacity(1),
|
pending_offers: Vec::with_capacity(1),
|
||||||
|
@ -212,6 +215,10 @@ where
|
||||||
// we just forward the axis events as is
|
// we just forward the axis events as is
|
||||||
handle.axis(details);
|
handle.axis(details);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn start_data(&self) -> &GrabStartData {
|
||||||
|
&self.start_data
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct OfferData {
|
struct OfferData {
|
||||||
|
|
|
@ -49,7 +49,8 @@ mod pointer;
|
||||||
pub use self::{
|
pub use self::{
|
||||||
keyboard::{keysyms, Error as KeyboardError, KeyboardHandle, Keysym, ModifiersState, XkbConfig},
|
keyboard::{keysyms, Error as KeyboardError, KeyboardHandle, Keysym, ModifiersState, XkbConfig},
|
||||||
pointer::{
|
pointer::{
|
||||||
AxisFrame, CursorImageRole, CursorImageStatus, PointerGrab, PointerHandle, PointerInnerHandle,
|
AxisFrame, CursorImageRole, CursorImageStatus, GrabStartData, PointerGrab, PointerHandle,
|
||||||
|
PointerInnerHandle,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -166,6 +166,15 @@ impl PointerHandle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the start data for the grab, if any.
|
||||||
|
pub fn grab_start_data(&self) -> Option<GrabStartData> {
|
||||||
|
let guard = self.inner.borrow();
|
||||||
|
match &guard.grab {
|
||||||
|
GrabStatus::Active(_, g) => Some(g.start_data().clone()),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Notify that the pointer moved
|
/// Notify that the pointer moved
|
||||||
///
|
///
|
||||||
/// You provide the new location of the pointer, in the form of:
|
/// You provide the new location of the pointer, in the form of:
|
||||||
|
@ -219,6 +228,24 @@ impl PointerHandle {
|
||||||
grab.axis(&mut handle, details);
|
grab.axis(&mut handle, details);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Access the current location of this pointer in the global space
|
||||||
|
pub fn current_location(&self) -> (f64, f64) {
|
||||||
|
self.inner.borrow().location
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Data about the event that started the grab.
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct GrabStartData {
|
||||||
|
/// The focused surface and its location, if any, at the start of the grab.
|
||||||
|
///
|
||||||
|
/// The location coordinates are in the global compositor space.
|
||||||
|
pub focus: Option<(WlSurface, (f64, f64))>,
|
||||||
|
/// The button that initiated the grab.
|
||||||
|
pub button: u32,
|
||||||
|
/// The location of the click that initiated the grab, in the global compositor space.
|
||||||
|
pub location: (f64, f64),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A trait to implement a pointer grab
|
/// A trait to implement a pointer grab
|
||||||
|
@ -257,6 +284,8 @@ pub trait PointerGrab {
|
||||||
);
|
);
|
||||||
/// An axis scroll was reported
|
/// An axis scroll was reported
|
||||||
fn axis(&mut self, handle: &mut PointerInnerHandle<'_>, details: AxisFrame);
|
fn axis(&mut self, handle: &mut PointerInnerHandle<'_>, details: AxisFrame);
|
||||||
|
/// The data about the event that started the grab.
|
||||||
|
fn start_data(&self) -> &GrabStartData;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This inner handle is accessed from inside a pointer grab logic, and directly
|
/// This inner handle is accessed from inside a pointer grab logic, and directly
|
||||||
|
@ -626,18 +655,23 @@ impl PointerGrab for DefaultGrab {
|
||||||
time: u32,
|
time: u32,
|
||||||
) {
|
) {
|
||||||
handle.button(button, state, serial, time);
|
handle.button(button, state, serial, time);
|
||||||
let current_focus = handle.current_focus().cloned();
|
|
||||||
handle.set_grab(
|
handle.set_grab(
|
||||||
serial,
|
serial,
|
||||||
ClickGrab {
|
ClickGrab {
|
||||||
current_focus,
|
start_data: GrabStartData {
|
||||||
pending_focus: None,
|
focus: handle.current_focus().cloned(),
|
||||||
|
button,
|
||||||
|
location: handle.current_location(),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
fn axis(&mut self, handle: &mut PointerInnerHandle<'_>, details: AxisFrame) {
|
fn axis(&mut self, handle: &mut PointerInnerHandle<'_>, details: AxisFrame) {
|
||||||
handle.axis(details);
|
handle.axis(details);
|
||||||
}
|
}
|
||||||
|
fn start_data(&self) -> &GrabStartData {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// A click grab, basic grab started when an user clicks a surface
|
// A click grab, basic grab started when an user clicks a surface
|
||||||
|
@ -646,8 +680,7 @@ impl PointerGrab for DefaultGrab {
|
||||||
// In case the user maintains several simultaneous clicks, release
|
// In case the user maintains several simultaneous clicks, release
|
||||||
// the grab once all are released.
|
// the grab once all are released.
|
||||||
struct ClickGrab {
|
struct ClickGrab {
|
||||||
current_focus: Option<(WlSurface, (f64, f64))>,
|
start_data: GrabStartData,
|
||||||
pending_focus: Option<(WlSurface, (f64, f64))>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PointerGrab for ClickGrab {
|
impl PointerGrab for ClickGrab {
|
||||||
|
@ -655,13 +688,11 @@ impl PointerGrab for ClickGrab {
|
||||||
&mut self,
|
&mut self,
|
||||||
handle: &mut PointerInnerHandle<'_>,
|
handle: &mut PointerInnerHandle<'_>,
|
||||||
location: (f64, f64),
|
location: (f64, f64),
|
||||||
focus: Option<(WlSurface, (f64, f64))>,
|
_focus: Option<(WlSurface, (f64, f64))>,
|
||||||
serial: u32,
|
serial: u32,
|
||||||
time: u32,
|
time: u32,
|
||||||
) {
|
) {
|
||||||
// buffer the future focus, but maintain the current one
|
handle.motion(location, self.start_data.focus.clone(), serial, time);
|
||||||
self.pending_focus = focus;
|
|
||||||
handle.motion(location, self.current_focus.clone(), serial, time);
|
|
||||||
}
|
}
|
||||||
fn button(
|
fn button(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -680,4 +711,7 @@ impl PointerGrab for ClickGrab {
|
||||||
fn axis(&mut self, handle: &mut PointerInnerHandle<'_>, details: AxisFrame) {
|
fn axis(&mut self, handle: &mut PointerInnerHandle<'_>, details: AxisFrame) {
|
||||||
handle.axis(details);
|
handle.axis(details);
|
||||||
}
|
}
|
||||||
|
fn start_data(&self) -> &GrabStartData {
|
||||||
|
&self.start_data
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue