Skip to content

Commit

Permalink
Discard mouse down after Cocoa window resize (rust-windowing#466)
Browse files Browse the repository at this point in the history
* Discard mouse down after Cocoa window resize

We are sending the mouse down event after the window resize has
completed, because Cocoa uses a modal event loop to implement window
resize. This leads to a mouse down without a matching mouse up.

* Also handle event discard in poll_events

Add some explanatory comments and a changelog entry.
  • Loading branch information
swiftcoder authored and francesca64 committed Apr 15, 2018
1 parent 2477d8c commit 19cd531
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
- Implemented `Refresh` event on Windows.
- Properly calculate the minimum and maximum window size on Windows, including window decorations.
- Map more `MouseCursor` variants to cursor icons on Windows.
- Discard the stray mouse down event being delivered after window resize on macOS.

# Version 0.12.0 (2018-04-06)

Expand Down
26 changes: 24 additions & 2 deletions src/platform/macos/events_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use std::collections::VecDeque;
use std::sync::{Arc, Mutex, Weak};
use super::window::Window2;
use std;
use std::cell::RefCell;
use super::DeviceId;


Expand All @@ -18,6 +19,7 @@ pub struct EventsLoop {
pub struct Shared {
pub windows: Mutex<Vec<Weak<Window2>>>,
pub pending_events: Mutex<VecDeque<Event>>,
pub discard_event: RefCell<bool>,
// The user event callback given via either of the `poll_events` or `run_forever` methods.
//
// We store the user's callback here so that it may be accessed by each of the window delegate
Expand Down Expand Up @@ -55,6 +57,7 @@ impl Shared {
Shared {
windows: Mutex::new(Vec::new()),
pending_events: Mutex::new(VecDeque::new()),
discard_event: RefCell::new(false),
user_callback: UserCallback { mutex: Mutex::new(None) },
}
}
Expand Down Expand Up @@ -99,6 +102,19 @@ impl Shared {
}
}

// Instructs the `EventsLoop` to discard the next input event.
//
// This is called when the window is resized, to avoid a delayed mouse down event being posted
// after the resize completes.
pub fn discard_next_event(&self) {
*self.discard_event.borrow_mut() = true;
}

fn should_discard_next_event(&self) -> bool {
let result = *self.discard_event.borrow();
*self.discard_event.borrow_mut() = false;
result
}
}


Expand Down Expand Up @@ -201,7 +217,11 @@ impl EventsLoop {

match event {
// Call the user's callback.
Some(event) => self.shared.user_callback.call_with_event(event),
Some(event) => {
if !self.shared.should_discard_next_event() {
self.shared.user_callback.call_with_event(event);
}
},
None => break,
}
}
Expand Down Expand Up @@ -254,7 +274,9 @@ impl EventsLoop {
let _: () = msg_send![pool, release];

if let Some(event) = maybe_event {
self.shared.user_callback.call_with_event(event);
if !self.shared.should_discard_next_event() {
self.shared.user_callback.call_with_event(event);
}
if let ControlFlow::Break = control_flow.get() {
break;
}
Expand Down
5 changes: 5 additions & 0 deletions src/platform/macos/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@ impl WindowDelegate {
let state: *mut c_void = *this.get_ivar("winitState");
let state = &mut *(state as *mut DelegateState);
emit_resize_event(state);

// discard the pending mouse down event
if let Some(shared) = state.shared.upgrade() {
shared.discard_next_event();
}
}
}

Expand Down

0 comments on commit 19cd531

Please sign in to comment.