ltk/input/pointer/
enter.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// SPDX-License-Identifier: LGPL-2.1-only
// Copyright (C) 2026 Liberux Labs, S. L. <info@liberux.net>

use smithay_client_toolkit::seat::pointer::{ PointerEvent, PointerEventKind };
use smithay_client_toolkit::reexports::client::
{
	protocol::wl_pointer::WlPointer,
	Connection, QueueHandle,
};

use crate::app::App;
use crate::event_loop::{ AppData, SurfaceFocus };

impl<A: App> AppData<A>
{
	pub( super ) fn on_pointer_enter(
		&mut self,
		_conn:    &Connection,
		_qh:      &QueueHandle<Self>,
		_pointer: &WlPointer,
		event:    &PointerEvent,
	)
	{
		let focus = self.focus_for_surface( &event.surface )
			.unwrap_or( SurfaceFocus::Main );
		if let PointerEventKind::Enter { serial } = event.kind
		{
			// Pointer just entered our surface — capture the
			// serial that wp_cursor_shape_device_v1::set_shape
			// requires, then push the initial cursor shape
			// *unconditionally*. Resetting `current_cursor_shape`
			// to `None` is what forces the dispatch: the
			// compositor was showing whatever the previous
			// client asked for (e.g. a text I-beam from a
			// terminal under our window), and we must claim
			// the cursor for our surface even when the target
			// equals what we last pushed.
			self.last_pointer_enter_serial = serial;
			self.current_cursor_shape = None;
			self.dispatch_cursor_shape( focus );
		}
	}
}