dioxus_html/
point_interaction.rs1use keyboard_types::Modifiers;
2
3use crate::{
4 geometry::{ClientPoint, Coordinates, ElementPoint, PagePoint, ScreenPoint},
5 input_data::{MouseButton, MouseButtonSet},
6};
7
8pub trait InteractionLocation {
10 fn client_coordinates(&self) -> ClientPoint;
12
13 fn screen_coordinates(&self) -> ScreenPoint;
15
16 fn page_coordinates(&self) -> PagePoint;
18}
19
20pub trait InteractionElementOffset: InteractionLocation {
22 fn coordinates(&self) -> Coordinates {
24 Coordinates::new(
25 self.screen_coordinates(),
26 self.client_coordinates(),
27 self.element_coordinates(),
28 self.page_coordinates(),
29 )
30 }
31
32 fn element_coordinates(&self) -> ElementPoint;
34}
35
36pub trait PointerInteraction: InteractionElementOffset + ModifiersInteraction {
38 fn trigger_button(&self) -> Option<MouseButton>;
40
41 fn held_buttons(&self) -> MouseButtonSet;
43}
44
45pub trait ModifiersInteraction {
47 fn modifiers(&self) -> Modifiers;
49}
50
51#[cfg(feature = "serialize")]
52#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone, Default)]
53pub struct SerializedPointInteraction {
54 pub alt_key: bool,
55
56 pub button: i16,
58
59 pub buttons: u16,
69
70 pub client_x: i32,
74
75 pub client_y: i32,
79
80 pub ctrl_key: bool,
82
83 pub meta_key: bool,
85
86 pub offset_x: i32,
88
89 pub offset_y: i32,
91
92 pub page_x: i32,
96
97 pub page_y: i32,
101
102 pub screen_x: i32,
104
105 pub screen_y: i32,
107
108 pub shift_key: bool,
110}
111
112#[cfg(feature = "serialize")]
113impl SerializedPointInteraction {
114 pub fn new(
115 trigger_button: Option<MouseButton>,
116 held_buttons: MouseButtonSet,
117 coordinates: Coordinates,
118 modifiers: Modifiers,
119 ) -> Self {
120 let alt_key = modifiers.contains(Modifiers::ALT);
121 let ctrl_key = modifiers.contains(Modifiers::CONTROL);
122 let meta_key = modifiers.contains(Modifiers::META);
123 let shift_key = modifiers.contains(Modifiers::SHIFT);
124
125 let [client_x, client_y]: [i32; 2] = coordinates.client().cast().into();
126 let [offset_x, offset_y]: [i32; 2] = coordinates.element().cast().into();
127 let [page_x, page_y]: [i32; 2] = coordinates.page().cast().into();
128 let [screen_x, screen_y]: [i32; 2] = coordinates.screen().cast().into();
129 Self {
130 button: trigger_button
131 .map_or(MouseButton::default(), |b| b)
132 .into_web_code(),
133 buttons: crate::input_data::encode_mouse_button_set(held_buttons),
134 meta_key,
135 ctrl_key,
136 shift_key,
137 alt_key,
138 client_x,
139 client_y,
140 screen_x,
141 screen_y,
142 offset_x,
143 offset_y,
144 page_x,
145 page_y,
146 }
147 }
148}
149
150#[cfg(feature = "serialize")]
151impl<E: PointerInteraction> From<&E> for SerializedPointInteraction {
152 fn from(data: &E) -> Self {
153 let trigger_button = data.trigger_button();
154 let held_buttons = data.held_buttons();
155 let coordinates = data.coordinates();
156 let modifiers = data.modifiers();
157 Self::new(trigger_button, held_buttons, coordinates, modifiers)
158 }
159}
160
161#[cfg(feature = "serialize")]
162impl PointerInteraction for SerializedPointInteraction {
163 fn held_buttons(&self) -> MouseButtonSet {
164 crate::input_data::decode_mouse_button_set(self.buttons)
165 }
166
167 fn trigger_button(&self) -> Option<MouseButton> {
168 Some(MouseButton::from_web_code(self.button))
169 }
170}
171
172#[cfg(feature = "serialize")]
173impl ModifiersInteraction for SerializedPointInteraction {
174 fn modifiers(&self) -> Modifiers {
175 let mut modifiers = Modifiers::empty();
176
177 if self.alt_key {
178 modifiers.insert(Modifiers::ALT);
179 }
180 if self.ctrl_key {
181 modifiers.insert(Modifiers::CONTROL);
182 }
183 if self.meta_key {
184 modifiers.insert(Modifiers::META);
185 }
186 if self.shift_key {
187 modifiers.insert(Modifiers::SHIFT);
188 }
189
190 modifiers
191 }
192}
193
194#[cfg(feature = "serialize")]
195impl InteractionLocation for SerializedPointInteraction {
196 fn client_coordinates(&self) -> ClientPoint {
197 ClientPoint::new(self.client_x.into(), self.client_y.into())
198 }
199
200 fn screen_coordinates(&self) -> ScreenPoint {
201 ScreenPoint::new(self.screen_x.into(), self.screen_y.into())
202 }
203
204 fn page_coordinates(&self) -> PagePoint {
205 PagePoint::new(self.page_x.into(), self.page_y.into())
206 }
207}
208
209#[cfg(feature = "serialize")]
210impl InteractionElementOffset for SerializedPointInteraction {
211 fn element_coordinates(&self) -> ElementPoint {
212 ElementPoint::new(self.offset_x.into(), self.offset_y.into())
213 }
214}