Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pointer constraints #174

Merged
merged 1 commit into from
Sep 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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),
Drakulix marked this conversation as resolved.
Show resolved Hide resolved
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