mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-24 06:11:30 +11:00
Add MacOS menu (#1583)
* feat: added MacOS menu * fix: ran fmt * extracted function into variable * idiomatic formatting * Set the default menu only during app startup * Don't set the activation policy in the menu init Co-authored-by: Artur Kovacs <kovacs.artur.barnabas@gmail.com>
This commit is contained in:
parent
1c4d6e7613
commit
e8cdf8b092
|
@ -24,6 +24,7 @@
|
||||||
- On Windows, added `WindowExtWindows::set_enable` to allow creating modal popup windows.
|
- On Windows, added `WindowExtWindows::set_enable` to allow creating modal popup windows.
|
||||||
- On macOS, emit `RedrawRequested` events immediately while the window is being resized.
|
- On macOS, emit `RedrawRequested` events immediately while the window is being resized.
|
||||||
- Implement `Default`, `Hash`, and `Eq` for `LogicalPosition`, `PhysicalPosition`, `LogicalSize`, and `PhysicalSize`.
|
- Implement `Default`, `Hash`, and `Eq` for `LogicalPosition`, `PhysicalPosition`, `LogicalSize`, and `PhysicalSize`.
|
||||||
|
- On macOS, initialize the Menu Bar with minimal defaults.
|
||||||
|
|
||||||
# 0.24.0 (2020-12-09)
|
# 0.24.0 (2020-12-09)
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ use crate::{
|
||||||
platform_impl::platform::{
|
platform_impl::platform::{
|
||||||
event::{EventProxy, EventWrapper},
|
event::{EventProxy, EventWrapper},
|
||||||
event_loop::{post_dummy_event, PanicInfo},
|
event_loop::{post_dummy_event, PanicInfo},
|
||||||
|
menu,
|
||||||
observer::{CFRunLoopGetMain, CFRunLoopWakeUp, EventLoopWaker},
|
observer::{CFRunLoopGetMain, CFRunLoopWakeUp, EventLoopWaker},
|
||||||
util::{IdRef, Never},
|
util::{IdRef, Never},
|
||||||
window::get_window_id,
|
window::get_window_id,
|
||||||
|
@ -274,6 +275,9 @@ impl AppState {
|
||||||
pub fn launched() {
|
pub fn launched() {
|
||||||
HANDLER.set_ready();
|
HANDLER.set_ready();
|
||||||
HANDLER.waker().start();
|
HANDLER.waker().start();
|
||||||
|
// The menubar initialization should be before the `NewEvents` event, to allow overriding
|
||||||
|
// of the default menu in the event
|
||||||
|
menu::initialize();
|
||||||
HANDLER.set_in_callback(true);
|
HANDLER.set_in_callback(true);
|
||||||
HANDLER.handle_nonuser_event(EventWrapper::StaticEvent(Event::NewEvents(
|
HANDLER.handle_nonuser_event(EventWrapper::StaticEvent(Event::NewEvents(
|
||||||
StartCause::Init,
|
StartCause::Init,
|
||||||
|
|
117
src/platform_impl/macos/menu.rs
Normal file
117
src/platform_impl/macos/menu.rs
Normal file
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ mod app_state;
|
||||||
mod event;
|
mod event;
|
||||||
mod event_loop;
|
mod event_loop;
|
||||||
mod ffi;
|
mod ffi;
|
||||||
|
mod menu;
|
||||||
mod monitor;
|
mod monitor;
|
||||||
mod observer;
|
mod observer;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
Loading…
Reference in a new issue