May 06, 2003
Fixing OS X Bugs With APE

Any of you using the Silk betas (it's at b3 now), or possibly WSX or another haxie that flashes the screen and shows a registration reminder might have seen a white box appear where the reminder appears in some Cocoa applications. It seems to appear as soon as the Cocoa application is ready to start processing events and the window is still on screen which is probably it happens so infrequently in other haxies and so much more often in Silk since I show it when the menu bar is ready. The window that shows the pretty icon and the text is a Carbon WindowRef with the class kOverlayWindowClass. I've tracked this "white" problem down to what seems to be a bug in Cocoa's handling of Carbon windows introduced in 10.2.

Cocoa's event loop does not support the Carbon event loop so Apple designed what seems to be an abstraction layer in Mac OS X 10.2. It's a really well designed layer it seems and it allows you to use pretty much all of Carbon in Cocoa applications although the above documentation doesn't seem to list the caveats of using the layer. Other than the quirk above and maybe another one. I'm not sure if I can begin a CGContext on a window that isn't on screen in Carbon. Anyways, this abstraction level places Carbon items into Cocoa class "wrappers". In the case of a Carbon window the class is question is oddly enough named NSCarbonWindow (where do they come up with these obscure names?). This class has a method called display that seems to set the clip area, and the visible area of the window and then if the windows have any handlers on it for updating the contents of the window, it calls them. The problem is that before it calls the handler, it ERASES the contents of the window.

I don't remember giving Cocoa permission to update the contents of the window. I've even passed kWindowNoUpdatesAttribute, kWindowNoActivatesAttribute, and kWindowOpaqueForEventsAttribute (which the documentation for on Apple's site is wrong since it says a window with that attribute set receives no events) separately and together and it still erases my window. For some reason -display is calling EraseWindowRegion() before it calls the event handlers. As far as I can tell, Carbon does not do this. Armed with the cause of the problem and the ASM dump of -display I created a patch with APE for -[NSCarbonWindow display]. From within my patch of -[NSCarbonWindow display] I set a patch on EraseWindowRegion and SendEventToEventTarget then call the original. When EraseWindowRegion is called I just return noErr in my patch. Then when SendEventToEventTarget is called I remove the patch for EraseWindowRegion and SendEventToEventTarget so that I don't get called if the real event handler wants to call either of those functions. After the real -[NSCarbonWindow display] is called I make sure both of my other patches are removed and if they aren't I remove them from there. I really do not want to do anything other than fix this "bug".

This method works perfectly and stops the "white" bug from appearing. At least I assume this is a bug. It seems to have no side effects whatsoever. This is a perfect example of APE fixing a bug in someone else's software. This is also a very good use of APE Lite. I'm not sure what our licensing policy is on licensing APE Lite to those that need to fix bugs in Mac OS X from their own application.

Digg This!

 Posted by rosyna at May 06, 2003 02:09 PM

Trackback Pings:

TrackBack URL for this entry:
http://www.unsanity.org/mt-tb.cgi/86.




Related:
Comments

I'm not sure what our licensing policy is on licensing APE Lite to those that need to fix bugs in Mac OS X from their own application.

Posted by: Jason L. on May 6, 2003 4:23 PM

Hurray! Youre back in business again, and I was almost starting to get worried about you being bought out by Bungie or something....

Posted by: Andreas Tellefsen on May 6, 2003 5:23 PM
Post a comment
Keep comments on topic. If a comment is unrelated to this post, it may be removed or moderated.





Remember Me?

(you may use HTML tags for style)