1use crate::coordinates::CoordinateTransformer;
7use crate::error::Result;
8use std::time::Instant;
9use tracing::debug;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
13pub enum MouseButton {
14 Left,
16 Right,
18 Middle,
20 Extra1,
22 Extra2,
24}
25
26impl MouseButton {
27 pub fn to_linux_button(&self) -> u32 {
29 match self {
30 MouseButton::Left => 0x110, MouseButton::Right => 0x111, MouseButton::Middle => 0x112, MouseButton::Extra1 => 0x113, MouseButton::Extra2 => 0x114, }
36 }
37
38 pub fn from_rdp_button(button: u16) -> Option<Self> {
40 match button {
41 0x1000 => Some(MouseButton::Left),
42 0x2000 => Some(MouseButton::Right),
43 0x4000 => Some(MouseButton::Middle),
44 0x0080 => Some(MouseButton::Extra1),
45 0x0100 => Some(MouseButton::Extra2),
46 _ => None,
47 }
48 }
49}
50
51#[derive(Debug, Clone)]
53pub enum MouseEvent {
54 Move {
56 x: f64,
58 y: f64,
60 timestamp: Instant,
62 },
63
64 ButtonDown {
66 button: MouseButton,
68 timestamp: Instant,
70 },
71
72 ButtonUp {
74 button: MouseButton,
76 timestamp: Instant,
78 },
79
80 Scroll {
82 delta_x: i32,
84 delta_y: i32,
86 timestamp: Instant,
88 },
89}
90
91pub struct MouseHandler {
93 current_x: f64,
95 current_y: f64,
96
97 button_states: [bool; 5],
99
100 last_event_time: Option<Instant>,
102
103 high_precision_scroll: bool,
105
106 scroll_accum_x: f64,
108 scroll_accum_y: f64,
109}
110
111impl MouseHandler {
112 pub fn new() -> Self {
114 Self {
115 current_x: 0.0,
116 current_y: 0.0,
117 button_states: [false; 5],
118 last_event_time: None,
119 high_precision_scroll: true,
120 scroll_accum_x: 0.0,
121 scroll_accum_y: 0.0,
122 }
123 }
124
125 pub fn handle_absolute_move(
127 &mut self,
128 rdp_x: u32,
129 rdp_y: u32,
130 transformer: &mut CoordinateTransformer,
131 ) -> Result<MouseEvent> {
132 let (stream_x, stream_y) = transformer.rdp_to_stream(rdp_x, rdp_y)?;
133
134 let (stream_x, stream_y) = transformer.clamp_to_bounds(stream_x, stream_y);
136
137 self.current_x = stream_x;
138 self.current_y = stream_y;
139
140 let timestamp = Instant::now();
141 self.last_event_time = Some(timestamp);
142
143 debug!(
144 "Mouse move: RDP({}, {}) -> Stream({:.2}, {:.2})",
145 rdp_x, rdp_y, stream_x, stream_y
146 );
147
148 Ok(MouseEvent::Move {
149 x: stream_x,
150 y: stream_y,
151 timestamp,
152 })
153 }
154
155 pub fn handle_relative_move(
157 &mut self,
158 delta_x: i32,
159 delta_y: i32,
160 transformer: &mut CoordinateTransformer,
161 ) -> Result<MouseEvent> {
162 let (stream_x, stream_y) = transformer.apply_relative_movement(delta_x, delta_y)?;
163
164 let (stream_x, stream_y) = transformer.clamp_to_bounds(stream_x, stream_y);
166
167 self.current_x = stream_x;
168 self.current_y = stream_y;
169
170 let timestamp = Instant::now();
171 self.last_event_time = Some(timestamp);
172
173 debug!(
174 "Mouse relative move: Delta({}, {}) -> Stream({:.2}, {:.2})",
175 delta_x, delta_y, stream_x, stream_y
176 );
177
178 Ok(MouseEvent::Move {
179 x: stream_x,
180 y: stream_y,
181 timestamp,
182 })
183 }
184
185 pub fn handle_button_down(&mut self, button: MouseButton) -> Result<MouseEvent> {
187 let button_index = Self::button_to_index(button);
188 self.button_states[button_index] = true;
189
190 let timestamp = Instant::now();
191 self.last_event_time = Some(timestamp);
192
193 debug!("Mouse button down: {:?}", button);
194
195 Ok(MouseEvent::ButtonDown { button, timestamp })
196 }
197
198 pub fn handle_button_up(&mut self, button: MouseButton) -> Result<MouseEvent> {
200 let button_index = Self::button_to_index(button);
201 self.button_states[button_index] = false;
202
203 let timestamp = Instant::now();
204 self.last_event_time = Some(timestamp);
205
206 debug!("Mouse button up: {:?}", button);
207
208 Ok(MouseEvent::ButtonUp { button, timestamp })
209 }
210
211 pub fn handle_scroll(&mut self, delta_x: i32, delta_y: i32) -> Result<MouseEvent> {
213 let timestamp = Instant::now();
214 self.last_event_time = Some(timestamp);
215
216 let (final_delta_x, final_delta_y) = if self.high_precision_scroll {
217 self.scroll_accum_x += delta_x as f64 / 120.0;
219 self.scroll_accum_y += delta_y as f64 / 120.0;
220
221 let x = self.scroll_accum_x.trunc() as i32;
222 let y = self.scroll_accum_y.trunc() as i32;
223
224 self.scroll_accum_x -= x as f64;
225 self.scroll_accum_y -= y as f64;
226
227 (x, y)
228 } else {
229 (delta_x / 120, delta_y / 120)
231 };
232
233 debug!("Mouse scroll: ({}, {})", final_delta_x, final_delta_y);
234
235 Ok(MouseEvent::Scroll {
236 delta_x: final_delta_x,
237 delta_y: final_delta_y,
238 timestamp,
239 })
240 }
241
242 pub fn current_position(&self) -> (f64, f64) {
244 (self.current_x, self.current_y)
245 }
246
247 pub fn is_button_pressed(&self, button: MouseButton) -> bool {
249 let index = Self::button_to_index(button);
250 self.button_states[index]
251 }
252
253 pub fn time_since_last_event(&self) -> Option<std::time::Duration> {
255 self.last_event_time.map(|t| t.elapsed())
256 }
257
258 pub fn set_high_precision_scroll(&mut self, enabled: bool) {
260 self.high_precision_scroll = enabled;
261 if !enabled {
262 self.scroll_accum_x = 0.0;
263 self.scroll_accum_y = 0.0;
264 }
265 }
266
267 fn button_to_index(button: MouseButton) -> usize {
269 match button {
270 MouseButton::Left => 0,
271 MouseButton::Right => 1,
272 MouseButton::Middle => 2,
273 MouseButton::Extra1 => 3,
274 MouseButton::Extra2 => 4,
275 }
276 }
277
278 pub fn reset(&mut self) {
280 self.button_states = [false; 5];
281 self.scroll_accum_x = 0.0;
282 self.scroll_accum_y = 0.0;
283 }
284}
285
286impl Default for MouseHandler {
287 fn default() -> Self {
288 Self::new()
289 }
290}
291
292#[cfg(test)]
293mod tests {
294 use super::*;
295 use crate::coordinates::MonitorInfo;
296
297 fn create_test_transformer() -> CoordinateTransformer {
298 let monitor = MonitorInfo {
299 id: 1,
300 name: "Primary".to_string(),
301 x: 0,
302 y: 0,
303 width: 1920,
304 height: 1080,
305 dpi: 96.0,
306 scale_factor: 1.0,
307 stream_x: 0,
308 stream_y: 0,
309 stream_width: 1920,
310 stream_height: 1080,
311 is_primary: true,
312 };
313
314 CoordinateTransformer::new(vec![monitor]).unwrap()
315 }
316
317 #[test]
318 fn test_mouse_handler_creation() {
319 let handler = MouseHandler::new();
320 let (x, y) = handler.current_position();
321 assert_eq!(x, 0.0);
322 assert_eq!(y, 0.0);
323 }
324
325 #[test]
326 fn test_absolute_move() {
327 let mut handler = MouseHandler::new();
328 let mut transformer = create_test_transformer();
329
330 let event = handler.handle_absolute_move(960, 540, &mut transformer).unwrap();
331
332 match event {
333 MouseEvent::Move { x, y, .. } => {
334 assert!(x > 0.0);
335 assert!(y > 0.0);
336 }
337 _ => panic!("Expected Move event"),
338 }
339
340 let (x, y) = handler.current_position();
341 assert!(x > 0.0);
342 assert!(y > 0.0);
343 }
344
345 #[test]
346 fn test_relative_move() {
347 let mut handler = MouseHandler::new();
348 let mut transformer = create_test_transformer();
349
350 let event = handler.handle_relative_move(10, 10, &mut transformer).unwrap();
351
352 match event {
353 MouseEvent::Move { .. } => {}
354 _ => panic!("Expected Move event"),
355 }
356 }
357
358 #[test]
359 fn test_button_press_release() {
360 let mut handler = MouseHandler::new();
361
362 let event = handler.handle_button_down(MouseButton::Left).unwrap();
364 match event {
365 MouseEvent::ButtonDown { button, .. } => {
366 assert_eq!(button, MouseButton::Left);
367 }
368 _ => panic!("Expected ButtonDown event"),
369 }
370
371 assert!(handler.is_button_pressed(MouseButton::Left));
372
373 let event = handler.handle_button_up(MouseButton::Left).unwrap();
375 match event {
376 MouseEvent::ButtonUp { button, .. } => {
377 assert_eq!(button, MouseButton::Left);
378 }
379 _ => panic!("Expected ButtonUp event"),
380 }
381
382 assert!(!handler.is_button_pressed(MouseButton::Left));
383 }
384
385 #[test]
386 fn test_scroll_event() {
387 let mut handler = MouseHandler::new();
388
389 let event = handler.handle_scroll(0, 120).unwrap();
390
391 match event {
392 MouseEvent::Scroll { delta_y, .. } => {
393 assert_eq!(delta_y, 1);
394 }
395 _ => panic!("Expected Scroll event"),
396 }
397 }
398
399 #[test]
400 fn test_high_precision_scroll() {
401 let mut handler = MouseHandler::new();
402 handler.set_high_precision_scroll(true);
403
404 for _ in 0..10 {
406 let _ = handler.handle_scroll(0, 12); }
408
409 let event = handler.handle_scroll(0, 0).unwrap();
411 match event {
412 MouseEvent::Scroll { delta_y, .. } => {
413 assert_eq!(delta_y, 0); }
415 _ => panic!("Expected Scroll event"),
416 }
417 }
418
419 #[test]
420 fn test_mouse_button_to_linux() {
421 assert_eq!(MouseButton::Left.to_linux_button(), 0x110);
422 assert_eq!(MouseButton::Right.to_linux_button(), 0x111);
423 assert_eq!(MouseButton::Middle.to_linux_button(), 0x112);
424 assert_eq!(MouseButton::Extra1.to_linux_button(), 0x113);
425 assert_eq!(MouseButton::Extra2.to_linux_button(), 0x114);
426 }
427
428 #[test]
429 fn test_mouse_button_from_rdp() {
430 assert_eq!(MouseButton::from_rdp_button(0x1000), Some(MouseButton::Left));
431 assert_eq!(MouseButton::from_rdp_button(0x2000), Some(MouseButton::Right));
432 assert_eq!(MouseButton::from_rdp_button(0x4000), Some(MouseButton::Middle));
433 assert_eq!(MouseButton::from_rdp_button(0x0080), Some(MouseButton::Extra1));
434 assert_eq!(MouseButton::from_rdp_button(0x0100), Some(MouseButton::Extra2));
435 assert_eq!(MouseButton::from_rdp_button(0x9999), None);
436 }
437
438 #[test]
439 fn test_multiple_button_states() {
440 let mut handler = MouseHandler::new();
441
442 handler.handle_button_down(MouseButton::Left).unwrap();
443 handler.handle_button_down(MouseButton::Right).unwrap();
444
445 assert!(handler.is_button_pressed(MouseButton::Left));
446 assert!(handler.is_button_pressed(MouseButton::Right));
447 assert!(!handler.is_button_pressed(MouseButton::Middle));
448
449 handler.handle_button_up(MouseButton::Left).unwrap();
450
451 assert!(!handler.is_button_pressed(MouseButton::Left));
452 assert!(handler.is_button_pressed(MouseButton::Right));
453 }
454
455 #[test]
456 fn test_mouse_reset() {
457 let mut handler = MouseHandler::new();
458
459 handler.handle_button_down(MouseButton::Left).unwrap();
460 handler.handle_button_down(MouseButton::Right).unwrap();
461 handler.scroll_accum_x = 5.0;
462 handler.scroll_accum_y = 5.0;
463
464 handler.reset();
465
466 assert!(!handler.is_button_pressed(MouseButton::Left));
467 assert!(!handler.is_button_pressed(MouseButton::Right));
468 assert_eq!(handler.scroll_accum_x, 0.0);
469 assert_eq!(handler.scroll_accum_y, 0.0);
470 }
471
472 #[test]
473 fn test_time_since_last_event() {
474 let mut handler = MouseHandler::new();
475
476 assert!(handler.time_since_last_event().is_none());
477
478 handler.handle_button_down(MouseButton::Left).unwrap();
479
480 assert!(handler.time_since_last_event().is_some());
481 assert!(handler.time_since_last_event().unwrap().as_millis() < 100);
482 }
483}