Disable menu item key equivalents while there are pending keystrokes
This commit is contained in:
parent
21862faa58
commit
b72d97ce78
5 changed files with 43 additions and 5 deletions
|
@ -192,11 +192,18 @@ impl App {
|
|||
cx.borrow_mut().quit();
|
||||
}
|
||||
}));
|
||||
foreground_platform.on_will_open_menu(Box::new({
|
||||
let cx = app.0.clone();
|
||||
move || {
|
||||
let mut cx = cx.borrow_mut();
|
||||
cx.keystroke_matcher.clear_pending();
|
||||
}
|
||||
}));
|
||||
foreground_platform.on_validate_menu_command(Box::new({
|
||||
let cx = app.0.clone();
|
||||
move |action| {
|
||||
let cx = cx.borrow_mut();
|
||||
cx.is_action_available(action)
|
||||
!cx.keystroke_matcher.has_pending_keystrokes() && cx.is_action_available(action)
|
||||
}
|
||||
}));
|
||||
foreground_platform.on_menu_command(Box::new({
|
||||
|
|
|
@ -123,6 +123,10 @@ impl Matcher {
|
|||
self.pending.clear();
|
||||
}
|
||||
|
||||
pub fn has_pending_keystrokes(&self) -> bool {
|
||||
!self.pending.is_empty()
|
||||
}
|
||||
|
||||
pub fn push_keystroke(
|
||||
&mut self,
|
||||
keystroke: Keystroke,
|
||||
|
|
|
@ -74,6 +74,7 @@ pub(crate) trait ForegroundPlatform {
|
|||
|
||||
fn on_menu_command(&self, callback: Box<dyn FnMut(&dyn Action)>);
|
||||
fn on_validate_menu_command(&self, callback: Box<dyn FnMut(&dyn Action) -> bool>);
|
||||
fn on_will_open_menu(&self, callback: Box<dyn FnMut()>);
|
||||
fn set_menus(&self, menus: Vec<Menu>, matcher: &keymap::Matcher);
|
||||
fn prompt_for_paths(
|
||||
&self,
|
||||
|
|
|
@ -93,6 +93,10 @@ unsafe fn build_classes() {
|
|||
sel!(validateMenuItem:),
|
||||
validate_menu_item as extern "C" fn(&mut Object, Sel, id) -> bool,
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(menuWillOpen:),
|
||||
menu_will_open as extern "C" fn(&mut Object, Sel, id),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(application:openURLs:),
|
||||
open_urls as extern "C" fn(&mut Object, Sel, id, id),
|
||||
|
@ -112,14 +116,21 @@ pub struct MacForegroundPlatformState {
|
|||
event: Option<Box<dyn FnMut(crate::Event) -> bool>>,
|
||||
menu_command: Option<Box<dyn FnMut(&dyn Action)>>,
|
||||
validate_menu_command: Option<Box<dyn FnMut(&dyn Action) -> bool>>,
|
||||
will_open_menu: Option<Box<dyn FnMut()>>,
|
||||
open_urls: Option<Box<dyn FnMut(Vec<String>)>>,
|
||||
finish_launching: Option<Box<dyn FnOnce() -> ()>>,
|
||||
menu_actions: Vec<Box<dyn Action>>,
|
||||
}
|
||||
|
||||
impl MacForegroundPlatform {
|
||||
unsafe fn create_menu_bar(&self, menus: Vec<Menu>, keystroke_matcher: &keymap::Matcher) -> id {
|
||||
unsafe fn create_menu_bar(
|
||||
&self,
|
||||
menus: Vec<Menu>,
|
||||
delegate: id,
|
||||
keystroke_matcher: &keymap::Matcher,
|
||||
) -> id {
|
||||
let menu_bar = NSMenu::new(nil).autorelease();
|
||||
menu_bar.setDelegate_(delegate);
|
||||
let mut state = self.0.borrow_mut();
|
||||
|
||||
state.menu_actions.clear();
|
||||
|
@ -130,6 +141,7 @@ impl MacForegroundPlatform {
|
|||
let menu_name = menu_config.name;
|
||||
|
||||
menu.setTitle_(ns_string(menu_name));
|
||||
menu.setDelegate_(delegate);
|
||||
|
||||
for item_config in menu_config.items {
|
||||
let item;
|
||||
|
@ -242,6 +254,10 @@ impl platform::ForegroundPlatform for MacForegroundPlatform {
|
|||
self.0.borrow_mut().menu_command = Some(callback);
|
||||
}
|
||||
|
||||
fn on_will_open_menu(&self, callback: Box<dyn FnMut()>) {
|
||||
self.0.borrow_mut().will_open_menu = Some(callback);
|
||||
}
|
||||
|
||||
fn on_validate_menu_command(&self, callback: Box<dyn FnMut(&dyn Action) -> bool>) {
|
||||
self.0.borrow_mut().validate_menu_command = Some(callback);
|
||||
}
|
||||
|
@ -249,7 +265,7 @@ impl platform::ForegroundPlatform for MacForegroundPlatform {
|
|||
fn set_menus(&self, menus: Vec<Menu>, keystroke_matcher: &keymap::Matcher) {
|
||||
unsafe {
|
||||
let app: id = msg_send![APP_CLASS, sharedApplication];
|
||||
app.setMainMenu_(self.create_menu_bar(menus, keystroke_matcher));
|
||||
app.setMainMenu_(self.create_menu_bar(menus, app.delegate(), keystroke_matcher));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -764,6 +780,17 @@ extern "C" fn validate_menu_item(this: &mut Object, _: Sel, item: id) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
extern "C" fn menu_will_open(this: &mut Object, _: Sel, _: id) {
|
||||
unsafe {
|
||||
let platform = get_foreground_platform(this);
|
||||
let mut platform = platform.0.borrow_mut();
|
||||
if let Some(mut callback) = platform.will_open_menu.take() {
|
||||
callback();
|
||||
platform.will_open_menu = Some(callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn ns_string(string: &str) -> id {
|
||||
NSString::alloc(nil).init_str(string).autorelease()
|
||||
}
|
||||
|
|
|
@ -73,9 +73,8 @@ impl super::ForegroundPlatform for ForegroundPlatform {
|
|||
}
|
||||
|
||||
fn on_menu_command(&self, _: Box<dyn FnMut(&dyn Action)>) {}
|
||||
|
||||
fn on_validate_menu_command(&self, _: Box<dyn FnMut(&dyn Action) -> bool>) {}
|
||||
|
||||
fn on_will_open_menu(&self, _: Box<dyn FnMut()>) {}
|
||||
fn set_menus(&self, _: Vec<crate::Menu>, _: &keymap::Matcher) {}
|
||||
|
||||
fn prompt_for_paths(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue