mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-24 02:01:18 +07:00
Keep track of output and window in PointerFocus separately
This commit is contained in:
+15
-26
@@ -778,12 +778,11 @@ impl State {
|
||||
|
||||
// Check if we have an active pointer constraint.
|
||||
let mut pointer_confined = None;
|
||||
if let Some(focus) = self.niri.pointer_focus.as_ref() {
|
||||
let focus_surface_loc = focus.surface.1;
|
||||
let pos_within_surface = pos.to_i32_round() - focus_surface_loc;
|
||||
if let Some(focus) = &self.niri.pointer_focus.surface {
|
||||
let pos_within_surface = pos.to_i32_round() - focus.1;
|
||||
|
||||
let mut pointer_locked = false;
|
||||
with_pointer_constraint(&focus.surface.0, &pointer, |constraint| {
|
||||
with_pointer_constraint(&focus.0, &pointer, |constraint| {
|
||||
let Some(constraint) = constraint else { return };
|
||||
if !constraint.is_active() {
|
||||
return;
|
||||
@@ -801,7 +800,7 @@ impl State {
|
||||
pointer_locked = true;
|
||||
}
|
||||
PointerConstraint::Confined(confine) => {
|
||||
pointer_confined = Some((focus.surface.clone(), confine.region().cloned()));
|
||||
pointer_confined = Some((focus.clone(), confine.region().cloned()));
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -810,7 +809,7 @@ impl State {
|
||||
if pointer_locked {
|
||||
pointer.relative_motion(
|
||||
self,
|
||||
Some(focus.surface.clone()),
|
||||
Some(focus.clone()),
|
||||
&RelativeMotionEvent {
|
||||
delta: event.delta(),
|
||||
delta_unaccel: event.delta_unaccel(),
|
||||
@@ -875,7 +874,7 @@ impl State {
|
||||
let mut prevent = false;
|
||||
|
||||
// Prevent the pointer from leaving the focused surface.
|
||||
if Some(&focus_surface.0) != under.as_ref().map(|x| &x.surface.0) {
|
||||
if Some(&focus_surface.0) != under.surface.as_ref().map(|(s, _)| s) {
|
||||
prevent = true;
|
||||
}
|
||||
|
||||
@@ -908,11 +907,10 @@ impl State {
|
||||
self.niri.maybe_activate_pointer_constraint(new_pos, &under);
|
||||
|
||||
self.niri.pointer_focus.clone_from(&under);
|
||||
let under = under.map(|u| u.surface);
|
||||
|
||||
pointer.motion(
|
||||
self,
|
||||
under.clone(),
|
||||
under.surface.clone(),
|
||||
&MotionEvent {
|
||||
location: new_pos,
|
||||
serial,
|
||||
@@ -922,7 +920,7 @@ impl State {
|
||||
|
||||
pointer.relative_motion(
|
||||
self,
|
||||
under,
|
||||
under.surface,
|
||||
&RelativeMotionEvent {
|
||||
delta: event.delta(),
|
||||
delta_unaccel: event.delta_unaccel(),
|
||||
@@ -971,11 +969,10 @@ impl State {
|
||||
let under = self.niri.surface_under_and_global_space(pos);
|
||||
self.niri.maybe_activate_pointer_constraint(pos, &under);
|
||||
self.niri.pointer_focus.clone_from(&under);
|
||||
let under = under.map(|u| u.surface);
|
||||
|
||||
pointer.motion(
|
||||
self,
|
||||
under,
|
||||
under.surface,
|
||||
&MotionEvent {
|
||||
location: pos,
|
||||
serial,
|
||||
@@ -1113,7 +1110,6 @@ impl State {
|
||||
};
|
||||
|
||||
let under = self.niri.surface_under_and_global_space(pos);
|
||||
let under = under.map(|u| u.surface);
|
||||
|
||||
let tablet_seat = self.niri.seat.tablet_seat();
|
||||
let tablet = tablet_seat.get_tablet(&TabletDescriptor::from(&event.device()));
|
||||
@@ -1140,7 +1136,7 @@ impl State {
|
||||
|
||||
tool.motion(
|
||||
pos,
|
||||
under,
|
||||
under.surface,
|
||||
&tablet,
|
||||
SERIAL_COUNTER.next_serial(),
|
||||
event.time_msec(),
|
||||
@@ -1195,7 +1191,6 @@ impl State {
|
||||
};
|
||||
|
||||
let under = self.niri.surface_under_and_global_space(pos);
|
||||
let under = under.map(|u| u.surface);
|
||||
|
||||
let tablet_seat = self.niri.seat.tablet_seat();
|
||||
let tool = tablet_seat.add_tool::<Self>(&self.niri.display_handle, &event.tool());
|
||||
@@ -1203,7 +1198,7 @@ impl State {
|
||||
if let Some(tablet) = tablet {
|
||||
match event.state() {
|
||||
ProximityState::In => {
|
||||
if let Some(under) = under {
|
||||
if let Some(under) = under.surface {
|
||||
tool.proximity_in(
|
||||
pos,
|
||||
under,
|
||||
@@ -1538,13 +1533,10 @@ impl State {
|
||||
};
|
||||
|
||||
let serial = SERIAL_COUNTER.next_serial();
|
||||
let under = self
|
||||
.niri
|
||||
.surface_under_and_global_space(touch_location)
|
||||
.map(|under| under.surface);
|
||||
let under = self.niri.surface_under_and_global_space(touch_location);
|
||||
handle.down(
|
||||
self,
|
||||
under,
|
||||
under.surface,
|
||||
&DownEvent {
|
||||
slot: evt.slot(),
|
||||
location: touch_location,
|
||||
@@ -1574,13 +1566,10 @@ impl State {
|
||||
let Some(touch_location) = self.compute_touch_location(&evt) else {
|
||||
return;
|
||||
};
|
||||
let under = self
|
||||
.niri
|
||||
.surface_under_and_global_space(touch_location)
|
||||
.map(|under| under.surface);
|
||||
let under = self.niri.surface_under_and_global_space(touch_location);
|
||||
handle.motion(
|
||||
self,
|
||||
under,
|
||||
under.surface,
|
||||
&TouchMotionEvent {
|
||||
slot: evt.slot(),
|
||||
location: touch_location,
|
||||
|
||||
+50
-35
@@ -201,7 +201,7 @@ pub struct Niri {
|
||||
pub cursor_texture_cache: CursorTextureCache,
|
||||
pub cursor_shape_manager_state: CursorShapeManagerState,
|
||||
pub dnd_icon: Option<WlSurface>,
|
||||
pub pointer_focus: Option<PointerFocus>,
|
||||
pub pointer_focus: PointerFocus,
|
||||
pub tablet_cursor_location: Option<Point<f64, Logical>>,
|
||||
pub gesture_swipe_3f_cumulative: Option<(f64, f64)>,
|
||||
|
||||
@@ -292,10 +292,14 @@ pub enum KeyboardFocus {
|
||||
ScreenshotUi,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
#[derive(Default, Clone, PartialEq, Eq)]
|
||||
pub struct PointerFocus {
|
||||
pub output: Output,
|
||||
pub surface: (WlSurface, Point<i32, Logical>),
|
||||
// Output under pointer.
|
||||
pub output: Option<Output>,
|
||||
// Surface under pointer and its location in global coordinate space.
|
||||
pub surface: Option<(WlSurface, Point<i32, Logical>)>,
|
||||
// If surface belongs to a window, this is that window.
|
||||
pub window: Option<Window>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
@@ -421,12 +425,11 @@ impl State {
|
||||
self.niri
|
||||
.maybe_activate_pointer_constraint(location, &under);
|
||||
self.niri.pointer_focus.clone_from(&under);
|
||||
let under = under.map(|u| u.surface);
|
||||
|
||||
let pointer = &self.niri.seat.get_pointer().unwrap();
|
||||
pointer.motion(
|
||||
self,
|
||||
under,
|
||||
under.surface,
|
||||
&MotionEvent {
|
||||
location,
|
||||
serial: SERIAL_COUNTER.next_serial(),
|
||||
@@ -560,11 +563,10 @@ impl State {
|
||||
.maybe_activate_pointer_constraint(location, &under);
|
||||
|
||||
self.niri.pointer_focus.clone_from(&under);
|
||||
let under = under.map(|u| u.surface);
|
||||
|
||||
pointer.motion(
|
||||
self,
|
||||
under,
|
||||
under.surface,
|
||||
&MotionEvent {
|
||||
location,
|
||||
serial: SERIAL_COUNTER.next_serial(),
|
||||
@@ -1225,7 +1227,7 @@ impl Niri {
|
||||
cursor_texture_cache: Default::default(),
|
||||
cursor_shape_manager_state,
|
||||
dnd_icon: None,
|
||||
pointer_focus: None,
|
||||
pointer_focus: PointerFocus::default(),
|
||||
tablet_cursor_location: None,
|
||||
gesture_swipe_3f_cumulative: None,
|
||||
|
||||
@@ -1622,32 +1624,39 @@ impl Niri {
|
||||
/// Pointer needs location in global space, and focused window location compatible with that
|
||||
/// global space. We don't have a global space for all windows, but this function converts the
|
||||
/// window location temporarily to the current global space.
|
||||
pub fn surface_under_and_global_space(
|
||||
&mut self,
|
||||
pos: Point<f64, Logical>,
|
||||
) -> Option<PointerFocus> {
|
||||
let (output, pos_within_output) = self.output_under(pos)?;
|
||||
pub fn surface_under_and_global_space(&mut self, pos: Point<f64, Logical>) -> PointerFocus {
|
||||
let mut rv = PointerFocus::default();
|
||||
|
||||
let Some((output, pos_within_output)) = self.output_under(pos) else {
|
||||
return rv;
|
||||
};
|
||||
rv.output = Some(output.clone());
|
||||
let output_pos_in_global_space = self.global_space.output_geometry(output).unwrap().loc;
|
||||
|
||||
if self.is_locked() {
|
||||
let state = self.output_state.get(output)?;
|
||||
let surface = state.lock_surface.as_ref()?;
|
||||
// We put lock surfaces at (0, 0).
|
||||
let point = pos_within_output;
|
||||
let (surface, point) = under_from_surface_tree(
|
||||
let Some(state) = self.output_state.get(output) else {
|
||||
return rv;
|
||||
};
|
||||
let Some(surface) = state.lock_surface.as_ref() else {
|
||||
return rv;
|
||||
};
|
||||
|
||||
rv.surface = under_from_surface_tree(
|
||||
surface.wl_surface(),
|
||||
point,
|
||||
pos_within_output,
|
||||
// We put lock surfaces at (0, 0).
|
||||
(0, 0),
|
||||
WindowSurfaceType::ALL,
|
||||
)?;
|
||||
return Some(PointerFocus {
|
||||
output: output.clone(),
|
||||
surface: (surface, point + output_pos_in_global_space),
|
||||
)
|
||||
.map(|(surface, pos_within_output)| {
|
||||
(surface, pos_within_output + output_pos_in_global_space)
|
||||
});
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
if self.screenshot_ui.is_open() {
|
||||
return None;
|
||||
return rv;
|
||||
}
|
||||
|
||||
let layers = layer_map_for_output(output);
|
||||
@@ -1665,6 +1674,7 @@ impl Niri {
|
||||
(surface, pos_within_layer + layer_pos_within_output)
|
||||
})
|
||||
})
|
||||
.map(|s| (s, None))
|
||||
};
|
||||
|
||||
let window_under = || {
|
||||
@@ -1680,6 +1690,7 @@ impl Niri {
|
||||
.map(|(s, pos_within_window)| {
|
||||
(s, pos_within_window + win_pos_within_output)
|
||||
})
|
||||
.map(|s| (s, Some(window.clone())))
|
||||
})
|
||||
};
|
||||
|
||||
@@ -1697,16 +1708,18 @@ impl Niri {
|
||||
.or_else(window_under);
|
||||
}
|
||||
|
||||
let (surface, surface_pos_within_output) = under
|
||||
let Some(((surface, surface_pos_within_output), window)) = under
|
||||
.or_else(|| layer_surface_under(Layer::Bottom))
|
||||
.or_else(|| layer_surface_under(Layer::Background))?;
|
||||
.or_else(|| layer_surface_under(Layer::Background))
|
||||
else {
|
||||
return rv;
|
||||
};
|
||||
|
||||
let surface_loc_in_global_space = surface_pos_within_output + output_pos_in_global_space;
|
||||
|
||||
Some(PointerFocus {
|
||||
output: output.clone(),
|
||||
surface: (surface, surface_loc_in_global_space),
|
||||
})
|
||||
rv.surface = Some((surface, surface_loc_in_global_space));
|
||||
rv.window = window;
|
||||
rv
|
||||
}
|
||||
|
||||
pub fn output_under_cursor(&self) -> Option<Output> {
|
||||
@@ -3231,11 +3244,13 @@ impl Niri {
|
||||
pub fn maybe_activate_pointer_constraint(
|
||||
&self,
|
||||
new_pos: Point<f64, Logical>,
|
||||
new_under: &Option<PointerFocus>,
|
||||
new_under: &PointerFocus,
|
||||
) {
|
||||
let Some(under) = new_under else { return };
|
||||
let Some((surface, surface_loc)) = &new_under.surface else {
|
||||
return;
|
||||
};
|
||||
let pointer = &self.seat.get_pointer().unwrap();
|
||||
with_pointer_constraint(&under.surface.0, pointer, |constraint| {
|
||||
with_pointer_constraint(surface, pointer, |constraint| {
|
||||
let Some(constraint) = constraint else { return };
|
||||
if constraint.is_active() {
|
||||
return;
|
||||
@@ -3243,7 +3258,7 @@ impl Niri {
|
||||
|
||||
// Constraint does not apply if not within region.
|
||||
if let Some(region) = constraint.region() {
|
||||
let new_pos_within_surface = new_pos.to_i32_round() - under.surface.1;
|
||||
let new_pos_within_surface = new_pos.to_i32_round() - *surface_loc;
|
||||
if !region.contains(new_pos_within_surface) {
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user