// SPDX-License-Identifier: GPL-3.0-only 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, 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) { 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| { 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) { 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, location: Point, ) { 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))); } } } }