diff --git a/frontend/src/utility-functions/input.ts b/frontend/src/utility-functions/input.ts index 222ea4f364..8bcdce196d 100644 --- a/frontend/src/utility-functions/input.ts +++ b/frontend/src/utility-functions/input.ts @@ -123,7 +123,10 @@ export function onPointerMove(e: PointerEvent, editor: EditorWrapper, documentSt const modifiers = makeKeyboardModifiersBitfield(e); if (detectShake(e)) editor.onMouseShake(e.clientX, e.clientY, e.buttons, modifiers); - editor.onMouseMove(e.clientX, e.clientY, e.buttons, modifiers); + + const coalesced = e.pointerType === "pen" && typeof e.getCoalescedEvents === "function" ? e.getCoalescedEvents() : []; + const samples = coalesced.length > 0 ? coalesced : [e]; + for (const sample of samples) editor.onMouseMove(sample.clientX, sample.clientY, sample.buttons, modifiers, ...pointerAttributes(sample)); } export function onPointerDown(e: PointerEvent, editor: EditorWrapper, dialogStore: DialogStore) { @@ -152,7 +155,7 @@ export function onPointerDown(e: PointerEvent, editor: EditorWrapper, dialogStor if (viewportPointerInteractionOngoing && isTargetingCanvas instanceof Element) { const modifiers = makeKeyboardModifiersBitfield(e); - editor.onMouseDown(e.clientX, e.clientY, e.buttons, modifiers); + editor.onMouseDown(e.clientX, e.clientY, e.buttons, modifiers, ...pointerAttributes(e)); } } @@ -170,7 +173,7 @@ export function onPointerUp(e: PointerEvent, editor: EditorWrapper) { if (textToolInteractiveInputElement) return; const modifiers = makeKeyboardModifiersBitfield(e); - editor.onMouseUp(e.clientX, e.clientY, e.buttons, modifiers); + editor.onMouseUp(e.clientX, e.clientY, e.buttons, modifiers, ...pointerAttributes(e)); } // Mouse events @@ -277,6 +280,12 @@ export function onFocusOut() { canvasFocused = false; } +function pointerAttributes(e: PointerEvent): [number, number | undefined, number | undefined, number | undefined, number | undefined, number | undefined, boolean] { + const isPen = e.pointerType === "pen"; + const eraser = isPen && (e.buttons & 0b10_0000) !== 0; // Pen eraser end is reported as the 32 button bit + return [e.timeStamp, isPen ? e.pressure : undefined, isPen ? e.tiltX : undefined, isPen ? e.tiltY : undefined, isPen ? e.twist : undefined, isPen ? e.tangentialPressure : undefined, eraser]; +} + function detectShake(e: PointerEvent | MouseEvent): boolean { const SENSITIVITY_DIRECTION_CHANGES = 3; const SENSITIVITY_DISTANCE_TO_DISPLACEMENT_RATIO = 0.1; diff --git a/frontend/wrapper/src/editor_commands.rs b/frontend/wrapper/src/editor_commands.rs index 8b068eacc5..4ba3dc9529 100644 --- a/frontend/wrapper/src/editor_commands.rs +++ b/frontend/wrapper/src/editor_commands.rs @@ -299,8 +299,31 @@ mod editor_commands { } /// Mouse movement within the screenspace bounds of the viewport - fn on_mouse_move(x: f64, y: f64, mouse_keys: u8, modifiers: u8) -> Message { - let editor_mouse_state = EditorPointerState::from_keys_and_editor_position(mouse_keys, (x, y).into()); + fn on_mouse_move( + x: f64, + y: f64, + mouse_keys: u8, + modifiers: u8, + time: Option, + pressure: Option, + tilt_x: Option, + tilt_y: Option, + twist: Option, + tangential: Option, + eraser: bool, + ) -> Message { + let editor_mouse_state = EditorPointerState { + time, + pressure, + tilt: match (tilt_x, tilt_y) { + (Some(tilt_x), Some(tilt_y)) => Some((tilt_x, tilt_y).into()), + _ => None, + }, + twist, + wheel: tangential, + eraser, + ..EditorPointerState::from_keys_and_editor_position(mouse_keys, (x, y).into()) + }; let modifier_keys = ModifierKeys::from_bits(modifiers).expect("Invalid modifier keys"); InputPreprocessorMessage::PointerMove { editor_mouse_state, modifier_keys }.into() } @@ -314,15 +337,61 @@ mod editor_commands { } /// A mouse button depressed within screenspace the bounds of the viewport - fn on_mouse_down(x: f64, y: f64, mouse_keys: u8, modifiers: u8) -> Message { - let editor_mouse_state = EditorPointerState::from_keys_and_editor_position(mouse_keys, (x, y).into()); + fn on_mouse_down( + x: f64, + y: f64, + mouse_keys: u8, + modifiers: u8, + time: Option, + pressure: Option, + tilt_x: Option, + tilt_y: Option, + twist: Option, + tangential: Option, + eraser: bool, + ) -> Message { + let editor_mouse_state = EditorPointerState { + time, + pressure, + tilt: match (tilt_x, tilt_y) { + (Some(tilt_x), Some(tilt_y)) => Some((tilt_x, tilt_y).into()), + _ => None, + }, + twist, + wheel: tangential, + eraser, + ..EditorPointerState::from_keys_and_editor_position(mouse_keys, (x, y).into()) + }; let modifier_keys = ModifierKeys::from_bits(modifiers).expect("Invalid modifier keys"); InputPreprocessorMessage::PointerDown { editor_mouse_state, modifier_keys }.into() } /// A mouse button released - fn on_mouse_up(x: f64, y: f64, mouse_keys: u8, modifiers: u8) -> Message { - let editor_mouse_state = EditorPointerState::from_keys_and_editor_position(mouse_keys, (x, y).into()); + fn on_mouse_up( + x: f64, + y: f64, + mouse_keys: u8, + modifiers: u8, + time: Option, + pressure: Option, + tilt_x: Option, + tilt_y: Option, + twist: Option, + tangential: Option, + eraser: bool, + ) -> Message { + let editor_mouse_state = EditorPointerState { + time, + pressure, + tilt: match (tilt_x, tilt_y) { + (Some(tilt_x), Some(tilt_y)) => Some((tilt_x, tilt_y).into()), + _ => None, + }, + twist, + wheel: tangential, + eraser, + ..EditorPointerState::from_keys_and_editor_position(mouse_keys, (x, y).into()) + }; let modifier_keys = ModifierKeys::from_bits(modifiers).expect("Invalid modifier keys"); InputPreprocessorMessage::PointerUp { editor_mouse_state, modifier_keys }.into() }