kozan_platform/pipeline/
input_state.rs1use kozan_core::input::{ButtonState, Modifiers, MouseButton};
7
8pub struct InputState {
13 cursor_x: f64,
14 cursor_y: f64,
15 scale_factor: f64,
16 modifiers: Modifiers,
17}
18
19impl InputState {
20 pub fn new(scale_factor: f64) -> Self {
21 Self {
22 cursor_x: 0.0,
23 cursor_y: 0.0,
24 scale_factor,
25 modifiers: Modifiers::EMPTY,
26 }
27 }
28
29 pub fn set_cursor_physical(&mut self, px: f64, py: f64) {
30 self.cursor_x = px / self.scale_factor;
31 self.cursor_y = py / self.scale_factor;
32 }
33
34 pub fn cursor(&self) -> (f64, f64) {
35 (self.cursor_x, self.cursor_y)
36 }
37
38 pub fn set_scale_factor(&mut self, factor: f64) {
39 self.scale_factor = factor;
40 }
41
42 pub fn scale_factor(&self) -> f64 {
43 self.scale_factor
44 }
45
46 pub fn modifiers(&self) -> Modifiers {
47 self.modifiers
48 }
49
50 pub fn set_modifiers_from_keyboard(&mut self, shift: bool, ctrl: bool, alt: bool, meta: bool) {
51 let mut m = Modifiers::EMPTY;
52 if shift {
53 m = m.with_shift();
54 }
55 if ctrl {
56 m = m.with_ctrl();
57 }
58 if alt {
59 m = m.with_alt();
60 }
61 if meta {
62 m = m.with_meta();
63 }
64 let mouse_bits = self.modifiers.bits() & Self::MOUSE_BUTTON_MASK;
65 self.modifiers = Modifiers::from_bits(m.bits() | mouse_bits);
66 }
67
68 pub fn update_button_modifier(&mut self, button: &MouseButton, state: ButtonState) {
69 let flag = match button {
70 MouseButton::Left => Modifiers::EMPTY.with_left_button(),
71 MouseButton::Right => Modifiers::EMPTY.with_right_button(),
72 MouseButton::Middle => Modifiers::EMPTY.with_middle_button(),
73 _ => return,
74 };
75 match state {
76 ButtonState::Pressed => self.modifiers |= flag,
77 ButtonState::Released => {
78 self.modifiers = Modifiers::from_bits(self.modifiers.bits() & !flag.bits());
79 }
80 }
81 }
82
83 const MOUSE_BUTTON_MASK: u16 = {
84 let l = Modifiers::EMPTY.with_left_button().bits();
85 let r = Modifiers::EMPTY.with_right_button().bits();
86 let m = Modifiers::EMPTY.with_middle_button().bits();
87 l | r | m
88 };
89}
90
91#[cfg(test)]
92mod tests {
93 use super::*;
94
95 #[test]
96 fn physical_to_logical_conversion() {
97 let mut state = InputState::new(2.0);
98 state.set_cursor_physical(200.0, 400.0);
99 assert_eq!(state.cursor(), (100.0, 200.0));
100 }
101
102 #[test]
103 fn modifiers_keyboard_preserves_mouse() {
104 let mut state = InputState::new(1.0);
105 state.update_button_modifier(&MouseButton::Left, ButtonState::Pressed);
106 state.set_modifiers_from_keyboard(true, false, false, false);
107 assert!(state.modifiers().shift());
108 assert!(state.modifiers().left_button());
109 }
110
111 #[test]
112 fn scale_factor_change() {
113 let mut state = InputState::new(1.0);
114 state.set_cursor_physical(100.0, 100.0);
115 assert_eq!(state.cursor(), (100.0, 100.0));
116 state.set_scale_factor(2.0);
117 state.set_cursor_physical(100.0, 100.0);
118 assert_eq!(state.cursor(), (50.0, 50.0));
119 }
120}