[macOS] Add native "Edit" menu.
This commit is contained in:
parent
e3213aaef5
commit
0fa669c097
|
@ -401,6 +401,14 @@
|
||||||
[b]Note:[/b] This method is implemented only on macOS.
|
[b]Note:[/b] This method is implemented only on macOS.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
<method name="get_system_menu_no_default_items" qualifiers="const">
|
||||||
|
<return type="bool" />
|
||||||
|
<param index="0" name="menu_id" type="int" enum="NativeMenu.SystemMenus" />
|
||||||
|
<description>
|
||||||
|
Returns [code]true[/code] if system menu has no default items.
|
||||||
|
[b]Note:[/b] This method is implemented only on macOS.
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
<method name="has_feature" qualifiers="const">
|
<method name="has_feature" qualifiers="const">
|
||||||
<return type="bool" />
|
<return type="bool" />
|
||||||
<param index="0" name="feature" type="int" enum="NativeMenu.Feature" />
|
<param index="0" name="feature" type="int" enum="NativeMenu.Feature" />
|
||||||
|
@ -720,6 +728,25 @@
|
||||||
[b]Note:[/b] This method is implemented only on macOS.
|
[b]Note:[/b] This method is implemented only on macOS.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
<method name="set_system_menu_hidden">
|
||||||
|
<return type="void" />
|
||||||
|
<param index="0" name="menu_id" type="int" enum="NativeMenu.SystemMenus" />
|
||||||
|
<param index="1" name="hidden" type="bool" />
|
||||||
|
<description>
|
||||||
|
Hides/shows the system menu. Only system menus with no default items can be hidden. When it is hidden, an item does not appear in a menu and its action cannot be invoked.
|
||||||
|
[b]Note:[/b] This method is implemented only on macOS.
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
|
<method name="set_system_menu_name">
|
||||||
|
<return type="void" />
|
||||||
|
<param index="0" name="menu_id" type="int" enum="NativeMenu.SystemMenus" />
|
||||||
|
<param index="1" name="string" type="String" />
|
||||||
|
<description>
|
||||||
|
Sets system menu name. If set to empty string, default menu name is restored.
|
||||||
|
[b]Note:[/b] On macOS, only [constant FILE_MENU_ID] can be renamed.
|
||||||
|
[b]Note:[/b] This method is implemented only on macOS.
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
</methods>
|
</methods>
|
||||||
<constants>
|
<constants>
|
||||||
<constant name="FEATURE_GLOBAL_MENU" value="0" enum="Feature">
|
<constant name="FEATURE_GLOBAL_MENU" value="0" enum="Feature">
|
||||||
|
@ -755,5 +782,11 @@
|
||||||
<constant name="DOCK_MENU_ID" value="5" enum="SystemMenus">
|
<constant name="DOCK_MENU_ID" value="5" enum="SystemMenus">
|
||||||
Dock icon right-click menu ID (on macOS this menu include standard application control items and a list of open windows).
|
Dock icon right-click menu ID (on macOS this menu include standard application control items and a list of open windows).
|
||||||
</constant>
|
</constant>
|
||||||
|
<constant name="EDIT_MENU_ID" value="6" enum="SystemMenus">
|
||||||
|
"Edit" menu ID (on macOS this menu includes "Cut", "Copy", and "Paste" items).
|
||||||
|
</constant>
|
||||||
|
<constant name="FILE_MENU_ID" value="7" enum="SystemMenus">
|
||||||
|
"File" menu ID (on macOS this menu is empty and is hidden by default, this menu is shown before "Edit" menu).
|
||||||
|
</constant>
|
||||||
</constants>
|
</constants>
|
||||||
</class>
|
</class>
|
||||||
|
|
|
@ -7168,6 +7168,9 @@ EditorNode::EditorNode() {
|
||||||
|
|
||||||
file_menu = memnew(PopupMenu);
|
file_menu = memnew(PopupMenu);
|
||||||
file_menu->set_name(TTR("Scene"));
|
file_menu->set_name(TTR("Scene"));
|
||||||
|
if (global_menu && NativeMenu::get_singleton()->has_system_menu(NativeMenu::FILE_MENU_ID)) {
|
||||||
|
file_menu->set_system_menu(NativeMenu::FILE_MENU_ID);
|
||||||
|
}
|
||||||
main_menu->add_child(file_menu);
|
main_menu->add_child(file_menu);
|
||||||
main_menu->set_menu_tooltip(0, TTR("Operations with scene files."));
|
main_menu->set_menu_tooltip(0, TTR("Operations with scene files."));
|
||||||
|
|
||||||
|
|
|
@ -217,6 +217,8 @@ private:
|
||||||
WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, const Rect2i &p_rect);
|
WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, const Rect2i &p_rect);
|
||||||
void _update_window_style(WindowData p_wd);
|
void _update_window_style(WindowData p_wd);
|
||||||
|
|
||||||
|
void _get_action_key(const StringName &p_name, String &r_keycode, unsigned int &r_keymask) const;
|
||||||
|
|
||||||
void _update_displays_arrangement();
|
void _update_displays_arrangement();
|
||||||
Point2i _get_native_screen_position(int p_screen) const;
|
Point2i _get_native_screen_position(int p_screen) const;
|
||||||
static void _displays_arrangement_changed(CGDirectDisplayID display_id, CGDisplayChangeSummaryFlags flags, void *user_info);
|
static void _displays_arrangement_changed(CGDirectDisplayID display_id, CGDisplayChangeSummaryFlags flags, void *user_info);
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
#include "tts_macos.h"
|
#include "tts_macos.h"
|
||||||
|
|
||||||
#include "core/config/project_settings.h"
|
#include "core/config/project_settings.h"
|
||||||
|
#include "core/input/input_map.h"
|
||||||
#include "core/io/marshalls.h"
|
#include "core/io/marshalls.h"
|
||||||
#include "core/math/geometry_2d.h"
|
#include "core/math/geometry_2d.h"
|
||||||
#include "core/os/keyboard.h"
|
#include "core/os/keyboard.h"
|
||||||
|
@ -3471,6 +3472,34 @@ bool DisplayServerMacOS::mouse_process_popups(bool p_close) {
|
||||||
return closed;
|
return closed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DisplayServerMacOS::_get_action_key(const StringName &p_name, String &r_keycode, unsigned int &r_keymask) const {
|
||||||
|
r_keycode = String();
|
||||||
|
r_keymask = 0;
|
||||||
|
|
||||||
|
const List<Ref<InputEvent>> *events = InputMap::get_singleton()->action_get_events(p_name);
|
||||||
|
if (!events) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const List<Ref<InputEvent>>::Element *first_event = events->front();
|
||||||
|
if (!first_event) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const Ref<InputEventKey> event = first_event->get();
|
||||||
|
if (event.is_null()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (event->get_keycode() != Key::NONE) {
|
||||||
|
r_keycode = KeyMappingMacOS::keycode_get_native_string(event->get_keycode() & KeyModifierMask::CODE_MASK);
|
||||||
|
r_keymask = KeyMappingMacOS::keycode_get_native_mask(event->get_keycode_with_modifiers());
|
||||||
|
} else if (event->get_physical_keycode() != Key::NONE) {
|
||||||
|
r_keycode = KeyMappingMacOS::keycode_get_native_string(event->get_physical_keycode() & KeyModifierMask::CODE_MASK);
|
||||||
|
r_keymask = KeyMappingMacOS::keycode_get_native_mask(event->get_physical_keycode_with_modifiers());
|
||||||
|
} else if (event->get_key_label() != Key::NONE) {
|
||||||
|
r_keycode = KeyMappingMacOS::keycode_get_native_string(event->get_key_label() & KeyModifierMask::CODE_MASK);
|
||||||
|
r_keymask = KeyMappingMacOS::keycode_get_native_mask(event->get_key_label_with_modifiers());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DisplayServerMacOS::DisplayServerMacOS(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Context p_context, Error &r_error) {
|
DisplayServerMacOS::DisplayServerMacOS(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Context p_context, Error &r_error) {
|
||||||
KeyMappingMacOS::initialize();
|
KeyMappingMacOS::initialize();
|
||||||
|
|
||||||
|
@ -3558,6 +3587,35 @@ DisplayServerMacOS::DisplayServerMacOS(const String &p_rendering_driver, WindowM
|
||||||
title = [NSString stringWithFormat:NSLocalizedString(@"Quit %@", nil), nsappname];
|
title = [NSString stringWithFormat:NSLocalizedString(@"Quit %@", nil), nsappname];
|
||||||
[application_menu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"];
|
[application_menu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"];
|
||||||
|
|
||||||
|
NSMenu *file_menu = [[NSMenu alloc] initWithTitle:NSLocalizedString(@"File", nil)];
|
||||||
|
menu_item = [file_menu addItemWithTitle:@"_start_" action:nil keyEquivalent:@""];
|
||||||
|
menu_item.hidden = YES;
|
||||||
|
menu_item.tag = MENU_TAG_START;
|
||||||
|
menu_item = [file_menu addItemWithTitle:@"_end_" action:nil keyEquivalent:@""];
|
||||||
|
menu_item.hidden = YES;
|
||||||
|
menu_item.tag = MENU_TAG_END;
|
||||||
|
|
||||||
|
NSMenu *edit_menu = [[NSMenu alloc] initWithTitle:NSLocalizedString(@"Edit", nil)];
|
||||||
|
String keycode;
|
||||||
|
unsigned int keymask = 0;
|
||||||
|
|
||||||
|
_get_action_key("ui_cut", keycode, keymask);
|
||||||
|
menu_item = [edit_menu addItemWithTitle:NSLocalizedString(@"Cut", nil) action:@selector(cut:) keyEquivalent:[NSString stringWithUTF8String:keycode.utf8().get_data()]];
|
||||||
|
[menu_item setKeyEquivalentModifierMask:keymask];
|
||||||
|
_get_action_key("ui_copy", keycode, keymask);
|
||||||
|
menu_item = [edit_menu addItemWithTitle:NSLocalizedString(@"Copy", nil) action:@selector(copy:) keyEquivalent:[NSString stringWithUTF8String:keycode.utf8().get_data()]];
|
||||||
|
[menu_item setKeyEquivalentModifierMask:keymask];
|
||||||
|
_get_action_key("ui_paste", keycode, keymask);
|
||||||
|
menu_item = [edit_menu addItemWithTitle:NSLocalizedString(@"Paste", nil) action:@selector(paste:) keyEquivalent:[NSString stringWithUTF8String:keycode.utf8().get_data()]];
|
||||||
|
[menu_item setKeyEquivalentModifierMask:keymask];
|
||||||
|
[edit_menu addItem:[NSMenuItem separatorItem]];
|
||||||
|
menu_item = [edit_menu addItemWithTitle:@"_start_" action:nil keyEquivalent:@""];
|
||||||
|
menu_item.hidden = YES;
|
||||||
|
menu_item.tag = MENU_TAG_START;
|
||||||
|
menu_item = [edit_menu addItemWithTitle:@"_end_" action:nil keyEquivalent:@""];
|
||||||
|
menu_item.hidden = YES;
|
||||||
|
menu_item.tag = MENU_TAG_END;
|
||||||
|
|
||||||
NSMenu *window_menu = [[NSMenu alloc] initWithTitle:NSLocalizedString(@"Window", nil)];
|
NSMenu *window_menu = [[NSMenu alloc] initWithTitle:NSLocalizedString(@"Window", nil)];
|
||||||
[window_menu addItemWithTitle:NSLocalizedString(@"Minimize", nil) action:@selector(performMiniaturize:) keyEquivalent:@"m"];
|
[window_menu addItemWithTitle:NSLocalizedString(@"Minimize", nil) action:@selector(performMiniaturize:) keyEquivalent:@"m"];
|
||||||
[window_menu addItemWithTitle:NSLocalizedString(@"Zoom", nil) action:@selector(performZoom:) keyEquivalent:@""];
|
[window_menu addItemWithTitle:NSLocalizedString(@"Zoom", nil) action:@selector(performZoom:) keyEquivalent:@""];
|
||||||
|
@ -3587,6 +3645,13 @@ DisplayServerMacOS::DisplayServerMacOS(const String &p_rendering_driver, WindowM
|
||||||
menu_item = [main_menu addItemWithTitle:@"" action:nil keyEquivalent:@""];
|
menu_item = [main_menu addItemWithTitle:@"" action:nil keyEquivalent:@""];
|
||||||
[main_menu setSubmenu:application_menu forItem:menu_item];
|
[main_menu setSubmenu:application_menu forItem:menu_item];
|
||||||
|
|
||||||
|
NSMenuItem *file_menu_item = [main_menu addItemWithTitle:NSLocalizedString(@"File", nil) action:nil keyEquivalent:@""];
|
||||||
|
file_menu_item.hidden = YES;
|
||||||
|
[main_menu setSubmenu:file_menu forItem:file_menu_item];
|
||||||
|
|
||||||
|
menu_item = [main_menu addItemWithTitle:NSLocalizedString(@"Edit", nil) action:nil keyEquivalent:@""];
|
||||||
|
[main_menu setSubmenu:edit_menu forItem:menu_item];
|
||||||
|
|
||||||
menu_item = [main_menu addItemWithTitle:NSLocalizedString(@"Window", nil) action:nil keyEquivalent:@""];
|
menu_item = [main_menu addItemWithTitle:NSLocalizedString(@"Window", nil) action:nil keyEquivalent:@""];
|
||||||
[main_menu setSubmenu:window_menu forItem:menu_item];
|
[main_menu setSubmenu:window_menu forItem:menu_item];
|
||||||
|
|
||||||
|
@ -3595,7 +3660,7 @@ DisplayServerMacOS::DisplayServerMacOS(const String &p_rendering_driver, WindowM
|
||||||
|
|
||||||
[main_menu setAutoenablesItems:NO];
|
[main_menu setAutoenablesItems:NO];
|
||||||
|
|
||||||
native_menu->_register_system_menus(main_menu, application_menu, window_menu, help_menu, dock_menu);
|
native_menu->_register_system_menus(main_menu, application_menu, window_menu, help_menu, dock_menu, edit_menu, file_menu, file_menu_item);
|
||||||
|
|
||||||
//!!!!!!!!!!!!!!!!!!!!!!!!!!
|
//!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
//TODO - do Vulkan and OpenGL support checks, driver selection and fallback
|
//TODO - do Vulkan and OpenGL support checks, driver selection and fallback
|
||||||
|
|
|
@ -76,6 +76,7 @@
|
||||||
- (void)setWindowID:(DisplayServer::WindowID)wid;
|
- (void)setWindowID:(DisplayServer::WindowID)wid;
|
||||||
- (void)updateLayerDelegate;
|
- (void)updateLayerDelegate;
|
||||||
- (void)cancelComposition;
|
- (void)cancelComposition;
|
||||||
|
- (void)processUIEvent:(const StringName &)name;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include "display_server_macos.h"
|
#include "display_server_macos.h"
|
||||||
#include "key_mapping_macos.h"
|
#include "key_mapping_macos.h"
|
||||||
|
|
||||||
|
#include "core/input/input_map.h"
|
||||||
#include "main/main.h"
|
#include "main/main.h"
|
||||||
|
|
||||||
@implementation GodotContentLayerDelegate
|
@implementation GodotContentLayerDelegate
|
||||||
|
@ -337,6 +338,65 @@
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: Edit menu actions
|
||||||
|
|
||||||
|
- (void)processUIEvent:(const StringName &)name {
|
||||||
|
DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
|
||||||
|
if (!ds || !ds->has_window(window_id)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const List<Ref<InputEvent>> *events = InputMap::get_singleton()->action_get_events(name);
|
||||||
|
if (!events) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const List<Ref<InputEvent>>::Element *first_event = events->front();
|
||||||
|
if (!first_event) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Ref<InputEventKey> event = first_event->get();
|
||||||
|
if (event.is_null()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DisplayServerMacOS::KeyEvent ke;
|
||||||
|
ke.window_id = window_id;
|
||||||
|
ke.macos_state = 0;
|
||||||
|
if (event->is_ctrl_pressed()) {
|
||||||
|
ke.macos_state |= NSEventModifierFlagControl;
|
||||||
|
}
|
||||||
|
if (event->is_shift_pressed()) {
|
||||||
|
ke.macos_state |= NSEventModifierFlagShift;
|
||||||
|
}
|
||||||
|
if (event->is_alt_pressed()) {
|
||||||
|
ke.macos_state |= NSEventModifierFlagOption;
|
||||||
|
}
|
||||||
|
if (event->is_meta_pressed()) {
|
||||||
|
ke.macos_state |= NSEventModifierFlagCommand;
|
||||||
|
}
|
||||||
|
ke.pressed = true;
|
||||||
|
ke.echo = false;
|
||||||
|
ke.raw = false;
|
||||||
|
ke.keycode = event->get_keycode();
|
||||||
|
ke.physical_keycode = event->get_physical_keycode();
|
||||||
|
ke.key_label = event->get_key_label();
|
||||||
|
ke.unicode = event->get_unicode();
|
||||||
|
|
||||||
|
ds->push_to_key_event_buffer(ke);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)copy:(id)sender {
|
||||||
|
[self processUIEvent:"ui_copy"];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)cut:(id)sender {
|
||||||
|
[self processUIEvent:"ui_cut"];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)paste:(id)sender {
|
||||||
|
[self processUIEvent:"ui_paste"];
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: Focus
|
// MARK: Focus
|
||||||
|
|
||||||
- (BOOL)canBecomeKeyView {
|
- (BOOL)canBecomeKeyView {
|
||||||
|
|
|
@ -102,7 +102,11 @@
|
||||||
} else {
|
} else {
|
||||||
// Otherwise redirect event to the engine.
|
// Otherwise redirect event to the engine.
|
||||||
if (DisplayServer::get_singleton()) {
|
if (DisplayServer::get_singleton()) {
|
||||||
[[[NSApplication sharedApplication] keyWindow] sendEvent:event];
|
if ([[NSApplication sharedApplication] keyWindow].sheet) {
|
||||||
|
[[[[NSApplication sharedApplication] keyWindow] sheetParent] sendEvent:event];
|
||||||
|
} else {
|
||||||
|
[[[NSApplication sharedApplication] keyWindow] sendEvent:event];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,12 +58,18 @@ class NativeMenuMacOS : public NativeMenu {
|
||||||
NSMenu *window_menu_ns = nullptr;
|
NSMenu *window_menu_ns = nullptr;
|
||||||
NSMenu *help_menu_ns = nullptr;
|
NSMenu *help_menu_ns = nullptr;
|
||||||
NSMenu *dock_menu_ns = nullptr;
|
NSMenu *dock_menu_ns = nullptr;
|
||||||
|
NSMenu *edit_menu_ns = nullptr;
|
||||||
|
NSMenu *file_menu_ns = nullptr;
|
||||||
|
|
||||||
|
NSMenuItem *file_menu_item = nullptr;
|
||||||
|
|
||||||
RID main_menu;
|
RID main_menu;
|
||||||
RID application_menu;
|
RID application_menu;
|
||||||
RID window_menu;
|
RID window_menu;
|
||||||
RID help_menu;
|
RID help_menu;
|
||||||
RID dock_menu;
|
RID dock_menu;
|
||||||
|
RID edit_menu;
|
||||||
|
RID file_menu;
|
||||||
|
|
||||||
int _get_system_menu_start(const NSMenu *p_menu) const;
|
int _get_system_menu_start(const NSMenu *p_menu) const;
|
||||||
int _get_system_menu_count(const NSMenu *p_menu) const;
|
int _get_system_menu_count(const NSMenu *p_menu) const;
|
||||||
|
@ -71,7 +77,7 @@ class NativeMenuMacOS : public NativeMenu {
|
||||||
NSMenuItem *_menu_add_item(NSMenu *p_menu, const String &p_label, Key p_accel, int p_index, int *r_out);
|
NSMenuItem *_menu_add_item(NSMenu *p_menu, const String &p_label, Key p_accel, int p_index, int *r_out);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void _register_system_menus(NSMenu *p_main_menu, NSMenu *p_application_menu, NSMenu *p_window_menu, NSMenu *p_help_menu, NSMenu *p_dock_menu);
|
void _register_system_menus(NSMenu *p_main_menu, NSMenu *p_application_menu, NSMenu *p_window_menu, NSMenu *p_help_menu, NSMenu *p_dock_menu, NSMenu *p_edit_menu, NSMenu *p_file_menu, NSMenuItem *p_file_menu_item);
|
||||||
NSMenu *_get_dock_menu();
|
NSMenu *_get_dock_menu();
|
||||||
|
|
||||||
void _menu_need_update(NSMenu *p_menu);
|
void _menu_need_update(NSMenu *p_menu);
|
||||||
|
@ -84,6 +90,10 @@ public:
|
||||||
virtual bool has_system_menu(SystemMenus p_menu_id) const override;
|
virtual bool has_system_menu(SystemMenus p_menu_id) const override;
|
||||||
virtual RID get_system_menu(SystemMenus p_menu_id) const override;
|
virtual RID get_system_menu(SystemMenus p_menu_id) const override;
|
||||||
|
|
||||||
|
virtual bool get_system_menu_no_default_items(SystemMenus p_menu_id) const override;
|
||||||
|
virtual void set_system_menu_name(SystemMenus p_menu_id, const String &p_string) override;
|
||||||
|
virtual void set_system_menu_hidden(SystemMenus p_menu_id, bool p_hidden) override;
|
||||||
|
|
||||||
virtual RID create_menu() override;
|
virtual RID create_menu() override;
|
||||||
virtual bool has_menu(const RID &p_rid) const override;
|
virtual bool has_menu(const RID &p_rid) const override;
|
||||||
virtual void free_menu(const RID &p_rid) override;
|
virtual void free_menu(const RID &p_rid) override;
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
|
|
||||||
#include "scene/resources/image_texture.h"
|
#include "scene/resources/image_texture.h"
|
||||||
|
|
||||||
void NativeMenuMacOS::_register_system_menus(NSMenu *p_main_menu, NSMenu *p_application_menu, NSMenu *p_window_menu, NSMenu *p_help_menu, NSMenu *p_dock_menu) {
|
void NativeMenuMacOS::_register_system_menus(NSMenu *p_main_menu, NSMenu *p_application_menu, NSMenu *p_window_menu, NSMenu *p_help_menu, NSMenu *p_dock_menu, NSMenu *p_edit_menu, NSMenu *p_file_menu, NSMenuItem *p_file_menu_item) {
|
||||||
{
|
{
|
||||||
MenuData *md = memnew(MenuData);
|
MenuData *md = memnew(MenuData);
|
||||||
md->menu = p_main_menu;
|
md->menu = p_main_menu;
|
||||||
|
@ -45,6 +45,24 @@ void NativeMenuMacOS::_register_system_menus(NSMenu *p_main_menu, NSMenu *p_appl
|
||||||
main_menu_ns = p_main_menu;
|
main_menu_ns = p_main_menu;
|
||||||
menu_lookup[md->menu] = main_menu;
|
menu_lookup[md->menu] = main_menu;
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
MenuData *md = memnew(MenuData);
|
||||||
|
md->menu = p_file_menu;
|
||||||
|
md->is_system = true;
|
||||||
|
file_menu = menus.make_rid(md);
|
||||||
|
file_menu_ns = p_file_menu;
|
||||||
|
menu_lookup[md->menu] = file_menu;
|
||||||
|
|
||||||
|
file_menu_item = p_file_menu_item;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
MenuData *md = memnew(MenuData);
|
||||||
|
md->menu = p_edit_menu;
|
||||||
|
md->is_system = true;
|
||||||
|
edit_menu = menus.make_rid(md);
|
||||||
|
edit_menu_ns = p_edit_menu;
|
||||||
|
menu_lookup[md->menu] = edit_menu;
|
||||||
|
}
|
||||||
{
|
{
|
||||||
MenuData *md = memnew(MenuData);
|
MenuData *md = memnew(MenuData);
|
||||||
md->menu = p_application_menu;
|
md->menu = p_application_menu;
|
||||||
|
@ -160,10 +178,10 @@ bool NativeMenuMacOS::_is_menu_opened(NSMenu *p_menu) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
int NativeMenuMacOS::_get_system_menu_start(const NSMenu *p_menu) const {
|
int NativeMenuMacOS::_get_system_menu_start(const NSMenu *p_menu) const {
|
||||||
if (p_menu == [NSApp mainMenu]) { // Skip Apple menu.
|
if (p_menu == [NSApp mainMenu]) { // Skip Apple, File and Edit menu.
|
||||||
return 1;
|
return 3;
|
||||||
}
|
}
|
||||||
if (p_menu == application_menu_ns || p_menu == window_menu_ns || p_menu == help_menu_ns) {
|
if (p_menu == application_menu_ns || p_menu == window_menu_ns || p_menu == help_menu_ns || p_menu == edit_menu_ns || p_menu == file_menu_ns) {
|
||||||
int count = [p_menu numberOfItems];
|
int count = [p_menu numberOfItems];
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
NSMenuItem *menu_item = [p_menu itemAtIndex:i];
|
NSMenuItem *menu_item = [p_menu itemAtIndex:i];
|
||||||
|
@ -176,10 +194,10 @@ int NativeMenuMacOS::_get_system_menu_start(const NSMenu *p_menu) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
int NativeMenuMacOS::_get_system_menu_count(const NSMenu *p_menu) const {
|
int NativeMenuMacOS::_get_system_menu_count(const NSMenu *p_menu) const {
|
||||||
if (p_menu == [NSApp mainMenu]) { // Skip Apple, Window and Help menu.
|
if (p_menu == [NSApp mainMenu]) { // Skip Apple, File, Edit, Window and Help menu.
|
||||||
return [p_menu numberOfItems] - 3;
|
return [p_menu numberOfItems] - 5;
|
||||||
}
|
}
|
||||||
if (p_menu == application_menu_ns || p_menu == window_menu_ns || p_menu == help_menu_ns) {
|
if (p_menu == application_menu_ns || p_menu == window_menu_ns || p_menu == help_menu_ns || p_menu == edit_menu_ns || p_menu == file_menu_ns) {
|
||||||
int start = 0;
|
int start = 0;
|
||||||
int count = [p_menu numberOfItems];
|
int count = [p_menu numberOfItems];
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
|
@ -215,6 +233,8 @@ bool NativeMenuMacOS::has_system_menu(SystemMenus p_menu_id) const {
|
||||||
case WINDOW_MENU_ID:
|
case WINDOW_MENU_ID:
|
||||||
case HELP_MENU_ID:
|
case HELP_MENU_ID:
|
||||||
case DOCK_MENU_ID:
|
case DOCK_MENU_ID:
|
||||||
|
case EDIT_MENU_ID:
|
||||||
|
case FILE_MENU_ID:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
@ -233,11 +253,37 @@ RID NativeMenuMacOS::get_system_menu(SystemMenus p_menu_id) const {
|
||||||
return help_menu;
|
return help_menu;
|
||||||
case DOCK_MENU_ID:
|
case DOCK_MENU_ID:
|
||||||
return dock_menu;
|
return dock_menu;
|
||||||
|
case EDIT_MENU_ID:
|
||||||
|
return edit_menu;
|
||||||
|
case FILE_MENU_ID:
|
||||||
|
return file_menu;
|
||||||
default:
|
default:
|
||||||
return RID();
|
return RID();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NativeMenuMacOS::get_system_menu_no_default_items(SystemMenus p_menu_id) const {
|
||||||
|
return p_menu_id == FILE_MENU_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NativeMenuMacOS::set_system_menu_name(SystemMenus p_menu_id, const String &p_string) {
|
||||||
|
if (p_menu_id == FILE_MENU_ID) {
|
||||||
|
if (p_string.is_empty()) {
|
||||||
|
[file_menu_item setTitle:NSLocalizedString(@"File", nil)];
|
||||||
|
[file_menu_ns setTitle:NSLocalizedString(@"File", nil)];
|
||||||
|
} else {
|
||||||
|
[file_menu_item setTitle:[NSString stringWithUTF8String:p_string.utf8().get_data()]];
|
||||||
|
[file_menu_ns setTitle:[NSString stringWithUTF8String:p_string.utf8().get_data()]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NativeMenuMacOS::set_system_menu_hidden(SystemMenus p_menu_id, bool p_hidden) {
|
||||||
|
if (p_menu_id == FILE_MENU_ID) {
|
||||||
|
file_menu_item.hidden = p_hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RID NativeMenuMacOS::create_menu() {
|
RID NativeMenuMacOS::create_menu() {
|
||||||
MenuData *md = memnew(MenuData);
|
MenuData *md = memnew(MenuData);
|
||||||
md->menu = [[NSMenu alloc] initWithTitle:@""];
|
md->menu = [[NSMenu alloc] initWithTitle:@""];
|
||||||
|
@ -1291,7 +1337,7 @@ void NativeMenuMacOS::clear(const RID &p_rid) {
|
||||||
ERR_FAIL_NULL(md);
|
ERR_FAIL_NULL(md);
|
||||||
ERR_FAIL_COND_MSG(_is_menu_opened(md->menu), "Can't remove open menu!");
|
ERR_FAIL_COND_MSG(_is_menu_opened(md->menu), "Can't remove open menu!");
|
||||||
|
|
||||||
if (p_rid == application_menu || p_rid == window_menu || p_rid == help_menu) {
|
if (p_rid == application_menu || p_rid == window_menu || p_rid == help_menu || p_rid == edit_menu || p_rid == file_menu) {
|
||||||
int start = _get_system_menu_start(md->menu);
|
int start = _get_system_menu_start(md->menu);
|
||||||
int count = _get_system_menu_count(md->menu);
|
int count = _get_system_menu_count(md->menu);
|
||||||
for (int i = start + count - 1; i >= start; i--) {
|
for (int i = start + count - 1; i >= start; i--) {
|
||||||
|
@ -1302,12 +1348,24 @@ void NativeMenuMacOS::clear(const RID &p_rid) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p_rid == main_menu) {
|
if (p_rid == main_menu) {
|
||||||
// Restore Apple, Window and Help menu.
|
// Restore Apple, File, Edit, Window and Help menu.
|
||||||
MenuData *md_app = menus.get_or_null(application_menu);
|
MenuData *md_app = menus.get_or_null(application_menu);
|
||||||
if (md_app) {
|
if (md_app) {
|
||||||
NSMenuItem *menu_item = [md->menu addItemWithTitle:@"" action:nil keyEquivalent:@""];
|
NSMenuItem *menu_item = [md->menu addItemWithTitle:@"" action:nil keyEquivalent:@""];
|
||||||
[md->menu setSubmenu:md_app->menu forItem:menu_item];
|
[md->menu setSubmenu:md_app->menu forItem:menu_item];
|
||||||
}
|
}
|
||||||
|
MenuData *md_file = menus.get_or_null(file_menu);
|
||||||
|
if (md_file) {
|
||||||
|
NSMenuItem *menu_item = [md->menu addItemWithTitle:@"File" action:nil keyEquivalent:@""];
|
||||||
|
menu_item.hidden = YES;
|
||||||
|
[md->menu setSubmenu:md_file->menu forItem:menu_item];
|
||||||
|
file_menu_item = menu_item;
|
||||||
|
}
|
||||||
|
MenuData *md_edit = menus.get_or_null(edit_menu);
|
||||||
|
if (md_edit) {
|
||||||
|
NSMenuItem *menu_item = [md->menu addItemWithTitle:@"Edit" action:nil keyEquivalent:@""];
|
||||||
|
[md->menu setSubmenu:md_edit->menu forItem:menu_item];
|
||||||
|
}
|
||||||
MenuData *md_win = menus.get_or_null(window_menu);
|
MenuData *md_win = menus.get_or_null(window_menu);
|
||||||
if (md_win) {
|
if (md_win) {
|
||||||
NSMenuItem *menu_item = [md->menu addItemWithTitle:@"Window" action:nil keyEquivalent:@""];
|
NSMenuItem *menu_item = [md->menu addItemWithTitle:@"Window" action:nil keyEquivalent:@""];
|
||||||
|
@ -1346,6 +1404,28 @@ NativeMenuMacOS::~NativeMenuMacOS() {
|
||||||
memdelete(md);
|
memdelete(md);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (file_menu.is_valid()) {
|
||||||
|
MenuData *md = menus.get_or_null(file_menu);
|
||||||
|
if (md) {
|
||||||
|
clear(file_menu);
|
||||||
|
menus.free(file_menu);
|
||||||
|
menu_lookup.erase(md->menu);
|
||||||
|
md->menu = nullptr;
|
||||||
|
file_menu_ns = nullptr;
|
||||||
|
memdelete(md);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (edit_menu.is_valid()) {
|
||||||
|
MenuData *md = menus.get_or_null(edit_menu);
|
||||||
|
if (md) {
|
||||||
|
clear(edit_menu);
|
||||||
|
menus.free(edit_menu);
|
||||||
|
menu_lookup.erase(md->menu);
|
||||||
|
md->menu = nullptr;
|
||||||
|
edit_menu_ns = nullptr;
|
||||||
|
memdelete(md);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (window_menu.is_valid()) {
|
if (window_menu.is_valid()) {
|
||||||
MenuData *md = menus.get_or_null(window_menu);
|
MenuData *md = menus.get_or_null(window_menu);
|
||||||
if (md) {
|
if (md) {
|
||||||
|
|
|
@ -99,6 +99,10 @@ RID PopupMenu::bind_global_menu() {
|
||||||
} else {
|
} else {
|
||||||
system_menus[system_menu_id] = this;
|
system_menus[system_menu_id] = this;
|
||||||
system_menu = nmenu->get_system_menu(system_menu_id);
|
system_menu = nmenu->get_system_menu(system_menu_id);
|
||||||
|
nmenu->set_system_menu_name(system_menu_id, get_name());
|
||||||
|
if (nmenu->get_system_menu_no_default_items(system_menu_id)) {
|
||||||
|
nmenu->set_system_menu_hidden(system_menu_id, false);
|
||||||
|
}
|
||||||
global_menu = system_menu;
|
global_menu = system_menu;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -154,6 +158,12 @@ void PopupMenu::unbind_global_menu() {
|
||||||
|
|
||||||
if (global_menu == system_menu && system_menus[system_menu_id] == this) {
|
if (global_menu == system_menu && system_menus[system_menu_id] == this) {
|
||||||
system_menus.erase(system_menu_id);
|
system_menus.erase(system_menu_id);
|
||||||
|
NativeMenu *nmenu = NativeMenu::get_singleton();
|
||||||
|
|
||||||
|
nmenu->set_system_menu_name(system_menu_id, String());
|
||||||
|
if (nmenu->get_system_menu_no_default_items(system_menu_id)) {
|
||||||
|
nmenu->set_system_menu_hidden(system_menu_id, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < items.size(); i++) {
|
for (int i = 0; i < items.size(); i++) {
|
||||||
|
|
|
@ -41,6 +41,10 @@ void NativeMenu::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("get_system_menu", "menu_id"), &NativeMenu::get_system_menu);
|
ClassDB::bind_method(D_METHOD("get_system_menu", "menu_id"), &NativeMenu::get_system_menu);
|
||||||
ClassDB::bind_method(D_METHOD("get_system_menu_name", "menu_id"), &NativeMenu::get_system_menu_name);
|
ClassDB::bind_method(D_METHOD("get_system_menu_name", "menu_id"), &NativeMenu::get_system_menu_name);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("get_system_menu_no_default_items", "menu_id"), &NativeMenu::get_system_menu_no_default_items);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_system_menu_name", "menu_id", "string"), &NativeMenu::set_system_menu_name);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_system_menu_hidden", "menu_id", "hidden"), &NativeMenu::set_system_menu_hidden);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("create_menu"), &NativeMenu::create_menu);
|
ClassDB::bind_method(D_METHOD("create_menu"), &NativeMenu::create_menu);
|
||||||
ClassDB::bind_method(D_METHOD("has_menu", "rid"), &NativeMenu::has_menu);
|
ClassDB::bind_method(D_METHOD("has_menu", "rid"), &NativeMenu::has_menu);
|
||||||
ClassDB::bind_method(D_METHOD("free_menu", "rid"), &NativeMenu::free_menu);
|
ClassDB::bind_method(D_METHOD("free_menu", "rid"), &NativeMenu::free_menu);
|
||||||
|
@ -125,6 +129,8 @@ void NativeMenu::_bind_methods() {
|
||||||
BIND_ENUM_CONSTANT(WINDOW_MENU_ID);
|
BIND_ENUM_CONSTANT(WINDOW_MENU_ID);
|
||||||
BIND_ENUM_CONSTANT(HELP_MENU_ID);
|
BIND_ENUM_CONSTANT(HELP_MENU_ID);
|
||||||
BIND_ENUM_CONSTANT(DOCK_MENU_ID);
|
BIND_ENUM_CONSTANT(DOCK_MENU_ID);
|
||||||
|
BIND_ENUM_CONSTANT(EDIT_MENU_ID);
|
||||||
|
BIND_ENUM_CONSTANT(FILE_MENU_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NativeMenu::has_feature(Feature p_feature) const {
|
bool NativeMenu::has_feature(Feature p_feature) const {
|
||||||
|
@ -152,11 +158,27 @@ String NativeMenu::get_system_menu_name(SystemMenus p_menu_id) const {
|
||||||
return "Help menu";
|
return "Help menu";
|
||||||
case DOCK_MENU_ID:
|
case DOCK_MENU_ID:
|
||||||
return "Dock menu";
|
return "Dock menu";
|
||||||
|
case EDIT_MENU_ID:
|
||||||
|
return "Edit menu";
|
||||||
|
case FILE_MENU_ID:
|
||||||
|
return "File menu";
|
||||||
default:
|
default:
|
||||||
return "Invalid";
|
return "Invalid";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NativeMenu::get_system_menu_no_default_items(SystemMenus p_menu_id) const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NativeMenu::set_system_menu_name(SystemMenus p_menu_id, const String &p_string) {
|
||||||
|
WARN_PRINT("Global menus are not supported on this platform.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void NativeMenu::set_system_menu_hidden(SystemMenus p_menu_id, bool p_hidden) {
|
||||||
|
WARN_PRINT("Global menus are not supported on this platform.");
|
||||||
|
}
|
||||||
|
|
||||||
RID NativeMenu::create_menu() {
|
RID NativeMenu::create_menu() {
|
||||||
WARN_PRINT("Global menus are not supported on this platform.");
|
WARN_PRINT("Global menus are not supported on this platform.");
|
||||||
return RID();
|
return RID();
|
||||||
|
|
|
@ -66,6 +66,8 @@ public:
|
||||||
WINDOW_MENU_ID,
|
WINDOW_MENU_ID,
|
||||||
HELP_MENU_ID,
|
HELP_MENU_ID,
|
||||||
DOCK_MENU_ID,
|
DOCK_MENU_ID,
|
||||||
|
EDIT_MENU_ID,
|
||||||
|
FILE_MENU_ID,
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual bool has_feature(Feature p_feature) const;
|
virtual bool has_feature(Feature p_feature) const;
|
||||||
|
@ -74,6 +76,10 @@ public:
|
||||||
virtual RID get_system_menu(SystemMenus p_menu_id) const;
|
virtual RID get_system_menu(SystemMenus p_menu_id) const;
|
||||||
virtual String get_system_menu_name(SystemMenus p_menu_id) const;
|
virtual String get_system_menu_name(SystemMenus p_menu_id) const;
|
||||||
|
|
||||||
|
virtual bool get_system_menu_no_default_items(SystemMenus p_menu_id) const;
|
||||||
|
virtual void set_system_menu_name(SystemMenus p_menu_id, const String &p_string);
|
||||||
|
virtual void set_system_menu_hidden(SystemMenus p_menu_id, bool p_hidden);
|
||||||
|
|
||||||
virtual RID create_menu();
|
virtual RID create_menu();
|
||||||
virtual bool has_menu(const RID &p_rid) const;
|
virtual bool has_menu(const RID &p_rid) const;
|
||||||
virtual void free_menu(const RID &p_rid);
|
virtual void free_menu(const RID &p_rid);
|
||||||
|
|
Loading…
Reference in New Issue