diff options
Diffstat (limited to 'carbon/tkMacOSXNotify.c')
-rw-r--r-- | carbon/tkMacOSXNotify.c | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/carbon/tkMacOSXNotify.c b/carbon/tkMacOSXNotify.c new file mode 100644 index 0000000..fdd5afd --- /dev/null +++ b/carbon/tkMacOSXNotify.c @@ -0,0 +1,196 @@ +/* + * tkMacOSXNotify.c -- + * + * This file contains the implementation of a tcl event source + * for the Carbon event loop. + * + * Copyright (c) 1995-1997 Sun Microsystems, Inc. + * Copyright 2001, Apple Computer, Inc. + * Copyright (c) 2005-2007 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. + */ + +#include "tkMacOSXPrivate.h" +#include "tkMacOSXEvent.h" +#include <pthread.h> + +/* + * The following static indicates whether this module has been initialized + * in the current thread. + */ + +typedef struct ThreadSpecificData { + int initialized; +} ThreadSpecificData; +static Tcl_ThreadDataKey dataKey; + +static void TkMacOSXNotifyExitHandler(ClientData clientData); +static void CarbonEventsSetupProc(ClientData clientData, int flags); +static void CarbonEventsCheckProc(ClientData clientData, int flags); + +/* + *---------------------------------------------------------------------- + * + * Tk_MacOSXSetupTkNotifier -- + * + * This procedure is called during Tk initialization to create + * the event source for Carbon events. + * + * Results: + * None. + * + * Side effects: + * A new event source is created. + * + *---------------------------------------------------------------------- + */ + +void +Tk_MacOSXSetupTkNotifier(void) +{ + ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, + sizeof(ThreadSpecificData)); + + if (!tsdPtr->initialized) { + /* HACK ALERT: There is a bug in Jaguar where when it goes to make + * the event queue for the Main Event Loop, it stores the Current + * event loop rather than the Main Event Loop in the Queue structure. + * So we have to make sure that the Main Event Queue gets set up on + * the main thread. Calling GetMainEventQueue will force this to + * happen. + */ + GetMainEventQueue(); + + tsdPtr->initialized = 1; + + /* + * Install Carbon events event source in main event loop thread. + */ + + if (GetCurrentEventLoop() == GetMainEventLoop()) { + if (!pthread_main_np()) { + /* + * Panic if the Carbon main event loop thread (i.e. the thread + * where HIToolbox was first loaded) is not the main + * application thread, as Carbon does not support this + * properly. + */ + + Tcl_Panic("Tk_MacOSXSetupTkNotifier: %s", + "first [load] of TkAqua has to occur in the main thread!"); + } + Tcl_CreateEventSource(CarbonEventsSetupProc, + CarbonEventsCheckProc, GetMainEventQueue()); + TkCreateExitHandler(TkMacOSXNotifyExitHandler, NULL); + } + } +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXNotifyExitHandler -- + * + * This function is called during finalization to clean up the + * TkMacOSXNotify module. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static void +TkMacOSXNotifyExitHandler( + ClientData clientData) /* Not used. */ +{ + ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, + sizeof(ThreadSpecificData)); + + Tcl_DeleteEventSource(CarbonEventsSetupProc, + CarbonEventsCheckProc, GetMainEventQueue()); + tsdPtr->initialized = 0; +} + +/* + *---------------------------------------------------------------------- + * + * CarbonEventsSetupProc -- + * + * This procedure implements the setup part of the Carbon Events event + * source. It is invoked by Tcl_DoOneEvent before entering the notifier + * to check for events. + * + * Results: + * None. + * + * Side effects: + * If Carbon events are queued, then the maximum block time will be set + * to 0 to ensure that the notifier returns control to Tcl. + * + *---------------------------------------------------------------------- + */ + +static void +CarbonEventsSetupProc( + ClientData clientData, + int flags) +{ + static Tcl_Time blockTime = { 0, 0 }; + + if (!(flags & TCL_WINDOW_EVENTS)) { + return; + } + + if (GetNumEventsInQueue((EventQueueRef) clientData)) { + Tcl_SetMaxBlockTime(&blockTime); + } +} + +/* + *---------------------------------------------------------------------- + * + * CarbonEventsCheckProc -- + * + * This procedure processes events sitting in the Carbon event queue. + * + * Results: + * None. + * + * Side effects: + * Moves applicable queued Carbon events onto the Tcl event queue. + * + *---------------------------------------------------------------------- + */ + +static void +CarbonEventsCheckProc( + ClientData clientData, + int flags) +{ + int numFound; + OSStatus err = noErr; + + if (!(flags & TCL_WINDOW_EVENTS)) { + return; + } + + numFound = GetNumEventsInQueue((EventQueueRef) clientData); + + /* + * Avoid starving other event sources: + */ + + if (numFound > 4) { + numFound = 4; + } + while (numFound > 0 && err == noErr) { + err = TkMacOSXReceiveAndDispatchEvent(); + numFound--; + } +} |