input: when updating pointer in the confined mode, recalibrate to the valid coordinates
This commit is contained in:
parent
a533ac1ec3
commit
9702aae523
1 changed files with 117 additions and 71 deletions
188
src/input/mod.rs
188
src/input/mod.rs
|
|
@ -354,27 +354,6 @@ impl State {
|
||||||
_ => {}
|
_ => {}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
let original_position = position;
|
|
||||||
position += event.delta().as_global();
|
|
||||||
|
|
||||||
let output = shell
|
|
||||||
.outputs()
|
|
||||||
.find(|output| output.geometry().to_f64().contains(position))
|
|
||||||
.cloned()
|
|
||||||
.unwrap_or(current_output.clone());
|
|
||||||
|
|
||||||
let output_geometry = output.geometry();
|
|
||||||
position.x = position.x.clamp(
|
|
||||||
output_geometry.loc.x as f64,
|
|
||||||
(output_geometry.loc.x + output_geometry.size.w - 1) as f64,
|
|
||||||
);
|
|
||||||
position.y = position.y.clamp(
|
|
||||||
output_geometry.loc.y as f64,
|
|
||||||
(output_geometry.loc.y + output_geometry.size.h - 1) as f64,
|
|
||||||
);
|
|
||||||
|
|
||||||
let new_under = State::surface_under(position, &output, &shell)
|
|
||||||
.map(|(target, pos)| (target, pos.as_logical()));
|
|
||||||
|
|
||||||
std::mem::drop(shell);
|
std::mem::drop(shell);
|
||||||
ptr.relative_motion(
|
ptr.relative_motion(
|
||||||
|
|
@ -392,6 +371,25 @@ impl State {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let original_position = position;
|
||||||
|
position += event.delta().as_global();
|
||||||
|
let shell = self.common.shell.read();
|
||||||
|
let output = shell
|
||||||
|
.outputs()
|
||||||
|
.find(|output| output.geometry().to_f64().contains(position))
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or(current_output.clone());
|
||||||
|
drop(shell);
|
||||||
|
let output_geometry = output.geometry();
|
||||||
|
position.x = position.x.clamp(
|
||||||
|
output_geometry.loc.x as f64,
|
||||||
|
(output_geometry.loc.x + output_geometry.size.w - 1) as f64,
|
||||||
|
);
|
||||||
|
position.y = position.y.clamp(
|
||||||
|
output_geometry.loc.y as f64,
|
||||||
|
(output_geometry.loc.y + output_geometry.size.h - 1) as f64,
|
||||||
|
);
|
||||||
|
|
||||||
if ptr.is_grabbed() {
|
if ptr.is_grabbed() {
|
||||||
if seat
|
if seat
|
||||||
.user_data()
|
.user_data()
|
||||||
|
|
@ -499,50 +497,90 @@ impl State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If confined, don't move pointer if it would go outside surface or region
|
// If confined, help user to update valid coordinates can improve user experience
|
||||||
if pointer_confined && let Some((surface, surface_loc)) = &under {
|
let shell = self.common.shell.read();
|
||||||
if new_under.as_ref().and_then(|(under, _)| under.wl_surface())
|
let new_under = if pointer_confined && let Some((surface, surface_loc)) = &under
|
||||||
!= surface.wl_surface()
|
{
|
||||||
{
|
let is_legal = |pos: Point<f64, Global>, shell: &Shell| {
|
||||||
ptr.frame(self);
|
let new_under = State::surface_under(pos, &output, shell)
|
||||||
return;
|
.map(|(target, pos)| (target, pos.as_logical()));
|
||||||
}
|
|
||||||
match surface {
|
//We should only check size, not the surface, so that we can move the mouse over the OSD in confined mode
|
||||||
PointerFocusTarget::WlSurface { surface, .. } => {
|
// if new_under.as_ref().and_then(|(under, _)| under.wl_surface())
|
||||||
if under_from_surface_tree(
|
// != surface.wl_surface()
|
||||||
surface,
|
// {
|
||||||
position.as_logical() - surface_loc.to_f64(),
|
// return (false, None);
|
||||||
(0, 0),
|
// }
|
||||||
WindowSurfaceType::ALL,
|
|
||||||
)
|
match surface {
|
||||||
.is_none()
|
PointerFocusTarget::WlSurface { surface, .. } => {
|
||||||
{
|
if under_from_surface_tree(
|
||||||
ptr.frame(self);
|
surface,
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PointerFocusTarget::X11Surface { surface, .. } => {
|
|
||||||
if surface
|
|
||||||
.surface_under(
|
|
||||||
position.as_logical() - surface_loc.to_f64(),
|
position.as_logical() - surface_loc.to_f64(),
|
||||||
(0, 0),
|
(0, 0),
|
||||||
WindowSurfaceType::ALL,
|
WindowSurfaceType::ALL,
|
||||||
)
|
)
|
||||||
.is_none()
|
.is_none()
|
||||||
{
|
{
|
||||||
ptr.frame(self);
|
return (false, None);
|
||||||
return;
|
}
|
||||||
|
}
|
||||||
|
PointerFocusTarget::X11Surface { surface, .. } => {
|
||||||
|
if surface
|
||||||
|
.surface_under(
|
||||||
|
position.as_logical() - surface_loc.to_f64(),
|
||||||
|
(0, 0),
|
||||||
|
WindowSurfaceType::ALL,
|
||||||
|
)
|
||||||
|
.is_none()
|
||||||
|
{
|
||||||
|
return (false, None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(region) = &confine_region
|
||||||
|
&& !region
|
||||||
|
.contains((pos.as_logical() - *surface_loc).to_i32_round())
|
||||||
|
{
|
||||||
|
return (false, None);
|
||||||
|
}
|
||||||
|
(true, new_under)
|
||||||
|
};
|
||||||
|
|
||||||
|
match is_legal(position, &shell) {
|
||||||
|
(true, under) => under,
|
||||||
|
_ => {
|
||||||
|
let y_only_pos = Point::new(original_position.x, position.y);
|
||||||
|
let x_only_pos = Point::new(position.x, original_position.y);
|
||||||
|
match is_legal(y_only_pos, &shell) {
|
||||||
|
(true, under) => {
|
||||||
|
position = y_only_pos;
|
||||||
|
under
|
||||||
|
}
|
||||||
|
_ => match is_legal(x_only_pos, &shell) {
|
||||||
|
(true, under) => {
|
||||||
|
position = x_only_pos;
|
||||||
|
under
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
position = original_position;
|
||||||
|
None
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
if let Some(region) = confine_region
|
|
||||||
&& !region
|
|
||||||
.contains((position.as_logical() - *surface_loc).to_i32_round())
|
|
||||||
{
|
|
||||||
ptr.frame(self);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
State::surface_under(position, &output, &shell)
|
||||||
|
.map(|(target, pos)| (target, pos.as_logical()))
|
||||||
|
};
|
||||||
|
|
||||||
|
drop(shell);
|
||||||
|
if pointer_confined && new_under.is_none() {
|
||||||
|
ptr.frame(self);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let serial = SERIAL_COUNTER.next_serial();
|
let serial = SERIAL_COUNTER.next_serial();
|
||||||
|
|
@ -557,24 +595,32 @@ impl State {
|
||||||
);
|
);
|
||||||
ptr.frame(self);
|
ptr.frame(self);
|
||||||
|
|
||||||
// If pointer is now in a constraint region, activate it
|
// If pointer is now in a constraint region and window is in focused, activate it
|
||||||
if let Some((under, surface_location)) = new_under
|
if let Some((under, surface_location)) = new_under
|
||||||
.and_then(|(target, loc)| Some((target.wl_surface()?.into_owned(), loc)))
|
.and_then(|(target, loc)| Some((target.wl_surface()?.into_owned(), loc)))
|
||||||
{
|
{
|
||||||
with_pointer_constraint(&under, &ptr, |constraint| match constraint {
|
let shell = self.common.shell.read();
|
||||||
Some(constraint) if !constraint.is_active() => {
|
let is_focused = seat
|
||||||
let region = match &*constraint {
|
.get_keyboard()
|
||||||
PointerConstraint::Locked(locked) => locked.region(),
|
.and_then(|k| k.current_focus())
|
||||||
PointerConstraint::Confined(confined) => confined.region(),
|
.is_some_and(|f| f.has_surface(&shell, &under));
|
||||||
};
|
|
||||||
let point =
|
if is_focused {
|
||||||
(ptr.current_location() - surface_location).to_i32_round();
|
with_pointer_constraint(&under, &ptr, |constraint| match constraint {
|
||||||
if region.is_none_or(|region| region.contains(point)) {
|
Some(constraint) if !constraint.is_active() => {
|
||||||
constraint.activate();
|
let region = match &*constraint {
|
||||||
|
PointerConstraint::Locked(locked) => locked.region(),
|
||||||
|
PointerConstraint::Confined(confined) => confined.region(),
|
||||||
|
};
|
||||||
|
let point =
|
||||||
|
(ptr.current_location() - surface_location).to_i32_round();
|
||||||
|
if region.is_none_or(|region| region.contains(point)) {
|
||||||
|
constraint.activate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
_ => {}
|
||||||
_ => {}
|
});
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut shell = self.common.shell.write();
|
let mut shell = self.common.shell.write();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue