Skip to content

Commit 8b6d598

Browse files
committed
Let PressSource represent a mouse without a button
1 parent 0507a76 commit 8b6d598

File tree

2 files changed

+23
-34
lines changed

2 files changed

+23
-34
lines changed

crates/kas-core/src/event/cx/press.rs

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,9 @@ impl GrabMode {
6464

6565
/// Source of a [`Press`] event
6666
///
67-
/// This identifies the source of a click, touch or similar event, including
68-
/// which mouse button is pressed and whether this is a double-click (see
69-
/// [`Self::repetitions`]).
67+
/// This identifies the source of a click, touch or pointer motion. It
68+
/// identifies which mouse button is pressed (if any) and whether this is a
69+
/// double-click (see [`Self::repetitions`]).
7070
///
7171
/// This may be used to track a click/touch, but note that identifiers may be
7272
/// re-used after the event completes, thus an [`Event::PressStart`] with
@@ -80,10 +80,11 @@ impl PressSource {
8080
const FLAG_TOUCH: u64 = 1 << 63;
8181

8282
/// Construct a mouse source
83-
pub(crate) fn mouse(button: MouseButton, repetitions: u32) -> Self {
83+
pub(crate) fn mouse(button: Option<MouseButton>, repetitions: u32) -> Self {
8484
let r = (repetitions as u64) << 32;
8585
debug_assert!(r & Self::FLAG_TOUCH == 0);
86-
let b = button as u8;
86+
// Note: MouseButton::try_from_u8 returns None on u8::MAX
87+
let b = button.map(|b| b as u8).unwrap_or(u8::MAX);
8788
Self(r | b as u64)
8889
}
8990

@@ -120,8 +121,8 @@ impl PressSource {
120121

121122
/// Identify the mouse button used
122123
///
123-
/// This always returns `Some(_)` for mouse events and `None` for touch
124-
/// events.
124+
/// This returns `Some(button)` for mouse events with a button. It returns
125+
/// `None` for touch events and mouse events without a button (e.g. motion).
125126
pub fn mouse_button(self) -> Option<MouseButton> {
126127
if self.is_mouse() {
127128
let b = self.0 as u8;
@@ -134,29 +135,19 @@ impl PressSource {
134135
/// Returns true if this represents the left mouse button or a touch event
135136
#[inline]
136137
pub fn is_primary(self) -> bool {
137-
match self.mouse_button() {
138-
None => true,
139-
Some(MouseButton::Left) => true,
140-
Some(_) => false,
141-
}
138+
self.is_touch() || self.mouse_button() == Some(MouseButton::Left)
142139
}
143140

144141
/// Returns true if this represents the right mouse button
145142
#[inline]
146143
pub fn is_secondary(self) -> bool {
147-
match self.mouse_button() {
148-
Some(MouseButton::Right) => true,
149-
None | Some(_) => false,
150-
}
144+
self.mouse_button() == Some(MouseButton::Right)
151145
}
152146

153147
/// Returns true if this represents the middle mouse button
154148
#[inline]
155149
pub fn is_tertiary(self) -> bool {
156-
match self.mouse_button() {
157-
Some(MouseButton::Middle) => true,
158-
None | Some(_) => false,
159-
}
150+
self.mouse_button() == Some(MouseButton::Middle)
160151
}
161152

162153
/// The `repetitions` value
@@ -325,7 +316,7 @@ impl GrabBuilder {
325316
} else if let Some(finger_id) = source.finger_id() {
326317
cx.touch.start_grab(finger_id, id.clone(), position, mode)
327318
} else {
328-
unreachable!()
319+
false
329320
};
330321

331322
if success {

crates/kas-core/src/event/cx/press/mouse.rs

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@ use winit::event::{ElementState, MouseButton, MouseScrollDelta};
2121
// TODO: this should be configurable or derived from the system
2222
const DOUBLE_CLICK_TIMEOUT: Duration = Duration::from_secs(1);
2323

24-
const FAKE_MOUSE_BUTTON: MouseButton = MouseButton::Button32;
25-
2624
#[derive(Clone, Debug)]
2725
struct PanDetails {
2826
c0: DVec2,
@@ -69,7 +67,7 @@ pub(crate) struct Mouse {
6967
pub(super) over: Option<Id>, // widget under the mouse
7068
pub(super) icon: CursorIcon, // non-grab icon
7169
old_icon: CursorIcon, // last icon set (grab or non-grab)
72-
last_click_button: MouseButton,
70+
last_click_button: Option<MouseButton>,
7371
last_click_repetitions: u32,
7472
last_click_timeout: Instant,
7573
last_pin: Option<(Id, DVec2)>,
@@ -85,7 +83,7 @@ impl Default for Mouse {
8583
over: None,
8684
icon: CursorIcon::Default,
8785
old_icon: CursorIcon::Default,
88-
last_click_button: FAKE_MOUSE_BUTTON,
86+
last_click_button: None,
8987
last_click_repetitions: 0,
9088
last_click_timeout: Instant::now(),
9189
last_pin: None,
@@ -287,7 +285,7 @@ impl<'a> EventCx<'a> {
287285
} else {
288286
last_pin = None;
289287
let press = Press {
290-
source: PressSource::mouse(grab.button, grab.repetitions),
288+
source: PressSource::mouse(Some(grab.button), grab.repetitions),
291289
id: self.mouse.over.clone(),
292290
coord: self.mouse.last_position.cast_nearest(),
293291
};
@@ -349,7 +347,7 @@ impl<'a> EventCx<'a> {
349347
self.mouse.samples.push_delta(delta);
350348
}
351349
self.mouse.last_position = position;
352-
self.mouse.last_click_button = FAKE_MOUSE_BUTTON;
350+
self.mouse.last_click_button = None;
353351

354352
self.set_over(window.re(), id.clone());
355353

@@ -359,7 +357,7 @@ impl<'a> EventCx<'a> {
359357
GrabDetails::Grab => {
360358
let target = grab.start_id.clone();
361359
let press = Press {
362-
source: PressSource::mouse(grab.button, grab.repetitions),
360+
source: PressSource::mouse(Some(grab.button), grab.repetitions),
363361
id,
364362
coord,
365363
};
@@ -380,7 +378,7 @@ impl<'a> EventCx<'a> {
380378
.map(|state| state.desc.id.clone())
381379
{
382380
let press = Press {
383-
source: PressSource::mouse(FAKE_MOUSE_BUTTON, 0),
381+
source: PressSource::mouse(None, 0),
384382
id,
385383
coord,
386384
};
@@ -397,7 +395,7 @@ impl<'a> EventCx<'a> {
397395

398396
/// Handle mouse cursor leaving the app.
399397
pub(in crate::event::cx) fn handle_cursor_left(&mut self, window: Node<'_>) {
400-
self.mouse.last_click_button = FAKE_MOUSE_BUTTON;
398+
self.mouse.last_click_button = None;
401399

402400
if self.mouse.grab.is_none() {
403401
self.set_over(window, None);
@@ -410,7 +408,7 @@ impl<'a> EventCx<'a> {
410408
window: Node<'_>,
411409
delta: MouseScrollDelta,
412410
) {
413-
self.mouse.last_click_button = FAKE_MOUSE_BUTTON;
411+
self.mouse.last_click_button = None;
414412

415413
let event = Event::Scroll(match delta {
416414
MouseScrollDelta::LineDelta(x, y) => ScrollDelta::Lines(x, y),
@@ -432,8 +430,8 @@ impl<'a> EventCx<'a> {
432430
) {
433431
if state == ElementState::Pressed {
434432
let now = Instant::now();
435-
if button != self.mouse.last_click_button || self.mouse.last_click_timeout < now {
436-
self.mouse.last_click_button = button;
433+
if Some(button) != self.mouse.last_click_button || self.mouse.last_click_timeout < now {
434+
self.mouse.last_click_button = Some(button);
437435
self.mouse.last_click_repetitions = 0;
438436
}
439437
self.mouse.last_click_repetitions += 1;
@@ -466,7 +464,7 @@ impl<'a> EventCx<'a> {
466464
self.set_nav_focus(id, FocusSource::Pointer);
467465
}
468466

469-
let source = PressSource::mouse(button, self.mouse.last_click_repetitions);
467+
let source = PressSource::mouse(Some(button), self.mouse.last_click_repetitions);
470468
let press = PressStart {
471469
source,
472470
id: Some(id.clone()),

0 commit comments

Comments
 (0)