-
Notifications
You must be signed in to change notification settings - Fork 891
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: added MacOS menu #1583
Merged
ArturKovacs
merged 9 commits into
rust-windowing:master
from
casperstorm:feat/macos-menu
Apr 24, 2021
Merged
feat: added MacOS menu #1583
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
74b5d65
feat: added MacOS menu
casperstorm 6c8a56d
fix: ran fmt
casperstorm 3ef6412
Merge branch 'master' into feat/macos-menu
casperstorm 78fd112
Merge branch 'master' into feat/macos-menu
casperstorm ca05139
extracted function into variable
casperstorm 02f8835
idiomatic formatting
casperstorm 611d1e8
Merge remote-tracking branch 'upstream/master' into feat/macos-menu
casperstorm 7f89bcc
Set the default menu only during app startup
ArturKovacs a8b7eb1
Don't set the activation policy in the menu init
ArturKovacs File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
use cocoa::appkit::{ | ||
NSApp, NSApplication, NSApplicationActivationPolicyRegular, NSEventModifierFlags, NSMenu, | ||
NSMenuItem, | ||
}; | ||
use cocoa::base::{nil, selector}; | ||
use cocoa::foundation::{NSAutoreleasePool, NSProcessInfo, NSString}; | ||
use objc::{ | ||
rc::autoreleasepool, | ||
runtime::{Object, Sel}, | ||
}; | ||
|
||
struct KeyEquivalent<'a> { | ||
key: &'a str, | ||
masks: Option<NSEventModifierFlags>, | ||
} | ||
|
||
pub fn initialize() { | ||
autoreleasepool(|| unsafe { | ||
let menubar = NSMenu::new(nil).autorelease(); | ||
let app_menu_item = NSMenuItem::new(nil).autorelease(); | ||
menubar.addItem_(app_menu_item); | ||
let app = NSApp(); | ||
app.setMainMenu_(menubar); | ||
|
||
let app_menu = NSMenu::new(nil); | ||
let process_name = NSProcessInfo::processInfo(nil).processName(); | ||
|
||
// About menu item | ||
let about_item_prefix = NSString::alloc(nil).init_str("About "); | ||
let about_item_title = about_item_prefix.stringByAppendingString_(process_name); | ||
let about_item = menu_item( | ||
about_item_title, | ||
selector("orderFrontStandardAboutPanel:"), | ||
None, | ||
); | ||
|
||
// Seperator menu item | ||
let sep_first = NSMenuItem::separatorItem(nil); | ||
|
||
// Hide application menu item | ||
let hide_item_prefix = NSString::alloc(nil).init_str("Hide "); | ||
let hide_item_title = hide_item_prefix.stringByAppendingString_(process_name); | ||
let hide_item = menu_item( | ||
hide_item_title, | ||
selector("hide:"), | ||
Some(KeyEquivalent { | ||
key: "h", | ||
masks: None, | ||
}), | ||
); | ||
|
||
// Hide other applications menu item | ||
let hide_others_item_title = NSString::alloc(nil).init_str("Hide Others"); | ||
let hide_others_item = menu_item( | ||
hide_others_item_title, | ||
selector("hideOtherApplications:"), | ||
Some(KeyEquivalent { | ||
key: "h", | ||
masks: Some( | ||
NSEventModifierFlags::NSAlternateKeyMask | ||
| NSEventModifierFlags::NSCommandKeyMask, | ||
), | ||
}), | ||
); | ||
|
||
// Show applications menu item | ||
let show_all_item_title = NSString::alloc(nil).init_str("Show All"); | ||
let show_all_item = menu_item( | ||
show_all_item_title, | ||
selector("unhideAllApplications:"), | ||
None, | ||
); | ||
|
||
// Seperator menu item | ||
let sep = NSMenuItem::separatorItem(nil); | ||
|
||
// Quit application menu item | ||
let quit_item_prefix = NSString::alloc(nil).init_str("Quit "); | ||
let quit_item_title = quit_item_prefix.stringByAppendingString_(process_name); | ||
let quit_item = menu_item( | ||
quit_item_title, | ||
selector("terminate:"), | ||
Some(KeyEquivalent { | ||
key: "q", | ||
masks: None, | ||
}), | ||
); | ||
|
||
app_menu.addItem_(about_item); | ||
app_menu.addItem_(sep_first); | ||
app_menu.addItem_(hide_item); | ||
app_menu.addItem_(hide_others_item); | ||
app_menu.addItem_(show_all_item); | ||
app_menu.addItem_(sep); | ||
app_menu.addItem_(quit_item); | ||
app_menu_item.setSubmenu_(app_menu); | ||
}); | ||
} | ||
|
||
fn menu_item( | ||
title: *mut Object, | ||
selector: Sel, | ||
key_equivalent: Option<KeyEquivalent<'_>>, | ||
) -> *mut Object { | ||
unsafe { | ||
let (key, masks) = match key_equivalent { | ||
Some(ke) => (NSString::alloc(nil).init_str(ke.key), ke.masks), | ||
None => (NSString::alloc(nil).init_str(""), None), | ||
}; | ||
let item = NSMenuItem::alloc(nil).initWithTitle_action_keyEquivalent_(title, selector, key); | ||
if let Some(masks) = masks { | ||
item.setKeyEquivalentModifierMask_(masks) | ||
} | ||
|
||
item | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,7 @@ mod app_state; | |
mod event; | ||
mod event_loop; | ||
mod ffi; | ||
mod menu; | ||
mod monitor; | ||
mod observer; | ||
mod util; | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should add the
Services
menu here (can be done by creating a menu item with an empty menu, and registering that as theservicesMenu
)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, not sure it make sense if we don't have any services to add?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I looked into how the Services menu is used. Winit uses a custom
NSView
subclass for the entire window surface. Applications and customNSView
types have to implement a certain protocol (see "Using Services" in the Apple Developer Documentation Archive). More specifically theNSView
has to provide an implementation forvalidRequestorForSendType
through which it must specify whether the currently selected thing is a valid target for a service that operates on the provided types of data. However winit has no idea what is selected currently. Given that winit doesn't provide APIs to handlevalidRequestorForSendType
messages, it's currently not possible to use the Services menu through winit (if I understand correctly). This is somewhat related to #1759 in that it's a macOS specific "event" that a higher level code may want to be able to handle.Anyhow I don't think we should be concerned about that for this PR. So with all that, just like @casperstorm wrote, it seems there's no point in adding the Services menu.