fix(core): handle AllModifiersRelease event on macOS to prevent modifier state getting out-of-sync with shortcuts. Fix #791
This commit is contained in:
parent
0b23a5cc30
commit
44dd54e2e1
|
@ -37,12 +37,12 @@ impl<'a> funnel::Source<'a> for DetectSource {
|
||||||
select.recv(&self.receiver)
|
select.recv(&self.receiver)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn receive(&self, op: SelectedOperation) -> Event {
|
fn receive(&self, op: SelectedOperation) -> Option<Event> {
|
||||||
let (input_event, source_id) = op
|
let (input_event, source_id) = op
|
||||||
.recv(&self.receiver)
|
.recv(&self.receiver)
|
||||||
.expect("unable to select data from DetectSource receiver");
|
.expect("unable to select data from DetectSource receiver");
|
||||||
match input_event {
|
match input_event {
|
||||||
InputEvent::Keyboard(keyboard_event) => Event {
|
InputEvent::Keyboard(keyboard_event) => Some(Event {
|
||||||
source_id,
|
source_id,
|
||||||
etype: EventType::Keyboard(KeyboardEvent {
|
etype: EventType::Keyboard(KeyboardEvent {
|
||||||
key: convert_to_engine_key(keyboard_event.key),
|
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),
|
status: convert_to_engine_status(keyboard_event.status),
|
||||||
variant: keyboard_event.variant.map(convert_to_engine_variant),
|
variant: keyboard_event.variant.map(convert_to_engine_variant),
|
||||||
}),
|
}),
|
||||||
},
|
}),
|
||||||
InputEvent::Mouse(mouse_event) => Event {
|
InputEvent::Mouse(mouse_event) => Some(Event {
|
||||||
source_id,
|
source_id,
|
||||||
etype: EventType::Mouse(MouseEvent {
|
etype: EventType::Mouse(MouseEvent {
|
||||||
status: convert_to_engine_status(mouse_event.status),
|
status: convert_to_engine_status(mouse_event.status),
|
||||||
button: convert_to_engine_mouse_button(mouse_event.button),
|
button: convert_to_engine_mouse_button(mouse_event.button),
|
||||||
}),
|
}),
|
||||||
},
|
}),
|
||||||
InputEvent::HotKey(hotkey_event) => Event {
|
InputEvent::HotKey(hotkey_event) => Some(Event {
|
||||||
source_id,
|
source_id,
|
||||||
etype: EventType::HotKey(HotKeyEvent {
|
etype: EventType::HotKey(HotKeyEvent {
|
||||||
hotkey_id: hotkey_event.hotkey_id,
|
hotkey_id: hotkey_event.hotkey_id,
|
||||||
}),
|
}),
|
||||||
},
|
}),
|
||||||
|
InputEvent::AllModifiersReleased => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,13 +45,13 @@ impl<'a> funnel::Source<'a> for ExitSource<'a> {
|
||||||
select.recv(&self.exit_signal)
|
select.recv(&self.exit_signal)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn receive(&self, op: SelectedOperation) -> Event {
|
fn receive(&self, op: SelectedOperation) -> Option<Event> {
|
||||||
let mode = op
|
let mode = op
|
||||||
.recv(&self.exit_signal)
|
.recv(&self.exit_signal)
|
||||||
.expect("unable to select data from ExitSource receiver");
|
.expect("unable to select data from ExitSource receiver");
|
||||||
Event {
|
Some(Event {
|
||||||
source_id: self.sequencer.next_id(),
|
source_id: self.sequencer.next_id(),
|
||||||
etype: EventType::ExitRequested(mode),
|
etype: EventType::ExitRequested(mode),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,6 +81,8 @@ pub fn init_and_spawn(
|
||||||
// Update the modifiers state
|
// Update the modifiers state
|
||||||
if let Some((modifier, is_pressed)) = get_modifier_status(&event) {
|
if let Some((modifier, is_pressed)) = get_modifier_status(&event) {
|
||||||
modifier_state_store_clone.update_state(modifier, is_pressed);
|
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)
|
// Update the key state (if needed)
|
||||||
|
|
|
@ -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 {
|
struct ModifiersState {
|
||||||
|
|
|
@ -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") {
|
if cfg!(target_os = "macos") {
|
||||||
let si_event = op
|
let si_event = op
|
||||||
.recv(&self.receiver)
|
.recv(&self.receiver)
|
||||||
.expect("unable to select data from SecureInputSource receiver");
|
.expect("unable to select data from SecureInputSource receiver");
|
||||||
|
|
||||||
Event {
|
Some(Event {
|
||||||
source_id: self.sequencer.next_id(),
|
source_id: self.sequencer.next_id(),
|
||||||
etype: match si_event {
|
etype: match si_event {
|
||||||
SecureInputEvent::Disabled => EventType::SecureInputDisabled,
|
SecureInputEvent::Disabled => EventType::SecureInputDisabled,
|
||||||
|
@ -64,13 +64,12 @@ impl<'a> funnel::Source<'a> for SecureInputSource<'a> {
|
||||||
EventType::SecureInputEnabled(SecureInputEnabledEvent { app_name, app_path })
|
EventType::SecureInputEnabled(SecureInputEnabledEvent { app_name, app_path })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
} else {
|
} else {
|
||||||
println!("noop");
|
Some(Event {
|
||||||
Event {
|
|
||||||
source_id: self.sequencer.next_id(),
|
source_id: self.sequencer.next_id(),
|
||||||
etype: EventType::NOOP,
|
etype: EventType::NOOP,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,12 +46,12 @@ impl<'a> funnel::Source<'a> for UISource<'a> {
|
||||||
select.recv(&self.ui_receiver)
|
select.recv(&self.ui_receiver)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn receive(&self, op: SelectedOperation) -> Event {
|
fn receive(&self, op: SelectedOperation) -> Option<Event> {
|
||||||
let ui_event = op
|
let ui_event = op
|
||||||
.recv(&self.ui_receiver)
|
.recv(&self.ui_receiver)
|
||||||
.expect("unable to select data from UISource receiver");
|
.expect("unable to select data from UISource receiver");
|
||||||
|
|
||||||
Event {
|
Some(Event {
|
||||||
source_id: self.sequencer.next_id(),
|
source_id: self.sequencer.next_id(),
|
||||||
etype: match ui_event {
|
etype: match ui_event {
|
||||||
UIEvent::TrayIconClick => EventType::TrayIconClicked,
|
UIEvent::TrayIconClick => EventType::TrayIconClicked,
|
||||||
|
@ -60,6 +60,6 @@ impl<'a> funnel::Source<'a> for UISource<'a> {
|
||||||
}
|
}
|
||||||
UIEvent::Heartbeat => EventType::Heartbeat,
|
UIEvent::Heartbeat => EventType::Heartbeat,
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user