From c35dddc203f0011fb1183864caeb98e5c380e375 Mon Sep 17 00:00:00 2001 From: Reinis Mazeiks Date: Sat, 7 May 2022 10:31:05 +0300 Subject: [PATCH] Create constructor for MouseData --- packages/html/src/events.rs | 71 +++++++++++++++++++++++------------- packages/html/src/input.rs | 73 +++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+), 26 deletions(-) diff --git a/packages/html/src/events.rs b/packages/html/src/events.rs index 414639523..4f2507292 100644 --- a/packages/html/src/events.rs +++ b/packages/html/src/events.rs @@ -5,8 +5,10 @@ use dioxus_core::*; pub mod on { //! Input events and associated data - use crate::geometry::{ClientPoint, ElementPoint, PagePoint, ScreenPoint}; - use crate::input::{MouseButton, MouseButtonSet}; + use crate::geometry::{ClientPoint, Coordinates, ElementPoint, PagePoint, ScreenPoint}; + use crate::input::{ + decode_mouse_button_set, encode_mouse_button_set, MouseButton, MouseButtonSet, + }; use enumset::EnumSet; use keyboard_types::Modifiers; use std::collections::HashMap; @@ -502,6 +504,9 @@ pub mod on { pub type MouseEvent = UiEvent; #[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))] #[derive(Debug, Clone)] + /// Data associated with a mouse event + /// + /// Do not use the deprecated fields; they may change or become private in the future. pub struct MouseData { /// True if the alt key was down when the mouse event was fired. #[deprecated(since = "0.3.0", note = "use modifiers() instead")] @@ -565,6 +570,43 @@ pub mod on { } impl MouseData { + pub fn new( + coordinates: Coordinates, + trigger_button: MouseButton, + held_buttons: MouseButtonSet, + modifiers: Modifiers, + ) -> Self { + let alt_key = modifiers.contains(Modifiers::ALT); + let ctrl_key = modifiers.contains(Modifiers::CONTROL); + let meta_key = modifiers.contains(Modifiers::META); + let shift_key = modifiers.contains(Modifiers::SHIFT); + + let [client_x, client_y]: [i32; 2] = coordinates.client().cast().into(); + let [offset_x, offset_y]: [i32; 2] = coordinates.element().cast().into(); + let [page_x, page_y]: [i32; 2] = coordinates.page().cast().into(); + let [screen_x, screen_y]: [i32; 2] = coordinates.screen().cast().into(); + + #[allow(deprecated)] + Self { + alt_key, + ctrl_key, + meta_key, + shift_key, + + button: trigger_button.into_web_code(), + buttons: encode_mouse_button_set(held_buttons), + + client_x, + client_y, + offset_x, + offset_y, + page_x, + page_y, + screen_x, + screen_y, + } + } + /// The event's coordinates relative to the application's viewport (as opposed to the coordinate within the page). /// /// For example, clicking in the top left corner of the viewport will always result in a mouse event with client coordinates (0., 0.), regardless of whether the page is scrolled horizontally. @@ -620,31 +662,8 @@ pub mod on { /// The set of mouse buttons which were held when the event occurred. pub fn held_buttons(&self) -> MouseButtonSet { - let mut set = EnumSet::empty(); - - // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/buttons #[allow(deprecated)] - { - if self.buttons & 0b1 != 0 { - set |= MouseButton::Primary; - } - if self.buttons & 0b10 != 0 { - set |= MouseButton::Secondary; - } - if self.buttons & 0b100 != 0 { - set |= MouseButton::Auxiliary; - } - if self.buttons & 0b1000 != 0 { - set |= MouseButton::Fourth; - } - if self.buttons & 0b10000 != 0 { - set |= MouseButton::Fifth; - } - if self.buttons & (!0b11111) != 0 { - set |= MouseButton::Unknown; - } - } - set + decode_mouse_button_set(self.buttons) } /// The mouse button that triggered the event diff --git a/packages/html/src/input.rs b/packages/html/src/input.rs index 7c722b384..b5bc73a44 100644 --- a/packages/html/src/input.rs +++ b/packages/html/src/input.rs @@ -41,7 +41,80 @@ impl MouseButton { _ => MouseButton::Unknown, } } + + /// Converts MouseButton into the corresponding button code + /// + /// MouseButton::Unknown will get mapped to -1 + pub fn into_web_code(self) -> i16 { + match self { + MouseButton::Primary => 0, + // not a typo; auxiliary and secondary are swapped unlike in the `buttons` field. + // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button + MouseButton::Auxiliary => 1, + MouseButton::Secondary => 2, + MouseButton::Fourth => 3, + MouseButton::Fifth => 4, + MouseButton::Unknown => -1, + } + } } /// A set of mouse buttons pub type MouseButtonSet = EnumSet; + +pub fn decode_mouse_button_set(code: u16) -> MouseButtonSet { + let mut set = EnumSet::empty(); + + // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/buttons + #[allow(deprecated)] + { + if code & 0b1 != 0 { + set |= MouseButton::Primary; + } + if code & 0b10 != 0 { + set |= MouseButton::Secondary; + } + if code & 0b100 != 0 { + set |= MouseButton::Auxiliary; + } + if code & 0b1000 != 0 { + set |= MouseButton::Fourth; + } + if code & 0b10000 != 0 { + set |= MouseButton::Fifth; + } + if code & (!0b11111) != 0 { + set |= MouseButton::Unknown; + } + } + + set +} + +pub fn encode_mouse_button_set(set: MouseButtonSet) -> u16 { + let mut code = 0; + + // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/buttons + { + if set.contains(MouseButton::Primary) { + code |= 0b1; + } + if set.contains(MouseButton::Secondary) { + code |= 0b10; + } + if set.contains(MouseButton::Auxiliary) { + code |= 0b100; + } + if set.contains(MouseButton::Fourth) { + code |= 0b1000; + } + if set.contains(MouseButton::Fifth) { + code |= 0b10000; + } + if set.contains(MouseButton::Unknown) { + code |= 0b100000; + } + } + + code +}