Main Quit item in Cocoa


#1

In the new Cocoa version, there seems to be a quit menu item in the File menu, which does work, and a main Quit item in the App menu, which does not.

Bruce


#2

yes… I’m currently stuck on that bug.

The only way to add things to the app menu is via an undocumented “setAppleMenu” method, but it behaves in a very bizarre way. Depending on the order in which you create or populate the menu, the OS sometimes adds its own set of standard items to you app menu, in which case your own items work, but the ones it has added don’t work. As I’ve got it now, it doesn’t add its own items, but the ones on there don’t work (???). I’ve wasted a lot of time messing about with this one, and am getting short of ideas…


#3

I’ve got NSApplicationLoad() commented out in mac_systemStats as its no longer a carbon “app” and doesn’t need it anymore from what I can tell.

Seems to have cleared the problem up for me :smiley:


#4

This is a real pain.

It’s actually more subtle - it depends on the order in which things get initialised. So if you do this:

NSApplicationLoad(); [NSApplication sharedApplication];

then the menus don’t work. But if you do this:

[NSApplication sharedApplication]; NSApplicationLoad();

then the menus work, but if you have a carbon window (e.g. in a plugin) then it doesn’t get any events.

…so I’m basically stumped. I can fix it so that the menus work, but the audio plugin hosting app won’t be able to run correctly…


#5

[quote=“jules”]then the menus don’t work. But if you do this:

[NSApplication sharedApplication]; NSApplicationLoad();

then the menus work, but if you have a carbon window (e.g. in a plugin) then it doesn’t get any events.

…so I’m basically stumped. I can fix it so that the menus work, but the audio plugin hosting app won’t be able to run correctly…[/quote]
I just ran into this using the plugin host app. My plugin UI wasn’t get drawing events properly and wasn’t drawing at all. It doesn’t seem to affect all plugins; I suspect it has to do with the particular UI code used in the plugin. I’m using a Carbon custom control with an event handler.

Any progress on this? I was able to get the plugin UI to work by calling NSApplicationLoad() first, but then as you say the Apple menu items don’t work correctly.


#6

So… I had an Apple DTS incident that was about to expire, so I burned it on this issue (you’re welcome :)). And they came through with a fix for the issue!

Basically, only Carbon apps should call NSApplicationLoad(), in order to support Cocoa windows. It shouldn’t be called from a Cocoa app. So the fact that it was “fixing” the Carbon drawing issue was a happy accident - with side effects, like the duplicate items in the application menu.

The fix is a change to CarbonViewWrapperComponent::timerCallback() in juce_mac_CarbonViewWrapperComponent.h (lives at src/native/mac/ in the trunk; it’s at build/macosx/platform_specific_code/ in version 1.50).

Here’s the original code:

void timerCallback()
{
	setOurSizeToEmbeddedViewSize();

	// To avoid strange overpainting problems when the UI is first opened, we'll
	// repaint it a few times during the first second that it's on-screen..
	if ((Time::getCurrentTime() - creationTime).inMilliseconds() < 1000)
		HIViewSetNeedsDisplay (embeddedView, true);
}

The fix is to also call HIViewSetNeedsDisplay() on embedded sub-views:

void timerCallback()
{
	setOurSizeToEmbeddedViewSize();

	// To avoid strange overpainting problems when the UI is first opened, we'll
	// repaint it a few times during the first second that it's on-screen..
	if ((Time::getCurrentTime() - creationTime).inMilliseconds() < 1000)
	{
		HIViewSetNeedsDisplay (embeddedView, true);

		// Here's the fix.  Call HIViewSetNeedsDisplay() on embedded sub-views.
	#if 1
		HIViewRef rootHIViewRef = HIViewGetRoot(wrapperWindow);
		#define kMaxHIViewDepth 10
		HIViewRef subHIViewRefs[kMaxHIViewDepth];
		int depth = 0;
		subHIViewRefs[depth] = HIViewGetFirstSubview(rootHIViewRef);
		while ( depth >= 0) {
			while (subHIViewRefs[depth]) {
				HIViewSetNeedsDisplay(subHIViewRefs[depth], YES);
				HIViewRef subHIViewRef = HIViewGetFirstSubview(subHIViewRefs[depth]);
				if ( subHIViewRef ) {
					depth++;
				}
				subHIViewRefs[depth] = subHIViewRef;
			}
			depth--;
			subHIViewRefs[depth] = HIViewGetNextView(subHIViewRefs[depth]);
		}
	#endif
	}
}

(Obviously you need to update the amalgamated file if you’re using that…)

This could probably be cleaned up, but I basically just copied the code from DTS and tried it out, and it works. Looking at this function more, it looks like it’s already a workaround for a weird drawing issue, so maybe this “fix for the workaround” sheds some light on the core problem. I definitely do notice a bit of flickering as that UI is initially displayed from all the redrawing.


#7

Excellent - thanks Jim, that’s very interesting!

What a convoluted way of writing it though… I’d have just done this:

[code] static void recursiveHIViewRepaint (HIViewRef view) throw()
{
HIViewSetNeedsDisplay (view, true);
HIViewRef child = HIViewGetFirstSubview (view);

    while (child != 0)
    {
        recursiveHIViewRepaint (child);
        child = HIViewGetNextView (child);
    }
}

void timerCallback()
{
    setOurSizeToEmbeddedViewSize();

    // To avoid strange overpainting problems when the UI is first opened, we'll
    // repaint it a few times during the first second that it's on-screen..
    if ((Time::getCurrentTime() - creationTime).inMilliseconds() < 1000)
        recursiveHIViewRepaint (HIViewGetRoot (wrapperWindow));
}[/code]

(presumably the line HIViewSetNeedsDisplay (embeddedView, true) is redundant if you’re updating the whole tree)

I’d have liked to know what the actual bug/problem really is, but Apple people probably get shot if they disclose that sort of information…


#8

Nice one, Jim!

Jules: does this mean we’ll be able to put e.g. About/Preferences menu items on the main App menu at some point down the road?

Pete


#9

You’ve been able to do that in a normal app for ages - this problem only applied when you app was hosting carbon plugins.


#10

Sorry, I hadn’t realised.

I can see it there in setMacMainMenu … via extraAppleMenuItems

Good stuff. :slight_smile:

Best wishes,

Pete