diff options
-rw-r--r-- | macosx/tkMacOSXCarbonEvents.c | 690 |
1 files changed, 0 insertions, 690 deletions
diff --git a/macosx/tkMacOSXCarbonEvents.c b/macosx/tkMacOSXCarbonEvents.c deleted file mode 100644 index e5803f5..0000000 --- a/macosx/tkMacOSXCarbonEvents.c +++ /dev/null @@ -1,690 +0,0 @@ -/* - * tkMacOSXCarbonEvents.c -- - * - * This file implements functions that register for and handle - * various Carbon Events and Timers. Most carbon events of interest - * to TkAqua are processed in a handler registered on the dispatcher - * event target so that we get first crack at them before HIToolbox - * dispatchers/processes them further. - * As some events are sent directly to the focus or app event target - * and not dispatched normally, we also register a handler on the - * application event target. - * - * Copyright 2001, Apple Computer, Inc. - * Copyright (c) 2005-2008 Daniel A. Steffen <das@users.sourceforge.net> - * - * See the file "license.terms" for information on usage and redistribution of - * this file, and for a DISCLAIMER OF ALL WARRANTIES. - * - * The following terms apply to all files originating from Apple - * Computer, Inc. ("Apple") and associated with the software - * unless explicitly disclaimed in individual files. - * - * - * Apple hereby grants permission to use, copy, modify, - * distribute, and license this software and its documentation - * for any purpose, provided that existing copyright notices are - * retained in all copies and that this notice is included - * verbatim in any distributions. No written agreement, license, - * or royalty fee is required for any of the authorized - * uses. Modifications to this software may be copyrighted by - * their authors and need not follow the licensing terms - * described here, provided that the new terms are clearly - * indicated on the first page of each file where they apply. - * - * - * IN NO EVENT SHALL APPLE, THE AUTHORS OR DISTRIBUTORS OF THE - * SOFTWARE BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, - * INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF - * THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, - * EVEN IF APPLE OR THE AUTHORS HAVE BEEN ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. APPLE, THE AUTHORS AND - * DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS - * SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND APPLE,THE - * AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE - * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - * - * GOVERNMENT USE: If you are acquiring this software on behalf - * of the U.S. government, the Government shall have only - * "Restricted Rights" in the software and related documentation - * as defined in the Federal Acquisition Regulations (FARs) in - * Clause 52.227.19 (c) (2). If you are acquiring the software - * on behalf of the Department of Defense, the software shall be - * classified as "Commercial Computer Software" and the - * Government shall have only "Restricted Rights" as defined in - * Clause 252.227-7013 (c) (1) of DFARs. Notwithstanding the - * foregoing, the authors grant the U.S. Government and others - * acting in its behalf permission to use and distribute the - * software in accordance with the terms specified in this - * license. - */ - -#include "tkMacOSXPrivate.h" -#include "tkMacOSXEvent.h" -#include "tkMacOSXDebug.h" - -/* -#ifdef TK_MAC_DEBUG -#define TK_MAC_DEBUG_CARBON_EVENTS -#endif -*/ - -/* - * Declarations of functions used only in this file: - */ - -static OSStatus CarbonEventHandlerProc(EventHandlerCallRef callRef, - EventRef event, void *userData); -static OSStatus InstallStandardApplicationEventHandler(void); -static void CarbonTimerProc(EventLoopTimerRef timer, void *userData); - -/* - * Static data used by several functions in this file: - */ - -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 - - -/* - *---------------------------------------------------------------------- - * - * CarbonEventHandlerProc -- - * - * This procedure is the handler for all registered CarbonEvents. - * - * Results: - * OS status code. - * - * Side effects: - * Dispatches CarbonEvents. - * - *---------------------------------------------------------------------- - */ - -static OSStatus -CarbonEventHandlerProc( - EventHandlerCallRef callRef, - EventRef event, - void *userData) -{ - OSStatus err = eventNotHandledErr; - TkMacOSXEvent macEvent; - MacEventStatus eventStatus; - - macEvent.eventRef = event; - macEvent.eClass = GetEventClass(event); - macEvent.eKind = GetEventKind(event); - macEvent.interp = (Tcl_Interp *) userData; - macEvent.callRef = callRef; - bzero(&eventStatus, sizeof(eventStatus)); - -#ifdef TK_MAC_DEBUG_CARBON_EVENTS - if (!(macEvent.eClass == kEventClassMouse && ( - macEvent.eKind == kEventMouseMoved || - macEvent.eKind == kEventMouseDragged))) { - TkMacOSXDbgMsg("Started handling %s", - TkMacOSXCarbonEventToAscii(event)); - TkMacOSXInitNamedDebugSymbol(HIToolbox, void, _DebugPrintEvent, - EventRef inEvent); - if (_DebugPrintEvent) { - /* - * Carbon-internal event debugging (c.f. Technote 2124) - */ - - _DebugPrintEvent(event); - } - } -#endif /* TK_MAC_DEBUG_CARBON_EVENTS */ - - TkMacOSXProcessEvent(&macEvent,&eventStatus); - if (eventStatus.stopProcessing) { - err = noErr; - } - -#ifdef TK_MAC_DEBUG_CARBON_EVENTS - if (macEvent.eKind != kEventMouseMoved && - macEvent.eKind != kEventMouseDragged) { - TkMacOSXDbgMsg("Finished handling %s: %s handled", - TkMacOSXCarbonEventToAscii(event), - eventStatus.stopProcessing ? " " : "not"); - } -#endif /* TK_MAC_DEBUG_CARBON_EVENTS */ - return err; -} - -/* - *---------------------------------------------------------------------- - * - * TkMacOSXInitCarbonEvents -- - * - * This procedure initializes all CarbonEvent handlers. - * - * Results: - * None. - * - * Side effects: - * Handlers for Carbon Events are registered. - * - *---------------------------------------------------------------------- - */ - -MODULE_SCOPE void -TkMacOSXInitCarbonEvents( - Tcl_Interp *interp) -{ - const EventTypeSpec dispatcherEventTypes[] = { - {kEventClassKeyboard, kEventRawKeyDown}, - {kEventClassKeyboard, kEventRawKeyRepeat}, - {kEventClassKeyboard, kEventRawKeyUp}, - {kEventClassKeyboard, kEventRawKeyModifiersChanged}, - {kEventClassKeyboard, kEventRawKeyRepeat}, - }; - const EventTypeSpec applicationEventTypes[] = { - {kEventClassMenu, kEventMenuBeginTracking}, - {kEventClassMenu, kEventMenuEndTracking}, - {kEventClassMenu, kEventMenuOpening}, - {kEventClassMenu, kEventMenuTargetItem}, - {kEventClassCommand, kEventCommandProcess}, - {kEventClassCommand, kEventCommandUpdateStatus}, - {kEventClassApplication, kEventAppActivated}, - {kEventClassApplication, kEventAppDeactivated}, - {kEventClassApplication, kEventAppQuit}, - {kEventClassApplication, kEventAppHidden}, - {kEventClassApplication, kEventAppShown}, - {kEventClassApplication, kEventAppAvailableWindowBoundsChanged}, - {kEventClassAppearance, kEventAppearanceScrollBarVariantChanged}, - }; - - carbonEventHandlerUPP = NewEventHandlerUPP(CarbonEventHandlerProc); - carbonEventInterp = interp; - ChkErr(InstallStandardApplicationEventHandler); - ChkErr(InstallEventHandler, GetEventDispatcherTarget(), - carbonEventHandlerUPP, GetEventTypeCount(dispatcherEventTypes), - dispatcherEventTypes, (void *) carbonEventInterp, NULL); - ChkErr(InstallEventHandler, GetApplicationEventTarget(), - carbonEventHandlerUPP, GetEventTypeCount(applicationEventTypes), - applicationEventTypes, (void *) carbonEventInterp, NULL); - -#ifdef TK_MAC_DEBUG_CARBON_EVENTS - TkMacOSXInitNamedSymbol(HIToolbox, void, DebugTraceEvent, OSType, UInt32, - Boolean); - if (DebugTraceEvent) { - unsigned int i; - const EventTypeSpec *e; - - for (i = 0, e = dispatcherEventTypes; - i < GetEventTypeCount(dispatcherEventTypes); i++, e++) { - DebugTraceEvent(e->eventClass, e->eventKind, 1); - } - for (i = 0, e = applicationEventTypes; - i < GetEventTypeCount(applicationEventTypes); i++, e++) { - DebugTraceEvent(e->eventClass, e->eventKind, 1); - } - DebugTraceEvent = NULL; /* Only enable tracing once. */ - } -#endif /* TK_MAC_DEBUG_CARBON_EVENTS */ -} - -/* - *---------------------------------------------------------------------- - * - * TkMacOSXInstallWindowCarbonEventHandler -- - * - * This procedure installs our window CarbonEvent handler. - * - * Results: - * None. - * - * Side effects: - * Handler for Carbon Events is registered. - * - *---------------------------------------------------------------------- - */ - -MODULE_SCOPE void -TkMacOSXInstallWindowCarbonEventHandler( - Tcl_Interp *interp, WindowRef window) -{ - const EventTypeSpec windowEventTypes[] = { - {kEventClassMouse, kEventMouseDown}, - {kEventClassMouse, kEventMouseUp}, - {kEventClassMouse, kEventMouseMoved}, - {kEventClassMouse, kEventMouseDragged}, - {kEventClassMouse, kEventMouseWheelMoved}, - {kEventClassWindow, kEventWindowActivated}, - {kEventClassWindow, kEventWindowDeactivated}, - {kEventClassWindow, kEventWindowUpdate}, - {kEventClassWindow, kEventWindowExpanding}, - {kEventClassWindow, kEventWindowBoundsChanged}, - {kEventClassWindow, kEventWindowDragStarted}, - {kEventClassWindow, kEventWindowDragCompleted}, - {kEventClassWindow, kEventWindowConstrain}, - {kEventClassWindow, kEventWindowGetRegion}, - {kEventClassWindow, kEventWindowDrawContent}, - }; - - ChkErr(InstallEventHandler, GetWindowEventTarget(window), - carbonEventHandlerUPP, GetEventTypeCount(windowEventTypes), - windowEventTypes, (void *) (interp ? interp : carbonEventInterp), - NULL); - -#ifdef TK_MAC_DEBUG_CARBON_EVENTS - TkMacOSXInitNamedSymbol(HIToolbox, void, DebugTraceEvent, OSType, UInt32, - Boolean); - if (DebugTraceEvent) { - unsigned int i; - const EventTypeSpec *e; - - for (i = 0, e = windowEventTypes; - i < GetEventTypeCount(windowEventTypes); i++, e++) { - if (!(e->eventClass == kEventClassMouse && ( - e->eventKind == kEventMouseMoved || - e->eventKind == kEventMouseDragged))) { - DebugTraceEvent(e->eventClass, e->eventKind, 1); - } - } - } -#endif /* TK_MAC_DEBUG_CARBON_EVENTS */ -} - -/* - *---------------------------------------------------------------------- - * - * InstallStandardApplicationEventHandler -- - * - * This procedure installs the carbon standard application event - * handler. - * - * Results: - * OS status code. - * - * Side effects: - * Standard handlers for application Carbon Events are registered. - * - *---------------------------------------------------------------------- - */ - -static OSStatus -InstallStandardApplicationEventHandler(void) -{ - OSStatus err = memFullErr; - - 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 TkMacOSXInitNamedSymbol() from HIToolbox - * version 343, may not exist in later versions). - */ - err = ChkErr(InstallStandardEventHandler, GetApplicationEventTarget()); - TkMacOSXInitNamedSymbol(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! - */ - - Tcl_Panic("RunApplicationEventLoop exited !"); - } - } - if (exitRaelEvent) { - ReleaseEvent(exitRaelEvent); - } - if (exitRaelEventHandlerRef) { - RemoveEventHandler(exitRaelEventHandlerRef); - } - if (exitRaelEventHandler) { - DisposeEventHandlerUPP(exitRaelEventHandler); - } - ) TK_ENDIF - return err; -} - -#if MAC_OS_X_VERSION_MIN_REQUIRED < 1050 -/* - *---------------------------------------------------------------------- - * - * ExitRaelEventHandlerProc -- - * - * This procedure is the dummy event handler used to break out of - * RAEL via longjmp, it is called as the first ever event handler - * in RAEL by posting a high priority dummy event. - * - * Results: - * None. Never returns ! - * - * Side effects: - * longjmp back to InstallStandardApplicationEventHandler(). - * - *---------------------------------------------------------------------- - */ - -static void -ExitRaelEventHandlerProc( - EventHandlerCallRef callRef, - EventRef event, - void *userData) -{ - longjmp(exitRaelJmpBuf, 1); -} -#endif - -/* - *---------------------------------------------------------------------- - * - * TkMacOSXRunTclEventLoop -- - * - * Process a limited number of tcl events. - * - * Results: - * Returns 1 if events were handled and 0 otherwise. - * - * Side effects: - * Runs the Tcl event loop. - * - *---------------------------------------------------------------------- - */ - -MODULE_SCOPE int -TkMacOSXRunTclEventLoop(void) -{ - int i = 4, result = 0; - - /* Avoid starving main event loop: process at most 4 events. */ - while(--i && Tcl_ServiceAll()) { - result = 1; - } - return result; -} - -/* - *---------------------------------------------------------------------- - * - * CarbonTimerProc -- - * - * This procedure is the carbon timer handler that runs the tcl - * event loop periodically. - * - * Results: - * None. - * - * Side effects: - * Runs the Tcl event loop. - * - *---------------------------------------------------------------------- - */ - -static void -CarbonTimerProc( - EventLoopTimerRef timer, - void *userData) -{ - if(carbonTimerEnabled > 0 && TkMacOSXRunTclEventLoop()) { -#ifdef TK_MAC_DEBUG_CARBON_EVENTS - TkMacOSXDbgMsg("Processed tcl events from carbon timer"); -#endif /* TK_MAC_DEBUG_CARBON_EVENTS */ - } -} - -/* - *---------------------------------------------------------------------- - * - * TkMacOSXStartTclEventLoopCarbonTimer -- - * - * This procedure installs (if necessary) and starts a carbon - * event timer that runs the tcl event loop periodically. - * It should be called whenever a nested carbon event loop might - * run by HIToolbox (e.g. during mouse tracking) to ensure that - * tcl events continue to be processed. - * - * Results: - * OS status code. - * - * Side effects: - * Carbon event timer is installed and started. - * - *---------------------------------------------------------------------- - */ - -MODULE_SCOPE OSStatus -TkMacOSXStartTclEventLoopCarbonTimer(void) -{ - OSStatus err = noErr; - - if (++carbonTimerEnabled > 0) { - if(!carbonTimer) { - EventLoopTimerUPP timerUPP = NewEventLoopTimerUPP(CarbonTimerProc); - - err = ChkErr(InstallEventLoopTimer, GetMainEventLoop(), - 5 * kEventDurationMillisecond, - 5 * kEventDurationMillisecond, - timerUPP, NULL, &carbonTimer); - } else { - err = ChkErr(SetEventLoopTimerNextFireTime, carbonTimer, - 5 * kEventDurationMillisecond); - } - } - return err; -} - -/* - *---------------------------------------------------------------------- - * - * TkMacOSXStopTclEventLoopCarbonTimer -- - * - * This procedure stops the carbon event timer started by - * TkMacOSXStartTclEventLoopCarbonTimer(). - * - * Results: - * OS status code. - * - * Side effects: - * Carbon event timer is stopped. - * - *---------------------------------------------------------------------- - */ - -MODULE_SCOPE OSStatus -TkMacOSXStopTclEventLoopCarbonTimer(void) -{ - OSStatus err = noErr; - - if (--carbonTimerEnabled == 0) { - if(carbonTimer) { - err = ChkErr(SetEventLoopTimerNextFireTime, carbonTimer, - kEventDurationForever); - } - } - return err; -} - -/* - *---------------------------------------------------------------------- - * - * TkMacOSXTrackingLoop -- - * - * Call with 1 before entering a mouse tracking loop (e.g. window - * resizing or menu tracking) to enable tcl event processing but - * disable carbon event processing (except for update events) - * during the loop, and with 0 after exiting the loop to reset. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -MODULE_SCOPE void -TkMacOSXTrackingLoop(int tracking) -{ - static int previousServiceMode = TCL_SERVICE_NONE; - - if (tracking) { - inTrackingLoop++; - previousServiceMode = Tcl_SetServiceMode(TCL_SERVICE_ALL); - TkMacOSXStartTclEventLoopCarbonTimer(); -#ifdef TK_MAC_DEBUG_CARBON_EVENTS - TkMacOSXDbgMsg("Entering tracking loop"); -#endif /* TK_MAC_DEBUG_CARBON_EVENTS */ - } else { - TkMacOSXStopTclEventLoopCarbonTimer(); - previousServiceMode = Tcl_SetServiceMode(previousServiceMode); - inTrackingLoop--; -#ifdef TK_MAC_DEBUG_CARBON_EVENTS - TkMacOSXDbgMsg("Exiting tracking loop"); -#endif /* TK_MAC_DEBUG_CARBON_EVENTS */ - } -} - -/* - *---------------------------------------------------------------------- - * - * TkMacOSXReceiveAndDispatchEvent -- - * - * This receives a carbon event and sends it to the carbon event - * dispatcher. - * - * Results: - * Mac OS status - * - * Side effects: - * This receives and dispatches the next Carbon event. - * - *---------------------------------------------------------------------- - */ -MODULE_SCOPE OSStatus -TkMacOSXReceiveAndDispatchEvent(void) -{ - static EventTargetRef targetRef = NULL; - int numEventTypes = 0; - const EventTypeSpec *eventTypes = NULL; - EventRef eventRef; - OSStatus err; - const EventTypeSpec trackingEventTypes[] = { - {'dniw', kEventWindowUpdate}, - {kEventClassWindow, kEventWindowUpdate}, - }; - - if (inTrackingLoop > 0) { - eventTypes = trackingEventTypes; - numEventTypes = GetEventTypeCount(trackingEventTypes); - } - - /* - * This is a poll, since we have already counted the events coming - * into this routine, and are guaranteed to have one waiting. - */ - - err = ReceiveNextEvent(numEventTypes, eventTypes, - kEventDurationNoWait, true, &eventRef); - if (err == noErr) { -#ifdef TK_MAC_DEBUG_CARBON_EVENTS - UInt32 kind = GetEventKind(eventRef); - - if (kind != kEventMouseMoved && kind != kEventMouseDragged) { - TkMacOSXDbgMsg("Dispatching %s", TkMacOSXCarbonEventToAscii(eventRef)); - TkMacOSXInitNamedDebugSymbol(HIToolbox, void, _DebugPrintEvent, - EventRef inEvent); - if (_DebugPrintEvent) { - /* Carbon-internal event debugging (c.f. Technote 2124) */ - _DebugPrintEvent(eventRef); - } - } -#endif /* TK_MAC_DEBUG_CARBON_EVENTS */ - if (!targetRef) { - targetRef = GetEventDispatcherTarget(); - } - TkMacOSXStartTclEventLoopCarbonTimer(); - err = SendEventToEventTarget(eventRef, targetRef); - TkMacOSXStopTclEventLoopCarbonTimer(); - if (err != noErr && err != eventLoopTimedOutErr - && err != eventNotHandledErr) { - TkMacOSXDbgMsg("SendEventToEventTarget(%s) failed: %ld", - TkMacOSXCarbonEventToAscii(eventRef), err); - } - ReleaseEvent(eventRef); - } else if (err != eventLoopTimedOutErr) { - TkMacOSXDbgMsg("ReceiveNextEvent failed: %ld", err); - } - return err; -} - -/* - * Local Variables: - * mode: objc - * c-basic-offset: 4 - * fill-column: 79 - * coding: utf-8 - * End: - */ |