Fix crash and clean up frontend -> backend input handling code (#1770)

This commit is contained in:
Keavon Chambers 2024-06-03 01:09:22 -07:00 committed by GitHub
parent 72ccba09af
commit 449729f1e1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 47 additions and 53 deletions

View file

@ -3,7 +3,6 @@ use crate::messages::prelude::*;
use bitflags::bitflags;
use glam::DVec2;
use std::collections::VecDeque;
// Origin is top left
@ -37,16 +36,35 @@ impl ViewportBounds {
}
}
#[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Hash, serde::Serialize, serde::Deserialize)]
use std::hash::{Hash, Hasher};
#[derive(Debug, Copy, Clone, Default, serde::Serialize, serde::Deserialize)]
pub struct ScrollDelta {
// TODO: Switch these to `f64` values (not trivial because floats don't provide PartialEq, Eq, and Hash)
pub x: i32,
pub y: i32,
pub z: i32,
pub x: f64,
pub y: f64,
pub z: f64,
}
impl PartialEq for ScrollDelta {
fn eq(&self, other: &Self) -> bool {
self.x == other.x && self.y == other.y && self.z == other.z
}
}
impl Eq for ScrollDelta {}
impl Hash for ScrollDelta {
fn hash<H: Hasher>(&self, state: &mut H) {
let no_negative_zero = |value: f64| if value == 0. { 0. } else { value };
no_negative_zero(self.x).to_bits().hash(state);
no_negative_zero(self.y).to_bits().hash(state);
no_negative_zero(self.z).to_bits().hash(state);
}
}
impl ScrollDelta {
pub fn new(x: i32, y: i32, z: i32) -> Self {
pub fn new(x: f64, y: f64, z: f64) -> Self {
Self { x, y, z }
}
@ -56,10 +74,11 @@ impl ScrollDelta {
pub fn scroll_delta(&self) -> f64 {
let (dx, dy) = (self.x, self.y);
dy.signum() as f64 * ((dy * dy + i32::min(dy.abs(), dx.abs()).pow(2)) as f64).sqrt()
dy.signum() as f64 * ((dy * dy + f64::min(dy.abs(), dx.abs()).powi(2)) as f64).sqrt()
}
}
// TODO: Document the difference between this and EditorMouseState
#[derive(Debug, Copy, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct MouseState {
pub position: ViewportPosition,
@ -68,28 +87,6 @@ pub struct MouseState {
}
impl MouseState {
pub fn new() -> Self {
Self::default()
}
pub fn from_position(x: f64, y: f64) -> Self {
Self {
position: (x, y).into(),
mouse_keys: MouseKeys::default(),
scroll_delta: ScrollDelta::default(),
}
}
pub fn from_keys_and_editor_position(keys: u8, position: ViewportPosition) -> Self {
let mouse_keys = MouseKeys::from_bits(keys).expect("Invalid modifier keys");
Self {
position,
mouse_keys,
scroll_delta: ScrollDelta::default(),
}
}
pub fn finish_transaction(&self, drag_start: DVec2, responses: &mut VecDeque<Message>) {
match drag_start.distance(self.position) <= DRAG_THRESHOLD {
true => responses.add(DocumentMessage::AbortTransaction),
@ -98,6 +95,7 @@ impl MouseState {
}
}
// TODO: Document the difference between this and MouseState
#[derive(Debug, Copy, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct EditorMouseState {
pub editor_position: EditorPosition,
@ -106,20 +104,8 @@ pub struct EditorMouseState {
}
impl EditorMouseState {
pub fn new() -> Self {
Self::default()
}
pub fn from_editor_position(x: f64, y: f64) -> Self {
Self {
editor_position: (x, y).into(),
mouse_keys: MouseKeys::default(),
scroll_delta: ScrollDelta::default(),
}
}
pub fn from_keys_and_editor_position(keys: u8, editor_position: EditorPosition) -> Self {
let mouse_keys = MouseKeys::from_bits(keys).expect("Invalid modifier keys");
let mouse_keys = MouseKeys::from_bits(keys).expect("Invalid decoding of MouseKeys");
Self {
editor_position,
@ -138,12 +124,16 @@ impl EditorMouseState {
}
bitflags! {
/// Based on <https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/buttons#value>.
#[derive(Default, Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[repr(transparent)]
pub struct MouseKeys: u8 {
const LEFT = 0b0000_0001;
const RIGHT = 0b0000_0010;
const MIDDLE = 0b0000_0100;
const NONE = 0b0000_0000;
const LEFT = 0b0000_0001;
const RIGHT = 0b0000_0010;
const MIDDLE = 0b0000_0100;
const BACK = 0b0000_1000;
const FORWARD = 0b0001_0000;
}
}

View file

@ -181,7 +181,7 @@ impl InputPreprocessorMessageHandler {
#[cfg(test)]
mod test {
use crate::messages::input_mapper::utility_types::input_keyboard::{Key, ModifierKeys};
use crate::messages::input_mapper::utility_types::input_mouse::EditorMouseState;
use crate::messages::input_mapper::utility_types::input_mouse::{EditorMouseState, MouseKeys, ScrollDelta};
use crate::messages::portfolio::utility_types::KeyboardPlatformLayout;
use crate::messages::prelude::*;
@ -189,7 +189,11 @@ mod test {
fn process_action_mouse_move_handle_modifier_keys() {
let mut input_preprocessor = InputPreprocessorMessageHandler::default();
let editor_mouse_state = EditorMouseState::from_editor_position(4., 809.);
let editor_mouse_state = EditorMouseState {
editor_position: (4., 809.).into(),
mouse_keys: MouseKeys::default(),
scroll_delta: ScrollDelta::default(),
};
let modifier_keys = ModifierKeys::ALT;
let message = InputPreprocessorMessage::PointerMove { editor_mouse_state, modifier_keys };
@ -208,7 +212,7 @@ mod test {
fn process_action_mouse_down_handle_modifier_keys() {
let mut input_preprocessor = InputPreprocessorMessageHandler::default();
let editor_mouse_state = EditorMouseState::new();
let editor_mouse_state = EditorMouseState::default();
let modifier_keys = ModifierKeys::CONTROL;
let message = InputPreprocessorMessage::PointerDown { editor_mouse_state, modifier_keys };
@ -227,7 +231,7 @@ mod test {
fn process_action_mouse_up_handle_modifier_keys() {
let mut input_preprocessor = InputPreprocessorMessageHandler::default();
let editor_mouse_state = EditorMouseState::new();
let editor_mouse_state = EditorMouseState::default();
let modifier_keys = ModifierKeys::SHIFT;
let message = InputPreprocessorMessage::PointerUp { editor_mouse_state, modifier_keys };

View file

@ -145,7 +145,7 @@ impl MessageHandler<NavigationMessage, NavigationMessageData<'_>> for Navigation
NavigationMessage::CanvasZoomMouseWheel => {
let scroll = ipp.mouse.scroll_delta.scroll_delta();
let mut zoom_factor = 1. + scroll.abs() * VIEWPORT_ZOOM_WHEEL_RATE;
if ipp.mouse.scroll_delta.y > 0 {
if ipp.mouse.scroll_delta.y > 0. {
zoom_factor = 1. / zoom_factor
}
zoom_factor *= Self::clamp_zoom(ptz.zoom * zoom_factor, document_bounds, old_zoom, ipp);

View file

@ -73,7 +73,7 @@ impl EditorTestUtils for Editor {
}
fn move_mouse(&mut self, x: f64, y: f64) {
let mut editor_mouse_state = EditorMouseState::new();
let mut editor_mouse_state = EditorMouseState::default();
editor_mouse_state.editor_position = ViewportPosition::new(x, y);
let modifier_keys = ModifierKeys::default();
self.input(InputPreprocessorMessage::PointerMove { editor_mouse_state, modifier_keys });

View file

@ -355,7 +355,7 @@ impl EditorHandle {
/// Mouse scrolling within the screenspace bounds of the viewport
#[wasm_bindgen(js_name = onWheelScroll)]
pub fn on_wheel_scroll(&self, x: f64, y: f64, mouse_keys: u8, wheel_delta_x: i32, wheel_delta_y: i32, wheel_delta_z: i32, modifiers: u8) {
pub fn on_wheel_scroll(&self, x: f64, y: f64, mouse_keys: u8, wheel_delta_x: f64, wheel_delta_y: f64, wheel_delta_z: f64, modifiers: u8) {
let mut editor_mouse_state = EditorMouseState::from_keys_and_editor_position(mouse_keys, (x, y).into());
editor_mouse_state.scroll_delta = ScrollDelta::new(wheel_delta_x, wheel_delta_y, wheel_delta_z);