Add the standard OS X "Window" menu

This commit is contained in:
Thomas Goyne 2016-03-13 12:04:17 -07:00
parent cac4ba910d
commit 9bbfdddde0
7 changed files with 133 additions and 5 deletions

View file

@ -265,6 +265,41 @@ struct app_updates final : public Command {
}
};
#ifdef __WXMAC__
struct app_minimize final : public Command {
CMD_NAME("app/minimize")
STR_MENU("Minimize")
STR_DISP("Minimize")
STR_HELP("Minimize the active window")
void operator()(agi::Context *c) override {
c->frame->Iconize();
}
};
struct app_maximize final : public Command {
CMD_NAME("app/maximize")
STR_MENU("Zoom")
STR_DISP("Zoom")
STR_HELP("Maximize the active window")
void operator()(agi::Context *c) override {
c->frame->Maximize(!c->frame->IsMaximized());
}
};
struct app_bring_to_front final : public Command {
CMD_NAME("app/bring_to_front")
STR_MENU("Bring All to Front")
STR_DISP("Bring All to Front")
STR_HELP("Bring forward all open documents to the front")
void operator()(agi::Context *) override {
osx::bring_to_front();
}
};
#endif
}
namespace cmd {
@ -281,6 +316,11 @@ namespace cmd {
reg(agi::make_unique<app_options>());
reg(agi::make_unique<app_toggle_global_hotkeys>());
reg(agi::make_unique<app_toggle_toolbar>());
#ifdef __WXMAC__
reg(agi::make_unique<app_minimize>());
reg(agi::make_unique<app_maximize>());
reg(agi::make_unique<app_bring_to_front>());
#endif
#ifdef WITH_UPDATE_CHECKER
reg(agi::make_unique<app_updates>());
#endif

View file

@ -47,6 +47,11 @@ namespace {
{nullptr}
};
const char *added_hotkeys_minimize[][3] = {
{"app/minimize", "Default", "Ctrl-M"},
{nullptr}
};
void migrate_hotkeys(const char *added[][3]) {
auto hk_map = hotkey::inst->GetHotkeyMap();
bool changed = false;
@ -109,6 +114,13 @@ void init() {
migrations.emplace_back("duplicate -> split");
}
#ifdef __WXMAC__
if (boost::find(migrations, "app/minimize") == end(migrations)) {
migrate_hotkeys(added_hotkeys_minimize);
migrations.emplace_back("app/minimize");
}
#endif
OPT_SET("App/Hotkey Migrations")->SetListString(std::move(migrations));
}

View file

@ -107,6 +107,9 @@
]
},
"Default" : {
"app/minimize" : [
"Ctrl-M"
],
"app/exit" : [
"Ctrl-Q"
],

View file

@ -36,6 +36,7 @@
{ "submenu" : "main/video", "text" : "&Video" },
{ "submenu" : "main/audio", "text" : "&Audio" },
{ "special" : "automation", "text" : "A&utomation" },
{ "submenu" : "main/window", "text" : "Window" },
{ "submenu" : "main/help", "text" : "&Help", "special" : "help" }
],
"main/file" : [
@ -200,6 +201,14 @@
{},
{ "command" : "app/toggle/toolbar" }
],
"main/window" : [
{ "command" : "app/minimize" },
{ "command" : "app/maximize" },
{},
{ "command" : "app/bring_to_front" },
{},
{ "special" : "window" }
],
"main/help" : [
{ "command" : "help/contents" },
{},

View file

@ -27,6 +27,7 @@
#include "format.h"
#include "libresrc/libresrc.h"
#include "options.h"
#include "utils.h"
#include <libaegisub/cajun/reader.h>
#include <libaegisub/hotkey.h>
@ -170,6 +171,10 @@ public:
{
}
void SetContext(agi::Context *c) {
context = c;
}
int AddCommand(cmd::Command *co, wxMenu *parent, std::string const& text = "") {
return AddCommand(co, parent, text.empty() ? co->StrMenu(context) : _(to_wx(text)));
}
@ -229,6 +234,8 @@ public:
}
void OnMenuOpen(wxMenuEvent &) {
if (!context)
return;
for (auto const& item : dynamic_items) UpdateItem(item);
for (auto item : mru) item->Update();
}
@ -237,7 +244,7 @@ public:
// This also gets clicks on unrelated things such as the toolbar, so
// the window ID ranges really need to be unique
size_t id = static_cast<size_t>(evt.GetId() - MENU_ID_BASE);
if (id < items.size())
if (id < items.size() && context)
cmd::call(items[id], context);
#ifdef __WXMAC__
@ -336,6 +343,11 @@ void process_menu_item(wxMenu *parent, agi::Context *c, json::Object const& ele,
std::string submenu, recent, command, text, special;
read_entry(ele, "special", &special);
#ifdef __WXMAC__
if (special == "window")
osx::make_windows_menu(parent);
#endif
if (read_entry(ele, "submenu", &submenu) && read_entry(ele, "text", &text)) {
wxString tl_text = _(to_wx(text));
parent->AppendSubMenu(build_menu(submenu, c, cm), tl_text);
@ -487,6 +499,21 @@ public:
namespace menu {
void GetMenuBar(std::string const& name, wxFrame *window, agi::Context *c) {
#ifdef __WXMAC__
auto bind_events = [&](CommandMenuBar *menu) {
window->Bind(wxEVT_ACTIVATE, [=](wxActivateEvent&) { menu->cm.SetContext(c); });
window->Bind(wxEVT_DESTROY, [=](wxWindowDestroyEvent&) {
if (!osx::activate_top_window_other_than(window))
menu->cm.SetContext(nullptr);
});
};
if (wxMenuBar *menu = wxMenuBar::MacGetCommonMenuBar()) {
bind_events(static_cast<CommandMenuBar *>(menu));
return;
}
#endif
auto menu = agi::make_unique<CommandMenuBar>(c);
for (auto const& item : get_menu(name)) {
std::string submenu, disp;
@ -502,9 +529,15 @@ namespace menu {
}
}
window->Bind(wxEVT_MENU_OPEN, &CommandManager::OnMenuOpen, &menu->cm);
window->Bind(wxEVT_MENU, &CommandManager::OnMenuClick, &menu->cm);
menu->Bind(wxEVT_MENU_OPEN, &CommandManager::OnMenuOpen, &menu->cm);
menu->Bind(wxEVT_MENU, &CommandManager::OnMenuClick, &menu->cm);
#ifdef __WXMAC__
bind_events(menu.get());
wxMenuBar::MacSetCommonMenuBar(menu.get());
#else
window->SetMenuBar(menu.get());
#endif
menu.release();
}

View file

@ -66,3 +66,25 @@ void RestartAegisub() {
[NSTask launchedTaskWithLaunchPath:helperPath
arguments:@[NSBundle.mainBundle.executablePath]];
}
namespace osx {
void make_windows_menu(wxMenu* wxmenu) {
NSApp.windowsMenu = wxmenu->GetHMenu();
}
bool activate_top_window_other_than(wxFrame *wx) {
NSWindow *w = wx->GetWXWindow();
for (NSNumber *windowNumber in [NSWindow windowNumbersWithOptions:0]) {
NSWindow *window = [NSApp windowWithWindowNumber:windowNumber.integerValue];
if (window && window.canBecomeMainWindow && window != w) {
[window makeMainWindow];
return true;
}
}
return false;
}
void bring_to_front() {
[NSApp arrangeInFront:nil];
}
}

View file

@ -99,11 +99,20 @@ agi::fs::path SaveFileSelector(wxString const& message, std::string const& optio
wxString LocalizedLanguageName(wxString const& lang);
namespace osx { namespace ime {
namespace osx {
/// Make the given menu the OS X Window menu
void make_windows_menu(wxMenu *wxmenu);
/// Activate a top-level document window other than the given one
bool activate_top_window_other_than(wxFrame *wx);
// Bring all windows to the front, maintaining relative z-order
void bring_to_front();
namespace ime {
/// Inject the IME helper into the given wxSTC
void inject(wxStyledTextCtrl *ctrl);
/// Invalidate any pending text from the IME
void invalidate(wxStyledTextCtrl *ctrl);
/// Give the IME a chance to process a key event and return whether it did
bool process_key_event(wxStyledTextCtrl *ctrl, wxKeyEvent &);
} }
}
}