Merge pull request #174 from pop-os/pointer-constraints_jammy
Pointer constraints
This commit is contained in:
commit
d051f41de6
16 changed files with 272 additions and 49 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
|
@ -3761,7 +3761,7 @@ checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9"
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smithay"
|
name = "smithay"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
source = "git+https://github.com/smithay//smithay?rev=58d5bdc#58d5bdca0d65b5f45408201770da0ce86b1fa057"
|
source = "git+https://github.com/smithay//smithay?rev=d3e1ef9#d3e1ef9584cb3eadec80e8961552447cb919d6aa"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"appendlist",
|
"appendlist",
|
||||||
"ash",
|
"ash",
|
||||||
|
|
|
||||||
|
|
@ -87,4 +87,4 @@ debug = true
|
||||||
lto = "fat"
|
lto = "fat"
|
||||||
|
|
||||||
[patch."https://github.com/Smithay/smithay.git"]
|
[patch."https://github.com/Smithay/smithay.git"]
|
||||||
smithay = { git = "https://github.com/smithay//smithay", rev = "58d5bdc" }
|
smithay = { git = "https://github.com/smithay//smithay", rev = "d3e1ef9" }
|
||||||
|
|
|
||||||
207
src/input/mod.rs
207
src/input/mod.rs
|
|
@ -41,7 +41,9 @@ use smithay::{
|
||||||
},
|
},
|
||||||
utils::{Logical, Point, Rectangle, Serial, SERIAL_COUNTER},
|
utils::{Logical, Point, Rectangle, Serial, SERIAL_COUNTER},
|
||||||
wayland::{
|
wayland::{
|
||||||
keyboard_shortcuts_inhibit::KeyboardShortcutsInhibitorSeat, seat::WaylandFocus,
|
keyboard_shortcuts_inhibit::KeyboardShortcutsInhibitorSeat,
|
||||||
|
pointer_constraints::{with_pointer_constraint, PointerConstraint},
|
||||||
|
seat::WaylandFocus,
|
||||||
shell::wlr_layer::Layer as WlrLayer,
|
shell::wlr_layer::Layer as WlrLayer,
|
||||||
},
|
},
|
||||||
xwayland::X11Surface,
|
xwayland::X11Surface,
|
||||||
|
|
@ -507,6 +509,70 @@ impl State {
|
||||||
let current_output = seat.active_output();
|
let current_output = seat.active_output();
|
||||||
|
|
||||||
let mut position = seat.get_pointer().unwrap().current_location();
|
let mut position = seat.get_pointer().unwrap().current_location();
|
||||||
|
|
||||||
|
let relative_pos = self
|
||||||
|
.common
|
||||||
|
.shell
|
||||||
|
.map_global_to_space(position, ¤t_output);
|
||||||
|
let overview = self.common.shell.overview_mode();
|
||||||
|
let output_geometry = current_output.geometry();
|
||||||
|
let workspace = self.common.shell.workspaces.active_mut(¤t_output);
|
||||||
|
let under = State::surface_under(
|
||||||
|
position,
|
||||||
|
relative_pos,
|
||||||
|
¤t_output,
|
||||||
|
output_geometry,
|
||||||
|
&self.common.shell.override_redirect_windows,
|
||||||
|
overview.0.clone(),
|
||||||
|
workspace,
|
||||||
|
);
|
||||||
|
|
||||||
|
let ptr = seat.get_pointer().unwrap();
|
||||||
|
|
||||||
|
let mut pointer_locked = false;
|
||||||
|
let mut pointer_confined = false;
|
||||||
|
let mut confine_region = None;
|
||||||
|
if let Some((surface, surface_loc)) = under
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|(target, l)| Some((target.wl_surface()?, l)))
|
||||||
|
{
|
||||||
|
with_pointer_constraint(&surface, &ptr, |constraint| match constraint {
|
||||||
|
Some(constraint) if constraint.is_active() => {
|
||||||
|
// Constraint does not apply if not within region
|
||||||
|
if !constraint.region().map_or(true, |x| {
|
||||||
|
x.contains(ptr.current_location().to_i32_round() - *surface_loc)
|
||||||
|
}) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
match &*constraint {
|
||||||
|
PointerConstraint::Locked(_locked) => {
|
||||||
|
pointer_locked = true;
|
||||||
|
}
|
||||||
|
PointerConstraint::Confined(confine) => {
|
||||||
|
pointer_confined = true;
|
||||||
|
confine_region = confine.region().cloned();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr.relative_motion(
|
||||||
|
self,
|
||||||
|
under.clone(),
|
||||||
|
&RelativeMotionEvent {
|
||||||
|
delta: event.delta(),
|
||||||
|
delta_unaccel: event.delta_unaccel(),
|
||||||
|
utime: event.time(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if pointer_locked {
|
||||||
|
ptr.frame(self);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
position += event.delta();
|
position += event.delta();
|
||||||
|
|
||||||
let output = self
|
let output = self
|
||||||
|
|
@ -516,6 +582,85 @@ impl State {
|
||||||
.find(|output| output.geometry().to_f64().contains(position))
|
.find(|output| output.geometry().to_f64().contains(position))
|
||||||
.cloned()
|
.cloned()
|
||||||
.unwrap_or(current_output.clone());
|
.unwrap_or(current_output.clone());
|
||||||
|
|
||||||
|
let workspace = self.common.shell.workspaces.active_mut(&output);
|
||||||
|
let output_geometry = output.geometry();
|
||||||
|
let new_under = State::surface_under(
|
||||||
|
position,
|
||||||
|
relative_pos,
|
||||||
|
&output,
|
||||||
|
output_geometry,
|
||||||
|
&self.common.shell.override_redirect_windows,
|
||||||
|
overview.0,
|
||||||
|
workspace,
|
||||||
|
);
|
||||||
|
|
||||||
|
position.x = position.x.clamp(
|
||||||
|
output_geometry.loc.x as f64,
|
||||||
|
(output_geometry.loc.x + output_geometry.size.w) as f64,
|
||||||
|
);
|
||||||
|
position.y = position.y.clamp(
|
||||||
|
output_geometry.loc.y as f64,
|
||||||
|
(output_geometry.loc.y + output_geometry.size.h) as f64,
|
||||||
|
);
|
||||||
|
|
||||||
|
// If confined, don't move pointer if it would go outside surface or region
|
||||||
|
if pointer_confined {
|
||||||
|
if let Some((surface, surface_loc)) = &under {
|
||||||
|
if new_under.as_ref().and_then(|(under, _)| under.wl_surface())
|
||||||
|
!= surface.wl_surface()
|
||||||
|
{
|
||||||
|
ptr.frame(self);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if let PointerFocusTarget::Element(element) = surface {
|
||||||
|
//if !element.is_in_input_region(&(position.to_i32_round() - *surface_loc).to_f64()) {
|
||||||
|
if !element.is_in_input_region(&(position - surface_loc.to_f64())) {
|
||||||
|
ptr.frame(self);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(region) = confine_region {
|
||||||
|
if !region.contains(position.to_i32_round() - *surface_loc) {
|
||||||
|
ptr.frame(self);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let serial = SERIAL_COUNTER.next_serial();
|
||||||
|
ptr.motion(
|
||||||
|
self,
|
||||||
|
under,
|
||||||
|
&MotionEvent {
|
||||||
|
location: position,
|
||||||
|
serial,
|
||||||
|
time: event.time_msec(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
ptr.frame(self);
|
||||||
|
|
||||||
|
// If pointer is now in a constraint region, activate it
|
||||||
|
if let Some((under, surface_location)) =
|
||||||
|
new_under.and_then(|(target, loc)| Some((target.wl_surface()?, loc)))
|
||||||
|
{
|
||||||
|
with_pointer_constraint(&under, &ptr, |constraint| match constraint {
|
||||||
|
Some(constraint) if !constraint.is_active() => {
|
||||||
|
let region = match &*constraint {
|
||||||
|
PointerConstraint::Locked(locked) => locked.region(),
|
||||||
|
PointerConstraint::Confined(confined) => confined.region(),
|
||||||
|
};
|
||||||
|
let point =
|
||||||
|
ptr.current_location().to_i32_round() - surface_location;
|
||||||
|
if region.map_or(true, |region| region.contains(point)) {
|
||||||
|
constraint.activate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if output != current_output {
|
if output != current_output {
|
||||||
for session in sessions_for_output(&self.common, ¤t_output) {
|
for session in sessions_for_output(&self.common, ¤t_output) {
|
||||||
session.cursor_leave(&seat, InputType::Pointer);
|
session.cursor_leave(&seat, InputType::Pointer);
|
||||||
|
|
@ -527,28 +672,6 @@ impl State {
|
||||||
|
|
||||||
seat.set_active_output(&output);
|
seat.set_active_output(&output);
|
||||||
}
|
}
|
||||||
let output_geometry = output.geometry();
|
|
||||||
|
|
||||||
position.x = (output_geometry.loc.x as f64)
|
|
||||||
.max(position.x)
|
|
||||||
.min((output_geometry.loc.x + output_geometry.size.w) as f64);
|
|
||||||
position.y = (output_geometry.loc.y as f64)
|
|
||||||
.max(position.y)
|
|
||||||
.min((output_geometry.loc.y + output_geometry.size.h) as f64);
|
|
||||||
|
|
||||||
let serial = SERIAL_COUNTER.next_serial();
|
|
||||||
let relative_pos = self.common.shell.map_global_to_space(position, &output);
|
|
||||||
let overview = self.common.shell.overview_mode();
|
|
||||||
let workspace = self.common.shell.workspaces.active_mut(&output);
|
|
||||||
let under = State::surface_under(
|
|
||||||
position,
|
|
||||||
relative_pos,
|
|
||||||
&output,
|
|
||||||
output_geometry,
|
|
||||||
&self.common.shell.override_redirect_windows,
|
|
||||||
overview.0,
|
|
||||||
workspace,
|
|
||||||
);
|
|
||||||
|
|
||||||
for session in sessions_for_output(&self.common, &output) {
|
for session in sessions_for_output(&self.common, &output) {
|
||||||
if let Some((geometry, offset)) = seat.cursor_geometry(
|
if let Some((geometry, offset)) = seat.cursor_geometry(
|
||||||
|
|
@ -562,27 +685,7 @@ impl State {
|
||||||
session.cursor_info(&seat, InputType::Pointer, geometry, offset);
|
session.cursor_info(&seat, InputType::Pointer, geometry, offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let ptr = seat.get_pointer().unwrap();
|
|
||||||
// Relative motion is sent first to ensure they're part of a `frame`
|
|
||||||
// TODO: Find more correct solution
|
|
||||||
ptr.relative_motion(
|
|
||||||
self,
|
|
||||||
under.clone(),
|
|
||||||
&RelativeMotionEvent {
|
|
||||||
delta: event.delta(),
|
|
||||||
delta_unaccel: event.delta_unaccel(),
|
|
||||||
utime: event.time(),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
ptr.motion(
|
|
||||||
self,
|
|
||||||
under,
|
|
||||||
&MotionEvent {
|
|
||||||
location: position,
|
|
||||||
serial,
|
|
||||||
time: event.time_msec(),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
#[cfg(feature = "debug")]
|
#[cfg(feature = "debug")]
|
||||||
if self.common.seats().position(|x| x == &seat).unwrap() == 0 {
|
if self.common.seats().position(|x| x == &seat).unwrap() == 0 {
|
||||||
let location = if let Some(output) = self.common.shell.outputs.first() {
|
let location = if let Some(output) = self.common.shell.outputs.first() {
|
||||||
|
|
@ -632,7 +735,8 @@ impl State {
|
||||||
session.cursor_info(&seat, InputType::Pointer, geometry, offset);
|
session.cursor_info(&seat, InputType::Pointer, geometry, offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
seat.get_pointer().unwrap().motion(
|
let ptr = seat.get_pointer().unwrap();
|
||||||
|
ptr.motion(
|
||||||
self,
|
self,
|
||||||
under,
|
under,
|
||||||
&MotionEvent {
|
&MotionEvent {
|
||||||
|
|
@ -641,6 +745,7 @@ impl State {
|
||||||
time: event.time_msec(),
|
time: event.time_msec(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
ptr.frame(self);
|
||||||
#[cfg(feature = "debug")]
|
#[cfg(feature = "debug")]
|
||||||
if self.common.seats().position(|x| x == &seat).unwrap() == 0 {
|
if self.common.seats().position(|x| x == &seat).unwrap() == 0 {
|
||||||
let location = if let Some(output) = self.common.shell.outputs.first() {
|
let location = if let Some(output) = self.common.shell.outputs.first() {
|
||||||
|
|
@ -784,7 +889,8 @@ impl State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
seat.get_pointer().unwrap().button(
|
let ptr = seat.get_pointer().unwrap();
|
||||||
|
ptr.button(
|
||||||
self,
|
self,
|
||||||
&ButtonEvent {
|
&ButtonEvent {
|
||||||
button,
|
button,
|
||||||
|
|
@ -793,6 +899,7 @@ impl State {
|
||||||
time: event.time_msec(),
|
time: event.time_msec(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
ptr.frame(self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InputEvent::PointerAxis { event, .. } => {
|
InputEvent::PointerAxis { event, .. } => {
|
||||||
|
|
@ -853,7 +960,9 @@ impl State {
|
||||||
} else if event.source() == AxisSource::Finger {
|
} else if event.source() == AxisSource::Finger {
|
||||||
frame = frame.stop(Axis::Vertical);
|
frame = frame.stop(Axis::Vertical);
|
||||||
}
|
}
|
||||||
seat.get_pointer().unwrap().axis(self, frame);
|
let ptr = seat.get_pointer().unwrap();
|
||||||
|
ptr.axis(self, frame);
|
||||||
|
ptr.frame(self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1200,6 +1309,7 @@ impl State {
|
||||||
time,
|
time,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
ptr.frame(self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
|
|
@ -1236,6 +1346,7 @@ impl State {
|
||||||
time,
|
time,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
ptr.frame(self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
|
|
@ -1275,6 +1386,7 @@ impl State {
|
||||||
time,
|
time,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
ptr.frame(self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1310,6 +1422,7 @@ impl State {
|
||||||
time,
|
time,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
ptr.frame(self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -906,6 +906,13 @@ impl PointerTarget<State> for CosmicMapped {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn frame(&self, seat: &Seat<State>, data: &mut State) {
|
||||||
|
match &self.element {
|
||||||
|
CosmicMappedInternal::Stack(s) => PointerTarget::frame(s, seat, data),
|
||||||
|
CosmicMappedInternal::Window(w) => PointerTarget::frame(w, seat, data),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
fn leave(&self, seat: &Seat<State>, data: &mut State, serial: Serial, time: u32) {
|
fn leave(&self, seat: &Seat<State>, data: &mut State, serial: Serial, time: u32) {
|
||||||
self.last_cursor_position.lock().unwrap().remove(&seat.id());
|
self.last_cursor_position.lock().unwrap().remove(&seat.id());
|
||||||
match &self.element {
|
match &self.element {
|
||||||
|
|
|
||||||
|
|
@ -1169,6 +1169,27 @@ impl PointerTarget<State> for CosmicStack {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn frame(&self, seat: &Seat<State>, data: &mut State) {
|
||||||
|
if let Some((location, serial, time)) = self
|
||||||
|
.0
|
||||||
|
.with_program(|p| p.last_location.lock().unwrap().clone())
|
||||||
|
{
|
||||||
|
self.pointer_leave_if_previous(seat, data, serial, time, location);
|
||||||
|
}
|
||||||
|
|
||||||
|
match self.0.with_program(|p| p.current_focus()) {
|
||||||
|
Focus::Header => PointerTarget::frame(&self.0, seat, data),
|
||||||
|
Focus::Window => self.0.with_program(|p| {
|
||||||
|
PointerTarget::frame(
|
||||||
|
&p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)],
|
||||||
|
seat,
|
||||||
|
data,
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn leave(&self, seat: &Seat<State>, data: &mut State, serial: Serial, time: u32) {
|
fn leave(&self, seat: &Seat<State>, data: &mut State, serial: Serial, time: u32) {
|
||||||
if let Some((location, serial, time)) = self
|
if let Some((location, serial, time)) = self
|
||||||
.0
|
.0
|
||||||
|
|
|
||||||
|
|
@ -757,6 +757,14 @@ impl PointerTarget<State> for CosmicSurface {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn frame(&self, seat: &Seat<State>, data: &mut State) {
|
||||||
|
match self {
|
||||||
|
CosmicSurface::Wayland(window) => PointerTarget::frame(window, seat, data),
|
||||||
|
CosmicSurface::X11(surface) => PointerTarget::frame(surface, seat, data),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn leave(
|
fn leave(
|
||||||
&self,
|
&self,
|
||||||
seat: &Seat<State>,
|
seat: &Seat<State>,
|
||||||
|
|
|
||||||
|
|
@ -585,6 +585,16 @@ impl PointerTarget<State> for CosmicWindow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn frame(&self, seat: &Seat<State>, data: &mut State) {
|
||||||
|
match self.0.with_program(|p| p.current_focus()) {
|
||||||
|
Focus::Header => PointerTarget::frame(&self.0, seat, data),
|
||||||
|
Focus::Window => self
|
||||||
|
.0
|
||||||
|
.with_program(|p| PointerTarget::frame(&p.window, seat, data)),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn leave(&self, seat: &Seat<State>, data: &mut State, serial: Serial, time: u32) {
|
fn leave(&self, seat: &Seat<State>, data: &mut State, serial: Serial, time: u32) {
|
||||||
let previous = self.0.with_program(|p| {
|
let previous = self.0.with_program(|p| {
|
||||||
if let Some(sessions) = p.window.user_data().get::<ScreencopySessions>() {
|
if let Some(sessions) = p.window.user_data().get::<ScreencopySessions>() {
|
||||||
|
|
|
||||||
|
|
@ -190,6 +190,16 @@ impl PointerTarget<State> for PointerFocusTarget {
|
||||||
PointerFocusTarget::ResizeFork(f) => PointerTarget::axis(f, seat, data, frame),
|
PointerFocusTarget::ResizeFork(f) => PointerTarget::axis(f, seat, data, frame),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn frame(&self, seat: &Seat<State>, data: &mut State) {
|
||||||
|
match self {
|
||||||
|
PointerFocusTarget::Element(w) => PointerTarget::frame(w, seat, data),
|
||||||
|
PointerFocusTarget::Fullscreen(w) => PointerTarget::frame(w, seat, data),
|
||||||
|
PointerFocusTarget::LayerSurface(l) => PointerTarget::frame(l, seat, data),
|
||||||
|
PointerFocusTarget::Popup(p) => PointerTarget::frame(p.wl_surface(), seat, data),
|
||||||
|
PointerFocusTarget::OverrideRedirect(s) => PointerTarget::frame(s, seat, data),
|
||||||
|
PointerFocusTarget::ResizeFork(f) => PointerTarget::frame(f, seat, data),
|
||||||
|
}
|
||||||
|
}
|
||||||
fn leave(&self, seat: &Seat<State>, data: &mut State, serial: Serial, time: u32) {
|
fn leave(&self, seat: &Seat<State>, data: &mut State, serial: Serial, time: u32) {
|
||||||
match self {
|
match self {
|
||||||
PointerFocusTarget::Element(w) => PointerTarget::leave(w, seat, data, serial, time),
|
PointerFocusTarget::Element(w) => PointerTarget::leave(w, seat, data, serial, time),
|
||||||
|
|
|
||||||
|
|
@ -152,6 +152,13 @@ impl PointerGrab<State> for ResizeGrab {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn frame(&mut self, data: &mut State, handle: &mut PointerInnerHandle<'_, State>) {
|
||||||
|
match self {
|
||||||
|
ResizeGrab::Floating(grab) => grab.frame(data, handle),
|
||||||
|
ResizeGrab::Tiling(grab) => grab.frame(data, handle),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn gesture_swipe_begin(
|
fn gesture_swipe_begin(
|
||||||
&mut self,
|
&mut self,
|
||||||
data: &mut State,
|
data: &mut State,
|
||||||
|
|
|
||||||
|
|
@ -311,6 +311,10 @@ impl PointerGrab<State> for MoveGrab {
|
||||||
handle.axis(state, details);
|
handle.axis(state, details);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn frame(&mut self, data: &mut State, handle: &mut PointerInnerHandle<'_, State>) {
|
||||||
|
handle.frame(data)
|
||||||
|
}
|
||||||
|
|
||||||
fn gesture_swipe_begin(
|
fn gesture_swipe_begin(
|
||||||
&mut self,
|
&mut self,
|
||||||
data: &mut State,
|
data: &mut State,
|
||||||
|
|
|
||||||
|
|
@ -164,6 +164,10 @@ impl PointerGrab<State> for ResizeSurfaceGrab {
|
||||||
handle.axis(data, details)
|
handle.axis(data, details)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn frame(&mut self, data: &mut State, handle: &mut PointerInnerHandle<'_, State>) {
|
||||||
|
handle.frame(data)
|
||||||
|
}
|
||||||
|
|
||||||
fn gesture_swipe_begin(
|
fn gesture_swipe_begin(
|
||||||
&mut self,
|
&mut self,
|
||||||
data: &mut State,
|
data: &mut State,
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,7 @@ impl PointerTarget<State> for ResizeForkTarget {
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
fn axis(&self, _seat: &Seat<State>, _data: &mut State, _frame: AxisFrame) {}
|
fn axis(&self, _seat: &Seat<State>, _data: &mut State, _frame: AxisFrame) {}
|
||||||
|
fn frame(&self, _seat: &Seat<State>, _data: &mut State) {}
|
||||||
fn gesture_swipe_begin(&self, _: &Seat<State>, _: &mut State, _: &GestureSwipeBeginEvent) {}
|
fn gesture_swipe_begin(&self, _: &Seat<State>, _: &mut State, _: &GestureSwipeBeginEvent) {}
|
||||||
fn gesture_swipe_update(&self, _: &Seat<State>, _: &mut State, _: &GestureSwipeUpdateEvent) {}
|
fn gesture_swipe_update(&self, _: &Seat<State>, _: &mut State, _: &GestureSwipeUpdateEvent) {}
|
||||||
fn gesture_swipe_end(&self, _: &Seat<State>, _: &mut State, _: &GestureSwipeEndEvent) {}
|
fn gesture_swipe_end(&self, _: &Seat<State>, _: &mut State, _: &GestureSwipeEndEvent) {}
|
||||||
|
|
@ -234,6 +235,10 @@ impl PointerGrab<State> for ResizeForkGrab {
|
||||||
handle.axis(data, details)
|
handle.axis(data, details)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn frame(&mut self, data: &mut State, handle: &mut PointerInnerHandle<'_, State>) {
|
||||||
|
handle.frame(data)
|
||||||
|
}
|
||||||
|
|
||||||
fn gesture_swipe_begin(
|
fn gesture_swipe_begin(
|
||||||
&mut self,
|
&mut self,
|
||||||
data: &mut State,
|
data: &mut State,
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,7 @@ use smithay::{
|
||||||
fractional_scale::{with_fractional_scale, FractionalScaleManagerState},
|
fractional_scale::{with_fractional_scale, FractionalScaleManagerState},
|
||||||
keyboard_shortcuts_inhibit::KeyboardShortcutsInhibitState,
|
keyboard_shortcuts_inhibit::KeyboardShortcutsInhibitState,
|
||||||
output::OutputManagerState,
|
output::OutputManagerState,
|
||||||
|
pointer_constraints::PointerConstraintsState,
|
||||||
pointer_gestures::PointerGesturesState,
|
pointer_gestures::PointerGesturesState,
|
||||||
presentation::PresentationState,
|
presentation::PresentationState,
|
||||||
primary_selection::PrimarySelectionState,
|
primary_selection::PrimarySelectionState,
|
||||||
|
|
@ -313,6 +314,7 @@ impl State {
|
||||||
let kde_decoration_state = KdeDecorationState::new::<Self>(&dh, Mode::Client);
|
let kde_decoration_state = KdeDecorationState::new::<Self>(&dh, Mode::Client);
|
||||||
let xdg_decoration_state = XdgDecorationState::new::<Self>(&dh);
|
let xdg_decoration_state = XdgDecorationState::new::<Self>(&dh);
|
||||||
XWaylandKeyboardGrabState::new::<Self>(&dh);
|
XWaylandKeyboardGrabState::new::<Self>(&dh);
|
||||||
|
PointerConstraintsState::new::<Self>(&dh);
|
||||||
PointerGesturesState::new::<Self>(&dh);
|
PointerGesturesState::new::<Self>(&dh);
|
||||||
SecurityContextState::new::<Self, _>(&dh, client_has_security_context);
|
SecurityContextState::new::<Self, _>(&dh, client_has_security_context);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -461,6 +461,8 @@ impl<P: Program + Send + 'static> PointerTarget<crate::state::State> for IcedEle
|
||||||
let _ = internal.update(true);
|
let _ = internal.update(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn frame(&self, _seat: &Seat<crate::state::State>, _data: &mut crate::state::State) {}
|
||||||
|
|
||||||
fn leave(
|
fn leave(
|
||||||
&self,
|
&self,
|
||||||
_seat: &Seat<crate::state::State>,
|
_seat: &Seat<crate::state::State>,
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ pub mod keyboard_shortcuts_inhibit;
|
||||||
pub mod layer_shell;
|
pub mod layer_shell;
|
||||||
pub mod output;
|
pub mod output;
|
||||||
pub mod output_configuration;
|
pub mod output_configuration;
|
||||||
|
pub mod pointer_constraints;
|
||||||
pub mod pointer_gestures;
|
pub mod pointer_gestures;
|
||||||
pub mod presentation;
|
pub mod presentation;
|
||||||
pub mod primary_selection;
|
pub mod primary_selection;
|
||||||
|
|
|
||||||
29
src/wayland/handlers/pointer_constraints.rs
Normal file
29
src/wayland/handlers/pointer_constraints.rs
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
|
use crate::state::State;
|
||||||
|
use smithay::{
|
||||||
|
delegate_pointer_constraints,
|
||||||
|
input::pointer::PointerHandle,
|
||||||
|
reexports::wayland_server::protocol::wl_surface::WlSurface,
|
||||||
|
wayland::{
|
||||||
|
pointer_constraints::{with_pointer_constraint, PointerConstraintsHandler},
|
||||||
|
seat::WaylandFocus,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
impl PointerConstraintsHandler for State {
|
||||||
|
fn new_constraint(&mut self, surface: &WlSurface, pointer: &PointerHandle<Self>) {
|
||||||
|
// XXX region
|
||||||
|
if pointer
|
||||||
|
.current_focus()
|
||||||
|
.and_then(|x| x.wl_surface())
|
||||||
|
.as_ref()
|
||||||
|
== Some(surface)
|
||||||
|
{
|
||||||
|
with_pointer_constraint(surface, pointer, |constraint| {
|
||||||
|
constraint.unwrap().activate();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delegate_pointer_constraints!(State);
|
||||||
Loading…
Add table
Add a link
Reference in a new issue