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) void initialise (const String& commandLine)
{ {
LookAndFeel::setDefaultLookAndFeel (&lookAndFeel); LookAndFeel::setDefaultLookAndFeel (&lookAndFeel);
settings = new StoredSettings(); settings = new StoredSettings();
icons = new Icons();
settings->initialise(); settings->initialise();
if (commandLine.isNotEmpty()) 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 = new ApplicationCommandManager();
commandManager->registerAllCommandsForTarget (this); commandManager->registerAllCommandsForTarget (this);
@@ -131,11 +137,7 @@ public:
bool moreThanOneInstanceAllowed() 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) void anotherInstanceStarted (const String& commandLine)


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

@@ -31,6 +31,13 @@
//============================================================================== //==============================================================================
namespace namespace
{ {
void hideDockIcon()
{
#if JUCE_MAC
Process::setDockIconVisible (false);
#endif
}
File getFile (const String& filename) File getFile (const String& filename)
{ {
return File::getCurrentWorkingDirectory().getChildFile (filename.unquoted()); return File::getCurrentWorkingDirectory().getChildFile (filename.unquoted());
@@ -53,6 +60,8 @@ namespace
*/ */
int resaveProject (const StringArray& args, bool justSaveResources) int resaveProject (const StringArray& args, bool justSaveResources)
{ {
hideDockIcon();
if (! checkArgumentCount (args, 2)) if (! checkArgumentCount (args, 2))
return 1; return 1;
@@ -145,6 +154,8 @@ namespace
int buildModules (const StringArray& args, const bool buildAllWithIndex) int buildModules (const StringArray& args, const bool buildAllWithIndex)
{ {
hideDockIcon();
if (! checkArgumentCount (args, 3)) if (! checkArgumentCount (args, 3))
return 1; return 1;
@@ -200,6 +211,8 @@ namespace
int listModules() int listModules()
{ {
hideDockIcon();
std::cout << "Downloading list of available modules..." << std::endl; std::cout << "Downloading list of available modules..." << std::endl;
ModuleList list; ModuleList list;
list.loadFromWebsite(); list.loadFromWebsite();
@@ -216,6 +229,8 @@ namespace
int showStatus (const StringArray& args) int showStatus (const StringArray& args)
{ {
hideDockIcon();
if (! checkArgumentCount (args, 2)) if (! checkArgumentCount (args, 2))
return 1; return 1;
@@ -256,6 +271,8 @@ namespace
//============================================================================== //==============================================================================
int showHelp() int showHelp()
{ {
hideDockIcon();
std::cout << "The Introjucer!" << std::endl std::cout << "The Introjucer!" << std::endl
<< std::endl << std::endl
<< "Usage: " << 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: public:
//============================================================================== //==============================================================================
/** Creates a lock object. /** 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); explicit InterProcessLock (const String& name);
/** Destructor. /** Destructor.
This will also release the lock if it's currently held by this process. This will also release the lock if it's currently held by this process.
*/ */
~InterProcessLock(); ~InterProcessLock();
@@ -55,17 +53,15 @@ public:
//============================================================================== //==============================================================================
/** Attempts to lock the critical section. /** 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 @returns true if the lock could be gained within the timeout period, or
false if the timeout expired. false if the timeout expired.
*/ */
bool enter (int timeOutMillisecs = -1); 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(); void exit();
//============================================================================== //==============================================================================
@@ -94,7 +90,7 @@ public:
otherwise there are no guarantees what will happen! Best just to use it 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. 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. /** Destructor.
@@ -103,14 +99,14 @@ public:
Make sure this object is created and deleted by the same thread, Make sure this object is created and deleted by the same thread,
otherwise there are no guarantees what will happen! otherwise there are no guarantees what will happen!
*/ */
inline ~ScopedLockType() { lock_.exit(); }
inline ~ScopedLockType() { ipLock.exit(); }
/** Returns true if the InterProcessLock was successfully locked. */ /** Returns true if the InterProcessLock was successfully locked. */
bool isLocked() const noexcept { return lockWasSuccessful; }
bool isLocked() const noexcept { return lockWasSuccessful; }
private: private:
//============================================================================== //==============================================================================
InterProcessLock& lock_;
InterProcessLock& ipLock;
bool lockWasSuccessful; bool lockWasSuccessful;
JUCE_DECLARE_NON_COPYABLE (ScopedLockType); 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(); extern void juce_initialiseMacMainMenu();
#endif #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: 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) void actionListenerCallback (const String& message)
{ {
JUCEApplication* const app = JUCEApplication::getInstance(); 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() JUCEApplication::JUCEApplication()
@@ -52,11 +85,6 @@ JUCEApplication::JUCEApplication()
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; jassertfalse;
} }
@@ -132,39 +158,44 @@ bool JUCEApplication::perform (const InvocationInfo& info)
return false; 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() 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 #endif
// let the app do its setting-up.. // let the app do its setting-up..
initialise (getCommandLineParameters()); 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; return true;
} }
@@ -172,7 +203,10 @@ int JUCEApplication::shutdownApp()
{ {
jassert (JUCEApplicationBase::getInstance() == this); jassert (JUCEApplicationBase::getInstance() == this);
broadcastCallback = nullptr;
#if JUCE_HANDLE_MULTIPLE_INSTANCES
if (multipleInstanceHandler != nullptr)
MessageManager::getInstance()->deregisterBroadcastListener (multipleInstanceHandler);
#endif
JUCE_TRY JUCE_TRY
{ {
@@ -181,6 +215,7 @@ int JUCEApplication::shutdownApp()
} }
JUCE_CATCH_EXCEPTION JUCE_CATCH_EXCEPTION
multipleInstanceHandler = nullptr;
return getApplicationReturnValue(); 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); static void sendUnhandledException (const std::exception*, const char* sourceFile, int lineNumber);
bool initialiseApp(); bool initialiseApp();
int shutdownApp(); int shutdownApp();
protected:
bool sendCommandLineToPreexistingInstance();
#endif #endif
private: private:
//============================================================================== //==============================================================================
ScopedPointer<InterProcessLock> appLock;
ScopedPointer<ActionListener> broadcastCallback;
struct MultipleInstanceHandler;
friend struct MultipleInstanceHandler;
friend class ScopedPointer<MultipleInstanceHandler>;
ScopedPointer<MultipleInstanceHandler> multipleInstanceHandler;
int appReturnValue; int appReturnValue;
bool stillInitialising; bool stillInitialising;


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

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


Loading…
Cancel
Save