aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsodiboo <37938646+sodiboo@users.noreply.github.com>2024-10-06 19:36:49 +0200
committerGitHub <noreply@github.com>2024-10-06 20:36:49 +0300
commit66be00041060ea092d611e8f2506a6ed5b3f2327 (patch)
treebbf0b28d4762309d4a2e71a248f905ea50957852
parent5fc669c2824d0101ce2d1740a2a502b6c34be54c (diff)
downloadniri-66be00041060ea092d611e8f2506a6ed5b3f2327.tar.gz
niri-66be00041060ea092d611e8f2506a6ed5b3f2327.tar.bz2
niri-66be00041060ea092d611e8f2506a6ed5b3f2327.zip
implement locked cursor position hints (#685)
* implement cursor position hints * Remove redundant fully qualified path * Find root surface * Convert nesting to if-return * Manually wrap error messages * Remove error!() prints * Add queue redraw --------- Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>
-rw-r--r--src/handlers/mod.rs56
1 files changed, 50 insertions, 6 deletions
diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs
index 6b0c2c6b..efb492a4 100644
--- a/src/handlers/mod.rs
+++ b/src/handlers/mod.rs
@@ -25,7 +25,7 @@ use smithay::reexports::wayland_server::protocol::wl_output::WlOutput;
use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
use smithay::reexports::wayland_server::Resource;
use smithay::utils::{Logical, Point, Rectangle, Size};
-use smithay::wayland::compositor::with_states;
+use smithay::wayland::compositor::{get_parent, with_states};
use smithay::wayland::dmabuf::{DmabufGlobal, DmabufHandler, DmabufState, ImportNotifier};
use smithay::wayland::drm_lease::{
DrmLease, DrmLeaseBuilder, DrmLeaseHandler, DrmLeaseRequest, DrmLeaseState, LeaseRejected,
@@ -35,7 +35,7 @@ use smithay::wayland::idle_inhibit::IdleInhibitHandler;
use smithay::wayland::idle_notify::{IdleNotifierHandler, IdleNotifierState};
use smithay::wayland::input_method::{InputMethodHandler, PopupSurface};
use smithay::wayland::output::OutputHandler;
-use smithay::wayland::pointer_constraints::PointerConstraintsHandler;
+use smithay::wayland::pointer_constraints::{with_pointer_constraint, PointerConstraintsHandler};
use smithay::wayland::security_context::{
SecurityContext, SecurityContextHandler, SecurityContextListenerSource,
};
@@ -146,11 +146,55 @@ impl PointerConstraintsHandler for State {
fn cursor_position_hint(
&mut self,
- _surface: &WlSurface,
- _pointer: &PointerHandle<Self>,
- _location: Point<f64, Logical>,
+ surface: &WlSurface,
+ pointer: &PointerHandle<Self>,
+ location: Point<f64, Logical>,
) {
- // FIXME
+ let is_constraint_active = with_pointer_constraint(surface, pointer, |constraint| {
+ constraint.map_or(false, |c| c.is_active())
+ });
+
+ if !is_constraint_active {
+ return;
+ }
+
+ // Logically the following two checks should always succeed (so, they should print
+ // error!()s if they fail). However, currently both can fail because niri's pointer focus
+ // doesn't take pointer grabs into account. So if you start, say, a middle-drag in Blender,
+ // then touchpad-swipe the window away, the niri pointer focus will change, even though the
+ // real pointer focus remains on the Blender surface due to the click grab.
+ //
+ // FIXME: add error!()s when niri pointer focus takes grabs into account. Alternatively,
+ // recompute the surface origin here (but that is a bit clunky).
+ let Some((ref focused_surface, origin)) = self.niri.pointer_focus.surface else {
+ return;
+ };
+
+ if focused_surface != surface {
+ return;
+ }
+
+ let mut root = surface.clone();
+ while let Some(parent) = get_parent(&root) {
+ root = parent;
+ }
+
+ let target = self
+ .niri
+ .output_for_root(&root)
+ .and_then(|output| self.niri.global_space.output_geometry(output))
+ .map_or(origin + location, |mut output_geometry| {
+ // i32 sizes are exclusive, but f64 sizes are inclusive.
+ output_geometry.size -= (1, 1).into();
+ (origin + location).constrain(output_geometry.to_f64())
+ });
+ pointer.set_location(target);
+
+ // Redraw to update the cursor position if it's visible.
+ if !self.niri.pointer_hidden {
+ // FIXME: redraw only outputs overlapping the cursor.
+ self.niri.queue_redraw_all();
+ }
}
}
delegate_pointer_constraints!(State);