mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2025-08-04 05:18:19 +00:00
Fix crash and clean up frontend -> backend input handling code (#1770)
This commit is contained in:
parent
72ccba09af
commit
449729f1e1
5 changed files with 47 additions and 53 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 };
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 });
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue