Extensions now support defining keyboard shortcuts (#1403, #3239)

This commit is contained in:
David Capello 2022-04-13 22:46:48 -03:00
parent 721e401052
commit e4c2995326
11 changed files with 232 additions and 71 deletions

View File

@ -1282,6 +1282,7 @@ download_themes = Download Themes
open_theme_folder = Open &Folder open_theme_folder = Open &Folder
language_extensions = Languages language_extensions = Languages
theme_extensions = Themes theme_extensions = Themes
keys_extensions = Keyboard Shortcuts
script_extensions = Scripts script_extensions = Scripts
palette_extensions = Palettes palette_extensions = Palettes
dithering_matrix_extensions = Dithering Matrices dithering_matrix_extensions = Dithering Matrices

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2019-2020 Igara Studio S.A. // Copyright (C) 2019-2022 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello // Copyright (C) 2001-2018 David Capello
// //
// This program is distributed under the terms of // This program is distributed under the terms of
@ -16,6 +16,7 @@
#include "app/commands/commands.h" #include "app/commands/commands.h"
#include "app/commands/params.h" #include "app/commands/params.h"
#include "app/console.h" #include "app/console.h"
#include "app/extensions.h"
#include "app/gui_xml.h" #include "app/gui_xml.h"
#include "app/i18n/strings.h" #include "app/i18n/strings.h"
#include "app/recent_files.h" #include "app/recent_files.h"
@ -417,10 +418,22 @@ void AppMenus::reload()
.FirstChild("gui") .FirstChild("gui")
.FirstChild("keyboard").ToElement(); .FirstChild("keyboard").ToElement();
// From a fresh start, load the default keys
KeyboardShortcuts::instance()->clear(); KeyboardShortcuts::instance()->clear();
KeyboardShortcuts::instance()->importFile(xmlKey, KeySource::Original); KeyboardShortcuts::instance()->importFile(xmlKey, KeySource::Original);
// Load user settings // Load extension-defined keys
for (const Extension* ext : App::instance()->extensions()) {
if (ext->isEnabled() &&
ext->hasKeys()) {
for (const auto& kv : ext->keys()) {
KeyboardShortcuts::instance()->importFile(
kv.second, KeySource::ExtensionDefined);
}
}
}
// Load user-defined keys
{ {
ResourceFinder rf; ResourceFinder rf;
rf.includeUserDir("user.aseprite-keys"); rf.includeUserDir("user.aseprite-keys");

View File

@ -58,7 +58,7 @@ using namespace ui;
namespace { namespace {
typedef std::map<AppMenuItem*, KeyPtr> MenuKeys; using MenuKeys = std::map<AppMenuItem*, KeyPtr>;
class HeaderSplitter : public Splitter { class HeaderSplitter : public Splitter {
public: public:
@ -195,7 +195,7 @@ private:
window.openWindowInForeground(); window.openWindowInForeground();
if (window.isModified()) { if (window.isModified()) {
m_key->disableAccel(origAccel); m_key->disableAccel(origAccel, KeySource::UserDefined);
if (!window.accel().isEmpty()) if (!window.accel().isEmpty())
m_key->add(window.accel(), KeySource::UserDefined, m_keys); m_key->add(window.accel(), KeySource::UserDefined, m_keys);
} }
@ -215,7 +215,7 @@ private:
accel.toString())) != 1) accel.toString())) != 1)
return; return;
m_key->disableAccel(accel); m_key->disableAccel(accel, KeySource::UserDefined);
window()->layout(); window()->layout();
} }

View File

@ -1277,6 +1277,10 @@ private:
if (extensionsList()->getItemsCount() > 0) if (extensionsList()->getItemsCount() > 0)
return; return;
loadExtensionsByCategory(
Extension::Category::Keys,
Strings::options_keys_extensions());
loadExtensionsByCategory( loadExtensionsByCategory(
Extension::Category::Languages, Extension::Category::Languages,
Strings::options_language_extensions()); Strings::options_language_extensions());

View File

@ -257,6 +257,12 @@ void Extension::executeExitActions()
#endif // ENABLE_SCRIPTING #endif // ENABLE_SCRIPTING
} }
void Extension::addKeys(const std::string& id, const std::string& path)
{
m_keys[id] = path;
updateCategory(Category::Keys);
}
void Extension::addLanguage(const std::string& id, const std::string& path) void Extension::addLanguage(const std::string& id, const std::string& path)
{ {
m_languages[id] = path; m_languages[id] = path;
@ -456,8 +462,10 @@ bool Extension::isDefaultTheme() const
void Extension::updateCategory(const Category newCategory) void Extension::updateCategory(const Category newCategory)
{ {
if (m_category == Category::None) if (m_category == Category::None ||
m_category == Category::Keys) {
m_category = newCategory; m_category = newCategory;
}
else if (m_category != newCategory) else if (m_category != newCategory)
m_category = Category::Multiple; m_category = Category::Multiple;
} }
@ -1016,6 +1024,24 @@ Extension* Extensions::loadExtension(const std::string& path,
auto contributes = json["contributes"]; auto contributes = json["contributes"];
if (contributes.is_object()) { if (contributes.is_object()) {
// Keys
auto keys = contributes["keys"];
if (keys.is_array()) {
for (const auto& key : keys.array_items()) {
std::string keyId = key["id"].string_value();
std::string keyPath = key["path"].string_value();
// The path must be always relative to the extension
keyPath = base::join_path(path, keyPath);
LOG("EXT: New keyboard shortcuts '%s' in '%s'\n",
keyId.c_str(),
keyPath.c_str());
extension->addKeys(keyId, keyPath);
}
}
// Languages // Languages
auto languages = contributes["languages"]; auto languages = contributes["languages"];
if (languages.is_array()) { if (languages.is_array()) {
@ -1130,6 +1156,7 @@ Extension* Extensions::loadExtension(const std::string& path,
void Extensions::generateExtensionSignals(Extension* extension) void Extensions::generateExtensionSignals(Extension* extension)
{ {
if (extension->hasKeys()) KeysChange(extension);
if (extension->hasLanguages()) LanguagesChange(extension); if (extension->hasLanguages()) LanguagesChange(extension);
if (extension->hasThemes()) ThemesChange(extension); if (extension->hasThemes()) ThemesChange(extension);
if (extension->hasPalettes()) PalettesChange(extension); if (extension->hasPalettes()) PalettesChange(extension);

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2020 Igara Studio S.A. // Copyright (C) 2020-2022 Igara Studio S.A.
// Copyright (C) 2017-2018 David Capello // Copyright (C) 2017-2018 David Capello
// //
// This program is distributed under the terms of // This program is distributed under the terms of
@ -36,6 +36,7 @@ namespace app {
public: public:
enum class Category { enum class Category {
None, None,
Keys,
Languages, Languages,
Themes, Themes,
Scripts, Scripts,
@ -78,10 +79,12 @@ namespace app {
const std::string& displayName() const { return m_displayName; } const std::string& displayName() const { return m_displayName; }
const Category category() const { return m_category; } const Category category() const { return m_category; }
const ExtensionItems& keys() const { return m_keys; }
const ExtensionItems& languages() const { return m_languages; } const ExtensionItems& languages() const { return m_languages; }
const ExtensionItems& themes() const { return m_themes; } const ExtensionItems& themes() const { return m_themes; }
const ExtensionItems& palettes() const { return m_palettes; } const ExtensionItems& palettes() const { return m_palettes; }
void addKeys(const std::string& id, const std::string& path);
void addLanguage(const std::string& id, const std::string& path); void addLanguage(const std::string& id, const std::string& path);
void addTheme(const std::string& id, const std::string& path); void addTheme(const std::string& id, const std::string& path);
void addPalette(const std::string& id, const std::string& path); void addPalette(const std::string& id, const std::string& path);
@ -98,6 +101,7 @@ namespace app {
bool canBeDisabled() const; bool canBeDisabled() const;
bool canBeUninstalled() const; bool canBeUninstalled() const;
bool hasKeys() const { return !m_keys.empty(); }
bool hasLanguages() const { return !m_languages.empty(); } bool hasLanguages() const { return !m_languages.empty(); }
bool hasThemes() const { return !m_themes.empty(); } bool hasThemes() const { return !m_themes.empty(); }
bool hasPalettes() const { return !m_palettes.empty(); } bool hasPalettes() const { return !m_palettes.empty(); }
@ -119,6 +123,7 @@ namespace app {
void exitScripts(); void exitScripts();
#endif #endif
ExtensionItems m_keys;
ExtensionItems m_languages; ExtensionItems m_languages;
ExtensionItems m_themes; ExtensionItems m_themes;
ExtensionItems m_palettes; ExtensionItems m_palettes;
@ -180,6 +185,7 @@ namespace app {
std::vector<Extension::DitheringMatrixInfo> ditheringMatrices(); std::vector<Extension::DitheringMatrixInfo> ditheringMatrices();
obs::signal<void(Extension*)> NewExtension; obs::signal<void(Extension*)> NewExtension;
obs::signal<void(Extension*)> KeysChange;
obs::signal<void(Extension*)> LanguagesChange; obs::signal<void(Extension*)> LanguagesChange;
obs::signal<void(Extension*)> ThemesChange; obs::signal<void(Extension*)> ThemesChange;
obs::signal<void(Extension*)> PalettesChange; obs::signal<void(Extension*)> PalettesChange;

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2018 Igara Studio S.A. // Copyright (C) 2018-2022 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello // Copyright (C) 2001-2018 David Capello
// //
// This program is distributed under the terms of // This program is distributed under the terms of
@ -15,6 +15,7 @@
#include "ui/accelerator.h" #include "ui/accelerator.h"
#include <memory> #include <memory>
#include <utility>
#include <vector> #include <vector>
namespace ui { namespace ui {
@ -31,6 +32,7 @@ namespace app {
enum class KeySource { enum class KeySource {
Original, Original,
ExtensionDefined,
UserDefined UserDefined
}; };
@ -98,20 +100,20 @@ namespace app {
return KeyAction(int(a) & int(b)); return KeyAction(int(a) & int(b));
} }
using KeySourceAccelList = std::vector<std::pair<KeySource, ui::Accelerator>>;
class Key { class Key {
public: public:
Key(const Key& key);
Key(Command* command, const Params& params, KeyContext keyContext); Key(Command* command, const Params& params, KeyContext keyContext);
Key(KeyType type, tools::Tool* tool); Key(KeyType type, tools::Tool* tool);
explicit Key(KeyAction action); explicit Key(KeyAction action);
explicit Key(WheelAction action); explicit Key(WheelAction action);
KeyType type() const { return m_type; } KeyType type() const { return m_type; }
const ui::Accelerators& accels() const { const ui::Accelerators& accels() const;
return (m_useUsers ? m_users: m_accels); const KeySourceAccelList addsKeys() const { return m_adds; }
} const KeySourceAccelList delsKeys() const { return m_dels; }
const ui::Accelerators& origAccels() const { return m_accels; }
const ui::Accelerators& userAccels() const { return m_users; }
const ui::Accelerators& userRemovedAccels() const { return m_userRemoved; }
void add(const ui::Accelerator& accel, void add(const ui::Accelerator& accel,
const KeySource source, const KeySource source,
@ -122,9 +124,15 @@ namespace app {
bool isLooselyPressed() const; bool isLooselyPressed() const;
bool hasAccel(const ui::Accelerator& accel) const; bool hasAccel(const ui::Accelerator& accel) const;
void disableAccel(const ui::Accelerator& accel); bool hasUserDefinedAccels() const;
// Resets user accelerators to the original ones. // The KeySource indicates from where the key was disabled
// (e.g. if it was removed from an extension-defined file, or from
// user-defined).
void disableAccel(const ui::Accelerator& accel,
const KeySource source);
// Resets user accelerators to the original & extension-defined ones.
void reset(); void reset();
void copyOriginalToUser(); void copyOriginalToUser();
@ -144,10 +152,11 @@ namespace app {
private: private:
KeyType m_type; KeyType m_type;
ui::Accelerators m_accels; // Default accelerators (from gui.xml) KeySourceAccelList m_adds;
ui::Accelerators m_users; // User-defined accelerators KeySourceAccelList m_dels;
ui::Accelerators m_userRemoved; // Default accelerators removed by user // Final list of accelerators after processing the
bool m_useUsers; // addition/deletion of extension-defined & user-defined keys.
mutable std::unique_ptr<ui::Accelerators> m_accels;
KeyContext m_keycontext; KeyContext m_keycontext;
// for KeyType::Command // for KeyType::Command
@ -161,8 +170,8 @@ namespace app {
WheelAction m_wheelAction; WheelAction m_wheelAction;
}; };
typedef std::shared_ptr<Key> KeyPtr; using KeyPtr = std::shared_ptr<Key> ;
typedef std::vector<KeyPtr> Keys; using Keys = std::vector<KeyPtr>;
std::string convertKeyContextToString(KeyContext keyContext); std::string convertKeyContextToString(KeyContext keyContext);
std::string convertKeyContextToUserFriendlyString(KeyContext keyContext); std::string convertKeyContextToUserFriendlyString(KeyContext keyContext);

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2018-2020 Igara Studio S.A. // Copyright (C) 2018-2022 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello // Copyright (C) 2001-2018 David Capello
// //
// This program is distributed under the terms of // This program is distributed under the terms of
@ -124,6 +124,32 @@ namespace {
return std::string(); return std::string();
} }
void erase_accel(app::KeySourceAccelList& kvs,
const app::KeySource source,
const ui::Accelerator& accel) {
for (auto it=kvs.begin(); it!=kvs.end(); ) {
auto& kv = *it;
if (kv.first == source &&
kv.second == accel) {
it = kvs.erase(it);
}
else
++it;
}
}
void erase_accels(app::KeySourceAccelList& kvs,
const app::KeySource source) {
for (auto it=kvs.begin(); it!=kvs.end(); ) {
auto& kv = *it;
if (kv.first == source) {
it = kvs.erase(it);
}
else
++it;
}
}
} // anonymous namespace } // anonymous namespace
namespace base { namespace base {
@ -171,9 +197,33 @@ using namespace ui;
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// Key // Key
Key::Key(const Key& k)
: m_type(k.m_type)
, m_adds(k.m_adds)
, m_dels(k.m_dels)
, m_keycontext(k.m_keycontext)
{
switch (m_type) {
case KeyType::Command:
m_command = k.m_command;
m_params = k.m_params;
break;
case KeyType::Tool:
case KeyType::Quicktool:
m_tool = k.m_tool;
break;
case KeyType::Action:
m_action = k.m_action;
break;
case KeyType::WheelAction:
m_action = k.m_action;
m_wheelAction = k.m_wheelAction;
break;
}
}
Key::Key(Command* command, const Params& params, KeyContext keyContext) Key::Key(Command* command, const Params& params, KeyContext keyContext)
: m_type(KeyType::Command) : m_type(KeyType::Command)
, m_useUsers(false)
, m_keycontext(keyContext) , m_keycontext(keyContext)
, m_command(command) , m_command(command)
, m_params(params) , m_params(params)
@ -182,7 +232,6 @@ Key::Key(Command* command, const Params& params, KeyContext keyContext)
Key::Key(KeyType type, tools::Tool* tool) Key::Key(KeyType type, tools::Tool* tool)
: m_type(type) : m_type(type)
, m_useUsers(false)
, m_keycontext(KeyContext::Any) , m_keycontext(KeyContext::Any)
, m_tool(tool) , m_tool(tool)
{ {
@ -190,7 +239,6 @@ Key::Key(KeyType type, tools::Tool* tool)
Key::Key(KeyAction action) Key::Key(KeyAction action)
: m_type(KeyType::Action) : m_type(KeyType::Action)
, m_useUsers(false)
, m_keycontext(KeyContext::Any) , m_keycontext(KeyContext::Any)
, m_action(action) , m_action(action)
{ {
@ -239,35 +287,63 @@ Key::Key(KeyAction action)
Key::Key(WheelAction wheelAction) Key::Key(WheelAction wheelAction)
: m_type(KeyType::WheelAction) : m_type(KeyType::WheelAction)
, m_useUsers(false)
, m_keycontext(KeyContext::MouseWheel) , m_keycontext(KeyContext::MouseWheel)
, m_action(KeyAction::None) , m_action(KeyAction::None)
, m_wheelAction(wheelAction) , m_wheelAction(wheelAction)
{ {
} }
const ui::Accelerators& Key::accels() const
{
if (!m_accels) {
m_accels = std::make_unique<ui::Accelerators>();
// Add default keys
for (const auto& kv : m_adds) {
if (kv.first == KeySource::Original)
m_accels->add(kv.second);
}
// Delete/add extension-defined keys
for (const auto& kv : m_dels) {
if (kv.first == KeySource::ExtensionDefined)
m_accels->remove(kv.second);
else {
ASSERT(kv.first != KeySource::Original);
}
}
for (const auto& kv : m_adds) {
if (kv.first == KeySource::ExtensionDefined)
m_accels->add(kv.second);
}
// Delete/add user-defined keys
for (const auto& kv : m_dels) {
if (kv.first == KeySource::UserDefined)
m_accels->remove(kv.second);
}
for (const auto& kv : m_adds) {
if (kv.first == KeySource::UserDefined)
m_accels->add(kv.second);
}
}
return *m_accels;
}
void Key::add(const ui::Accelerator& accel, void Key::add(const ui::Accelerator& accel,
const KeySource source, const KeySource source,
KeyboardShortcuts& globalKeys) KeyboardShortcuts& globalKeys)
{ {
Accelerators* accels = &m_accels; m_adds.emplace_back(source, accel);
m_accels.reset();
if (source == KeySource::UserDefined) {
if (!m_useUsers) {
m_useUsers = true;
m_users = m_accels;
}
accels = &m_users;
}
// Remove the accelerator from other commands // Remove the accelerator from other commands
if (source == KeySource::UserDefined) { if (source == KeySource::ExtensionDefined ||
globalKeys.disableAccel(accel, m_keycontext, this); source == KeySource::UserDefined) {
m_userRemoved.remove(accel); erase_accel(m_dels, source, accel);
}
// Add the accelerator globalKeys.disableAccel(accel, source, m_keycontext, this);
accels->add(accel); }
} }
const ui::Accelerator* Key::isPressed(const Message* msg, const ui::Accelerator* Key::isPressed(const Message* msg,
@ -322,31 +398,47 @@ bool Key::hasAccel(const ui::Accelerator& accel) const
return accels().has(accel); return accels().has(accel);
} }
void Key::disableAccel(const ui::Accelerator& accel) bool Key::hasUserDefinedAccels() const
{ {
if (!m_useUsers) { for (const auto& kv : m_adds) {
m_useUsers = true; if (kv.first == KeySource::UserDefined)
m_users = m_accels; return true;
} }
return false;
}
m_users.remove(accel); void Key::disableAccel(const ui::Accelerator& accel,
const KeySource source)
{
// It doesn't make sense that the default keyboard shortcuts file
// (gui.xml) removes some accelerator.
ASSERT(source != KeySource::Original);
if (m_accels.has(accel)) erase_accel(m_adds, source, accel);
m_userRemoved.add(accel); erase_accel(m_dels, source, accel);
m_dels.emplace_back(source, accel);
m_accels.reset();
} }
void Key::reset() void Key::reset()
{ {
m_users.clear(); erase_accels(m_adds, KeySource::UserDefined);
m_userRemoved.clear(); erase_accels(m_dels, KeySource::UserDefined);
m_useUsers = false; m_accels.reset();
} }
void Key::copyOriginalToUser() void Key::copyOriginalToUser()
{ {
m_users = m_accels; // Erase all user-defined keys
m_userRemoved.clear(); erase_accels(m_adds, KeySource::UserDefined);
m_useUsers = true; erase_accels(m_dels, KeySource::UserDefined);
// Then copy all original & extension-defined keys as user-defined
auto copy = m_adds;
for (const auto& kv : copy)
m_adds.emplace_back(KeySource::UserDefined, kv.second);
m_accels.reset();
} }
std::string Key::triggerString() const std::string Key::triggerString() const
@ -465,7 +557,7 @@ void KeyboardShortcuts::importFile(TiXmlElement* rootElement, KeySource source)
} }
} }
else else
key->disableAccel(accel); key->disableAccel(accel, source);
} }
} }
} }
@ -494,7 +586,7 @@ void KeyboardShortcuts::importFile(TiXmlElement* rootElement, KeySource source)
if (!removed) if (!removed)
key->add(accel, source, *this); key->add(accel, source, *this);
else else
key->disableAccel(accel); key->disableAccel(accel, source);
} }
} }
} }
@ -522,7 +614,7 @@ void KeyboardShortcuts::importFile(TiXmlElement* rootElement, KeySource source)
if (!removed) if (!removed)
key->add(accel, source, *this); key->add(accel, source, *this);
else else
key->disableAccel(accel); key->disableAccel(accel, source);
} }
} }
} }
@ -550,7 +642,7 @@ void KeyboardShortcuts::importFile(TiXmlElement* rootElement, KeySource source)
if (!removed) if (!removed)
key->add(accel, source, *this); key->add(accel, source, *this);
else else
key->disableAccel(accel); key->disableAccel(accel, source);
} }
} }
} }
@ -578,7 +670,7 @@ void KeyboardShortcuts::importFile(TiXmlElement* rootElement, KeySource source)
if (!removed) if (!removed)
key->add(accel, source, *this); key->add(accel, source, *this);
else else
key->disableAccel(accel); key->disableAccel(accel, source);
} }
} }
} }
@ -633,11 +725,13 @@ void KeyboardShortcuts::exportKeys(TiXmlElement& parent, KeyType type)
if (key->type() != type) if (key->type() != type)
continue; continue;
for (const ui::Accelerator& accel : key->userRemovedAccels()) for (const auto& kv : key->delsKeys())
exportAccel(parent, key.get(), accel, true); if (kv.first == KeySource::UserDefined)
exportAccel(parent, key.get(), kv.second, true);
for (const ui::Accelerator& accel : key->userAccels()) for (const auto& kv : key->addsKeys())
exportAccel(parent, key.get(), accel, false); if (kv.first == KeySource::UserDefined)
exportAccel(parent, key.get(), kv.second, false);
} }
} }
@ -773,17 +867,19 @@ KeyPtr KeyboardShortcuts::wheelAction(WheelAction wheelAction)
} }
void KeyboardShortcuts::disableAccel(const ui::Accelerator& accel, void KeyboardShortcuts::disableAccel(const ui::Accelerator& accel,
const KeySource source,
const KeyContext keyContext, const KeyContext keyContext,
const Key* newKey) const Key* newKey)
{ {
for (KeyPtr& key : m_keys) { for (KeyPtr& key : m_keys) {
if (key->keycontext() == keyContext && if (key.get() != newKey &&
key->keycontext() == keyContext &&
key->hasAccel(accel) && key->hasAccel(accel) &&
// Tools can contain the same keyboard shortcut // Tools can contain the same keyboard shortcut
(key->type() != KeyType::Tool || (key->type() != KeyType::Tool ||
newKey == nullptr || newKey == nullptr ||
newKey->type() != KeyType::Tool)) { newKey->type() != KeyType::Tool)) {
key->disableAccel(accel); key->disableAccel(accel, source);
} }
} }
} }
@ -885,7 +981,7 @@ bool KeyboardShortcuts::hasMouseWheelCustomization() const
{ {
for (const KeyPtr& key : m_keys) { for (const KeyPtr& key : m_keys) {
if (key->type() == KeyType::WheelAction && if (key->type() == KeyType::WheelAction &&
!key->userAccels().empty()) key->hasUserDefinedAccels())
return true; return true;
} }
return false; return false;

View File

@ -1,4 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2022 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello // Copyright (C) 2001-2018 David Capello
// //
// This program is distributed under the terms of // This program is distributed under the terms of
@ -50,6 +51,7 @@ namespace app {
KeyPtr wheelAction(WheelAction action); KeyPtr wheelAction(WheelAction action);
void disableAccel(const ui::Accelerator& accel, void disableAccel(const ui::Accelerator& accel,
const KeySource source,
const KeyContext keyContext, const KeyContext keyContext,
const Key* newKey); const Key* newKey);

View File

@ -24,9 +24,11 @@ MainMenuBar::MainMenuBar()
{ {
Extensions& extensions = App::instance()->extensions(); Extensions& extensions = App::instance()->extensions();
m_extScripts = // Reload the main menu if there are changes in keyboard shortcuts
extensions.ScriptsChange.connect( // or scripts when extensions are installed/uninstalled or
[this]{ reload(); }); // enabled/disabled.
m_extKeys = extensions.KeysChange.connect( [this]{ reload(); });
m_extScripts = extensions.ScriptsChange.connect( [this]{ reload(); });
} }
void MainMenuBar::reload() void MainMenuBar::reload()

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2020 Igara Studio S.A // Copyright (C) 2020-2022 Igara Studio S.A
// Copyright (C) 2001-2015 David Capello // Copyright (C) 2001-2015 David Capello
// //
// This program is distributed under the terms of // This program is distributed under the terms of
@ -21,6 +21,7 @@ namespace app {
void reload(); void reload();
private: private:
obs::scoped_connection m_extKeys;
obs::scoped_connection m_extScripts; obs::scoped_connection m_extScripts;
}; };