Skip to content

Commit

Permalink
WIP pointer constraints
Browse files Browse the repository at this point in the history
Depends on Smithay/smithay#872.

For some reason, pointer confinment isn't working correctly here at the
moment, even though the code matches Anvil...

May need solution to Smithay/smithay#1126 for
behavior to be correct.
  • Loading branch information
ids1024 committed Sep 14, 2023
1 parent e1fc182 commit d7c92bf
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 17 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,5 @@ debug = true
lto = "fat"

[patch."https://github.com/Smithay/smithay.git"]
smithay = { git = "https://github.com/smithay//smithay", rev = "5affbde525" }
# smithay = { git = "https://github.com/smithay//smithay", rev = "5affbde525" }
smithay = { git = "https://github.com/ids1024/smithay", branch = "pointer-constrant" }
112 changes: 97 additions & 15 deletions src/input/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,13 @@ use calloop::{timer::Timer, RegistrationToken};
use cosmic_protocols::screencopy::v1::server::zcosmic_screencopy_session_v1::InputType;
#[allow(deprecated)]
use smithay::{
backend::input::{
Axis, AxisSource, Device, DeviceCapability, GestureBeginEvent, GestureEndEvent,
GesturePinchUpdateEvent as _, GestureSwipeUpdateEvent as _, InputBackend, InputEvent,
KeyState, PointerAxisEvent,
backend::{
input::{
Axis, AxisSource, Device, DeviceCapability, GestureBeginEvent, GestureEndEvent,
GesturePinchUpdateEvent as _, GestureSwipeUpdateEvent as _, InputBackend, InputEvent,
KeyState, PointerAxisEvent,
},
renderer::utils::with_renderer_surface_state,
},
desktop::{layer_map_for_output, space::SpaceElement, WindowSurfaceType},
input::{
Expand All @@ -40,7 +43,9 @@ use smithay::{
},
utils::{Logical, Point, Rectangle, Serial, SERIAL_COUNTER},
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,
},
xwayland::X11Surface,
Expand Down Expand Up @@ -545,7 +550,7 @@ impl State {
&output,
output_geometry,
&self.common.shell.override_redirect_windows,
overview.0,
overview.0.clone(),
workspace,
);

Expand All @@ -561,7 +566,44 @@ impl State {
session.cursor_info(&seat, InputType::Pointer, geometry, offset);
}
}

let ptr = seat.get_pointer().unwrap();

let mut pointer_locked = false;
let mut confine_rect = None;
if let Some((under, surface_loc)) = under
.as_ref()
.and_then(|(target, l)| Some((target.wl_surface()?, l)))
{
let surface_size = with_renderer_surface_state(&under, |surface_state| {
surface_state.surface_size()
});
with_pointer_constraint(&under, &ptr, |constraint| match constraint {
Some(constraint) if constraint.is_active() => {
match &*constraint {
PointerConstraint::Locked(_locked) => {
// TODO handle region
pointer_locked = true;
}
PointerConstraint::Confined(_locked) => {
// For now, just confine to surface, ignoring region
// TODO handle region
if let Some(surface_size) = surface_size {
confine_rect = Some(
Rectangle::from_loc_and_size(
*surface_loc,
surface_size,
)
.to_f64(),
);
}
}
}
}
_ => {}
});
}

// Relative motion is sent first to ensure they're part of a `frame`
// TODO: Find more correct solution
ptr.relative_motion(
Expand All @@ -573,15 +615,55 @@ impl State {
utime: event.time(),
},
);
ptr.motion(
self,
under,
&MotionEvent {
location: position,
serial,
time: event.time_msec(),
},
);
if !pointer_locked {
// If confined, clamp to surface rectangle
if let Some(rect) = confine_rect {
position.x =
position.x.clamp(rect.loc.x, rect.loc.x + rect.size.w - 1.);
position.y =
position.y.clamp(rect.loc.y, rect.loc.y + rect.size.h - 1.);
}

ptr.motion(
self,
under,
&MotionEvent {
location: position,
serial,
time: event.time_msec(),
},
);

// If pointer is now in a constraint region, activate it
let workspace = self.common.shell.workspaces.active_mut(&output);
if let Some((under, surface_location)) = State::surface_under(
position,
relative_pos,
&output,
output_geometry,
&self.common.shell.override_redirect_windows,
overview.0,
workspace,
)
.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();
}
}
_ => {}
});
}
}
// XXX frame
#[cfg(feature = "debug")]
if self.common.seats().position(|x| x == &seat).unwrap() == 0 {
let location = if let Some(output) = self.common.shell.outputs.first() {
Expand Down
2 changes: 2 additions & 0 deletions src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ use smithay::{
fractional_scale::{with_fractional_scale, FractionalScaleManagerState},
keyboard_shortcuts_inhibit::KeyboardShortcutsInhibitState,
output::OutputManagerState,
pointer_constraints::PointerConstraintsState,
pointer_gestures::PointerGesturesState,
presentation::PresentationState,
primary_selection::PrimarySelectionState,
Expand Down Expand Up @@ -313,6 +314,7 @@ impl State {
let kde_decoration_state = KdeDecorationState::new::<Self>(&dh, Mode::Client);
let xdg_decoration_state = XdgDecorationState::new::<Self>(&dh);
XWaylandKeyboardGrabState::new::<Self>(&dh);
PointerConstraintsState::new::<Self>(&dh);
PointerGesturesState::new::<Self>(&dh);
SecurityContextState::new::<Self, _>(&dh, client_has_security_context);

Expand Down
1 change: 1 addition & 0 deletions src/wayland/handlers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub mod keyboard_shortcuts_inhibit;
pub mod layer_shell;
pub mod output;
pub mod output_configuration;
pub mod pointer_constraints;
pub mod pointer_gestures;
pub mod presentation;
pub mod primary_selection;
Expand Down
29 changes: 29 additions & 0 deletions src/wayland/handlers/pointer_constraints.rs
Original file line number Diff line number Diff line change
@@ -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);

0 comments on commit d7c92bf

Please sign in to comment.