Skip to content

Commit

Permalink
Merge pull request #174 from pop-os/pointer-constraints_jammy
Browse files Browse the repository at this point in the history
Pointer constraints
  • Loading branch information
Drakulix authored Sep 29, 2023
2 parents 0b057f1 + 373af07 commit d051f41
Show file tree
Hide file tree
Showing 16 changed files with 272 additions and 49 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.

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

[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 changes: 160 additions & 47 deletions src/input/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,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 @@ -507,6 +509,70 @@ impl State {
let current_output = seat.active_output();

let mut position = seat.get_pointer().unwrap().current_location();

let relative_pos = self
.common
.shell
.map_global_to_space(position, &current_output);
let overview = self.common.shell.overview_mode();
let output_geometry = current_output.geometry();
let workspace = self.common.shell.workspaces.active_mut(&current_output);
let under = State::surface_under(
position,
relative_pos,
&current_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();

let output = self
Expand All @@ -516,6 +582,85 @@ impl State {
.find(|output| output.geometry().to_f64().contains(position))
.cloned()
.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 {
for session in sessions_for_output(&self.common, &current_output) {
session.cursor_leave(&seat, InputType::Pointer);
Expand All @@ -527,28 +672,6 @@ impl State {

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) {
if let Some((geometry, offset)) = seat.cursor_geometry(
Expand All @@ -562,27 +685,7 @@ impl State {
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")]
if self.common.seats().position(|x| x == &seat).unwrap() == 0 {
let location = if let Some(output) = self.common.shell.outputs.first() {
Expand Down Expand Up @@ -632,7 +735,8 @@ impl State {
session.cursor_info(&seat, InputType::Pointer, geometry, offset);
}
}
seat.get_pointer().unwrap().motion(
let ptr = seat.get_pointer().unwrap();
ptr.motion(
self,
under,
&MotionEvent {
Expand All @@ -641,6 +745,7 @@ impl State {
time: event.time_msec(),
},
);
ptr.frame(self);
#[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 Expand Up @@ -784,7 +889,8 @@ impl State {
}
}
};
seat.get_pointer().unwrap().button(
let ptr = seat.get_pointer().unwrap();
ptr.button(
self,
&ButtonEvent {
button,
Expand All @@ -793,6 +899,7 @@ impl State {
time: event.time_msec(),
},
);
ptr.frame(self);
}
}
InputEvent::PointerAxis { event, .. } => {
Expand Down Expand Up @@ -853,7 +960,9 @@ impl State {
} else if event.source() == AxisSource::Finger {
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);
}
}
}
Expand Down Expand Up @@ -1200,6 +1309,7 @@ impl State {
time,
},
);
ptr.frame(self);
}
}
Ok(None) => {
Expand Down Expand Up @@ -1236,6 +1346,7 @@ impl State {
time,
},
);
ptr.frame(self);
}
}
Ok(None) => {
Expand Down Expand Up @@ -1275,6 +1386,7 @@ impl State {
time,
},
);
ptr.frame(self);
}
}
}
Expand Down Expand Up @@ -1310,6 +1422,7 @@ impl State {
time,
},
);
ptr.frame(self);
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions src/shell/element/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
self.last_cursor_position.lock().unwrap().remove(&seat.id());
match &self.element {
Expand Down
21 changes: 21 additions & 0 deletions src/shell/element/stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
if let Some((location, serial, time)) = self
.0
Expand Down
8 changes: 8 additions & 0 deletions src/shell/element/surface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
&self,
seat: &Seat<State>,
Expand Down
10 changes: 10 additions & 0 deletions src/shell/element/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
let previous = self.0.with_program(|p| {
if let Some(sessions) = p.window.user_data().get::<ScreencopySessions>() {
Expand Down
Loading

0 comments on commit d051f41

Please sign in to comment.