From ac78bab72414f86bb4bac2bbde6d69f3674cfd5d Mon Sep 17 00:00:00 2001 From: Kristofer Rye Date: Wed, 22 Jan 2020 16:55:48 -0600 Subject: [PATCH] macos: Add a hook to update stale modifiers Sometimes, `ViewState` and `event` might have different values for their stored `modifiers` flags. These are internally stored as a bitmask in the latter and an enum in the former. We can check to see if they differ, and if they do, automatically dispatch an event to update consumers of modifier state as well as the stored `state.modifiers`. That's what the hook does. This hook is then called in the key_down, mouse_entered, mouse_exited, mouse_click, scroll_wheel, and pressure_change_with_event callbacks, which each will contain updated modifiers. Signed-off-by: Kristofer Rye --- src/platform_impl/macos/view.rs | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/src/platform_impl/macos/view.rs b/src/platform_impl/macos/view.rs index b6cbcc6fd5..14131b071b 100644 --- a/src/platform_impl/macos/view.rs +++ b/src/platform_impl/macos/view.rs @@ -623,6 +623,18 @@ fn retrieve_keycode(event: id) -> Option { }) } +// Update `state.modifiers` if `event` has something different +fn update_potentially_stale_modifiers(state: &mut ViewState, event: id) { + if state.modifiers != event_mods(event) { + state.modifiers = event_mods(event); + trace!("Modifiers are stale; updating modifiers"); + AppState::queue_event(EventWrapper::StaticEvent(Event::WindowEvent { + window_id: WindowId(get_window_id(state.ns_window)), + event: WindowEvent::ModifiersChanged(state.modifiers), + })); + } +} + extern "C" fn key_down(this: &Object, _sel: Sel, event: id) { trace!("Triggered `keyDown`"); unsafe { @@ -638,6 +650,8 @@ extern "C" fn key_down(this: &Object, _sel: Sel, event: id) { let is_repeat = msg_send![event, isARepeat]; + update_potentially_stale_modifiers(state, event); + #[allow(deprecated)] let window_event = Event::WindowEvent { window_id, @@ -762,8 +776,6 @@ extern "C" fn flags_changed(this: &Object, _sel: Sel, event: id) { })); } - trace!("Queueing event with modifiers {:?}", state.modifiers); - AppState::queue_event(EventWrapper::StaticEvent(Event::WindowEvent { // TODO Maybe memoize get_window_id if it's safe to reuse? window_id: WindowId(get_window_id(state.ns_window)), @@ -834,6 +846,8 @@ fn mouse_click(this: &Object, event: id, button: MouseButton, button_state: Elem let state_ptr: *mut c_void = *this.get_ivar("winitState"); let state = &mut *(state_ptr as *mut ViewState); + update_potentially_stale_modifiers(state, event); + let window_event = Event::WindowEvent { window_id: WindowId(get_window_id(state.ns_window)), event: WindowEvent::MouseInput { @@ -932,6 +946,8 @@ extern "C" fn mouse_entered(this: &Object, _sel: Sel, event: id) { let state_ptr: *mut c_void = *this.get_ivar("winitState"); let state = &mut *(state_ptr as *mut ViewState); + update_potentially_stale_modifiers(state, event); + let enter_event = Event::WindowEvent { window_id: WindowId(get_window_id(state.ns_window)), event: WindowEvent::CursorEntered { @@ -945,12 +961,14 @@ extern "C" fn mouse_entered(this: &Object, _sel: Sel, event: id) { trace!("Completed `mouseEntered`"); } -extern "C" fn mouse_exited(this: &Object, _sel: Sel, _event: id) { +extern "C" fn mouse_exited(this: &Object, _sel: Sel, event: id) { trace!("Triggered `mouseExited`"); unsafe { let state_ptr: *mut c_void = *this.get_ivar("winitState"); let state = &mut *(state_ptr as *mut ViewState); + update_potentially_stale_modifiers(state, event); + let window_event = Event::WindowEvent { window_id: WindowId(get_window_id(state.ns_window)), event: WindowEvent::CursorLeft { @@ -990,6 +1008,8 @@ extern "C" fn scroll_wheel(this: &Object, _sel: Sel, event: id) { let state_ptr: *mut c_void = *this.get_ivar("winitState"); let state = &mut *(state_ptr as *mut ViewState); + update_potentially_stale_modifiers(state, event); + let window_event = Event::WindowEvent { window_id: WindowId(get_window_id(state.ns_window)), event: WindowEvent::MouseWheel { @@ -1012,6 +1032,8 @@ extern "C" fn pressure_change_with_event(this: &Object, _sel: Sel, event: id) { let state_ptr: *mut c_void = *this.get_ivar("winitState"); let state = &mut *(state_ptr as *mut ViewState); + update_potentially_stale_modifiers(state, event); + let pressure = event.pressure(); let stage = event.stage();