diff --git a/extras/Introjucer/Source/Application/jucer_Application.h b/extras/Introjucer/Source/Application/jucer_Application.h index 4bace9c07f..e2941689b2 100644 --- a/extras/Introjucer/Source/Application/jucer_Application.h +++ b/extras/Introjucer/Source/Application/jucer_Application.h @@ -608,7 +608,7 @@ private: stopTimer(); delete this; - if (JUCEApplication::getInstance() != nullptr) + if (JUCEApplicationBase::getInstance() != nullptr) getApp().closeModalCompsAndQuit(); } diff --git a/extras/Introjucer/Source/Application/jucer_MainWindow.cpp b/extras/Introjucer/Source/Application/jucer_MainWindow.cpp index 08b7f1649e..352e545301 100644 --- a/extras/Introjucer/Source/Application/jucer_MainWindow.cpp +++ b/extras/Introjucer/Source/Application/jucer_MainWindow.cpp @@ -369,7 +369,7 @@ void MainWindowList::closeWindow (MainWindow* w) #if ! JUCE_MAC if (windows.size() == 1) { - JUCEApplication::getInstance()->systemRequestedQuit(); + JUCEApplicationBase::getInstance()->systemRequestedQuit(); } else #endif diff --git a/extras/Introjucer/Source/ComponentEditor/jucer_GeneratedCode.cpp b/extras/Introjucer/Source/ComponentEditor/jucer_GeneratedCode.cpp index c88d109e1d..d6db35cf89 100644 --- a/extras/Introjucer/Source/ComponentEditor/jucer_GeneratedCode.cpp +++ b/extras/Introjucer/Source/ComponentEditor/jucer_GeneratedCode.cpp @@ -331,7 +331,7 @@ void GeneratedCode::applyToCode (String& code, headerGuard << String::toHexString ((className + "xx" + fileNameRoot).hashCode64()).toUpperCase() << "__"; replaceTemplate (code, "headerGuard", headerGuard); - replaceTemplate (code, "version", JUCEApplication::getInstance()->getApplicationVersion()); + replaceTemplate (code, "version", JUCEApplicationBase::getInstance()->getApplicationVersion()); replaceTemplate (code, "creationTime", Time::getCurrentTime().toString (true, true, true)); replaceTemplate (code, "className", className); diff --git a/extras/audio plugin host/Source/HostStartup.cpp b/extras/audio plugin host/Source/HostStartup.cpp index 6c59794e14..1e9233cec5 100644 --- a/extras/audio plugin host/Source/HostStartup.cpp +++ b/extras/audio plugin host/Source/HostStartup.cpp @@ -75,7 +75,7 @@ public: if (mainWindow != nullptr) mainWindow->tryToQuitApplication(); else - JUCEApplication::quit(); + JUCEApplicationBase::quit(); } const String getApplicationName() { return "Juce Plug-In Host"; } diff --git a/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h b/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h index 87bc9a99fb..d0613cc4a1 100644 --- a/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h +++ b/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h @@ -31,7 +31,7 @@ extern AudioProcessor* JUCE_CALLTYPE createPluginFilter(); /** A class that can be used to run a simple standalone application containing your filter. - Just create one of these objects in your JUCEApplication::initialise() method, and + Just create one of these objects in your JUCEApplicationBase::initialise() method, and let it do its work. It will create your filter object using the same createFilter() function that the other plugin wrappers use. */ @@ -63,7 +63,7 @@ public: if (filter == nullptr) { jassertfalse // Your filter didn't create correctly! In a standalone app that's not too great. - JUCEApplication::quit(); + JUCEApplicationBase::quit(); } filter->setPlayConfigDetails (JucePlugin_MaxNumInputChannels, @@ -243,7 +243,7 @@ public: /** @internal */ void closeButtonPressed() override { - JUCEApplication::quit(); + JUCEApplicationBase::quit(); } /** @internal */ diff --git a/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp b/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp index 2864959e3e..f65e7e43a0 100644 --- a/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp +++ b/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp @@ -232,7 +232,7 @@ public: ~SharedMessageThread() { signalThreadShouldExit(); - JUCEApplication::quit(); + JUCEApplicationBase::quit(); waitForThreadToExit (5000); clearSingletonInstance(); } diff --git a/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp b/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp index 299af9d0f7..2f0d30b443 100644 --- a/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp +++ b/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp @@ -1375,7 +1375,7 @@ public: { String hostName ("Juce VST Host"); - if (JUCEApplication* app = JUCEApplication::getInstance()) + if (JUCEApplicationBase* app = JUCEApplicationBase::getInstance()) hostName = app->getApplicationName(); hostName.copyToUTF8 ((char*) ptr, (size_t) jmin (kVstMaxVendorStrLen, kVstMaxProductStrLen) - 1); diff --git a/modules/juce_core/juce_core.h b/modules/juce_core/juce_core.h index 582700dacb..5ce5ca3f32 100644 --- a/modules/juce_core/juce_core.h +++ b/modules/juce_core/juce_core.h @@ -119,7 +119,7 @@ /* Config: JUCE_CATCH_UNHANDLED_EXCEPTIONS If enabled, this will add some exception-catching code to forward unhandled exceptions - to your JUCEApplication::unhandledException() callback. + to your JUCEApplicationBase::unhandledException() callback. */ #ifndef JUCE_CATCH_UNHANDLED_EXCEPTIONS //#define JUCE_CATCH_UNHANDLED_EXCEPTIONS 1 diff --git a/modules/juce_core/system/juce_PlatformDefs.h b/modules/juce_core/system/juce_PlatformDefs.h index 0608acbca0..47b4a5b591 100644 --- a/modules/juce_core/system/juce_PlatformDefs.h +++ b/modules/juce_core/system/juce_PlatformDefs.h @@ -222,17 +222,17 @@ namespace juce #if ! JUCE_MODULE_AVAILABLE_juce_gui_basics #define JUCE_CATCH_EXCEPTION JUCE_CATCH_ALL #else - /** Used in try-catch blocks, this macro will send exceptions to the JUCEApplication + /** Used in try-catch blocks, this macro will send exceptions to the JUCEApplicationBase object so they can be logged by the application if it wants to. */ #define JUCE_CATCH_EXCEPTION \ catch (const std::exception& e) \ { \ - juce::JUCEApplication::sendUnhandledException (&e, __FILE__, __LINE__); \ + juce::JUCEApplicationBase::sendUnhandledException (&e, __FILE__, __LINE__); \ } \ catch (...) \ { \ - juce::JUCEApplication::sendUnhandledException (nullptr, __FILE__, __LINE__); \ + juce::JUCEApplicationBase::sendUnhandledException (nullptr, __FILE__, __LINE__); \ } #endif diff --git a/modules/juce_core/threads/juce_Process.h b/modules/juce_core/threads/juce_Process.h index 20ad152c72..f3efd66285 100644 --- a/modules/juce_core/threads/juce_Process.h +++ b/modules/juce_core/threads/juce_Process.h @@ -36,7 +36,7 @@ This contains methods for controlling the current application at the process-level. - @see Thread, JUCEApplication + @see Thread, JUCEApplicationBase */ class JUCE_API Process { @@ -63,7 +63,7 @@ public: immediately - it's intended only for use only when something goes horribly wrong. - @see JUCEApplication::quit + @see JUCEApplicationBase::quit */ static void JUCE_CALLTYPE terminate(); diff --git a/modules/juce_events/juce_events.h b/modules/juce_events/juce_events.h index d58d8a280a..799adc0267 100644 --- a/modules/juce_events/juce_events.h +++ b/modules/juce_events/juce_events.h @@ -38,6 +38,7 @@ namespace juce #include "messages/juce_DeletedAtShutdown.h" #include "messages/juce_NotificationType.h" #include "messages/juce_ApplicationBase.h" +#include "messages/juce_Initialisation.h" #include "broadcasters/juce_ListenerList.h" #include "broadcasters/juce_ActionBroadcaster.h" #include "broadcasters/juce_ActionListener.h" diff --git a/modules/juce_events/messages/juce_ApplicationBase.cpp b/modules/juce_events/messages/juce_ApplicationBase.cpp index 7ca7761e40..a5610fa248 100644 --- a/modules/juce_events/messages/juce_ApplicationBase.cpp +++ b/modules/juce_events/messages/juce_ApplicationBase.cpp @@ -26,6 +26,8 @@ JUCEApplicationBase::CreateInstanceFunction JUCEApplicationBase::createInstance JUCEApplicationBase* JUCEApplicationBase::appInstance = nullptr; JUCEApplicationBase::JUCEApplicationBase() + : appReturnValue (0), + stillInitialising (true) { jassert (isStandaloneApp() && appInstance == nullptr); appInstance = this; @@ -37,6 +39,11 @@ JUCEApplicationBase::~JUCEApplicationBase() appInstance = nullptr; } +void JUCEApplicationBase::setApplicationReturnValue (const int newReturnValue) noexcept +{ + appReturnValue = newReturnValue; +} + // This is called on the Mac and iOS where the OS doesn't allow the stack to unwind on shutdown.. void JUCEApplicationBase::appWillTerminateByForce() { @@ -53,3 +60,230 @@ void JUCEApplicationBase::appWillTerminateByForce() MessageManager::deleteInstance(); } } + +void JUCEApplicationBase::quit() +{ + MessageManager::getInstance()->stopDispatchLoop(); +} + +void JUCEApplicationBase::sendUnhandledException (const std::exception* const e, + const char* const sourceFile, + const int lineNumber) +{ + if (JUCEApplicationBase* const app = JUCEApplicationBase::getInstance()) + app->unhandledException (e, sourceFile, lineNumber); +} + +//============================================================================== +#if ! (JUCE_IOS || JUCE_ANDROID) + #define JUCE_HANDLE_MULTIPLE_INSTANCES 1 +#endif + +#if JUCE_HANDLE_MULTIPLE_INSTANCES +struct JUCEApplicationBase::MultipleInstanceHandler : public ActionListener +{ +public: + MultipleInstanceHandler (const String& appName) + : appLock ("juceAppLock_" + appName) + { + } + + bool sendCommandLineToPreexistingInstance() + { + if (appLock.enter (0)) + return false; + + JUCEApplicationBase* const app = JUCEApplicationBase::getInstance(); + jassert (app != nullptr); + + MessageManager::broadcastMessage (app->getApplicationName() + + "/" + app->getCommandLineParameters()); + return true; + } + + void actionListenerCallback (const String& message) override + { + if (JUCEApplicationBase* const app = JUCEApplicationBase::getInstance()) + { + const String appName (app->getApplicationName()); + + if (message.startsWith (appName + "/")) + app->anotherInstanceStarted (message.substring (appName.length() + 1)); + } + } + +private: + InterProcessLock appLock; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MultipleInstanceHandler) +}; + +bool JUCEApplicationBase::sendCommandLineToPreexistingInstance() +{ + jassert (multipleInstanceHandler == nullptr); // this must only be called once! + + multipleInstanceHandler = new MultipleInstanceHandler (getApplicationName()); + return multipleInstanceHandler->sendCommandLineToPreexistingInstance(); +} + +#else +struct JUCEApplicationBase::MultipleInstanceHandler {}; +#endif + +//============================================================================== +#if JUCE_ANDROID + +StringArray JUCEApplicationBase::getCommandLineParameterArray() { return StringArray(); } +String JUCEApplicationBase::getCommandLineParameters() { return String::empty; } + +#else + +#if JUCE_WINDOWS + +String JUCE_CALLTYPE JUCEApplicationBase::getCommandLineParameters() +{ + return CharacterFunctions::findEndOfToken (CharPointer_UTF16 (GetCommandLineW()), + CharPointer_UTF16 (L" "), + CharPointer_UTF16 (L"\"")).findEndOfWhitespace(); +} + +StringArray JUCE_CALLTYPE JUCEApplicationBase::getCommandLineParameterArray() +{ + StringArray s; + + int argc = 0; + if (LPWSTR* const argv = CommandLineToArgvW (GetCommandLineW(), &argc)) + { + s = StringArray (argv + 1, argc - 1); + LocalFree (argv); + } + + return s; +} + +#else + +#if JUCE_IOS + extern int juce_iOSMain (int argc, const char* argv[]); +#endif + +#if JUCE_MAC + extern void initialiseNSApplication(); +#endif + +extern const char* const* juce_argv; // declared in juce_core +extern int juce_argc; + +String JUCEApplicationBase::getCommandLineParameters() +{ + String argString; + + for (int i = 1; i < juce_argc; ++i) + { + String arg (juce_argv[i]); + + if (arg.containsChar (' ') && ! arg.isQuotedString()) + arg = arg.quoted ('"'); + + argString << arg << ' '; + } + + return argString.trim(); +} + +StringArray JUCEApplicationBase::getCommandLineParameterArray() +{ + return StringArray (juce_argv + 1, juce_argc - 1); +} + +int JUCEApplicationBase::main (int argc, const char* argv[]) +{ + JUCE_AUTORELEASEPOOL + { + juce_argc = argc; + juce_argv = argv; + + #if JUCE_MAC + initialiseNSApplication(); + #endif + + #if JUCE_IOS + return juce_iOSMain (argc, argv); + #else + return JUCEApplicationBase::main(); + #endif + } +} + +#endif + +//============================================================================== +int JUCEApplicationBase::main() +{ + ScopedJuceInitialiser_GUI libraryInitialiser; + jassert (createInstance != nullptr); + + const ScopedPointer app (createInstance()); + jassert (app != nullptr); + + if (! app->initialiseApp()) + return 0; + + JUCE_TRY + { + // loop until a quit message is received.. + MessageManager::getInstance()->runDispatchLoop(); + } + JUCE_CATCH_EXCEPTION + + return app->shutdownApp(); +} + +#endif + +//============================================================================== +bool JUCEApplicationBase::initialiseApp() +{ + #if JUCE_HANDLE_MULTIPLE_INSTANCES + if ((! moreThanOneInstanceAllowed()) && sendCommandLineToPreexistingInstance()) + { + DBG ("Another instance is running - quitting..."); + return false; + } + #endif + + // let the app do its setting-up.. + initialise (getCommandLineParameters()); + + stillInitialising = false; + + if (MessageManager::getInstance()->hasStopMessageBeenSent()) + return false; + + #if JUCE_HANDLE_MULTIPLE_INSTANCES + if (multipleInstanceHandler != nullptr) + MessageManager::getInstance()->registerBroadcastListener (multipleInstanceHandler); + #endif + + return true; +} + +int JUCEApplicationBase::shutdownApp() +{ + jassert (JUCEApplicationBase::getInstance() == this); + + #if JUCE_HANDLE_MULTIPLE_INSTANCES + if (multipleInstanceHandler != nullptr) + MessageManager::getInstance()->deregisterBroadcastListener (multipleInstanceHandler); + #endif + + JUCE_TRY + { + // give the app a chance to clean up.. + shutdown(); + } + JUCE_CATCH_EXCEPTION + + multipleInstanceHandler = nullptr; + return getApplicationReturnValue(); +} diff --git a/modules/juce_events/messages/juce_ApplicationBase.h b/modules/juce_events/messages/juce_ApplicationBase.h index 350441090e..51f098c9bd 100644 --- a/modules/juce_events/messages/juce_ApplicationBase.h +++ b/modules/juce_events/messages/juce_ApplicationBase.h @@ -30,11 +30,57 @@ /** Abstract base class for application classes. - This class shouldn't be used directly - you'll normally use JUCEApplication as - the base for your app, and that inherits from this, adding some more functionality - to it. + Note that in the juce_gui_basics module, there's a utility class JUCEApplication + which derives from JUCEApplicationBase, and takes care of a few chores. Most + of the time you'll want to derive your class from JUCEApplication rather than + using JUCEApplicationBase directly, but if you're not using the juce_gui_basics + module then you might need to go straight to this base class. - @see JUCEApplication + Any application that wants to run an event loop must declare a subclass of + JUCEApplicationBase, and implement its various pure virtual methods. + + It then needs to use the START_JUCE_APPLICATION macro somewhere in a CPP file + to declare an instance of this class and generate suitable platform-specific + boilerplate code to launch the app. + + e.g. @code + class MyJUCEApp : public JUCEApplication + { + public: + MyJUCEApp() {} + ~MyJUCEApp() {} + + void initialise (const String& commandLine) + { + myMainWindow = new MyApplicationWindow(); + myMainWindow->setBounds (100, 100, 400, 500); + myMainWindow->setVisible (true); + } + + void shutdown() + { + myMainWindow = nullptr; + } + + const String getApplicationName() + { + return "Super JUCE-o-matic"; + } + + const String getApplicationVersion() + { + return "1.0"; + } + + private: + ScopedPointer myMainWindow; + }; + + // this generates boilerplate code to launch our app class: + START_JUCE_APPLICATION (MyJUCEApp) + @endcode + + @see JUCEApplication, START_JUCE_APPLICATION */ class JUCE_API JUCEApplicationBase { @@ -51,13 +97,10 @@ public: static JUCEApplicationBase* getInstance() noexcept { return appInstance; } //============================================================================== - /** Returns the application's name. - An application must implement this to name itself. - */ + /** Returns the application's name. */ virtual const String getApplicationName() = 0; - /** Returns the application's version number. - */ + /** Returns the application's version number. */ virtual const String getApplicationVersion() = 0; /** Checks whether multiple instances of the app are allowed. @@ -148,24 +191,90 @@ public: const String& sourceFilename, int lineNumber) = 0; + //============================================================================== + /** Signals that the main message loop should stop and the application should terminate. + + This isn't synchronous, it just posts a quit message to the main queue, and + when this message arrives, the message loop will stop, the shutdown() method + will be called, and the app will exit. + + Note that this will cause an unconditional quit to happen, so if you need an + extra level before this, e.g. to give the user the chance to save their work + and maybe cancel the quit, you'll need to handle this in the systemRequestedQuit() + method - see that method's help for more info. + + @see MessageManager + */ + static void quit(); + + //============================================================================== + /** Returns the application's command line parameters as a set of strings. + @see getCommandLineParameters + */ + static StringArray JUCE_CALLTYPE getCommandLineParameterArray(); + + /** Returns the application's command line parameters as a single string. + @see getCommandLineParameterArray + */ + static String JUCE_CALLTYPE getCommandLineParameters(); + + //============================================================================== + /** Sets the value that should be returned as the application's exit code when the + app quits. + + This is the value that's returned by the main() function. Normally you'd leave this + as 0 unless you want to indicate an error code. + + @see getApplicationReturnValue + */ + void setApplicationReturnValue (int newReturnValue) noexcept; + + /** Returns the value that has been set as the application's exit code. + @see setApplicationReturnValue + */ + int getApplicationReturnValue() const noexcept { return appReturnValue; } + //============================================================================== /** Returns true if this executable is running as an app (as opposed to being a plugin or other kind of shared library. */ - static inline bool isStandaloneApp() noexcept { return createInstance != nullptr; } + static bool isStandaloneApp() noexcept { return createInstance != nullptr; } + + /** Returns true if the application hasn't yet completed its initialise() method + and entered the main event loop. + + This is handy for things like splash screens to know when the app's up-and-running + properly. + */ + bool isInitialising() const noexcept { return stillInitialising; } + //============================================================================== #ifndef DOXYGEN + // The following methods are for internal use only... + static int main(); + static int main (int argc, const char* argv[]); + static void appWillTerminateByForce(); typedef JUCEApplicationBase* (*CreateInstanceFunction)(); static CreateInstanceFunction createInstance; -protected: - virtual int shutdownApp() = 0; + virtual bool initialiseApp(); + static void JUCE_CALLTYPE sendUnhandledException (const std::exception*, const char* sourceFile, int lineNumber); + bool sendCommandLineToPreexistingInstance(); #endif private: //============================================================================== static JUCEApplicationBase* appInstance; + int appReturnValue; + bool stillInitialising; + + struct MultipleInstanceHandler; + friend struct MultipleInstanceHandler; + friend struct ContainerDeletePolicy; + ScopedPointer multipleInstanceHandler; + + int shutdownApp(); JUCE_DECLARE_NON_COPYABLE (JUCEApplicationBase) }; diff --git a/modules/juce_events/messages/juce_DeletedAtShutdown.h b/modules/juce_events/messages/juce_DeletedAtShutdown.h index d454009613..ce1f10eddb 100644 --- a/modules/juce_events/messages/juce_DeletedAtShutdown.h +++ b/modules/juce_events/messages/juce_DeletedAtShutdown.h @@ -30,7 +30,7 @@ /** Classes derived from this will be automatically deleted when the application exits. - After JUCEApplication::shutdown() has been called, any objects derived from + After JUCEApplicationBase::shutdown() has been called, any objects derived from DeletedAtShutdown which are still in existence will be deleted in the reverse order to that in which they were created. @@ -55,7 +55,7 @@ public: /** Deletes all extant objects. This shouldn't be used by applications, as it's called automatically - in the shutdown code of the JUCEApplication class. + in the shutdown code of the JUCEApplicationBase class. */ static void deleteAll(); diff --git a/modules/juce_gui_basics/application/juce_Initialisation.h b/modules/juce_events/messages/juce_Initialisation.h similarity index 85% rename from modules/juce_gui_basics/application/juce_Initialisation.h rename to modules/juce_events/messages/juce_Initialisation.h index 46a39be504..4a93b0f040 100644 --- a/modules/juce_gui_basics/application/juce_Initialisation.h +++ b/modules/juce_events/messages/juce_Initialisation.h @@ -63,28 +63,29 @@ JUCE_API void JUCE_CALLTYPE shutdownJuce_GUI(); main() function, because it'll take care of shutting down whenever you return from the main() call. */ -class ScopedJuceInitialiser_GUI +class JUCE_API ScopedJuceInitialiser_GUI { public: /** The constructor simply calls initialiseJuce_GUI(). */ - ScopedJuceInitialiser_GUI() { initialiseJuce_GUI(); } + ScopedJuceInitialiser_GUI(); /** The destructor simply calls shutdownJuce_GUI(). */ - ~ScopedJuceInitialiser_GUI() { shutdownJuce_GUI(); } + ~ScopedJuceInitialiser_GUI(); }; //============================================================================== -/* +/** To start a JUCE app, use this macro: START_JUCE_APPLICATION (AppSubClass) where - AppSubClass is the name of a class derived from JUCEApplication. - - See the JUCEApplication class documentation (juce_Application.h) for more details. + AppSubClass is the name of a class derived from JUCEApplication or JUCEApplicationBase. + See the JUCEApplication and JUCEApplicationBase class documentation for more details. */ -#if JUCE_ANDROID +#ifdef DOXYGEN + #define START_JUCE_APPLICATION(AppClass) +#elif JUCE_ANDROID #define START_JUCE_APPLICATION(AppClass) \ - juce::JUCEApplication* juce_CreateApplication() { return new AppClass(); } + juce::JUCEApplicationBase* juce_CreateApplication() { return new AppClass(); } #else #if JUCE_WINDOWS @@ -105,8 +106,8 @@ public: static juce::JUCEApplicationBase* juce_CreateApplication() { return new AppClass(); } \ extern "C" JUCE_MAIN_FUNCTION \ { \ - juce::JUCEApplication::createInstance = &juce_CreateApplication; \ - return juce::JUCEApplication::main (JUCE_MAIN_FUNCTION_ARGS); \ + juce::JUCEApplicationBase::createInstance = &juce_CreateApplication; \ + return juce::JUCEApplicationBase::main (JUCE_MAIN_FUNCTION_ARGS); \ } #endif diff --git a/modules/juce_events/messages/juce_MessageManager.cpp b/modules/juce_events/messages/juce_MessageManager.cpp index d766528bd9..925c27acc0 100644 --- a/modules/juce_events/messages/juce_MessageManager.cpp +++ b/modules/juce_events/messages/juce_MessageManager.cpp @@ -334,3 +334,6 @@ JUCE_API void JUCE_CALLTYPE shutdownJuce_GUI() MessageManager::deleteInstance(); } } + +ScopedJuceInitialiser_GUI::ScopedJuceInitialiser_GUI() { initialiseJuce_GUI(); } +ScopedJuceInitialiser_GUI::~ScopedJuceInitialiser_GUI() { shutdownJuce_GUI(); } diff --git a/modules/juce_events/messages/juce_MessageManager.h b/modules/juce_events/messages/juce_MessageManager.h index 37c00bbc47..86dd62ebe6 100644 --- a/modules/juce_events/messages/juce_MessageManager.h +++ b/modules/juce_events/messages/juce_MessageManager.h @@ -41,7 +41,7 @@ typedef void* (MessageCallbackFunction) (void* userData); /** This class is in charge of the application's event-dispatch loop. - @see Message, CallbackMessage, MessageManagerLock, JUCEApplication + @see Message, CallbackMessage, MessageManagerLock, JUCEApplication, JUCEApplicationBase */ class JUCE_API MessageManager { diff --git a/modules/juce_gui_basics/application/juce_Application.cpp b/modules/juce_gui_basics/application/juce_Application.cpp index 63cf8c1954..93b54be6a1 100644 --- a/modules/juce_gui_basics/application/juce_Application.cpp +++ b/modules/juce_gui_basics/application/juce_Application.cpp @@ -22,104 +22,29 @@ ============================================================================== */ -#if JUCE_MAC - extern void juce_initialiseMacMainMenu(); -#endif -#if ! (JUCE_IOS || JUCE_ANDROID) - #define JUCE_HANDLE_MULTIPLE_INSTANCES 1 -#endif +JUCEApplication::JUCEApplication() {} +JUCEApplication::~JUCEApplication() {} //============================================================================== -#if JUCE_HANDLE_MULTIPLE_INSTANCES -struct JUCEApplication::MultipleInstanceHandler : public ActionListener -{ -public: - MultipleInstanceHandler (const String& appName) - : appLock ("juceAppLock_" + appName) - { - } - - bool sendCommandLineToPreexistingInstance() - { - if (appLock.enter (0)) - return false; - - JUCEApplication* const app = JUCEApplication::getInstance(); - jassert (app != nullptr); - - MessageManager::broadcastMessage (app->getApplicationName() - + "/" + app->getCommandLineParameters()); - return true; - } - - void actionListenerCallback (const String& message) override - { - if (JUCEApplication* const app = JUCEApplication::getInstance()) - { - const String appName (app->getApplicationName()); - - if (message.startsWith (appName + "/")) - app->anotherInstanceStarted (message.substring (appName.length() + 1)); - } - } - -private: - InterProcessLock appLock; - - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MultipleInstanceHandler) -}; -#else -struct JUCEApplication::MultipleInstanceHandler {}; -#endif - -//============================================================================== -JUCEApplication::JUCEApplication() - : appReturnValue (0), - stillInitialising (true) +JUCEApplication* JUCE_CALLTYPE JUCEApplication::getInstance() noexcept { + return dynamic_cast (JUCEApplicationBase::getInstance()); } -JUCEApplication::~JUCEApplication() -{ -} - -//============================================================================== bool JUCEApplication::moreThanOneInstanceAllowed() { return true; } void JUCEApplication::anotherInstanceStarted (const String&) {} void JUCEApplication::suspended() {} void JUCEApplication::resumed() {} -void JUCEApplication::systemRequestedQuit() -{ - quit(); -} +void JUCEApplication::systemRequestedQuit() { quit(); } -void JUCEApplication::quit() -{ - MessageManager::getInstance()->stopDispatchLoop(); -} - -void JUCEApplication::setApplicationReturnValue (const int newReturnValue) noexcept -{ - appReturnValue = newReturnValue; -} - -//============================================================================== void JUCEApplication::unhandledException (const std::exception*, const String&, int) { jassertfalse; } -void JUCEApplication::sendUnhandledException (const std::exception* const e, - const char* const sourceFile, - const int lineNumber) -{ - if (JUCEApplicationBase* const app = JUCEApplicationBase::getInstance()) - app->unhandledException (e, sourceFile, lineNumber); -} - //============================================================================== ApplicationCommandTarget* JUCEApplication::getNextCommandTarget() { @@ -137,8 +62,7 @@ void JUCEApplication::getCommandInfo (const CommandID commandID, ApplicationComm { result.setInfo (TRANS("Quit"), TRANS("Quits the application"), - "Application", - 0); + "Application", 0); result.defaultKeypresses.add (KeyPress ('q', ModifierKeys::commandModifier, 0)); } @@ -155,148 +79,21 @@ bool JUCEApplication::perform (const InvocationInfo& info) return false; } -#if JUCE_HANDLE_MULTIPLE_INSTANCES -bool JUCEApplication::sendCommandLineToPreexistingInstance() -{ - jassert (multipleInstanceHandler == nullptr); // this must only be called once! - - multipleInstanceHandler = new MultipleInstanceHandler (getApplicationName()); - return multipleInstanceHandler->sendCommandLineToPreexistingInstance(); -} +//============================================================================== +#if JUCE_MAC + extern void juce_initialiseMacMainMenu(); #endif -//============================================================================== bool JUCEApplication::initialiseApp() { - #if JUCE_HANDLE_MULTIPLE_INSTANCES - if ((! moreThanOneInstanceAllowed()) && sendCommandLineToPreexistingInstance()) - { - DBG ("Another instance is running - quitting..."); - return false; - } - #endif - - // let the app do its setting-up.. - initialise (getCommandLineParameters()); - - stillInitialising = false; - - if (! MessageManager::getInstance()->hasStopMessageBeenSent()) + if (JUCEApplicationBase::initialiseApp()) { #if JUCE_MAC juce_initialiseMacMainMenu(); // (needs to get the app's name) #endif - #if JUCE_HANDLE_MULTIPLE_INSTANCES - if (multipleInstanceHandler != nullptr) - MessageManager::getInstance()->registerBroadcastListener (multipleInstanceHandler); - #endif + return true; } - return true; + return false; } - -int JUCEApplication::shutdownApp() -{ - jassert (JUCEApplicationBase::getInstance() == this); - - #if JUCE_HANDLE_MULTIPLE_INSTANCES - if (multipleInstanceHandler != nullptr) - MessageManager::getInstance()->deregisterBroadcastListener (multipleInstanceHandler); - #endif - - JUCE_TRY - { - // give the app a chance to clean up.. - shutdown(); - } - JUCE_CATCH_EXCEPTION - - multipleInstanceHandler = nullptr; - return getApplicationReturnValue(); -} - -//============================================================================== -#if JUCE_ANDROID - -StringArray JUCEApplication::getCommandLineParameterArray() { return StringArray(); } -String JUCEApplication::getCommandLineParameters() { return String::empty; } - -#else - -int JUCEApplication::main() -{ - ScopedJuceInitialiser_GUI libraryInitialiser; - jassert (createInstance != nullptr); - - const ScopedPointer app (dynamic_cast (createInstance())); - jassert (app != nullptr); - - if (! app->initialiseApp()) - return 0; - - JUCE_TRY - { - // loop until a quit message is received.. - MessageManager::getInstance()->runDispatchLoop(); - } - JUCE_CATCH_EXCEPTION - - return app->shutdownApp(); -} - -#if ! JUCE_WINDOWS -#if JUCE_IOS - extern int juce_iOSMain (int argc, const char* argv[]); -#endif - -#if JUCE_MAC - extern void initialiseNSApplication(); -#endif - -extern const char* const* juce_argv; // declared in juce_core -extern int juce_argc; - -StringArray JUCEApplication::getCommandLineParameterArray() -{ - return StringArray (juce_argv + 1, juce_argc - 1); -} - -String JUCEApplication::getCommandLineParameters() -{ - String argString; - - for (int i = 1; i < juce_argc; ++i) - { - String arg (juce_argv[i]); - - if (arg.containsChar (' ') && ! arg.isQuotedString()) - arg = arg.quoted ('"'); - - argString << arg << ' '; - } - - return argString.trim(); -} - -int JUCEApplication::main (int argc, const char* argv[]) -{ - JUCE_AUTORELEASEPOOL - { - juce_argc = argc; - juce_argv = argv; - - #if JUCE_MAC - initialiseNSApplication(); - #endif - - #if JUCE_IOS - return juce_iOSMain (argc, argv); - #else - return JUCEApplication::main(); - #endif - } -} -#endif - -#endif diff --git a/modules/juce_gui_basics/application/juce_Application.h b/modules/juce_gui_basics/application/juce_Application.h index 5b3d820b61..bd4f82cb96 100644 --- a/modules/juce_gui_basics/application/juce_Application.h +++ b/modules/juce_gui_basics/application/juce_Application.h @@ -31,24 +31,27 @@ An instance of this class is used to specify initialisation and shutdown code for the application. - An application that wants to run in the JUCE framework needs to declare a - subclass of JUCEApplication and implement its various pure virtual methods. + Any application that wants to run an event loop must declare a subclass of + JUCEApplicationBase or JUCEApplication, and implement its various pure virtual + methods. - It then needs to use the START_JUCE_APPLICATION macro somewhere in a cpp file - to declare an instance of this class and generate a suitable platform-specific - main() function. + It then needs to use the START_JUCE_APPLICATION macro somewhere in a CPP file + to declare an instance of this class and generate suitable platform-specific + boilerplate code to launch the app. + + Note that this class is derived from JUCEApplicationBase, which contains most + of the useful methods and functionality. This derived class is here simply as + a convenient way to also inherit from an ApplicationCommandTarget, and to implement + default versions of some of the pure virtual base class methods. But you can derive + your app object directly from JUCEApplicationBase if you want to, and by doing so + can avoid having a dependency on the juce_gui_basics module. e.g. @code class MyJUCEApp : public JUCEApplication { public: - MyJUCEApp() - { - } - - ~MyJUCEApp() - { - } + MyJUCEApp() {} + ~MyJUCEApp() {} void initialise (const String& commandLine) { @@ -59,7 +62,7 @@ void shutdown() { - myMainWindow = 0; + myMainWindow = nullptr; } const String getApplicationName() @@ -73,19 +76,19 @@ } private: - ScopedPointer myMainWindow; + ScopedPointer myMainWindow; }; - // this creates wrapper code to actually launch the app properly. + // this generates boilerplate code to launch our app class: START_JUCE_APPLICATION (MyJUCEApp) @endcode - @see MessageManager + @see JUCEApplicationBase, START_JUCE_APPLICATION */ class JUCE_API JUCEApplication : public JUCEApplicationBase, public ApplicationCommandTarget { -protected: +public: //============================================================================== /** Constructs a JUCE app object. @@ -95,37 +98,23 @@ protected: */ JUCEApplication(); -public: /** Destructor. If subclasses implement a constructor or destructor, they shouldn't call any JUCE code in there - put your startup/shutdown code in initialise() and shutdown() instead. */ - virtual ~JUCEApplication(); + ~JUCEApplication(); //============================================================================== /** Returns the global instance of the application object being run. */ - static JUCEApplication* getInstance() noexcept { return dynamic_cast (JUCEApplicationBase::getInstance()); } + static JUCEApplication* JUCE_CALLTYPE getInstance() noexcept; //============================================================================== - /** Returns true if the application hasn't yet completed its initialise() method - and entered the main event loop. - - This is handy for things like splash screens to know when the app's up-and-running - properly. - */ - bool isInitialising() const noexcept { return stillInitialising; } - - //============================================================================== - /** Returns the application's name. - - An application must implement this to name itself. - */ + /** Returns the application's name. */ virtual const String getApplicationName() = 0; - /** Returns the application's version number. - */ + /** Returns the application's version number. */ virtual const String getApplicationVersion() = 0; /** Checks whether multiple instances of the app are allowed. @@ -138,13 +127,12 @@ public: callback to anotherInstanceStarted() to tell you about this - which gives you a chance to react to what the user was trying to do. */ - virtual bool moreThanOneInstanceAllowed(); + bool moreThanOneInstanceAllowed() override; /** Indicates that the user has tried to start up another instance of the app. - This will get called even if moreThanOneInstanceAllowed() is false. */ - virtual void anotherInstanceStarted (const String& commandLine); + void anotherInstanceStarted (const String& commandLine) override; /** Called when the operating system is trying to close the application. @@ -158,17 +146,17 @@ public: in the same way as those from your own application code. So e.g. you'd call this method from a "quit" item on a menu bar. */ - virtual void systemRequestedQuit(); + void systemRequestedQuit() override; /** This method is called when the application is being put into background mode by the operating system. */ - virtual void suspended(); + void suspended() override; /** This method is called when the application is being woken from background mode by the operating system. */ - virtual void resumed(); + void resumed() override; /** If any unhandled exceptions make it through to the message dispatch loop, this callback will be triggered, in case you want to log them or do some other @@ -178,54 +166,9 @@ public: passed-in will be valid. If the exception is of unknown type, this pointer will be null. */ - virtual void unhandledException (const std::exception* e, - const String& sourceFilename, - int lineNumber); - - //============================================================================== - /** Signals that the main message loop should stop and the application should terminate. - - This isn't synchronous, it just posts a quit message to the main queue, and - when this message arrives, the message loop will stop, the shutdown() method - will be called, and the app will exit. - - Note that this will cause an unconditional quit to happen, so if you need an - extra level before this, e.g. to give the user the chance to save their work - and maybe cancel the quit, you'll need to handle this in the systemRequestedQuit() - method - see that method's help for more info. - - @see MessageManager - */ - static void quit(); - - /** Sets the value that should be returned as the application's exit code when the - app quits. - - This is the value that's returned by the main() function. Normally you'd leave this - as 0 unless you want to indicate an error code. - - @see getApplicationReturnValue - */ - void setApplicationReturnValue (int newReturnValue) noexcept; - - /** Returns the value that has been set as the application's exit code. - @see setApplicationReturnValue - */ - int getApplicationReturnValue() const noexcept { return appReturnValue; } - - /** Returns the application's command line parameters as a set of strings. - @see getCommandLineParameters - */ - static StringArray JUCE_CALLTYPE getCommandLineParameterArray(); - - /** Returns the application's command line parameters as a single string. - @see getCommandLineParameterArray - */ - static String JUCE_CALLTYPE getCommandLineParameters(); - - /** Returns true if this executable is running as an app (as opposed to being a plugin - or other kind of shared library. */ - static inline bool isStandaloneApp() noexcept { return createInstance != nullptr; } + void unhandledException (const std::exception* e, + const String& sourceFilename, + int lineNumber) override; //============================================================================== /** @internal */ @@ -237,28 +180,8 @@ public: /** @internal */ bool perform (const InvocationInfo&); - //============================================================================== - #ifndef DOXYGEN - // The following methods are internal calls - not for public use. - static int main(); - static int main (int argc, const char* argv[]); - static void sendUnhandledException (const std::exception*, const char* sourceFile, int lineNumber); - bool initialiseApp(); - int shutdownApp(); - -protected: - bool sendCommandLineToPreexistingInstance(); - #endif - private: - //============================================================================== - struct MultipleInstanceHandler; - friend struct MultipleInstanceHandler; - friend struct ContainerDeletePolicy; - ScopedPointer multipleInstanceHandler; - - int appReturnValue; - bool stillInitialising; + bool initialiseApp() override; JUCE_DECLARE_NON_COPYABLE (JUCEApplication) }; diff --git a/modules/juce_gui_basics/commands/juce_ApplicationCommandID.h b/modules/juce_gui_basics/commands/juce_ApplicationCommandID.h index 4e92952793..6dbd8b11fe 100644 --- a/modules/juce_gui_basics/commands/juce_ApplicationCommandID.h +++ b/modules/juce_gui_basics/commands/juce_ApplicationCommandID.h @@ -55,7 +55,7 @@ namespace StandardApplicationCommandIDs This command is recognised by the JUCEApplication class, so if it is invoked and no other ApplicationCommandTarget handles the event first, the JUCEApplication - object will catch it and call JUCEApplication::systemRequestedQuit(). + object will catch it and call JUCEApplicationBase::systemRequestedQuit(). */ static const CommandID quit = 0x1001; diff --git a/modules/juce_gui_basics/juce_gui_basics.h b/modules/juce_gui_basics/juce_gui_basics.h index 376611f88a..6272a79c38 100644 --- a/modules/juce_gui_basics/juce_gui_basics.h +++ b/modules/juce_gui_basics/juce_gui_basics.h @@ -238,7 +238,6 @@ class ApplicationCommandManagerListener; #include "properties/juce_SliderPropertyComponent.h" #include "properties/juce_TextPropertyComponent.h" #include "application/juce_Application.h" -#include "application/juce_Initialisation.h" #include "misc/juce_BubbleComponent.h" } diff --git a/modules/juce_gui_basics/native/juce_android_Windowing.cpp b/modules/juce_gui_basics/native/juce_android_Windowing.cpp index ac67eef81b..9fa4733777 100644 --- a/modules/juce_gui_basics/native/juce_android_Windowing.cpp +++ b/modules/juce_gui_basics/native/juce_android_Windowing.cpp @@ -41,7 +41,7 @@ JUCE_JNI_CALLBACK (JUCE_ANDROID_ACTIVITY_CLASSNAME, launchApp, void, (JNIEnv* en initialiseJuce_GUI(); - JUCEApplication* app = dynamic_cast (JUCEApplicationBase::createInstance()); + JUCEApplicationBase* app = JUCEApplicationBase::createInstance(); if (! app->initialiseApp()) exit (0); diff --git a/modules/juce_gui_basics/native/juce_ios_Windowing.mm b/modules/juce_gui_basics/native/juce_ios_Windowing.mm index 4a4afb9b82..963179d0f4 100644 --- a/modules/juce_gui_basics/native/juce_ios_Windowing.mm +++ b/modules/juce_gui_basics/native/juce_ios_Windowing.mm @@ -41,7 +41,8 @@ { initialiseJuce_GUI(); - JUCEApplication* app = dynamic_cast (JUCEApplicationBase::createInstance()); + JUCEApplicationBase* app = JUCEApplicationBase::createInstance(); + if (! app->initialiseApp()) exit (0); } @@ -53,15 +54,13 @@ - (void) applicationDidEnterBackground: (UIApplication*) application { - JUCEApplicationBase* const app = JUCEApplicationBase::getInstance(); - if (app != nullptr) + if (JUCEApplicationBase* const app = JUCEApplicationBase::getInstance()) app->suspended(); } - (void) applicationWillEnterForeground: (UIApplication*) application { - JUCEApplicationBase* const app = JUCEApplicationBase::getInstance(); - if (app != nullptr) + if (JUCEApplicationBase* const app = JUCEApplicationBase::getInstance()) app->resumed(); } diff --git a/modules/juce_gui_basics/native/juce_mac_FileChooser.mm b/modules/juce_gui_basics/native/juce_mac_FileChooser.mm index d1663d8ed7..11bd0ef4cc 100644 --- a/modules/juce_gui_basics/native/juce_mac_FileChooser.mm +++ b/modules/juce_gui_basics/native/juce_mac_FileChooser.mm @@ -118,7 +118,7 @@ void FileChooser::showPlatformDialog (Array& results, JUCE_AUTORELEASEPOOL { ScopedPointer tempMenu; - if (JUCEApplication::isStandaloneApp()) + if (JUCEApplicationBase::isStandaloneApp()) tempMenu = new TemporaryMainMenuWithStandardCommands(); StringArray* filters = new StringArray(); diff --git a/modules/juce_gui_basics/native/juce_mac_MainMenu.mm b/modules/juce_gui_basics/native/juce_mac_MainMenu.mm index c08a2b0998..9ed798c72e 100644 --- a/modules/juce_gui_basics/native/juce_mac_MainMenu.mm +++ b/modules/juce_gui_basics/native/juce_mac_MainMenu.mm @@ -662,9 +662,9 @@ namespace MainMenuHelpers static void rebuildMainMenu (const PopupMenu* extraItems) { // this can't be used in a plugin! - jassert (JUCEApplication::isStandaloneApp()); + jassert (JUCEApplicationBase::isStandaloneApp()); - if (JUCEApplication* app = JUCEApplication::getInstance()) + if (JUCEApplicationBase* app = JUCEApplicationBase::getInstance()) { JUCE_AUTORELEASEPOOL { diff --git a/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm b/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm index c531b34129..6792da31db 100644 --- a/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm +++ b/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm @@ -1388,7 +1388,7 @@ private: static void mouseDown (id self, SEL s, NSEvent* ev) { - if (JUCEApplication::isStandaloneApp()) + if (JUCEApplicationBase::isStandaloneApp()) asyncMouseDown (self, s, ev); else // In some host situations, the host will stop modal loops from working @@ -1401,7 +1401,7 @@ private: static void mouseUp (id self, SEL s, NSEvent* ev) { - if (JUCEApplication::isStandaloneApp()) + if (JUCEApplicationBase::isStandaloneApp()) asyncMouseUp (self, s, ev); else // In some host situations, the host will stop modal loops from working diff --git a/modules/juce_gui_basics/native/juce_win32_Windowing.cpp b/modules/juce_gui_basics/native/juce_win32_Windowing.cpp index 92cbd9c144..97f94cb716 100644 --- a/modules/juce_gui_basics/native/juce_win32_Windowing.cpp +++ b/modules/juce_gui_basics/native/juce_win32_Windowing.cpp @@ -162,7 +162,7 @@ static void setWindowZOrder (HWND hwnd, HWND insertAfter) //============================================================================== static void setDPIAwareness() { - if (JUCEApplication::isStandaloneApp()) + if (JUCEApplicationBase::isStandaloneApp()) { if (setProcessDPIAware == nullptr) { @@ -2457,7 +2457,7 @@ private: return 0; case WM_QUERYENDSESSION: - if (JUCEApplication* const app = JUCEApplication::getInstance()) + if (JUCEApplicationBase* const app = JUCEApplicationBase::getInstance()) { app->systemRequestedQuit(); return MessageManager::getInstance()->hasStopMessageBeenSent(); @@ -3158,28 +3158,6 @@ String SystemClipboard::getTextFromClipboard() return result; } -//============================================================================== -String JUCE_CALLTYPE JUCEApplication::getCommandLineParameters() -{ - return CharacterFunctions::findEndOfToken (CharPointer_UTF16 (GetCommandLineW()), - CharPointer_UTF16 (L" "), - CharPointer_UTF16 (L"\"")).findEndOfWhitespace(); -} - -StringArray JUCE_CALLTYPE JUCEApplication::getCommandLineParameterArray() -{ - StringArray s; - - int argc = 0; - if (LPWSTR* const argv = CommandLineToArgvW (GetCommandLineW(), &argc)) - { - s = StringArray (argv + 1, argc - 1); - LocalFree (argv); - } - - return s; -} - //============================================================================== void Desktop::setKioskComponent (Component* kioskModeComponent, bool enableOrDisable, bool /*allowMenusAndBars*/) { diff --git a/modules/juce_gui_basics/properties/juce_PropertyPanel.h b/modules/juce_gui_basics/properties/juce_PropertyPanel.h index 394921f434..4984f424ab 100644 --- a/modules/juce_gui_basics/properties/juce_PropertyPanel.h +++ b/modules/juce_gui_basics/properties/juce_PropertyPanel.h @@ -79,7 +79,7 @@ public: /** Calls the refresh() method of all PropertyComponents in the panel */ void refreshAll() const; - /** Returns true if there no properties have been added. */ + /** Returns true if the panel contains no properties. */ bool isEmpty() const; /** Returns the height that the panel needs in order to display all of its content diff --git a/modules/juce_gui_basics/windows/juce_DocumentWindow.cpp b/modules/juce_gui_basics/windows/juce_DocumentWindow.cpp index 7bcf8bfb97..b6e29e9df1 100644 --- a/modules/juce_gui_basics/windows/juce_DocumentWindow.cpp +++ b/modules/juce_gui_basics/windows/juce_DocumentWindow.cpp @@ -165,8 +165,8 @@ void DocumentWindow::closeButtonPressed() If your app is centred around this window such that the whole app should quit when the window is closed, then you will probably want to use this method as an opportunity - to call JUCEApplication::quit(), and leave the window to be deleted later by your - JUCEApplication::shutdown() method. (Doing it this way means that your window will + to call JUCEApplicationBase::quit(), and leave the window to be deleted later by your + JUCEApplicationBase::shutdown() method. (Doing it this way means that your window will still get cleaned-up if the app is quit by some other means (e.g. a cmd-Q on the mac or closing it via the taskbar icon on Windows). */ diff --git a/modules/juce_gui_basics/windows/juce_DocumentWindow.h b/modules/juce_gui_basics/windows/juce_DocumentWindow.h index 8f2783fb27..0bf7cc8a91 100644 --- a/modules/juce_gui_basics/windows/juce_DocumentWindow.h +++ b/modules/juce_gui_basics/windows/juce_DocumentWindow.h @@ -173,8 +173,8 @@ public: If your app is centred around this window such that the whole app should quit when the window is closed, then you will probably want to use this method as an opportunity - to call JUCEApplication::quit(), and leave the window to be deleted later by your - JUCEApplication::shutdown() method. (Doing it this way means that your window will + to call JUCEApplicationBase::quit(), and leave the window to be deleted later by your + JUCEApplicationBase::shutdown() method. (Doing it this way means that your window will still get cleaned-up if the app is quit by some other means (e.g. a cmd-Q on the mac or closing it via the taskbar icon on Windows). diff --git a/modules/juce_gui_extra/misc/juce_SplashScreen.h b/modules/juce_gui_extra/misc/juce_SplashScreen.h index aa9db7929a..1d4d48ba23 100644 --- a/modules/juce_gui_extra/misc/juce_SplashScreen.h +++ b/modules/juce_gui_extra/misc/juce_SplashScreen.h @@ -32,7 +32,7 @@ This will automatically position itself, and can be told to delete itself after being on-screen for a minimum length of time. - To use it, just create one of these in your JUCEApplication::initialise() method, + To use it, just create one of these in your JUCEApplicationBase::initialise() method, and when your initialisation tasks have finished running, call its deleteAfterDelay() method to make it automatically get rid of itself. @@ -78,9 +78,9 @@ public: When called, the constructor will position the SplashScreen in the centre of the display, and after the time specified, it will automatically delete itself. - Bear in mind that if you call this during your JUCEApplication::initialise() + Bear in mind that if you call this during your JUCEApplicationBase::initialise() method and then block the message thread by performing some kind of task, then - obviously neither your splash screen or any other GUI won't appear until you + obviously neither your splash screen nor any other GUI will appear until you allow the message thread to resume and do its work. So if you have time-consuming tasks to do during startup, use a background thread for them.