diff --git a/src/app/app.cpp b/src/app/app.cpp index 3831d1d85..a6e636939 100644 --- a/src/app/app.cpp +++ b/src/app/app.cpp @@ -226,6 +226,8 @@ void App::run() // Initialize Steam API #ifdef ENABLE_STEAM steam::SteamAPI steam; + if (steam.initialized()) + she::instance()->activateApp(); #endif #ifdef ENABLE_UPDATER diff --git a/src/app/commands/cmd_close_file.cpp b/src/app/commands/cmd_close_file.cpp index 93095d8f1..cd34b8fbf 100644 --- a/src/app/commands/cmd_close_file.cpp +++ b/src/app/commands/cmd_close_file.cpp @@ -50,7 +50,7 @@ protected: Workspace* workspace = App::instance()->workspace(); WorkspaceView* view = workspace->activeView(); if (view) - workspace->closeView(view); + workspace->closeView(view, false); } }; @@ -60,12 +60,17 @@ public: : Command("CloseAllFiles", "Close All Files", CmdRecordableFlag) { + m_quitting = false; } Command* clone() const override { return new CloseAllFilesCommand(*this); } protected: + void onLoadParams(const Params& params) override { + m_quitting = params.get_as("quitting"); + } + void onExecute(Context* context) override { Workspace* workspace = App::instance()->workspace(); @@ -78,11 +83,13 @@ protected: } for (auto docView : docViews) { - if (!workspace->closeView(docView)) + if (!workspace->closeView(docView, m_quitting)) break; } } +private: + bool m_quitting; }; Command* CommandFactory::createCloseFileCommand() diff --git a/src/app/commands/cmd_exit.cpp b/src/app/commands/cmd_exit.cpp index 53e57edf4..852918ed9 100644 --- a/src/app/commands/cmd_exit.cpp +++ b/src/app/commands/cmd_exit.cpp @@ -11,6 +11,7 @@ #include "app/app.h" #include "app/commands/command.h" +#include "app/commands/commands.h" #include "app/context.h" #include "app/document.h" #include "app/ui/main_window.h" @@ -34,22 +35,17 @@ ExitCommand::ExitCommand() { } -void ExitCommand::onExecute(Context* context) +void ExitCommand::onExecute(Context* ctx) { - const doc::Documents& docs = context->documents(); - bool modifiedFiles = false; + if (ctx->hasModifiedDocuments()) { + Command* closeAll = CommandsModule::instance()->getCommandByName(CommandId::CloseAllFiles); + Params params; + params.set("quitting", "1"); + ctx->executeCommand(closeAll, params); - for (doc::Documents::const_iterator it=docs.begin(), end=docs.end(); it!=end; ++it) { - const Document* document = static_cast(*it); - if (document->isModified()) { - modifiedFiles = true; - break; - } - } - - if (modifiedFiles) { - if (ui::Alert::show("Warning<hasModifiedDocuments()) + return; } // Close the window diff --git a/src/app/context.cpp b/src/app/context.cpp index f2e0139b6..21d906d89 100644 --- a/src/app/context.cpp +++ b/src/app/context.cpp @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2001-2015 David Capello +// Copyright (C) 2001-2016 David Capello // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as @@ -38,6 +38,14 @@ app::Document* Context::activeDocument() const return static_cast(doc::Context::activeDocument()); } +bool Context::hasModifiedDocuments() const +{ + for (auto doc : documents()) + if (static_cast(doc)->isModified()) + return true; + return false; +} + void Context::executeCommand(const char* commandName) { Command* cmd = CommandsModule::instance()->getCommandByName(commandName); diff --git a/src/app/context.h b/src/app/context.h index 44edec984..e0463ce69 100644 --- a/src/app/context.h +++ b/src/app/context.h @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2001-2015 David Capello +// Copyright (C) 2001-2016 David Capello // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as @@ -63,6 +63,7 @@ namespace app { void sendDocumentToTop(doc::Document* document); app::Document* activeDocument() const; + bool hasModifiedDocuments() const; void executeCommand(const char* commandName); virtual void executeCommand(Command* command, const Params& params = Params()); diff --git a/src/app/ui/data_recovery_view.cpp b/src/app/ui/data_recovery_view.cpp index 4bfa0928b..8f9bc1fe0 100644 --- a/src/app/ui/data_recovery_view.cpp +++ b/src/app/ui/data_recovery_view.cpp @@ -218,7 +218,7 @@ void DataRecoveryView::onWorkspaceViewSelected() { } -bool DataRecoveryView::onCloseView(Workspace* workspace) +bool DataRecoveryView::onCloseView(Workspace* workspace, bool quitting) { workspace->removeView(this); return true; diff --git a/src/app/ui/data_recovery_view.h b/src/app/ui/data_recovery_view.h index f27207dcf..039d7bfc9 100644 --- a/src/app/ui/data_recovery_view.h +++ b/src/app/ui/data_recovery_view.h @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2001-2015 David Capello +// Copyright (C) 2001-2016 David Capello // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as @@ -34,7 +34,7 @@ namespace app { // WorkspaceView implementation ui::Widget* getContentWidget() override { return this; } void onWorkspaceViewSelected() override; - bool onCloseView(Workspace* workspace) override; + bool onCloseView(Workspace* workspace, bool quitting) override; void onTabPopup(Workspace* workspace) override; // Triggered when the list is empty (because the user deleted all diff --git a/src/app/ui/devconsole_view.cpp b/src/app/ui/devconsole_view.cpp index 1e9738979..f329baa7c 100644 --- a/src/app/ui/devconsole_view.cpp +++ b/src/app/ui/devconsole_view.cpp @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2001-2015 David Capello +// Copyright (C) 2001-2016 David Capello // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as @@ -109,7 +109,7 @@ void DevConsoleView::onWorkspaceViewSelected() m_entry->requestFocus(); } -bool DevConsoleView::onCloseView(Workspace* workspace) +bool DevConsoleView::onCloseView(Workspace* workspace, bool quitting) { workspace->removeView(this); return true; diff --git a/src/app/ui/devconsole_view.h b/src/app/ui/devconsole_view.h index 3fd60de0f..eaefc6403 100644 --- a/src/app/ui/devconsole_view.h +++ b/src/app/ui/devconsole_view.h @@ -36,7 +36,7 @@ namespace app { bool canCloneWorkspaceView() override { return true; } WorkspaceView* cloneWorkspaceView() override; void onWorkspaceViewSelected() override; - bool onCloseView(Workspace* workspace) override; + bool onCloseView(Workspace* workspace, bool quitting) override; void onTabPopup(Workspace* workspace) override; // EngineDelegate impl diff --git a/src/app/ui/document_view.cpp b/src/app/ui/document_view.cpp index 48f9af230..267ac24ed 100644 --- a/src/app/ui/document_view.cpp +++ b/src/app/ui/document_view.cpp @@ -220,7 +220,7 @@ void DocumentView::onClonedFrom(WorkspaceView* from) ->setViewScroll(View::getView(srcEditor)->viewScroll()); } -bool DocumentView::onCloseView(Workspace* workspace) +bool DocumentView::onCloseView(Workspace* workspace, bool quitting) { if (m_editor->isMovingPixels()) m_editor->dropMovingPixels(); @@ -247,8 +247,12 @@ bool DocumentView::onCloseView(Workspace* workspace) // see if the sprite has changes while (m_document->isModified()) { // ask what want to do the user with the changes in the sprite - int ret = Alert::show("Warning<name().c_str()); + int ret = Alert::show("Warning" + "<name().c_str(), + quitting ? "quitting": "closing"); if (ret == 1) { // "save": save the changes diff --git a/src/app/ui/document_view.h b/src/app/ui/document_view.h index 7d9ef3ba1..c45e24fbe 100644 --- a/src/app/ui/document_view.h +++ b/src/app/ui/document_view.h @@ -67,7 +67,7 @@ namespace app { WorkspaceView* cloneWorkspaceView() override; void onWorkspaceViewSelected() override; void onClonedFrom(WorkspaceView* from) override; - bool onCloseView(Workspace* workspace) override; + bool onCloseView(Workspace* workspace, bool quitting) override; void onTabPopup(Workspace* workspace) override; InputChainElement* onGetInputChainElement() override { return this; } diff --git a/src/app/ui/home_view.cpp b/src/app/ui/home_view.cpp index 690b5b9c4..1897bdbf0 100644 --- a/src/app/ui/home_view.cpp +++ b/src/app/ui/home_view.cpp @@ -89,7 +89,7 @@ TabIcon HomeView::getTabIcon() return TabIcon::HOME; } -bool HomeView::onCloseView(Workspace* workspace) +bool HomeView::onCloseView(Workspace* workspace, bool quitting) { workspace->removeView(this); return true; diff --git a/src/app/ui/home_view.h b/src/app/ui/home_view.h index 691510d5d..a07dffc40 100644 --- a/src/app/ui/home_view.h +++ b/src/app/ui/home_view.h @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2001-2015 David Capello +// Copyright (C) 2001-2016 David Capello // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as @@ -50,7 +50,7 @@ namespace app { // WorkspaceView implementation ui::Widget* getContentWidget() override { return this; } - bool onCloseView(Workspace* workspace) override; + bool onCloseView(Workspace* workspace, bool quitting) override; void onTabPopup(Workspace* workspace) override; void onWorkspaceViewSelected() override; diff --git a/src/app/ui/main_window.cpp b/src/app/ui/main_window.cpp index 818ea7972..627a55743 100644 --- a/src/app/ui/main_window.cpp +++ b/src/app/ui/main_window.cpp @@ -298,7 +298,7 @@ void MainWindow::onCloseTab(Tabs* tabs, TabView* tabView) WorkspaceView* view = dynamic_cast(tabView); ASSERT(view); if (view) - m_workspace->closeView(view); + m_workspace->closeView(view, false); } void MainWindow::onCloneTab(Tabs* tabs, TabView* tabView, int pos) diff --git a/src/app/ui/workspace.cpp b/src/app/ui/workspace.cpp index c13e012c2..70f4dd0a4 100644 --- a/src/app/ui/workspace.cpp +++ b/src/app/ui/workspace.cpp @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2001-2015 David Capello +// Copyright (C) 2001-2016 David Capello // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as @@ -75,9 +75,9 @@ void Workspace::removeView(WorkspaceView* view) panel->removeView(view); } -bool Workspace::closeView(WorkspaceView* view) +bool Workspace::closeView(WorkspaceView* view, bool quitting) { - return view->onCloseView(this); + return view->onCloseView(this, quitting); } WorkspaceView* Workspace::activeView() diff --git a/src/app/ui/workspace.h b/src/app/ui/workspace.h index 25dceccb2..65803fe2b 100644 --- a/src/app/ui/workspace.h +++ b/src/app/ui/workspace.h @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2001-2015 David Capello +// Copyright (C) 2001-2016 David Capello // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as @@ -39,7 +39,7 @@ namespace app { // Closes the given view. Returns false if the user cancels the // operation. - bool closeView(WorkspaceView* view); + bool closeView(WorkspaceView* view, bool quitting); WorkspaceView* activeView(); void setActiveView(WorkspaceView* view); diff --git a/src/app/ui/workspace_view.h b/src/app/ui/workspace_view.h index 15d0e6317..e6084ea82 100644 --- a/src/app/ui/workspace_view.h +++ b/src/app/ui/workspace_view.h @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2001-2015 David Capello +// Copyright (C) 2001-2016 David Capello // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as @@ -37,7 +37,7 @@ namespace app { // Returns true if the view was closed successfully or false if // the user cancels the operation. - virtual bool onCloseView(Workspace* workspace) = 0; + virtual bool onCloseView(Workspace* workspace, bool quitting) = 0; virtual void onTabPopup(Workspace* workspace) = 0; diff --git a/src/she/alleg4/she.cpp b/src/she/alleg4/she.cpp index 3fdea8128..f0e828c4e 100644 --- a/src/she/alleg4/she.cpp +++ b/src/she/alleg4/she.cpp @@ -144,6 +144,10 @@ public: delete this; } + void activateApp() override { + // Do nothing + } + void finishLaunching() override { // Do nothing } diff --git a/src/she/osx/app.h b/src/she/osx/app.h index f0352b84d..91842f64b 100644 --- a/src/she/osx/app.h +++ b/src/she/osx/app.h @@ -22,6 +22,7 @@ namespace she { ~OSXApp(); bool init(); + void activateApp(); void finishLaunching(); private: diff --git a/src/she/osx/app.mm b/src/she/osx/app.mm index 801b0c962..900ce804f 100644 --- a/src/she/osx/app.mm +++ b/src/she/osx/app.mm @@ -27,11 +27,25 @@ public: [m_app setActivationPolicy:NSApplicationActivationPolicyRegular]; [m_app setDelegate:m_appDelegate]; - [m_app activateIgnoringOtherApps:YES]; + + // Don't activate the application ignoring other apps. This is + // called by OS X when the application is launched by the user + // from the application bundle. In this way, we can execute + // aseprite from the command line/bash scripts and the app will + // not be activated. + //[m_app activateIgnoringOtherApps:YES]; return true; } + // We might need to call this function when the app is launched from + // Steam. It appears that there is a bug on OS X Steam client where + // the app is launched, activated, and then the Steam client is + // activated again. + void activateApp() { + [m_app activateIgnoringOtherApps:YES]; + } + void finishLaunching() { [m_app finishLaunching]; } @@ -67,6 +81,11 @@ bool OSXApp::init() return m_impl->init(); } +void OSXApp::activateApp() +{ + m_impl->activateApp(); +} + void OSXApp::finishLaunching() { m_impl->finishLaunching(); diff --git a/src/she/osx/view.mm b/src/she/osx/view.mm index 42e103e34..b291af1d1 100644 --- a/src/she/osx/view.mm +++ b/src/she/osx/view.mm @@ -91,7 +91,8 @@ bool is_key_pressed(KeyScancode scancode) - (id)initWithFrame:(NSRect)frameRect { - m_nsCursor = [NSCursor arrowCursor]; + // We start without the system mouse cursor + m_nsCursor = nil; m_visibleMouse = true; m_pointerType = she::PointerType::Unknown; diff --git a/src/she/skia/skia_system.h b/src/she/skia/skia_system.h index 2f9654903..ebb4ee376 100644 --- a/src/she/skia/skia_system.h +++ b/src/she/skia/skia_system.h @@ -57,6 +57,12 @@ public: delete this; } + void activateApp() override { +#if __APPLE__ + OSXApp::instance()->activateApp(); +#endif + } + void finishLaunching() override { #if __APPLE__ // Start processing NSApplicationDelegate events. (E.g. after diff --git a/src/she/system.h b/src/she/system.h index 9cf224ba3..cce34ad29 100644 --- a/src/she/system.h +++ b/src/she/system.h @@ -32,6 +32,7 @@ namespace she { public: virtual ~System() { } virtual void dispose() = 0; + virtual void activateApp() = 0; virtual void finishLaunching() = 0; virtual Capabilities capabilities() const = 0; virtual Logger* logger() = 0; diff --git a/src/steam/steam.cpp b/src/steam/steam.cpp index 9a8ed1160..29d8cd821 100644 --- a/src/steam/steam.cpp +++ b/src/steam/steam.cpp @@ -35,16 +35,20 @@ typedef void (*SteamAPI_Shutdown_Func)(); class SteamAPI::Impl { public: - Impl() { + Impl() : m_initialized(false) { m_steamLib = base::load_dll( base::join_path(base::get_file_path(base::get_app_path()), STEAM_API_DLL_FILENAME)); - if (!m_steamLib) + if (!m_steamLib) { + LOG("Steam library not found...\n"); return; + } auto SteamAPI_Init = base::get_dll_proc(m_steamLib, "SteamAPI_Init"); - if (!SteamAPI_Init) + if (!SteamAPI_Init) { + LOG("SteamAPI_Init not found...\n"); return; + } if (!SteamAPI_Init()) { LOG("Steam is not initialized...\n"); @@ -52,6 +56,7 @@ public: } LOG("Steam initialized...\n"); + m_initialized = true; } ~Impl() { @@ -67,8 +72,13 @@ public: base::unload_dll(m_steamLib); } + bool initialized() const { + return m_initialized; + } + private: base::dll m_steamLib; + bool m_initialized; }; SteamAPI::SteamAPI() @@ -81,4 +91,9 @@ SteamAPI::~SteamAPI() delete m_impl; } +bool SteamAPI::initialized() const +{ + return m_impl->initialized(); +} + } // namespace steam diff --git a/src/steam/steam.h b/src/steam/steam.h index 907eee58a..236682c5a 100644 --- a/src/steam/steam.h +++ b/src/steam/steam.h @@ -15,6 +15,8 @@ public: SteamAPI(); ~SteamAPI(); + bool initialized() const; + private: class Impl; Impl* m_impl; diff --git a/third_party/freetype2 b/third_party/freetype2 index 27e2f011e..8529e84fb 160000 --- a/third_party/freetype2 +++ b/third_party/freetype2 @@ -1 +1 @@ -Subproject commit 27e2f011ebef85144724c30f63285852612aafa0 +Subproject commit 8529e84fb4bb22abfc5c4d9cafbb06025a8b909d