From b70b015d8e93070f8cfb10b42f444ed478c185a8 Mon Sep 17 00:00:00 2001 From: das Date: Thu, 8 Nov 2007 14:26:50 +0000 Subject: * macosx/tkMacOSXCarbonEvents.c (InstallStandardApplicationEventHandler): on Mac OS X Leopard, replace the 2005-11-27 approach of installing the standard application handler by calling RAEL and immediately longjmping out of it from an event handler, as that now leads to crashes in -[NSView unlockFocus] whenever HIToolbox uses Cocoa in Leopard (Help menu, Nav Services, Color Picker). Instead call InstallStandardEventHandler() on the application and menubar event targets, as Leopard ISEH finally handles these correctly. Unfortunately need a HIToolbox-internal SPI to retrieve the menubar event target, no public API appears have that functionality. --- ChangeLog | 55 +++++++++++++++ macosx/tkMacOSXCarbonEvents.c | 154 ++++++++++++++++++++++++++---------------- 2 files changed, 150 insertions(+), 59 deletions(-) diff --git a/ChangeLog b/ChangeLog index e0b5295..7a2c84d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,58 @@ +2007-11-09 Daniel Steffen + + * macosx/tkMacOSXCarbonEvents.c + (InstallStandardApplicationEventHandler): on Mac OS X Leopard, replace + the 2005-11-27 approach of installing the standard application handler + by calling RAEL and immediately longjmping out of it from an event + handler, as that now leads to crashes in -[NSView unlockFocus] whenever + HIToolbox uses Cocoa in Leopard (Help menu, Nav Services, Color + Picker). Instead call InstallStandardEventHandler() on the application + and menubar event targets, as Leopard ISEH finally handles these + correctly. Unfortunately need a HIToolbox-internal SPI to retrieve the + menubar event target, no public API appears have that functionality. + + * macosx/tkMacOSXDebug.c: make TkMacOSXInitNamedDebugSymbol() + * macosx/tkMacOSXDebug.h: available outside of debug builds as + the new Leopard ISAEH needs it. + + * macosx/tkMacOSXButton.c: replace HiliteControl() by modern API + * macosx/tkMacOSXMenubutton.c: for activation and enabling; + distinguish inactive and disabled + look&feel; correct activation handling + to match that of container toplevel. + + * macosx/tkMacOSXMenubutton.c: correct size computation of bevelbutton + variant to match that of buttons; + fix crash with bitmap due to NULL GC; + delay picParams setup until needed; + formatting cleanup. [Bug 1824521] + + * library/menu.tcl: correct handling of menubutton "active" + state on Aqua to match that of buttons. + + * macosx/tkMacOSXDefault.h: correct button & menubutton active + foreground and background colors and + menubutton border width. + + * macosx/tkMacOSXWindowEvent.c: handle kEventWindowExpanding carbon + * macosx/tkMacOSXCarbonEvents.c: event instead of kEventWindowExpanded + to ensure activate event arrives after + window is remapped, also need to + process all Tk events generated by + remapping in the event handler to + ensure children are remapped before + activate event is processed. + + * macosx/tkMacOSXSubwindows.c: add pixmap size field to MacDrawable + * macosx/tkMacOSXInt.h: struct; add flag for B&W pixmaps. + * macosx/tkMacOSXDraw.c: + * macosx/tkMacOSXEmbed.c: + * macosx/tkMacOSXMenu.c: + + * macosx/tkMacOSXPrivate.h: correct Leopard HIToolboxVersionNumber. + + * macosx/ttkMacOSXTheme.c: add error checking; cleanup formatting. + 2007-11-07 Joe English * generic/ttk/ttkTheme.c(Ttk_ElementSize): Fixed longstanding, diff --git a/macosx/tkMacOSXCarbonEvents.c b/macosx/tkMacOSXCarbonEvents.c index 6b28cf3..65b792e 100644 --- a/macosx/tkMacOSXCarbonEvents.c +++ b/macosx/tkMacOSXCarbonEvents.c @@ -60,7 +60,7 @@ * software in accordance with the terms specified in this * license. * - * RCS: @(#) $Id: tkMacOSXCarbonEvents.c,v 1.17 2007/06/29 03:20:00 das Exp $ + * RCS: @(#) $Id: tkMacOSXCarbonEvents.c,v 1.18 2007/11/08 14:26:50 das Exp $ */ #include "tkMacOSXPrivate.h" @@ -80,21 +80,28 @@ static OSStatus CarbonEventHandlerProc(EventHandlerCallRef callRef, EventRef event, void *userData); static OSStatus InstallStandardApplicationEventHandler(void); -static void ExitRaelEventHandlerProc(EventHandlerCallRef callRef, - EventRef event, void *userData) __attribute__ ((__noreturn__)); static void CarbonTimerProc(EventLoopTimerRef timer, void *userData); /* * Static data used by several functions in this file: */ -static jmp_buf exitRaelJmpBuf; static EventLoopTimerRef carbonTimer = NULL; static int carbonTimerEnabled = 0; static EventHandlerUPP carbonEventHandlerUPP = NULL; static Tcl_Interp *carbonEventInterp = NULL; static int inTrackingLoop = 0; +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1050 +/* + * For InstallStandardApplicationEventHandler(): + */ + +static jmp_buf exitRaelJmpBuf; +static void ExitRaelEventHandlerProc(EventHandlerCallRef callRef, + EventRef event, void *userData) __attribute__ ((__noreturn__)); +#endif + /* *---------------------------------------------------------------------- @@ -130,8 +137,9 @@ CarbonEventHandlerProc( bzero(&eventStatus, sizeof(eventStatus)); #ifdef TK_MAC_DEBUG_CARBON_EVENTS - if (macEvent.eKind != kEventMouseMoved && - macEvent.eKind != kEventMouseDragged) { + if (!(macEvent.eClass == kEventClassMouse && ( + macEvent.eKind == kEventMouseMoved || + macEvent.eKind == kEventMouseDragged))) { TkMacOSXDbgMsg("Started handling %s", TkMacOSXCarbonEventToAscii(event)); TkMacOSXInitNamedDebugSymbol(HIToolbox, void, _DebugPrintEvent, @@ -249,7 +257,7 @@ TkMacOSXInitCarbonEvents( _TraceEventByName(CFSTR("kEventWindowActivated")); _TraceEventByName(CFSTR("kEventWindowDeactivated")); _TraceEventByName(CFSTR("kEventWindowUpdate")); - _TraceEventByName(CFSTR("kEventWindowExpanded")); + _TraceEventByName(CFSTR("kEventWindowExpanding")); _TraceEventByName(CFSTR("kEventWindowBoundsChanged")); _TraceEventByName(CFSTR("kEventWindowDragStarted")); _TraceEventByName(CFSTR("kEventWindowDragCompleted")); @@ -289,7 +297,7 @@ TkMacOSXInstallWindowCarbonEventHandler( {kEventClassWindow, kEventWindowActivated}, {kEventClassWindow, kEventWindowDeactivated}, {kEventClassWindow, kEventWindowUpdate}, - {kEventClassWindow, kEventWindowExpanded}, + {kEventClassWindow, kEventWindowExpanding}, {kEventClassWindow, kEventWindowBoundsChanged}, {kEventClassWindow, kEventWindowDragStarted}, {kEventClassWindow, kEventWindowDragCompleted}, @@ -324,65 +332,92 @@ TkMacOSXInstallWindowCarbonEventHandler( static OSStatus InstallStandardApplicationEventHandler(void) { - /* - * This is a hack to workaround missing Carbon API to install the standard - * application event handler (InstallStandardEventHandler() does not work - * on the application target). The only way to install the standard app - * handler is to call RunApplicationEventLoop(), but since we are running - * our own event loop, we'll immediately need to break out of RAEL again: - * we do this via longjmp out of the ExitRaelEventHandlerProc event handler - * called first off from RAEL by posting a high priority dummy event. - * This workaround is derived from a similar approach in Technical Q&A 1061. - */ - enum { - kExitRaelEvent = 'ExiT' - }; - const EventTypeSpec exitRaelEventType = { - kExitRaelEvent, kExitRaelEvent - }; - EventHandlerUPP exitRaelEventHandler; - EventHandlerRef exitRaelEventHandlerRef = NULL; - EventRef exitRaelEvent = NULL; OSStatus err = memFullErr; - exitRaelEventHandler = NewEventHandlerUPP( - (EventHandlerProcPtr) ExitRaelEventHandlerProc); - if (exitRaelEventHandler) { - err = ChkErr(InstallEventHandler, GetEventDispatcherTarget(), - exitRaelEventHandler, 1, &exitRaelEventType, NULL, - &exitRaelEventHandlerRef); - } - if (err == noErr) { - err = ChkErr(CreateEvent, NULL, kExitRaelEvent, kExitRaelEvent, - GetCurrentEventTime(), kEventAttributeNone, &exitRaelEvent); - } - if (err == noErr) { - err = ChkErr(PostEventToQueue, GetMainEventQueue(), exitRaelEvent, - kEventPriorityHigh); - } - if (err == noErr) { - if (!setjmp(exitRaelJmpBuf)) { - RunApplicationEventLoop(); + TK_IF_HI_TOOLBOX(5, + /* + * The approach below does not work correctly in Leopard, it leads to + * crashes in [NSView unlockFocus] whenever HIToolbox uses Cocoa (Help + * menu, Nav Services, Color Picker). While it is now possible to + * install the standard app handler with InstallStandardEventHandler(), + * to fully replicate RAEL the standard menubar event handler also needs + * to be installed. Unfortunately there appears to be no public API to + * obtain the menubar event target. As a workaround, for now we resort + * to calling the HIToolbox-internal GetMenuBarEventTarget() directly + * (symbol acquired via TkMacOSXInitNamedDebugSymbol() from HIToolbox + * version 343, may not exist in later versions). + */ + err = ChkErr(InstallStandardEventHandler, GetApplicationEventTarget()); + TkMacOSXInitNamedDebugSymbol(HIToolbox, EventTargetRef, + GetMenuBarEventTarget, void); + if (GetMenuBarEventTarget) { + ChkErr(InstallStandardEventHandler, GetMenuBarEventTarget()); + } else { + TkMacOSXDbgMsg("Unable to install standard menubar event handler"); + } + ) TK_ELSE_HI_TOOLBOX (5, + /* + * This is a hack to workaround missing Carbon API to install the + * standard application event handler (InstallStandardEventHandler() + * does not work on the application target). The only way to install the + * standard app handler is to call RunApplicationEventLoop(), but since + * we are running our own event loop, we'll immediately need to break + * out of RAEL again: we do this via longjmp out of the + * ExitRaelEventHandlerProc event handler called first off from RAEL by + * posting a high priority dummy event. This workaround is derived from + * a similar approach in Technical Q&A 1061. + */ + enum { + kExitRaelEvent = 'ExiT' + }; + const EventTypeSpec exitRaelEventType = { + kExitRaelEvent, kExitRaelEvent + }; + EventHandlerUPP exitRaelEventHandler; + EventHandlerRef exitRaelEventHandlerRef = NULL; + EventRef exitRaelEvent = NULL; + + exitRaelEventHandler = NewEventHandlerUPP( + (EventHandlerProcPtr) ExitRaelEventHandlerProc); + if (exitRaelEventHandler) { + err = ChkErr(InstallEventHandler, GetEventDispatcherTarget(), + exitRaelEventHandler, 1, &exitRaelEventType, NULL, + &exitRaelEventHandlerRef); + } + if (err == noErr) { + err = ChkErr(CreateEvent, NULL, kExitRaelEvent, kExitRaelEvent, + GetCurrentEventTime(), kEventAttributeNone, + &exitRaelEvent); + } + if (err == noErr) { + err = ChkErr(PostEventToQueue, GetMainEventQueue(), exitRaelEvent, + kEventPriorityHigh); + } + if (err == noErr) { + if (!setjmp(exitRaelJmpBuf)) { + RunApplicationEventLoop(); - /* - * This point should never be reached! - */ + /* + * This point should never be reached! + */ - Tcl_Panic("RunApplicationEventLoop exited !"); + Tcl_Panic("RunApplicationEventLoop exited !"); + } } - } - if (exitRaelEvent) { - ReleaseEvent(exitRaelEvent); - } - if (exitRaelEventHandlerRef) { - RemoveEventHandler(exitRaelEventHandlerRef); - } - if (exitRaelEventHandler) { - DisposeEventHandlerUPP(exitRaelEventHandler); - } + if (exitRaelEvent) { + ReleaseEvent(exitRaelEvent); + } + if (exitRaelEventHandlerRef) { + RemoveEventHandler(exitRaelEventHandlerRef); + } + if (exitRaelEventHandler) { + DisposeEventHandlerUPP(exitRaelEventHandler); + } + ) TK_ENDIF return err; } +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1050 /* *---------------------------------------------------------------------- * @@ -409,6 +444,7 @@ ExitRaelEventHandlerProc( { longjmp(exitRaelJmpBuf, 1); } +#endif /* *---------------------------------------------------------------------- -- cgit v0.12