Browse Source

Cleaned up some application startup code.

tags/2021-05-28
jules 13 years ago
parent
commit
8a006e589c
6 changed files with 117 additions and 59 deletions
  1. +10
    -8
      extras/Introjucer/Source/Application/jucer_Application.h
  2. +17
    -0
      extras/Introjucer/Source/Application/jucer_CommandLine.cpp
  3. +9
    -13
      modules/juce_core/threads/juce_InterProcessLock.h
  4. +70
    -35
      modules/juce_gui_basics/application/juce_Application.cpp
  5. +8
    -2
      modules/juce_gui_basics/application/juce_Application.h
  6. +3
    -1
      modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm

+ 10
- 8
extras/Introjucer/Source/Application/jucer_Application.h View File

@@ -45,10 +45,7 @@ public:
void initialise (const String& commandLine)
{
LookAndFeel::setDefaultLookAndFeel (&lookAndFeel);
settings = new StoredSettings();
icons = new Icons();
settings->initialise();
if (commandLine.isNotEmpty())
@@ -63,6 +60,15 @@ public:
}
}
if (sendCommandLineToPreexistingInstance())
{
DBG ("Another instance is running - quitting...");
quit();
return;
}
icons = new Icons();
commandManager = new ApplicationCommandManager();
commandManager->registerAllCommandsForTarget (this);
@@ -131,11 +137,7 @@ public:
bool moreThanOneInstanceAllowed()
{
#ifndef JUCE_LINUX
return false;
#else
return true; //xxx should be false but doesn't work on linux..
#endif
return true; // this is handled manually in initialise()
}
void anotherInstanceStarted (const String& commandLine)


+ 17
- 0
extras/Introjucer/Source/Application/jucer_CommandLine.cpp View File

@@ -31,6 +31,13 @@
//==============================================================================
namespace
{
void hideDockIcon()
{
#if JUCE_MAC
Process::setDockIconVisible (false);
#endif
}
File getFile (const String& filename)
{
return File::getCurrentWorkingDirectory().getChildFile (filename.unquoted());
@@ -53,6 +60,8 @@ namespace
*/
int resaveProject (const StringArray& args, bool justSaveResources)
{
hideDockIcon();
if (! checkArgumentCount (args, 2))
return 1;
@@ -145,6 +154,8 @@ namespace
int buildModules (const StringArray& args, const bool buildAllWithIndex)
{
hideDockIcon();
if (! checkArgumentCount (args, 3))
return 1;
@@ -200,6 +211,8 @@ namespace
int listModules()
{
hideDockIcon();
std::cout << "Downloading list of available modules..." << std::endl;
ModuleList list;
list.loadFromWebsite();
@@ -216,6 +229,8 @@ namespace
int showStatus (const StringArray& args)
{
hideDockIcon();
if (! checkArgumentCount (args, 2))
return 1;
@@ -256,6 +271,8 @@ namespace
//==============================================================================
int showHelp()
{
hideDockIcon();
std::cout << "The Introjucer!" << std::endl
<< std::endl
<< "Usage: " << std::endl


+ 9
- 13
modules/juce_core/threads/juce_InterProcessLock.h View File

@@ -41,13 +41,11 @@ class JUCE_API InterProcessLock
public:
//==============================================================================
/** Creates a lock object.
@param name a name that processes will use to identify this lock object
@param name a name that processes will use to identify this lock object
*/
explicit InterProcessLock (const String& name);
/** Destructor.
This will also release the lock if it's currently held by this process.
*/
~InterProcessLock();
@@ -55,17 +53,15 @@ public:
//==============================================================================
/** Attempts to lock the critical section.
@param timeOutMillisecs how many milliseconds to wait if the lock
is already held by another process - a value of
0 will return immediately, negative values will wait
forever
@param timeOutMillisecs how many milliseconds to wait if the lock is already
held by another process - a value of 0 will return
immediately, negative values will wait forever
@returns true if the lock could be gained within the timeout period, or
false if the timeout expired.
*/
bool enter (int timeOutMillisecs = -1);
/** Releases the lock if it's currently held by this process.
*/
/** Releases the lock if it's currently held by this process. */
void exit();
//==============================================================================
@@ -94,7 +90,7 @@ public:
otherwise there are no guarantees what will happen! Best just to use it
as a local stack object, rather than creating one with the new() operator.
*/
explicit ScopedLockType (InterProcessLock& lock) : lock_ (lock) { lockWasSuccessful = lock.enter(); }
explicit ScopedLockType (InterProcessLock& lock) : ipLock (lock) { lockWasSuccessful = lock.enter(); }
/** Destructor.
@@ -103,14 +99,14 @@ public:
Make sure this object is created and deleted by the same thread,
otherwise there are no guarantees what will happen!
*/
inline ~ScopedLockType() { lock_.exit(); }
inline ~ScopedLockType() { ipLock.exit(); }
/** Returns true if the InterProcessLock was successfully locked. */
bool isLocked() const noexcept { return lockWasSuccessful; }
bool isLocked() const noexcept { return lockWasSuccessful; }
private:
//==============================================================================
InterProcessLock& lock_;
InterProcessLock& ipLock;
bool lockWasSuccessful;
JUCE_DECLARE_NON_COPYABLE (ScopedLockType);


+ 70
- 35
modules/juce_gui_basics/application/juce_Application.cpp View File

@@ -27,21 +27,54 @@
extern void juce_initialiseMacMainMenu();
#endif
#if ! (JUCE_IOS || JUCE_ANDROID)
#define JUCE_HANDLE_MULTIPLE_INSTANCES 1
#endif
//==============================================================================
class AppBroadcastCallback : public ActionListener
#if JUCE_HANDLE_MULTIPLE_INSTANCES
struct JUCEApplication::MultipleInstanceHandler : public ActionListener
{
public:
AppBroadcastCallback() { MessageManager::getInstance()->registerBroadcastListener (this); }
~AppBroadcastCallback() { MessageManager::getInstance()->deregisterBroadcastListener (this); }
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)
{
JUCEApplication* const app = JUCEApplication::getInstance();
if (app != 0 && message.startsWith (app->getApplicationName() + "/"))
app->anotherInstanceStarted (message.substring (app->getApplicationName().length() + 1));
if (app != nullptr)
{
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()
@@ -52,11 +85,6 @@ JUCEApplication::JUCEApplication()
JUCEApplication::~JUCEApplication()
{
if (appLock != nullptr)
{
appLock->exit();
appLock = nullptr;
}
}
//==============================================================================
@@ -82,9 +110,7 @@ void JUCEApplication::setApplicationReturnValue (const int newReturnValue) noexc
}
//==============================================================================
void JUCEApplication::unhandledException (const std::exception*,
const String&,
const int)
void JUCEApplication::unhandledException (const std::exception*, const String&, int)
{
jassertfalse;
}
@@ -132,39 +158,44 @@ 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();
}
#endif
//==============================================================================
bool JUCEApplication::initialiseApp()
{
#if ! (JUCE_IOS || JUCE_ANDROID)
jassert (appLock == nullptr); // initialiseApp must only be called once!
if (! moreThanOneInstanceAllowed())
#if JUCE_HANDLE_MULTIPLE_INSTANCES
if ((! moreThanOneInstanceAllowed()) && sendCommandLineToPreexistingInstance())
{
appLock = new InterProcessLock ("juceAppLock_" + getApplicationName());
if (! appLock->enter(0))
{
appLock = nullptr;
MessageManager::broadcastMessage (getApplicationName() + "/" + getCommandLineParameters());
DBG ("Another instance is running - quitting...");
return false;
}
DBG ("Another instance is running - quitting...");
return false;
}
#endif
// let the app do its setting-up..
initialise (getCommandLineParameters());
#if JUCE_MAC
juce_initialiseMacMainMenu(); // needs to be called after the app object has created, to get its name
#endif
stillInitialising = false;
#if ! (JUCE_IOS || JUCE_ANDROID)
broadcastCallback = new AppBroadcastCallback();
#endif
if (! MessageManager::getInstance()->hasStopMessageBeenSent())
{
#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
}
stillInitialising = false;
return true;
}
@@ -172,7 +203,10 @@ int JUCEApplication::shutdownApp()
{
jassert (JUCEApplicationBase::getInstance() == this);
broadcastCallback = nullptr;
#if JUCE_HANDLE_MULTIPLE_INSTANCES
if (multipleInstanceHandler != nullptr)
MessageManager::getInstance()->deregisterBroadcastListener (multipleInstanceHandler);
#endif
JUCE_TRY
{
@@ -181,6 +215,7 @@ int JUCEApplication::shutdownApp()
}
JUCE_CATCH_EXCEPTION
multipleInstanceHandler = nullptr;
return getApplicationReturnValue();
}


+ 8
- 2
modules/juce_gui_basics/application/juce_Application.h View File

@@ -246,12 +246,18 @@ public:
static void sendUnhandledException (const std::exception*, const char* sourceFile, int lineNumber);
bool initialiseApp();
int shutdownApp();
protected:
bool sendCommandLineToPreexistingInstance();
#endif
private:
//==============================================================================
ScopedPointer<InterProcessLock> appLock;
ScopedPointer<ActionListener> broadcastCallback;
struct MultipleInstanceHandler;
friend struct MultipleInstanceHandler;
friend class ScopedPointer<MultipleInstanceHandler>;
ScopedPointer<MultipleInstanceHandler> multipleInstanceHandler;
int appReturnValue;
bool stillInitialising;


+ 3
- 1
modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm View File

@@ -103,7 +103,6 @@ public:
styleMask: getNSWindowStyleMask (windowStyleFlags)
backing: NSBackingStoreBuffered
defer: YES];
setOwner (window, this);
[window orderOut: nil];
#if defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
@@ -132,6 +131,9 @@ public:
#if defined (MAC_OS_X_VERSION_10_7) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7)
if ((windowStyleFlags & (windowHasMaximiseButton | windowHasTitleBar)) == (windowHasMaximiseButton | windowHasTitleBar))
[window setCollectionBehavior: NSWindowCollectionBehaviorFullScreenPrimary];
if ([window respondsToSelector: @selector (setRestorable:)])
[window setRestorable: NO];
#endif
}


Loading…
Cancel
Save