summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBen Bridle <ben@derelict.engineering>2024-12-16 14:22:33 +1300
committerBen Bridle <ben@derelict.engineering>2024-12-16 14:22:33 +1300
commit393d4f309ba238f81d100aae409a784f82d88c15 (patch)
treea6ce747bde68b5ac93efaf308cb63442e5e87604 /src
parent598e503f9898580b40c7a63b343eb2b1d168c2c3 (diff)
downloadphosphor-393d4f309ba238f81d100aae409a784f82d88c15.zip
Only send Event::CursorExit when all mouse buttons are released
This is to allow a user to drag an element inside the program window and for the mouse cursor to move in and out of the window during the drag operation. This is the intuitive and expected behaviour.
Diffstat (limited to 'src')
-rw-r--r--src/lib.rs2
-rw-r--r--src/phosphor.rs22
-rw-r--r--src/window.rs12
3 files changed, 34 insertions, 2 deletions
diff --git a/src/lib.rs b/src/lib.rs
index acf8287..1da2e91 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -5,7 +5,7 @@ mod window_program;
mod phosphor;
pub use events::{Request, Event, Action, Axis, MouseButton, SizeBounds};
-pub(crate) use window::PhosphorWindow;
+pub(crate) use window::{PhosphorWindow, PointerState};
pub use window_builder::WindowBuilder;
pub use window_program::WindowProgram;
diff --git a/src/phosphor.rs b/src/phosphor.rs
index ab13cb0..08c71da 100644
--- a/src/phosphor.rs
+++ b/src/phosphor.rs
@@ -134,10 +134,16 @@ impl PhosphorApplication {
}
}
WindowEvent::CursorEntered { .. } => {
+ window.pointer_state = PointerState::In;
handle!(Event::CursorEnter);
}
WindowEvent::CursorLeft { .. } => {
- handle!(Event::CursorExit);
+ if window.mouse_buttons.iter().all(|b| !b) {
+ window.pointer_state = PointerState::Out;
+ handle!(Event::CursorExit);
+ } else {
+ window.pointer_state = PointerState::PendingOut;
+ }
}
WindowEvent::MouseWheel { delta, .. } => match delta {
MouseScrollDelta::LineDelta(x, y) => {
@@ -159,6 +165,20 @@ impl PhosphorApplication {
WinitMouseButton::Forward => handle!(Event::MouseButton { button: MouseButton::Forward, action }),
_ => (),
}
+ // Keep track of mouse button hold states, and mark cursor as out when all are released.
+ let button_index = match button {
+ WinitMouseButton::Left => 0,
+ WinitMouseButton::Middle => 1,
+ WinitMouseButton::Right => 2,
+ WinitMouseButton::Back => 3,
+ WinitMouseButton::Forward => 4,
+ _ => return,
+ };
+ window.mouse_buttons[button_index] = action.is_pressed();
+ if window.pointer_state == PointerState::PendingOut && window.mouse_buttons.iter().all(|b| !b) {
+ window.pointer_state = PointerState::Out;
+ handle!(Event::CursorExit);
+ }
}
WindowEvent::RedrawRequested => {
window.redraw();
diff --git a/src/window.rs b/src/window.rs
index 70c9c02..f031af5 100644
--- a/src/window.rs
+++ b/src/window.rs
@@ -18,11 +18,21 @@ fn to_physical_size(dimensions: Dimensions, scale: u32) -> PhysicalSize<u32> {
}
+#[derive(Copy, Clone, Debug, PartialEq)]
+pub enum PointerState {
+ In,
+ Out,
+ PendingOut,
+}
+
+
pub(crate) struct PhosphorWindow {
pub winit: Rc<Window>,
pub program: Box<dyn WindowProgram>,
pub requests: EventQueue<Request>,
pub pointer: Option<Position>,
+ pub pointer_state: PointerState,
+ pub mouse_buttons: [bool; 5],
pub marked_for_destruction: bool,
pub size_bounds: SizeBounds, // logical dimensions
@@ -79,6 +89,8 @@ impl PhosphorWindow {
program: builder.program,
requests: EventQueue::new(),
pointer: None,
+ pointer_state: PointerState::Out,
+ mouse_buttons: [false; 5],
marked_for_destruction: false,
size_bounds,