aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/input.rs85
-rw-r--r--src/niri.rs44
2 files changed, 76 insertions, 53 deletions
diff --git a/src/input.rs b/src/input.rs
index a86045bd..cf2c59ba 100644
--- a/src/input.rs
+++ b/src/input.rs
@@ -439,6 +439,9 @@ impl State {
pointer.frame(self);
+ // We moved the regular pointer, so show it now.
+ self.niri.tablet_cursor_location = None;
+
// Redraw to update the cursor position.
// FIXME: redraw only outputs overlapping the cursor.
self.niri.queue_redraw_all();
@@ -487,6 +490,9 @@ impl State {
pointer.frame(self);
+ // We moved the regular pointer, so show it now.
+ self.niri.tablet_cursor_location = None;
+
// Redraw to update the cursor position.
// FIXME: redraw only outputs overlapping the cursor.
self.niri.queue_redraw_all();
@@ -596,25 +602,9 @@ impl State {
return;
};
- let serial = SERIAL_COUNTER.next_serial();
-
- let pointer = self.niri.seat.get_pointer().unwrap();
-
let under = self.niri.surface_under_and_global_space(pos);
- self.niri.pointer_focus = under.clone();
let under = under.map(|u| u.surface);
- pointer.motion(
- self,
- under.clone(),
- &MotionEvent {
- location: pos,
- serial,
- time: event.time_msec(),
- },
- );
- pointer.frame(self);
-
let tablet_seat = self.niri.seat.tablet_seat();
let tablet = tablet_seat.get_tablet(&TabletDescriptor::from(&event.device()));
let tool = tablet_seat.get_tool(&event.tool());
@@ -645,6 +635,8 @@ impl State {
SERIAL_COUNTER.next_serial(),
event.time_msec(),
);
+
+ self.niri.tablet_cursor_location = Some(pos);
}
// Redraw to update the cursor position.
@@ -660,15 +652,21 @@ impl State {
let serial = SERIAL_COUNTER.next_serial();
tool.tip_down(serial, event.time_msec());
- let pointer = self.niri.seat.get_pointer().unwrap();
- if !pointer.is_grabbed() {
- if let Some(window) = self.niri.window_under_cursor() {
+ if let Some(pos) = self.niri.tablet_cursor_location {
+ if let Some(window) = self.niri.window_under(pos) {
let window = window.clone();
self.niri.layout.activate_window(&window);
- } else if let Some(output) = self.niri.output_under_cursor() {
+
+ // FIXME: granular.
+ self.niri.queue_redraw_all();
+ } else if let Some((output, _)) = self.niri.output_under(pos) {
+ let output = output.clone();
self.niri.layout.activate_output(&output);
+
+ // FIXME: granular.
+ self.niri.queue_redraw_all();
}
- };
+ }
}
TabletToolTipState::Up => {
tool.tip_up(event.time_msec());
@@ -681,39 +679,34 @@ impl State {
return;
};
- let serial = SERIAL_COUNTER.next_serial();
-
- let pointer = self.niri.seat.get_pointer().unwrap();
-
let under = self.niri.surface_under_and_global_space(pos);
- self.niri.pointer_focus = under.clone();
let under = under.map(|u| u.surface);
- pointer.motion(
- self,
- under.clone(),
- &MotionEvent {
- location: pos,
- serial,
- time: event.time_msec(),
- },
- );
- pointer.frame(self);
-
let tablet_seat = self.niri.seat.tablet_seat();
let tool = tablet_seat.add_tool::<Self>(&self.niri.display_handle, &event.tool());
let tablet = tablet_seat.get_tablet(&TabletDescriptor::from(&event.device()));
- if let (Some(under), Some(tablet)) = (under, tablet) {
+ if let Some(tablet) = tablet {
match event.state() {
- ProximityState::In => tool.proximity_in(
- pos,
- under,
- &tablet,
- SERIAL_COUNTER.next_serial(),
- event.time_msec(),
- ),
- ProximityState::Out => tool.proximity_out(event.time_msec()),
+ ProximityState::In => {
+ if let Some(under) = under {
+ tool.proximity_in(
+ pos,
+ under,
+ &tablet,
+ SERIAL_COUNTER.next_serial(),
+ event.time_msec(),
+ );
+ }
+ self.niri.tablet_cursor_location = Some(pos);
+ }
+ ProximityState::Out => {
+ tool.proximity_out(event.time_msec());
+ self.niri.tablet_cursor_location = None;
+ }
}
+
+ // FIXME: granular.
+ self.niri.queue_redraw_all();
}
}
InputEvent::TabletToolButton { event, .. } => {
diff --git a/src/niri.rs b/src/niri.rs
index 544ae16d..45b1d4f4 100644
--- a/src/niri.rs
+++ b/src/niri.rs
@@ -74,7 +74,7 @@ use smithay::wayland::shell::xdg::decoration::XdgDecorationState;
use smithay::wayland::shell::xdg::XdgShellState;
use smithay::wayland::shm::ShmState;
use smithay::wayland::socket::ListeningSocketSource;
-use smithay::wayland::tablet_manager::TabletManagerState;
+use smithay::wayland::tablet_manager::{TabletManagerState, TabletSeatTrait};
use smithay::wayland::text_input::TextInputManagerState;
use smithay::wayland::virtual_keyboard::VirtualKeyboardManagerState;
@@ -157,6 +157,7 @@ pub struct Niri {
pub cursor_shape_manager_state: CursorShapeManagerState,
pub dnd_icon: Option<WlSurface>,
pub pointer_focus: Option<PointerFocus>,
+ pub tablet_cursor_location: Option<Point<f64, Logical>>,
pub lock_state: LockState,
@@ -645,6 +646,23 @@ impl Niri {
let cursor_manager =
CursorManager::new(&config_.cursor.xcursor_theme, config_.cursor.xcursor_size);
+ let (tx, rx) = calloop::channel::channel();
+ event_loop
+ .insert_source(rx, move |event, _, state| {
+ if let calloop::channel::Event::Msg(image) = event {
+ state.niri.cursor_manager.set_cursor_image(image);
+ // FIXME: granular.
+ state.niri.queue_redraw_all();
+ }
+ })
+ .unwrap();
+ seat.tablet_seat()
+ .on_cursor_surface(move |_tool, new_image| {
+ if let Err(err) = tx.send(new_image) {
+ warn!("error sending new tablet cursor image: {err:?}");
+ };
+ });
+
let screenshot_ui = ScreenshotUi::new();
let socket_source = ListeningSocketSource::new_auto().unwrap();
@@ -724,6 +742,7 @@ impl Niri {
cursor_shape_manager_state,
dnd_icon: None,
pointer_focus: None,
+ tablet_cursor_location: None,
lock_state: LockState::Unlocked,
@@ -980,17 +999,21 @@ impl Niri {
Some((output, pos_within_output))
}
- pub fn window_under_cursor(&self) -> Option<&Window> {
+ pub fn window_under(&self, pos: Point<f64, Logical>) -> Option<&Window> {
if self.is_locked() || self.screenshot_ui.is_open() {
return None;
}
- let pos = self.seat.get_pointer().unwrap().current_location();
let (output, pos_within_output) = self.output_under(pos)?;
let (window, _loc) = self.layout.window_under(output, pos_within_output)?;
Some(window)
}
+ pub fn window_under_cursor(&self) -> Option<&Window> {
+ let pos = self.seat.get_pointer().unwrap().current_location();
+ self.window_under(pos)
+ }
+
/// Returns the surface under cursor and its position in the global space.
///
/// Pointer needs location in global space, and focused window location compatible with that
@@ -1223,7 +1246,12 @@ impl Niri {
let _span = tracy_client::span!("Niri::pointer_element");
let output_scale = output.current_scale();
let output_pos = self.global_space.output_geometry(output).unwrap().loc;
- let pointer_pos = self.seat.get_pointer().unwrap().current_location() - output_pos.to_f64();
+
+ // Check whether we need to draw the tablet cursor or the regular cursor.
+ let pointer_pos = self
+ .tablet_cursor_location
+ .unwrap_or_else(|| self.seat.get_pointer().unwrap().current_location());
+ let pointer_pos = pointer_pos - output_pos.to_f64();
// Get the render cursor to draw.
let cursor_scale = output_scale.integer_scale();
@@ -1294,6 +1322,11 @@ impl Niri {
pub fn refresh_pointer_outputs(&mut self) {
let _span = tracy_client::span!("Niri::refresh_pointer_outputs");
+ // Check whether we need to draw the tablet cursor or the regular cursor.
+ let pointer_pos = self
+ .tablet_cursor_location
+ .unwrap_or_else(|| self.seat.get_pointer().unwrap().current_location());
+
match self.cursor_manager.cursor_image().clone() {
CursorImageStatus::Surface(ref surface) => {
let hotspot = with_states(surface, |states| {
@@ -1306,7 +1339,6 @@ impl Niri {
.hotspot
});
- let pointer_pos = self.seat.get_pointer().unwrap().current_location();
let surface_pos = pointer_pos.to_i32_round() - hotspot;
let bbox = bbox_from_surface_tree(surface, surface_pos);
@@ -1364,8 +1396,6 @@ impl Niri {
Default::default()
};
- let pointer_pos = self.seat.get_pointer().unwrap().current_location();
-
let mut dnd_scale = 1;
for output in self.global_space.outputs() {
let geo = self.global_space.output_geometry(output).unwrap();