Closed Bug 377166 Opened 19 years ago Closed 19 years ago

Mac applicationDockMenu delegate method not called after process restart

Categories

(Toolkit :: Startup and Profile System, defect)

x86
macOS
defect
Not set
normal

Tracking

()

RESOLVED FIXED

People

(Reporter: cbarrett, Assigned: smichaud)

References

Details

Attachments

(1 file, 1 obsolete file)

I'm having trouble determining exactly *what* the problem is, but I do know that when Firefox has to do a relaunch (e.g. the first time you run a fresh build), the App delegate is not getting set properly. http://mxr.mozilla.org/seamonkey/source/toolkit/xre/nsAppRunner.cpp#2866 That is where we're is currently calling out and setting the mac application delegate (it's used for installing ourselves as handlers to various Apple Events for opening files). I'm not entirely sure how this will manifest itself in a build a user would run (first run?).
Actually, in my tests the NSApp delegate does get set (correctly, on the second "bounce", to MacApplicationDelegate) when Firefox relaunches. And the applicationShouldTerminate: delegate method does get called (in my patch to bug 377506). But the applicationDockMenu: delegate method (which should get called every time Dock application menu is opened) _doesn't_ get called. Bug 364326 and bug 368336 only happen when Firefox relaunches, and appear to be caused by the above-mentioned problem with the applicationDockMenu: message. So this bug (377166) may block bugs 364326 and 368336. I haven't yet figured out why the applicationDockMenu: message doesn't get called when Firefox relaunches. But I have a couple more tricks up my sleeve, and will be spending the next couple of days trying to find out.
Attached patch Preliminary patch (hackish) (obsolete) — Splinter Review
Here's a preliminary patch that fixes this problem in my tests. But it's quite possible that I'll have to change it (and even change the module where I put it) before I'm done with it. I hope the reasons for this will become clear :-) The ultimate cause of this problem is an Apple design flaw: Apple has two sets of published APIs for programming Dock menus (one for Cocoa apps that uses the NSApplication delegate applicationDockMenu: method, and a more powerful one for Carbon apps that uses GetApplicationDockTileMenu() and SetApplicationDockTileMenu() (from the "Dock Manager Reference"), GetWindowDockTileMenu() and SetWindowDockTileMenu() (from the "Window Manager Reference") and the Carbon events kEventAppGetDockTileMenu and kEventWindowGetDockTileMenu (from the "Carbon Event Manager Reference")). But these two Dock APIs don't interoperate well (or possibly at all), you must "choose" one or the other, and the "choice" tends to be made in quite an arbitrary manner. Minefield as it now stands (using Cocoa widgets) normally "chooses" to use the Cocoa Dock API. But when Minefield restarts (and its Dock icon does the infamous double-bump or double-bounce), Minefield instead "chooses" the Carbon Dock API. As best I can tell, the "choice" is determined by "who" makes the first call to the following undocumented method (it's part of the totally undocumented CoreDock API, which is defined in the HIServices framework): long CoreDockRegisterClientWithRunLoop(CoreDockMessageProc inProc, void *inUserData, CFRunLoopRef inRunLoop); This method "registers" a callback (inProc) to receive CoreDock "messages" (which appear to mostly be related to Dock menus). The higher-level Cocoa and Carbon Dock APIs each have their own callback: CoreDockMessageProc _NSCoreDockMessageReceive; //AppKit framework CoreDockMessageProc DockCallback; //HIToolbox framework But, while CoreDockRegisterClientWithRunLoop() is always (in Cocoa-widget Minefield) called at least twice (once on behalf of each Dock API), only the first call has any effect. And (as far as I can tell) there's no way (documented or undocumented) to reset the "registered client" to NULL (so that the next call to CoreDockRegisterClientWithRunLoop() _would_ have an effect). So the "choice" depends entirely on "who" gets in the first call to CoreDockRegisterClientWithRunLoop(). Here are the two methods from which CoreDockRegisterClientWithRunLoop() normally gets called: BOOL _NSDoOneTimeDockRegistration(void); //AppKit, for Cocoa void _FirstEventTime(void); //HIToolbox, for Carbon As far as I can tell, _NSDoOneTimeDockRegistration() is only ever called from a Cocoa context (from [NSApplication _registerWithDock], which is in turn called on the first call to [NSApplication sharedApplication]). But _FirstEventTime() can be called from either a Carbon or a Cocoa context (e.g. [NSApplication nextEventMatchingMask]). Fortunately, usually the first thing you do in a Cocoa app is to call [NSApplication sharedApplication] (which does all kinds of needed initialization). My patch arranges that _NSDoOneTimeDockRegistration() is always called (from [NSApplication sharedApplication]) before _FirstEventTime(). But I'm not sure there aren't other ways that are more stable and predictable. I'll be looking for them. (I'll also try to find out why _NSDoOneTimeDockRegistration() doesn't get called first on the double-bump.)
I've just discovered that my "preliminary patch" (attachment 264184 [details] [diff] [review]) doesn't work in a shared build (a debug build) -- when a Minefield shared build restarts it still "chooses" the Carbon Dock API. It does work in a static build (so people can test with it). But it's clear that I will need to revise it.
Here's a better patch (hopefully the final one). It works in both a static build and a shared build. Looking through XRE_main() in toolkit/src/nsAppRunner.cpp, I discovered that, on relaunch, a call is made to ReceiveNextEvent(). This is one of the ways to invoke a call to _FirstEventTime(). And since it happens before the first call to [NSApplication sharedApplication], it causes the browser (on the second bump) to choose the "Carbon Dock API". I've fixed the problem by adding a call to [NSApplication sharedApplication] before the call to ReceiveNextEvent().
Attachment #264184 - Attachment is obsolete: true
Attachment #264246 - Flags: review?(joshmoz)
Summary: Mac application delegate not installed after process restart → Mac applicationDockMenu delegate method not called after process restart
Assignee: nobody → smichaud
Flags: blocking1.9+
Attachment #264246 - Flags: review?(joshmoz)
Attachment #264246 - Flags: review?(benjamin)
Attachment #264246 - Flags: review+
Comment on attachment 264246 [details] [diff] [review] Revised patch (hopefully final) Why do we need the MOZ_WIDGET_COCOA ifdef? IIUC, we only use cocoa widgets on trunk for macosx, so we don't need the ifdef.
Attachment #264246 - Flags: review?(benjamin) → review+
> Why do we need the MOZ_WIDGET_COCOA ifdef? To be consistent with the rest of nsAppRunner.cpp -- it's used in a couple of other places in this file.
>> Why do we need the MOZ_WIDGET_COCOA ifdef? > > To be consistent with the rest of nsAppRunner.cpp -- it's used in a > couple of other places in this file. Though it's true that my patch is the only place a MOZ_WIDGET_COCOA ifdef is used inside an XP_MACOSX ifdef. So then ... should I keep the MOZ_WIDGET_COCOA ifdef or get rid of it?
landed on trunk without the MOZ_WIDGET_COCOA stuff
Status: NEW → RESOLVED
Closed: 19 years ago
Resolution: --- → FIXED
I am trying to launch instances of Firefox that I have built from the command-line. Even after checking out this morning, I am still seeing this problem. The symptoms are that I launch in Terminal, and 1) sometimes I do not get a window or a Dock icon 2) other times I do get a window, but I do not get a Dock icon and the browser will not accept key press events and the menu reflects Terminal, not Minefield. I can start FF 2.0.0.3 on the command line and it works fine. Are you all sure you are done with this bug?
I often start Minefield from the command line, and I've never had anything like the trouble you describe. But I always make the distro's Contents/MacOS directory the current directory, and run "./firefox". Do you do things differently?
I do this all the time as well, ./objdir/dist/MinefieldDebug.app/Contents/MacOS/firefox Is there another bug for what you're seeing, Ray, with full steps to reduce?
I cannot believe how stupid this was. Or I was, perhaps. My script was launching Firefox with: /Users/ray/mo/trowser/mozilla/dist/Minefield.app/Contents/Macos/firefox This launches Firefox, because HFS+ is case-insensitive file system, but it does not set up the menus and messes up the app. Launching with this works: /Users/ray/mo/trowser/mozilla/dist/Minefield.app/Contents/MacOS/firefox
Component: XRE Startup → Startup and Profile System
QA Contact: xre.startup → startup
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: