mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-30 13:20:28 +00:00
Fix hang if we press Cmd-S two or more times quickly to launch File > Save
With this we avoid to unintentional execute two or more times a command when we are already in a command execution.
This commit is contained in:
parent
2ab27ade9b
commit
79795b97a9
@ -730,7 +730,7 @@ void AppMenus::createNativeMenus()
|
|||||||
about.execute = [native]{
|
about.execute = [native]{
|
||||||
if (can_call_global_shortcut(&native)) {
|
if (can_call_global_shortcut(&native)) {
|
||||||
Command* cmd = Commands::instance()->byId(CommandId::About());
|
Command* cmd = Commands::instance()->byId(CommandId::About());
|
||||||
UIContext::instance()->executeCommand(cmd);
|
UIContext::instance()->executeCommandFromMenuOrShortcut(cmd);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
about.validate = [native](os::MenuItem* item){
|
about.validate = [native](os::MenuItem* item){
|
||||||
@ -743,7 +743,7 @@ void AppMenus::createNativeMenus()
|
|||||||
preferences.execute = [native]{
|
preferences.execute = [native]{
|
||||||
if (can_call_global_shortcut(&native)) {
|
if (can_call_global_shortcut(&native)) {
|
||||||
Command* cmd = Commands::instance()->byId(CommandId::Options());
|
Command* cmd = Commands::instance()->byId(CommandId::Options());
|
||||||
UIContext::instance()->executeCommand(cmd);
|
UIContext::instance()->executeCommandFromMenuOrShortcut(cmd);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
preferences.validate = [native](os::MenuItem* item){
|
preferences.validate = [native](os::MenuItem* item){
|
||||||
|
@ -18,7 +18,9 @@
|
|||||||
#include "app/console.h"
|
#include "app/console.h"
|
||||||
#include "app/doc.h"
|
#include "app/doc.h"
|
||||||
#include "app/site.h"
|
#include "app/site.h"
|
||||||
|
#include "base/scoped_value.h"
|
||||||
#include "doc/layer.h"
|
#include "doc/layer.h"
|
||||||
|
#include "ui/system.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
@ -93,24 +95,33 @@ void Context::notifyActiveSiteChanged()
|
|||||||
notify_observers<const Site&>(&ContextObserver::onActiveSiteChange, site);
|
notify_observers<const Site&>(&ContextObserver::onActiveSiteChange, site);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Context::executeCommand(const char* commandName)
|
void Context::executeCommandFromMenuOrShortcut(Command* command, const Params& params)
|
||||||
{
|
{
|
||||||
Command* cmd = Commands::instance()->byId(commandName);
|
ui::assert_ui_thread();
|
||||||
if (cmd)
|
|
||||||
executeCommand(cmd);
|
// With this we avoid executing a command when we are inside another
|
||||||
else
|
// command (e.g. if we press Cmd-S quickly the program can enter two
|
||||||
throw std::runtime_error("Invalid command name");
|
// times in the File > Save command and hang).
|
||||||
|
static Command* executingCommand = nullptr;
|
||||||
|
if (executingCommand) { // Ignore command execution
|
||||||
|
LOG(VERBOSE, "CTXT: Ignoring command %s because we are inside %s\n",
|
||||||
|
command->id().c_str(), executingCommand->id().c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
base::ScopedValue<Command*> commandGuard(executingCommand,
|
||||||
|
command, nullptr);
|
||||||
|
|
||||||
|
executeCommand(command, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Context::executeCommand(Command* command, const Params& params)
|
void Context::executeCommand(Command* command, const Params& params)
|
||||||
{
|
{
|
||||||
Console console;
|
ASSERT(command);
|
||||||
|
if (!command)
|
||||||
ASSERT(command != NULL);
|
|
||||||
if (command == NULL)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
LOG(VERBOSE) << "CTXT: Executing command " << command->id() << "\n";
|
Console console;
|
||||||
|
LOG(VERBOSE, "CTXT: Executing command %s\n", command->id().c_str());
|
||||||
try {
|
try {
|
||||||
m_flags.update(this);
|
m_flags.update(this);
|
||||||
|
|
||||||
@ -122,14 +133,14 @@ void Context::executeCommand(Command* command, const Params& params)
|
|||||||
BeforeCommandExecution(ev);
|
BeforeCommandExecution(ev);
|
||||||
|
|
||||||
if (ev.isCanceled()) {
|
if (ev.isCanceled()) {
|
||||||
LOG(VERBOSE) << "CTXT: Command " << command->id() << " was canceled/simulated.\n";
|
LOG(VERBOSE, "CTXT: Command %s was canceled/simulated.\n", command->id().c_str());
|
||||||
}
|
}
|
||||||
else if (command->isEnabled(this)) {
|
else if (command->isEnabled(this)) {
|
||||||
command->execute(this);
|
command->execute(this);
|
||||||
LOG(VERBOSE) << "CTXT: Command " << command->id() << " executed successfully\n";
|
LOG(VERBOSE, "CTXT: Command %s executed successfully\n", command->id().c_str());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LOG(VERBOSE) << "CTXT: Command " << command->id() << " is disabled\n";
|
LOG(VERBOSE, "CTXT: Command %s is disabled\n", command->id().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
AfterCommandExecution(ev);
|
AfterCommandExecution(ev);
|
||||||
@ -139,20 +150,19 @@ void Context::executeCommand(Command* command, const Params& params)
|
|||||||
app_rebuild_documents_tabs();
|
app_rebuild_documents_tabs();
|
||||||
}
|
}
|
||||||
catch (base::Exception& e) {
|
catch (base::Exception& e) {
|
||||||
LOG(ERROR) << "CTXT: Exception caught executing " << command->id() << " command\n"
|
LOG(ERROR, "CTXT: Exception caught executing %s command\n%s\n",
|
||||||
<< e.what() << "\n";
|
command->id().c_str(), e.what());
|
||||||
|
|
||||||
Console::showException(e);
|
Console::showException(e);
|
||||||
}
|
}
|
||||||
catch (std::exception& e) {
|
catch (std::exception& e) {
|
||||||
LOG(ERROR) << "CTXT: std::exception caught executing " << command->id() << " command\n"
|
LOG(ERROR, "CTXT: std::exception caught executing %s command\n%s\n",
|
||||||
<< e.what() << "\n";
|
command->id().c_str(), e.what());
|
||||||
|
|
||||||
console.printf("An error ocurred executing the command.\n\nDetails:\n%s", e.what());
|
console.printf("An error ocurred executing the command.\n\nDetails:\n%s", e.what());
|
||||||
}
|
}
|
||||||
#ifdef NDEBUG
|
#ifdef NDEBUG
|
||||||
catch (...) {
|
catch (...) {
|
||||||
LOG(ERROR) << "CTXT: Unknown exception executing " << command->id() << " command\n";
|
LOG(ERROR, "CTXT: Unknown exception executing %s command\n",
|
||||||
|
command->id().c_str());
|
||||||
|
|
||||||
console.printf("An unknown error ocurred executing the command.\n"
|
console.printf("An unknown error ocurred executing the command.\n"
|
||||||
"Please save your work, close the program, try it\n"
|
"Please save your work, close the program, try it\n"
|
||||||
|
@ -88,7 +88,7 @@ namespace app {
|
|||||||
bool hasModifiedDocuments() const;
|
bool hasModifiedDocuments() const;
|
||||||
void notifyActiveSiteChanged();
|
void notifyActiveSiteChanged();
|
||||||
|
|
||||||
void executeCommand(const char* commandName);
|
void executeCommandFromMenuOrShortcut(Command* command, const Params& params = Params());
|
||||||
virtual void executeCommand(Command* command, const Params& params = Params());
|
virtual void executeCommand(Command* command, const Params& params = Params());
|
||||||
|
|
||||||
virtual DocView* getFirstDocView(Doc* document) const {
|
virtual DocView* getFirstDocView(Doc* document) const {
|
||||||
|
@ -502,7 +502,7 @@ bool CustomizedGuiManager::onProcessMessage(Message* msg)
|
|||||||
if (getForegroundWindow() == App::instance()->mainWindow()) {
|
if (getForegroundWindow() == App::instance()->mainWindow()) {
|
||||||
// OK, so we can execute the command represented
|
// OK, so we can execute the command represented
|
||||||
// by the pressed-key in the message...
|
// by the pressed-key in the message...
|
||||||
UIContext::instance()->executeCommand(
|
UIContext::instance()->executeCommandFromMenuOrShortcut(
|
||||||
command, key->params());
|
command, key->params());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -141,7 +141,7 @@ void AppMenuItem::onClick()
|
|||||||
|
|
||||||
UIContext* context = UIContext::instance();
|
UIContext* context = UIContext::instance();
|
||||||
if (m_command->isEnabled(context)) {
|
if (m_command->isEnabled(context)) {
|
||||||
context->executeCommand(m_command, params);
|
context->executeCommandFromMenuOrShortcut(m_command, params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -232,7 +232,7 @@ bool DrawingState::onKeyDown(Editor* editor, KeyMessage* msg)
|
|||||||
->getCommandFromKeyMessage(msg, &command, ¶ms)) {
|
->getCommandFromKeyMessage(msg, &command, ¶ms)) {
|
||||||
// We accept zoom commands.
|
// We accept zoom commands.
|
||||||
if (command->id() == CommandId::Zoom()) {
|
if (command->id() == CommandId::Zoom()) {
|
||||||
UIContext::instance()->executeCommand(command, params);
|
UIContext::instance()->executeCommandFromMenuOrShortcut(command, params);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -436,7 +436,7 @@ bool MovingPixelsState::onKeyDown(Editor* editor, KeyMessage* msg)
|
|||||||
// The escape key drop pixels and deselect the mask.
|
// The escape key drop pixels and deselect the mask.
|
||||||
if (msg->scancode() == kKeyEsc) { // TODO make this key customizable
|
if (msg->scancode() == kKeyEsc) { // TODO make this key customizable
|
||||||
Command* cmd = Commands::instance()->byId(CommandId::DeselectMask());
|
Command* cmd = Commands::instance()->byId(CommandId::DeselectMask());
|
||||||
UIContext::instance()->executeCommand(cmd);
|
UIContext::instance()->executeCommandFromMenuOrShortcut(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -406,7 +406,7 @@ bool StandbyState::onDoubleClick(Editor* editor, MouseMessage* msg)
|
|||||||
else if (int(editor->getToolLoopModifiers()) & int(tools::ToolLoopModifiers::kIntersectSelection))
|
else if (int(editor->getToolLoopModifiers()) & int(tools::ToolLoopModifiers::kIntersectSelection))
|
||||||
params.set("mode", "intersect");
|
params.set("mode", "intersect");
|
||||||
|
|
||||||
UIContext::instance()->executeCommand(selectTileCmd, params);
|
UIContext::instance()->executeCommandFromMenuOrShortcut(selectTileCmd, params);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Show slice properties when we double-click it
|
// Show slice properties when we double-click it
|
||||||
@ -416,7 +416,7 @@ bool StandbyState::onDoubleClick(Editor* editor, MouseMessage* msg)
|
|||||||
Command* cmd = Commands::instance()->byId(CommandId::SliceProperties());
|
Command* cmd = Commands::instance()->byId(CommandId::SliceProperties());
|
||||||
Params params;
|
Params params;
|
||||||
params.set("id", base::convert_to<std::string>(hit.slice()->id()).c_str());
|
params.set("id", base::convert_to<std::string>(hit.slice()->id()).c_str());
|
||||||
UIContext::instance()->executeCommand(cmd, params);
|
UIContext::instance()->executeCommandFromMenuOrShortcut(cmd, params);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -137,13 +137,13 @@ void HomeView::onWorkspaceViewSelected()
|
|||||||
void HomeView::onNewFile()
|
void HomeView::onNewFile()
|
||||||
{
|
{
|
||||||
Command* command = Commands::instance()->byId(CommandId::NewFile());
|
Command* command = Commands::instance()->byId(CommandId::NewFile());
|
||||||
UIContext::instance()->executeCommand(command);
|
UIContext::instance()->executeCommandFromMenuOrShortcut(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HomeView::onOpenFile()
|
void HomeView::onOpenFile()
|
||||||
{
|
{
|
||||||
Command* command = Commands::instance()->byId(CommandId::OpenFile());
|
Command* command = Commands::instance()->byId(CommandId::OpenFile());
|
||||||
UIContext::instance()->executeCommand(command);
|
UIContext::instance()->executeCommandFromMenuOrShortcut(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HomeView::onResize(ui::ResizeEvent& ev)
|
void HomeView::onResize(ui::ResizeEvent& ev)
|
||||||
|
@ -452,7 +452,7 @@ void MainWindow::onTabsContainerDoubleClicked(Tabs* tabs)
|
|||||||
Doc* oldDoc = UIContext::instance()->activeDocument();
|
Doc* oldDoc = UIContext::instance()->activeDocument();
|
||||||
|
|
||||||
Command* command = Commands::instance()->byId(CommandId::NewFile());
|
Command* command = Commands::instance()->byId(CommandId::NewFile());
|
||||||
UIContext::instance()->executeCommand(command);
|
UIContext::instance()->executeCommandFromMenuOrShortcut(command);
|
||||||
|
|
||||||
Doc* newDoc = UIContext::instance()->activeDocument();
|
Doc* newDoc = UIContext::instance()->activeDocument();
|
||||||
if (newDoc != oldDoc) {
|
if (newDoc != oldDoc) {
|
||||||
|
@ -111,7 +111,7 @@ void PalettePopup::onLoadPal()
|
|||||||
SetPaletteCommand* cmd = static_cast<SetPaletteCommand*>(
|
SetPaletteCommand* cmd = static_cast<SetPaletteCommand*>(
|
||||||
Commands::instance()->byId(CommandId::SetPalette()));
|
Commands::instance()->byId(CommandId::SetPalette()));
|
||||||
cmd->setPalette(palette);
|
cmd->setPalette(palette);
|
||||||
UIContext::instance()->executeCommand(cmd);
|
UIContext::instance()->executeCommandFromMenuOrShortcut(cmd);
|
||||||
|
|
||||||
m_paletteListBox.requestFocus();
|
m_paletteListBox.requestFocus();
|
||||||
}
|
}
|
||||||
|
@ -308,7 +308,7 @@ void RecentFilesListBox::onClick(const std::string& path)
|
|||||||
Command* command = Commands::instance()->byId(CommandId::OpenFile());
|
Command* command = Commands::instance()->byId(CommandId::OpenFile());
|
||||||
Params params;
|
Params params;
|
||||||
params.set("filename", path.c_str());
|
params.set("filename", path.c_str());
|
||||||
UIContext::instance()->executeCommand(command, params);
|
UIContext::instance()->executeCommandFromMenuOrShortcut(command, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RecentFilesListBox::onUpdateRecentListFromUIItems(const base::paths& pinnedPaths,
|
void RecentFilesListBox::onUpdateRecentListFromUIItems(const base::paths& pinnedPaths,
|
||||||
@ -346,7 +346,7 @@ void RecentFoldersListBox::onClick(const std::string& path)
|
|||||||
Command* command = Commands::instance()->byId(CommandId::OpenFile());
|
Command* command = Commands::instance()->byId(CommandId::OpenFile());
|
||||||
Params params;
|
Params params;
|
||||||
params.set("folder", path.c_str());
|
params.set("folder", path.c_str());
|
||||||
UIContext::instance()->executeCommand(command, params);
|
UIContext::instance()->executeCommandFromMenuOrShortcut(command, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RecentFoldersListBox::onUpdateRecentListFromUIItems(const base::paths& pinnedPaths,
|
void RecentFoldersListBox::onUpdateRecentListFromUIItems(const base::paths& pinnedPaths,
|
||||||
|
@ -515,7 +515,7 @@ public:
|
|||||||
Command* cmd = Commands::instance()->byId(CommandId::GotoFrame());
|
Command* cmd = Commands::instance()->byId(CommandId::GotoFrame());
|
||||||
Params params;
|
Params params;
|
||||||
params.set("frame", text().c_str());
|
params.set("frame", text().c_str());
|
||||||
UIContext::instance()->executeCommand(cmd, params);
|
UIContext::instance()->executeCommandFromMenuOrShortcut(cmd, params);
|
||||||
|
|
||||||
// Select the text again
|
// Select the text again
|
||||||
selectAllText();
|
selectAllText();
|
||||||
@ -813,7 +813,7 @@ void StatusBar::onPixelFormatChanged(DocEvent& ev)
|
|||||||
void StatusBar::newFrame()
|
void StatusBar::newFrame()
|
||||||
{
|
{
|
||||||
Command* cmd = Commands::instance()->byId(CommandId::NewFrame());
|
Command* cmd = Commands::instance()->byId(CommandId::NewFrame());
|
||||||
UIContext::instance()->executeCommand(cmd);
|
UIContext::instance()->executeCommandFromMenuOrShortcut(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StatusBar::onChangeZoom(const render::Zoom& zoom)
|
void StatusBar::onChangeZoom(const render::Zoom& zoom)
|
||||||
|
@ -83,7 +83,7 @@ void AniControls::onClickButton()
|
|||||||
|
|
||||||
Command* cmd = Commands::instance()->byId(getCommandId(item));
|
Command* cmd = Commands::instance()->byId(getCommandId(item));
|
||||||
if (cmd) {
|
if (cmd) {
|
||||||
UIContext::instance()->executeCommand(cmd);
|
UIContext::instance()->executeCommandFromMenuOrShortcut(cmd);
|
||||||
updateUsingEditor(current_editor);
|
updateUsingEditor(current_editor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user