From f907be2e9cdd66e3acbb5959a626abb28ad51ee7 Mon Sep 17 00:00:00 2001 From: Giorgio Mendieta <31053658+GiorgioMendieta@users.noreply.github.com> Date: Sat, 23 May 2026 12:39:31 +0200 Subject: [PATCH] feat: open data folder from menu bar --- CMakeLists.txt | 3 ++- src/dusk/macos_menu.hpp | 13 +++++++++ src/dusk/macos_menu.mm | 60 +++++++++++++++++++++++++++++++++++++++++ src/m_Do/m_Do_main.cpp | 6 +++++ 4 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 src/dusk/macos_menu.hpp create mode 100644 src/dusk/macos_menu.mm diff --git a/CMakeLists.txt b/CMakeLists.txt index 696e8a74bb..ae5105e7b3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -579,8 +579,9 @@ endif () if (APPLE AND NOT IOS AND NOT TVOS) find_library(APPKIT_FRAMEWORK AppKit REQUIRED) - target_sources(dusklight PRIVATE src/dusk/file_select_macos.mm) + target_sources(dusklight PRIVATE src/dusk/file_select_macos.mm src/dusk/macos_menu.mm) set_source_files_properties(src/dusk/file_select_macos.mm PROPERTIES COMPILE_FLAGS -fobjc-arc) + set_source_files_properties(src/dusk/macos_menu.mm PROPERTIES COMPILE_FLAGS -fobjc-arc) target_link_libraries(dusklight PRIVATE ${APPKIT_FRAMEWORK}) endif () diff --git a/src/dusk/macos_menu.hpp b/src/dusk/macos_menu.hpp new file mode 100644 index 0000000000..6e3849e45e --- /dev/null +++ b/src/dusk/macos_menu.hpp @@ -0,0 +1,13 @@ +#pragma once + +// Only include this header on macOS +#if defined(__APPLE__) && !TARGET_OS_IOS && !TARGET_OS_TV && !TARGET_OS_MACCATALYST + +namespace dusk { + +// App menu actions (e.g., "Open Data Folder..." in the app name menu) +void InstallMacOSAppMenuActions(); + +} // namespace dusk + +#endif diff --git a/src/dusk/macos_menu.mm b/src/dusk/macos_menu.mm new file mode 100644 index 0000000000..e5ff3376ba --- /dev/null +++ b/src/dusk/macos_menu.mm @@ -0,0 +1,60 @@ +#include "macos_menu.hpp" + +#include "dusk/data.hpp" + +#import + +@interface DuskAppMenuTarget : NSObject +- (void)openDataFolder:(id)sender; +@end + +@implementation DuskAppMenuTarget +- (void)openDataFolder:(id)sender { + (void)sender; + dusk::data::open_data_path(); +} +@end + +namespace dusk { +namespace { + +DuskAppMenuTarget *shared_app_menu_target() { + static DuskAppMenuTarget *target = [DuskAppMenuTarget new]; + return target; +} + +} // namespace + +void InstallMacOSAppMenuActions() { + NSMenu *mainMenu = [NSApp mainMenu]; + if (mainMenu == nil || [mainMenu numberOfItems] == 0) { + return; + } + + NSMenu *appMenu = [[mainMenu itemAtIndex:0] submenu]; + if (appMenu == nil) { + return; + } + + if ([appMenu itemWithTitle:@"Open Data Folder..."] != nil) { + return; + } + + NSUInteger insertIndex = [appMenu numberOfItems]; + + for (NSMenuItem *existingItem in [appMenu itemArray]) { + if ([existingItem action] == @selector(terminate:)) { + insertIndex = [appMenu indexOfItem:existingItem]; + break; + } + } + + NSMenuItem *item = + [[NSMenuItem alloc] initWithTitle:@"Open Data Folder..." + action:@selector(openDataFolder:) + keyEquivalent:@""]; + + [item setTarget:shared_app_menu_target()]; + [appMenu insertItem:item atIndex:insertIndex]; +} +} // namespace dusk diff --git a/src/m_Do/m_Do_main.cpp b/src/m_Do/m_Do_main.cpp index fbd872efc4..614d24d45a 100644 --- a/src/m_Do/m_Do_main.cpp +++ b/src/m_Do/m_Do_main.cpp @@ -92,6 +92,7 @@ #include "tracy/Tracy.hpp" #include #ifdef __APPLE__ +#include "dusk/macos_menu.hpp" #include #endif @@ -590,6 +591,11 @@ int game_main(int argc, char* argv[]) { auroraInfo = aurora_initialize(argc, argv, &config); } +#if defined(__APPLE__) && !TARGET_OS_IOS && !TARGET_OS_TV && !TARGET_OS_MACCATALYST + // macOS specific app menu actions + dusk::InstallMacOSAppMenuActions(); +#endif + #ifdef DUSK_DISCORD if (dusk::getSettings().game.enableDiscordPresence) { dusk::discord::initialize();