wayland: implement new_constraint, remove_constraint and cursor_position_hint for PointerConstraintsHandler
new_constraint: check if the surface has pointer focus, keyboard focus, and if the pointer is within toplevel geometry or constraint region. If these conditions are met, then enable the constraint. remove_constraint: apply last cursor position hint that saved in seat. cursor_position_hint: save the cursor position hints provided by the client to the seat.
This commit is contained in:
parent
4fb7d49316
commit
208c2128cd
4 changed files with 156 additions and 42 deletions
|
|
@ -1,35 +1,123 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::state::State;
|
||||
use crate::{shell::CosmicSurface, state::State, utils::prelude::*};
|
||||
use smithay::{
|
||||
input::pointer::PointerHandle,
|
||||
reexports::wayland_server::protocol::wl_surface::WlSurface,
|
||||
utils::{Logical, Point},
|
||||
wayland::{
|
||||
pointer_constraints::{PointerConstraintsHandler, with_pointer_constraint},
|
||||
seat::WaylandFocus,
|
||||
},
|
||||
wayland::{pointer_constraints::PointerConstraintsHandler, seat::WaylandFocus},
|
||||
};
|
||||
|
||||
pub use smithay::wayland::pointer_constraints::{PointerConstraintRef, with_pointer_constraint};
|
||||
|
||||
impl PointerConstraintsHandler for State {
|
||||
fn new_constraint(&mut self, surface: &WlSurface, pointer: &PointerHandle<Self>) {
|
||||
// XXX region
|
||||
if pointer
|
||||
.current_focus()
|
||||
.is_some_and(|x| x.wl_surface().as_deref() == Some(surface))
|
||||
{
|
||||
let seat = self
|
||||
.common
|
||||
.shell
|
||||
.read()
|
||||
.seats
|
||||
.iter()
|
||||
.find(|s| s.get_pointer().as_ref() == Some(pointer))
|
||||
.cloned();
|
||||
|
||||
let (is_under, is_focused, surface_location) = if let Some(seat) = seat {
|
||||
seat.set_pointer_constraint_hint(None);
|
||||
let current_output = seat.active_output();
|
||||
let position = seat.get_pointer().unwrap().current_location().as_global();
|
||||
let shell = self.common.shell.read();
|
||||
let under = State::surface_under(position, ¤t_output, &shell);
|
||||
let mut surface_location = None;
|
||||
|
||||
let is_under = if let Some((target, target_loc)) = under
|
||||
&& let Some(under_surface) = target.wl_surface()
|
||||
{
|
||||
if *under_surface == *surface {
|
||||
surface_location = Some(target_loc);
|
||||
true
|
||||
} else {
|
||||
CosmicSurface::surface_tree_offset(surface, &under_surface).is_some_and(
|
||||
|offset| {
|
||||
surface_location = Some(target_loc - offset.to_f64().as_global());
|
||||
true
|
||||
},
|
||||
)
|
||||
}
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
let is_focused = seat
|
||||
.get_keyboard()
|
||||
.and_then(|k| k.current_focus())
|
||||
.is_some_and(|f| f.has_surface(&shell, surface));
|
||||
|
||||
(is_under, is_focused, surface_location)
|
||||
} else {
|
||||
(false, false, None)
|
||||
};
|
||||
|
||||
if is_focused && is_under {
|
||||
with_pointer_constraint(surface, pointer, |constraint| {
|
||||
constraint.unwrap().activate();
|
||||
if let Some(constraint) = constraint {
|
||||
if let Some(region) = constraint.region() {
|
||||
if let Some(surface_location) = surface_location
|
||||
&& let position = pointer.current_location()
|
||||
&& let point = (position - surface_location.as_logical()).to_i32_round()
|
||||
&& region.contains(point)
|
||||
{
|
||||
constraint.activate();
|
||||
}
|
||||
} else {
|
||||
constraint.activate();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_constraint(&mut self, surface: &WlSurface, pointer: &PointerHandle<Self>) {
|
||||
if with_pointer_constraint(surface, pointer, |constraint| constraint.is_none()) {
|
||||
let seat = self
|
||||
.common
|
||||
.shell
|
||||
.read()
|
||||
.seats
|
||||
.iter()
|
||||
.find(|s| s.get_pointer().as_ref() == Some(pointer))
|
||||
.cloned();
|
||||
|
||||
if let Some(seat) = seat
|
||||
&& let Some((hint_surface, hint_location)) = seat.pointer_constraint_hint()
|
||||
&& hint_surface == *surface
|
||||
{
|
||||
self.apply_cursor_hint(surface, pointer, hint_location);
|
||||
seat.set_pointer_constraint_hint(None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn cursor_position_hint(
|
||||
&mut self,
|
||||
_surface: &WlSurface,
|
||||
_pointer: &PointerHandle<Self>,
|
||||
_location: Point<f64, Logical>,
|
||||
surface: &WlSurface,
|
||||
pointer: &PointerHandle<Self>,
|
||||
location: Point<f64, Logical>,
|
||||
) {
|
||||
// TODO
|
||||
if with_pointer_constraint(surface, pointer, |constraint| {
|
||||
constraint.is_some_and(|c| c.is_active())
|
||||
}) {
|
||||
let seat = self
|
||||
.common
|
||||
.shell
|
||||
.read()
|
||||
.seats
|
||||
.iter()
|
||||
.find(|s| s.get_pointer().as_ref() == Some(pointer))
|
||||
.cloned();
|
||||
|
||||
if let Some(seat) = seat {
|
||||
seat.set_pointer_constraint_hint(Some((surface.clone(), location)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue