fix(core): handle AllModifiersRelease event on macOS to prevent modifier state getting out-of-sync with shortcuts. Fix #791

This commit is contained in:
Federico Terzi 2021-10-13 22:36:25 +02:00
parent 0b23a5cc30
commit 44dd54e2e1
6 changed files with 28 additions and 19 deletions

View File

@ -37,12 +37,12 @@ impl<'a> funnel::Source<'a> for DetectSource {
select.recv(&self.receiver)
}
fn receive(&self, op: SelectedOperation) -> Event {
fn receive(&self, op: SelectedOperation) -> Option<Event> {
let (input_event, source_id) = op
.recv(&self.receiver)
.expect("unable to select data from DetectSource receiver");
match input_event {
InputEvent::Keyboard(keyboard_event) => Event {
InputEvent::Keyboard(keyboard_event) => Some(Event {
source_id,
etype: EventType::Keyboard(KeyboardEvent {
key: convert_to_engine_key(keyboard_event.key),
@ -50,20 +50,21 @@ impl<'a> funnel::Source<'a> for DetectSource {
status: convert_to_engine_status(keyboard_event.status),
variant: keyboard_event.variant.map(convert_to_engine_variant),
}),
},
InputEvent::Mouse(mouse_event) => Event {
}),
InputEvent::Mouse(mouse_event) => Some(Event {
source_id,
etype: EventType::Mouse(MouseEvent {
status: convert_to_engine_status(mouse_event.status),
button: convert_to_engine_mouse_button(mouse_event.button),
}),
},
InputEvent::HotKey(hotkey_event) => Event {
}),
InputEvent::HotKey(hotkey_event) => Some(Event {
source_id,
etype: EventType::HotKey(HotKeyEvent {
hotkey_id: hotkey_event.hotkey_id,
}),
},
}),
InputEvent::AllModifiersReleased => None,
}
}
}

View File

@ -45,13 +45,13 @@ impl<'a> funnel::Source<'a> for ExitSource<'a> {
select.recv(&self.exit_signal)
}
fn receive(&self, op: SelectedOperation) -> Event {
fn receive(&self, op: SelectedOperation) -> Option<Event> {
let mode = op
.recv(&self.exit_signal)
.expect("unable to select data from ExitSource receiver");
Event {
Some(Event {
source_id: self.sequencer.next_id(),
etype: EventType::ExitRequested(mode),
}
})
}
}

View File

@ -81,6 +81,8 @@ pub fn init_and_spawn(
// Update the modifiers state
if let Some((modifier, is_pressed)) = get_modifier_status(&event) {
modifier_state_store_clone.update_state(modifier, is_pressed);
} else if let InputEvent::AllModifiersReleased = &event {
modifier_state_store_clone.clear_state();
}
// Update the key state (if needed)

View File

@ -91,6 +91,13 @@ impl ModifierStateStore {
}
}
}
pub fn clear_state(&self) {
let mut state = self.state.lock().expect("unable to obtain modifier state");
for (_, status) in &mut state.modifiers {
status.release();
}
}
}
struct ModifiersState {

View File

@ -50,13 +50,13 @@ impl<'a> funnel::Source<'a> for SecureInputSource<'a> {
}
}
fn receive(&self, op: SelectedOperation) -> Event {
fn receive(&self, op: SelectedOperation) -> Option<Event> {
if cfg!(target_os = "macos") {
let si_event = op
.recv(&self.receiver)
.expect("unable to select data from SecureInputSource receiver");
Event {
Some(Event {
source_id: self.sequencer.next_id(),
etype: match si_event {
SecureInputEvent::Disabled => EventType::SecureInputDisabled,
@ -64,13 +64,12 @@ impl<'a> funnel::Source<'a> for SecureInputSource<'a> {
EventType::SecureInputEnabled(SecureInputEnabledEvent { app_name, app_path })
}
},
}
})
} else {
println!("noop");
Event {
Some(Event {
source_id: self.sequencer.next_id(),
etype: EventType::NOOP,
}
})
}
}
}

View File

@ -46,12 +46,12 @@ impl<'a> funnel::Source<'a> for UISource<'a> {
select.recv(&self.ui_receiver)
}
fn receive(&self, op: SelectedOperation) -> Event {
fn receive(&self, op: SelectedOperation) -> Option<Event> {
let ui_event = op
.recv(&self.ui_receiver)
.expect("unable to select data from UISource receiver");
Event {
Some(Event {
source_id: self.sequencer.next_id(),
etype: match ui_event {
UIEvent::TrayIconClick => EventType::TrayIconClicked,
@ -60,6 +60,6 @@ impl<'a> funnel::Source<'a> for UISource<'a> {
}
UIEvent::Heartbeat => EventType::Heartbeat,
},
}
})
}
}