Skip to content

Commit 973cfe7

Browse files
committed
[u] Add MousePressure event
Upstreams 07bf685feee40cc541b2764300815a600356188c
1 parent 6c9e61a commit 973cfe7

5 files changed

Lines changed: 113 additions & 9 deletions

File tree

crates/gpui/src/elements/div.rs

Lines changed: 54 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ use super::ImageCacheProvider;
4040
use crate::{
4141
Action, AnyDrag, AnyElement, AnyTooltip, AnyView, App, ClickEvent, DispatchPhase, Display, Element, ElementId, Entity, FocusHandle, Global,
4242
GlobalElementId, Hitbox, HitboxBehavior, HitboxId, IntoElement, KeyContext, KeyDownEvent, KeyUpEvent, KeyboardButton, KeyboardClickEvent, LayoutId,
43-
ModifiersChangedEvent, MouseButton, MouseClickEvent, MouseDownEvent, MouseMoveEvent, MouseUpEvent, Overflow, ParentElement, Render, ScrollWheelEvent,
44-
Style, StyleRefinement, Styled, Task, TooltipId, Visibility, Window, WindowControlArea
43+
ModifiersChangedEvent, MouseButton, MouseClickEvent, MouseDownEvent, MouseMoveEvent, MousePressureEvent, MouseUpEvent, Overflow, ParentElement, Render,
44+
ScrollWheelEvent, Style, StyleRefinement, Styled, Task, TooltipId, Visibility, Window, WindowControlArea
4545
};
4646

4747
const DRAG_THRESHOLD: f64 = 2.;
@@ -126,6 +126,30 @@ impl Interactivity {
126126
}));
127127
}
128128

129+
/// Bind the given callback to the mouse pressure event, during the bubble phase
130+
/// the imperative API equivalent to [`InteractiveElement::on_mouse_pressure`].
131+
///
132+
/// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback.
133+
pub fn on_mouse_pressure(&mut self, listener: impl Fn(&MousePressureEvent, &mut Window, &mut App) + 'static) {
134+
self.mouse_pressure_listeners.push(Box::new(move |event, phase, hitbox, window, cx| {
135+
if phase == DispatchPhase::Bubble && hitbox.is_hovered(window) {
136+
(listener)(event, window, cx)
137+
}
138+
}));
139+
}
140+
141+
/// Bind the given callback to the mouse pressure event, during the capture phase
142+
/// the imperative API equivalent to [`InteractiveElement::on_mouse_pressure`].
143+
///
144+
/// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback.
145+
pub fn capture_mouse_pressure(&mut self, listener: impl Fn(&MousePressureEvent, &mut Window, &mut App) + 'static) {
146+
self.mouse_pressure_listeners.push(Box::new(move |event, phase, hitbox, window, cx| {
147+
if phase == DispatchPhase::Capture && hitbox.is_hovered(window) {
148+
(listener)(event, window, cx)
149+
}
150+
}));
151+
}
152+
129153
/// Bind the given callback to the mouse up event for the given button, during the bubble phase.
130154
/// The imperative API equivalent to [`InteractiveElement::on_mouse_up`].
131155
///
@@ -597,6 +621,24 @@ pub trait InteractiveElement: Sized {
597621
self
598622
}
599623

624+
/// Bind the given callback to the mouse pressure event, during the bubble phase
625+
/// the fluent API equivalent to [`Interactivity::on_mouse_pressure`]
626+
///
627+
/// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback.
628+
fn on_mouse_pressure(mut self, listener: impl Fn(&MousePressureEvent, &mut Window, &mut App) + 'static) -> Self {
629+
self.interactivity().on_mouse_pressure(listener);
630+
self
631+
}
632+
633+
/// Bind the given callback to the mouse pressure event, during the capture phase
634+
/// the fluent API equivalent to [`Interactivity::on_mouse_pressure`]
635+
///
636+
/// See [`Context::listener`](crate::Context::listener) to get access to a view's state from this callback.
637+
fn capture_mouse_pressure(mut self, listener: impl Fn(&MousePressureEvent, &mut Window, &mut App) + 'static) -> Self {
638+
self.interactivity().capture_mouse_pressure(listener);
639+
self
640+
}
641+
600642
/// Bind the given callback to the mouse up event for the given button, during the bubble phase.
601643
/// The fluent API equivalent to [`Interactivity::on_mouse_up`].
602644
///
@@ -972,17 +1014,13 @@ pub trait StatefulInteractiveElement: InteractiveElement {
9721014

9731015
pub(crate) type MouseDownListener = Box<dyn Fn(&MouseDownEvent, DispatchPhase, &Hitbox, &mut Window, &mut App) + 'static>;
9741016
pub(crate) type MouseUpListener = Box<dyn Fn(&MouseUpEvent, DispatchPhase, &Hitbox, &mut Window, &mut App) + 'static>;
975-
9761017
pub(crate) type MouseMoveListener = Box<dyn Fn(&MouseMoveEvent, DispatchPhase, &Hitbox, &mut Window, &mut App) + 'static>;
977-
1018+
pub(crate) type MousePressureListener = Box<dyn Fn(&MousePressureEvent, DispatchPhase, &Hitbox, &mut Window, &mut App) + 'static>;
9781019
pub(crate) type ScrollWheelListener = Box<dyn Fn(&ScrollWheelEvent, DispatchPhase, &Hitbox, &mut Window, &mut App) + 'static>;
979-
9801020
pub(crate) type ClickListener = Rc<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>;
981-
9821021
pub(crate) type DragListener = Box<dyn Fn(&dyn Any, Point<Pixels>, &mut Window, &mut App) -> AnyView + 'static>;
9831022

9841023
type DropListener = Box<dyn Fn(&dyn Any, &mut Window, &mut App) + 'static>;
985-
9861024
type CanDropPredicate = Box<dyn Fn(&dyn Any, &mut Window, &mut App) -> bool + 'static>;
9871025

9881026
pub(crate) struct TooltipBuilder {
@@ -1227,6 +1265,7 @@ pub struct Interactivity {
12271265
pub(crate) group_drag_over_styles: Vec<(TypeId, GroupStyle)>,
12281266
pub(crate) mouse_down_listeners: Vec<MouseDownListener>,
12291267
pub(crate) mouse_up_listeners: Vec<MouseUpListener>,
1268+
pub(crate) mouse_pressure_listeners: Vec<MousePressureListener>,
12301269
pub(crate) mouse_move_listeners: Vec<MouseMoveListener>,
12311270
pub(crate) scroll_wheel_listeners: Vec<ScrollWheelListener>,
12321271
pub(crate) key_down_listeners: Vec<KeyDownListener>,
@@ -1369,6 +1408,7 @@ impl Interactivity {
13691408
|| self.hover_listener.is_some()
13701409
|| !self.mouse_up_listeners.is_empty()
13711410
|| !self.mouse_down_listeners.is_empty()
1411+
|| !self.mouse_pressure_listeners.is_empty()
13721412
|| !self.mouse_move_listeners.is_empty()
13731413
|| !self.click_listeners.is_empty()
13741414
|| !self.scroll_wheel_listeners.is_empty()
@@ -1583,6 +1623,13 @@ impl Interactivity {
15831623
})
15841624
}
15851625

1626+
for listener in self.mouse_pressure_listeners.drain(..) {
1627+
let hitbox = hitbox.clone();
1628+
window.on_mouse_event(move |event: &MousePressureEvent, phase, window, cx| {
1629+
listener(event, phase, &hitbox, window, cx);
1630+
})
1631+
}
1632+
15861633
for listener in self.mouse_move_listeners.drain(..) {
15871634
let hitbox = hitbox.clone();
15881635
window.on_mouse_event(move |event: &MouseMoveEvent, phase, window, cx| {

crates/gpui/src/interactive.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,40 @@ pub struct MouseClickEvent {
174174
pub up: MouseUpEvent
175175
}
176176

177+
/// The stage of a pressure click event.
178+
#[derive(Clone, Copy, Debug, Default, PartialEq)]
179+
pub enum PressureStage {
180+
/// No pressure.
181+
#[default]
182+
Zero,
183+
/// Normal click pressure.
184+
Normal,
185+
/// High pressure, enough to trigger a force click.
186+
Force
187+
}
188+
189+
/// A mouse pressure event from the platform. Generated when a force-sensitive trackpad is pressed hard.
190+
/// Currently only implemented for macOS trackpads.
191+
#[derive(Debug, Clone, Default)]
192+
pub struct MousePressureEvent {
193+
/// Pressure of the current stage as a float between 0 and 1
194+
pub pressure: f32,
195+
/// The pressure stage of the event.
196+
pub stage: PressureStage,
197+
/// The position of the mouse on the window.
198+
pub position: Point<Pixels>,
199+
/// The modifiers that were held down when the mouse pressure changed.
200+
pub modifiers: Modifiers
201+
}
202+
203+
impl Sealed for MousePressureEvent {}
204+
impl InputEvent for MousePressureEvent {
205+
fn to_platform_input(self) -> PlatformInput {
206+
PlatformInput::MousePressure(self)
207+
}
208+
}
209+
impl MouseEvent for MousePressureEvent {}
210+
177211
/// A click event that was generated by a keyboard button being pressed and released.
178212
#[derive(Clone, Debug, Default)]
179213
pub struct KeyboardClickEvent {
@@ -544,6 +578,8 @@ pub enum PlatformInput {
544578
MouseDown(MouseDownEvent),
545579
/// The mouse was released.
546580
MouseUp(MouseUpEvent),
581+
/// Mouse pressure.
582+
MousePressure(MousePressureEvent),
547583
/// The mouse was moved.
548584
MouseMove(MouseMoveEvent),
549585
/// The mouse exited the window.
@@ -562,6 +598,7 @@ impl PlatformInput {
562598
PlatformInput::ModifiersChanged { .. } => None,
563599
PlatformInput::MouseDown(event) => Some(event),
564600
PlatformInput::MouseUp(event) => Some(event),
601+
PlatformInput::MousePressure(event) => Some(event),
565602
PlatformInput::MouseMove(event) => Some(event),
566603
PlatformInput::MouseExited(event) => Some(event),
567604
PlatformInput::ScrollWheel(event) => Some(event),
@@ -576,6 +613,7 @@ impl PlatformInput {
576613
PlatformInput::ModifiersChanged(event) => Some(event),
577614
PlatformInput::MouseDown(_) => None,
578615
PlatformInput::MouseUp(_) => None,
616+
PlatformInput::MousePressure(_) => None,
579617
PlatformInput::MouseMove(_) => None,
580618
PlatformInput::MouseExited(_) => None,
581619
PlatformInput::ScrollWheel(_) => None,

crates/gpui/src/platform/mac/events.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ use core_graphics::event::CGKeyCode;
99
use objc::{msg_send, sel, sel_impl};
1010

1111
use crate::{
12-
Capslock, KeyDownEvent, KeyUpEvent, Keystroke, Modifiers, ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseExitEvent, MouseMoveEvent, MouseUpEvent,
13-
NavigationDirection, Pixels, PlatformInput, ScrollDelta, ScrollWheelEvent, TouchPhase,
12+
Capslock, KeyDownEvent, KeyUpEvent, Keystroke, Modifiers, ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseExitEvent, MouseMoveEvent,
13+
MousePressureEvent, MouseUpEvent, NavigationDirection, Pixels, PlatformInput, PressureStage, ScrollDelta, ScrollWheelEvent, TouchPhase,
1414
platform::mac::{
1515
LMGetKbdType, NSStringExt, TISCopyCurrentKeyboardLayoutInputSource, TISGetInputSourceProperty, UCKeyTranslate, kTISPropertyUnicodeKeyLayoutData
1616
},
@@ -173,6 +173,23 @@ impl PlatformInput {
173173
})
174174
})
175175
}
176+
NSEventType::NSEventTypePressure => {
177+
let stage = native_event.stage();
178+
let pressure = native_event.pressure();
179+
180+
window_height.map(|window_height| {
181+
Self::MousePressure(MousePressureEvent {
182+
stage: match stage {
183+
1 => PressureStage::Normal,
184+
2 => PressureStage::Force,
185+
_ => PressureStage::Zero
186+
},
187+
pressure,
188+
modifiers: read_modifiers(native_event),
189+
position: point(px(native_event.locationInWindow().x as f32), window_height - px(native_event.locationInWindow().y as f32))
190+
})
191+
})
192+
}
176193
// Some mice (like Logitech MX Master) send navigation buttons as swipe events
177194
NSEventType::NSEventTypeSwipe => {
178195
let navigation_direction = match native_event.phase() {

crates/gpui/src/platform/mac/window.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ unsafe fn build_classes() {
112112
decl.add_method(sel!(otherMouseDown:), handle_view_event as extern "C" fn(&Object, Sel, id));
113113
decl.add_method(sel!(otherMouseUp:), handle_view_event as extern "C" fn(&Object, Sel, id));
114114
decl.add_method(sel!(mouseMoved:), handle_view_event as extern "C" fn(&Object, Sel, id));
115+
decl.add_method(sel!(pressureChangeWithEvent:), handle_view_event as extern "C" fn(&Object, Sel, id));
115116
decl.add_method(sel!(mouseExited:), handle_view_event as extern "C" fn(&Object, Sel, id));
116117
decl.add_method(sel!(mouseDragged:), handle_view_event as extern "C" fn(&Object, Sel, id));
117118
decl.add_method(sel!(scrollWheel:), handle_view_event as extern "C" fn(&Object, Sel, id));

crates/gpui/src/window.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3275,6 +3275,7 @@ impl Window {
32753275
self.modifiers = mouse_up.modifiers;
32763276
PlatformInput::MouseUp(mouse_up)
32773277
}
3278+
PlatformInput::MousePressure(mouse_pressure) => PlatformInput::MousePressure(mouse_pressure),
32783279
PlatformInput::MouseExited(mouse_exited) => {
32793280
self.modifiers = mouse_exited.modifiers;
32803281
PlatformInput::MouseExited(mouse_exited)

0 commit comments

Comments
 (0)