applicationDidBecomeActive not triggered on a "NSDocument" macos application


#1

Hi, I recently tried to add some code when a NSDocument (aka Juce Application with multiple instances allowed) receive focus and no documents are opened. Because no documents are opened the focusChanged callback does nothing. So I changed the following code in juce_mac_MessageManager.mm

static void applicationDidBecomeActive (id /*self*/, SEL, NSNotification*)  {
    focusChanged();
    if (auto* app = JUCEApplicationBase::getInstance())
    {
        app->resumed();
    }
}
static void applicationDidResignActive (id /*self*/, SEL, NSNotification*)  {
    focusChanged();
    if (auto* app = JUCEApplicationBase::getInstance())
    {
        app->suspended();
    }
}

Because I’m just a JUCE newbie I would like to know if there is any catch with that approach?

Thanks


#2

suspended() and resumed() are called when the app enters or exits a background state, and only really make sense for a mobile application where the user can switch between multiple apps and put the off screen ones into a suspended state.

What exactly are you trying to achieve here? applicationDidBecomeActive() and applicationDidResignActive() will call this method which will notify any peers of focus gain or loss. In your post you say that no windows are open, so it’s logical that no the focusChanged() callback doesn’t do anything as there’s nothing to give focus to, unless I’m misunderstanding something?


#3

Hi Ed, I known that the suspended() and resumed() only makes sense for the mobile apps but I didn’t want to add other methods to the JuceApplication class.

What I want to do is when the user clicks on the dock icon of the application, if no windows (documents) are open then I want to call the new document template dialog. That’s a standard behaviour on most OSX apps.


#4

You could work around this by always having an invisible component on the desktop which will receive focus when the user clicks on the dock icon and your process moves to the foreground. Then in your component you just need to override the Component::focusGained() method and spawn your template dialog window if there are no other windows visible.


#5

Ok. I will try that. Thanks


#6

Because I didn’t like the hack of an invisible component (triggers other kind of issues) and I didn’t want to misuse the resume and suspend methods, I did it the proper AppKit way. For future reference:
File juce_mac_MessageManager.mm

(...)
addMethod (@selector (applicationShouldHandleReopen:hasVisibleWindows:), applicationShouldHandleReopen,          "B@:@B");
(...)
static BOOL applicationShouldHandleReopen(id /*self*/, SEL, NSNotification*, BOOL hasVisibleWindows) {
    if (auto* app = JUCEApplicationBase::getInstance()) {
        return app->reopen(hasVisibleWindows);
    }
    return NO;
    }
(...)

File juce_ApplicationBase.h

(...)
virtual bool reopen(bool hasVisibleWindows) { return false; }
(...)

I can make a pull request if you find it useful.