1use keyboard_types::Modifiers;
4use kurbo::{Point, Vec2};
5
6#[repr(u8)]
8#[derive(PartialEq, Eq, Clone, Copy, Debug, Default)]
9pub enum PointerButton {
10 #[default]
11 None = 0,
12
13 Primary = 1,
15
16 Secondary = 2,
18
19 Auxiliary = 3,
21
22 X1 = 4,
24
25 X2 = 5,
27}
28
29impl From<isize> for PointerButton {
30 fn from(value: isize) -> Self {
31 match value {
32 0 => PointerButton::None,
33 1 => PointerButton::Primary,
34 2 => PointerButton::Secondary,
35 3 => PointerButton::Auxiliary,
36 4 => PointerButton::X1,
37 5 => PointerButton::X2,
38 _ => PointerButton::None,
39 }
40 }
41}
42
43impl PointerButton {
44 #[inline]
46 pub fn is_primary(self) -> bool {
47 self == PointerButton::Primary
48 }
49
50 #[inline]
52 pub fn is_secondary(self) -> bool {
53 self == PointerButton::Secondary
54 }
55
56 #[inline]
58 pub fn is_auxiliary(self) -> bool {
59 self == PointerButton::Auxiliary
60 }
61
62 #[inline]
64 pub fn is_x1(self) -> bool {
65 self == PointerButton::X1
66 }
67
68 #[inline]
70 pub fn is_x2(self) -> bool {
71 self == PointerButton::X2
72 }
73}
74
75#[derive(PartialEq, Eq, Clone, Copy, Default)]
77pub struct PointerButtons(u8);
78
79impl PointerButtons {
80 #[inline]
82 pub fn empty() -> PointerButtons {
83 PointerButtons(0)
84 }
85
86 #[inline]
87 fn mask(button: PointerButton) -> u8 {
88 match button {
89 PointerButton::None => 0,
90 _ => 1u8 << ((button as u8) - 1),
91 }
92 }
93
94 #[inline]
96 pub fn insert(&mut self, button: PointerButton) {
97 self.0 |= Self::mask(button);
98 }
99
100 #[inline]
102 pub fn insert_all(&mut self, buttons: PointerButtons) {
103 self.0 |= buttons.0;
104 }
105
106 #[inline]
108 pub fn remove(&mut self, button: PointerButton) {
109 self.0 &= !Self::mask(button);
110 }
111
112 #[inline]
114 pub fn remove_all(&mut self, buttons: PointerButtons) {
115 self.0 &= !buttons.0;
116 }
117
118 #[inline]
120 pub fn with(mut self, button: PointerButton) -> PointerButtons {
121 self.0 |= Self::mask(button);
122 self
123 }
124
125 #[inline]
127 pub fn without(mut self, button: PointerButton) -> PointerButtons {
128 self.0 &= !Self::mask(button);
129 self
130 }
131
132 #[inline]
134 pub fn clear(&mut self) {
135 self.0 = 0;
136 }
137
138 #[inline]
140 pub fn contains(self, button: PointerButton) -> bool {
141 (self.0 & Self::mask(button)) != 0
142 }
143
144 #[inline]
146 pub fn is_empty(self) -> bool {
147 self.0 == 0
148 }
149
150 #[inline]
152 pub fn is_superset(self, buttons: PointerButtons) -> bool {
153 self.0 & buttons.0 == buttons.0
154 }
155
156 #[inline]
158 pub fn has_primary(self) -> bool {
159 self.contains(PointerButton::Primary)
160 }
161
162 #[inline]
164 pub fn has_secondary(self) -> bool {
165 self.contains(PointerButton::Secondary)
166 }
167
168 #[inline]
170 pub fn has_auxiliary(self) -> bool {
171 self.contains(PointerButton::Auxiliary)
172 }
173
174 #[inline]
176 pub fn has_x1(self) -> bool {
177 self.contains(PointerButton::X1)
178 }
179
180 #[inline]
182 pub fn has_x2(self) -> bool {
183 self.contains(PointerButton::X2)
184 }
185}
186
187impl From<u8> for PointerButtons {
188 fn from(value: u8) -> Self {
189 PointerButtons(value & 0b1_1111)
190 }
191}
192
193impl std::fmt::Debug for PointerButtons {
194 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
195 write!(f, "PointerButtons({:05b})", self.0)
196 }
197}
198
199#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
201pub enum PointerType {
202 #[default]
203 Mouse,
204 Pen,
205}
206
207#[derive(Debug, Clone, Copy, Default)]
209pub struct PointerEvent {
210 pub viewport_pos: Point,
212
213 pub wheel_delta: Vec2,
215
216 pub button: PointerButton,
219
220 pub buttons: PointerButtons,
224
225 pub mods: Modifiers,
227
228 pub count: u8,
231
232 pub did_focus_window: bool,
234
235 pub pressure: f32,
238
239 pub tangential_pressure: f32,
242
243 pub tilt: Vec2,
245
246 pub twist: f32,
249
250 pub pointer_type: PointerType,
252}
253
254impl PointerEvent {
255 #[inline]
256 pub(crate) fn synthetic_move(viewport_pos: Point) -> Self {
257 Self {
258 viewport_pos,
259 button: PointerButton::None,
260 buttons: PointerButtons::empty(),
261 count: 0,
262 ..Self::default()
263 }
264 }
265
266 #[inline]
267 pub(crate) fn synthetic_primary_down(viewport_pos: Point, click_count: u8) -> Self {
268 let buttons = PointerButtons::empty().with(PointerButton::Primary);
269 Self {
270 viewport_pos,
271 button: PointerButton::Primary,
272 buttons,
273 count: click_count.max(1),
274 pressure: 1.0,
275 ..Self::default()
276 }
277 }
278
279 #[inline]
280 pub(crate) fn synthetic_primary_up(viewport_pos: Point) -> Self {
281 Self {
282 viewport_pos,
283 button: PointerButton::Primary,
284 buttons: PointerButtons::empty(),
285 count: 0,
286 pressure: 0.0,
287 ..Self::default()
288 }
289 }
290}