diff options
author | Kevin Walzer <kw@codebykevin.com> | 2015-03-21 01:22:30 (GMT) |
---|---|---|
committer | Kevin Walzer <kw@codebykevin.com> | 2015-03-21 01:22:30 (GMT) |
commit | 6596343ef6a711a8b5a51e17c946f206a90efe16 (patch) | |
tree | aa5390457f8371d6bf3eb56d179db157eaecc722 /macosx/tkMacOSXNotify.c | |
parent | 4f6c1ad7943f8c595d9d539a6c6c33c96832554b (diff) | |
download | tk-6596343ef6a711a8b5a51e17c946f206a90efe16.zip tk-6596343ef6a711a8b5a51e17c946f206a90efe16.tar.gz tk-6596343ef6a711a8b5a51e17c946f206a90efe16.tar.bz2 |
Cleanup and simplification of memory management in event loop; now works more smoothly; thanks to Marc Culler for patches
Diffstat (limited to 'macosx/tkMacOSXNotify.c')
-rw-r--r-- | macosx/tkMacOSXNotify.c | 117 |
1 files changed, 48 insertions, 69 deletions
diff --git a/macosx/tkMacOSXNotify.c b/macosx/tkMacOSXNotify.c index ab68931..905ada5 100644 --- a/macosx/tkMacOSXNotify.c +++ b/macosx/tkMacOSXNotify.c @@ -18,9 +18,9 @@ #include <pthread.h> #import <objc/objc-auto.h> +/* This is not used for anything at the moment. */ typedef struct ThreadSpecificData { - int initialized, sendEventNestingLevel; - NSEvent *currentEvent; + int initialized; } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; @@ -34,6 +34,7 @@ static void TkMacOSXEventsCheckProc(ClientData clientData, int flags); #pragma mark TKApplication(TKNotify) @interface NSApplication(TKNotify) +/* We need to declare this hidden method. */ - (void) _modalSession: (NSModalSession) session sendEvent: (NSEvent *) event; @end @@ -48,42 +49,30 @@ static void TkMacOSXEventsCheckProc(ClientData clientData, int flags); @end @implementation TKApplication(TKNotify) +/* Redisplay all of our windows, then call super. */ - (NSEvent *) nextEventMatchingMask: (NSUInteger) mask untilDate: (NSDate *) expiration inMode: (NSString *) mode dequeue: (BOOL) deqFlag { NSAutoreleasePool *pool = [NSAutoreleasePool new]; - [NSApp makeWindowsPerform:@selector(tkDisplayIfNeeded) inOrder:NO]; - - int oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL); - NSEvent *event = [[super nextEventMatchingMask:mask untilDate:expiration - inMode:mode dequeue:deqFlag] retain]; - - Tcl_SetServiceMode(oldMode); - if (event) { - TSD_INIT(); - if (tsdPtr->sendEventNestingLevel) { - if (![NSApp tkProcessEvent:event]) { - [event release]; - event = nil; - } - } - } [pool drain]; - return [event autorelease]; + NSEvent *event = [super nextEventMatchingMask:mask + untilDate:expiration + inMode:mode + dequeue:deqFlag]; + return event; } +/* + * Call super then check the pasteboard. + */ - (void) sendEvent: (NSEvent *) theEvent { - TSD_INIT(); - int oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL); - - tsdPtr->sendEventNestingLevel++; + NSAutoreleasePool *pool = [NSAutoreleasePool new]; [super sendEvent:theEvent]; - tsdPtr->sendEventNestingLevel--; - Tcl_SetServiceMode(oldMode); [NSApp tkCheckPasteboard]; + [pool drain]; } @end @@ -161,7 +150,8 @@ Tk_MacOSXSetupTkNotifier(void) "first [load] of TkAqua has to occur in the main thread!"); } Tcl_CreateEventSource(TkMacOSXEventsSetupProc, - TkMacOSXEventsCheckProc, GetMainEventQueue()); + TkMacOSXEventsCheckProc, + GetMainEventQueue()); TkCreateExitHandler(TkMacOSXNotifyExitHandler, NULL); Tcl_SetServiceMode(TCL_SERVICE_ALL); TclMacOSXNotifierAddRunLoopMode(NSEventTrackingRunLoopMode); @@ -194,7 +184,8 @@ TkMacOSXNotifyExitHandler( TSD_INIT(); Tcl_DeleteEventSource(TkMacOSXEventsSetupProc, - TkMacOSXEventsCheckProc, GetMainEventQueue()); + TkMacOSXEventsCheckProc, + GetMainEventQueue()); tsdPtr->initialized = 0; } @@ -203,16 +194,19 @@ TkMacOSXNotifyExitHandler( * * TkMacOSXEventsSetupProc -- * - * This procedure implements the setup part of the TkAqua Events event - * source. It is invoked by Tcl_DoOneEvent before entering the notifier - * to check for events. + * This procedure implements the setup part of the MacOSX event + * source. It is invoked by Tcl_DoOneEvent before calling + * TkMacOSXEventsProc to process all queued NSEvents. In our + * case, all we need to do is to set the Tcl MaxBlockTime to + * 0 before starting the loop to process all queued NSEvents. * * Results: * None. * * Side effects: - * If TkAqua events are queued, then the maximum block time will be set - * to 0 to ensure that the notifier returns control to Tcl. + * + * If NSEvents are queued, then the maximum block time will be set + * to 0 to ensure that control returns immediately to Tcl. * *---------------------------------------------------------------------- */ @@ -225,19 +219,13 @@ TkMacOSXEventsSetupProc( if (flags & TCL_WINDOW_EVENTS && ![[NSRunLoop currentRunLoop] currentMode]) { static const Tcl_Time zeroBlockTime = { 0, 0 }; - TSD_INIT(); - - if (!tsdPtr->currentEvent) { - NSEvent *currentEvent = [NSApp nextEventMatchingMask:NSAnyEventMask - untilDate:[NSDate distantPast] - inMode:GetRunLoopMode(TkMacOSXGetModalSession()) - dequeue:YES]; - if (currentEvent) { - tsdPtr->currentEvent = [currentEvent retain]; - } - } - if (tsdPtr->currentEvent) { + /* Call this with dequeue=NO -- just checking if the queue is empty. */ + NSEvent *currentEvent = [NSApp nextEventMatchingMask:NSAnyEventMask + untilDate:[NSDate distantPast] + inMode:GetRunLoopMode(TkMacOSXGetModalSession()) + dequeue:NO]; + if (currentEvent) { Tcl_SetMaxBlockTime(&zeroBlockTime); } } @@ -248,17 +236,18 @@ TkMacOSXEventsSetupProc( * * TkMacOSXEventsCheckProc -- * - * This procedure processes events sitting in the TkAqua event queue. + * This procedure loops through all NSEvents waiting in the + * TKApplication event queue, generating X events from them. * * Results: * None. * * Side effects: - * Moves applicable queued TkAqua events onto the Tcl event queue. + * NSevents are used to generate X events, which are added to the + * Tcl event queue. * *---------------------------------------------------------------------- */ - static void TkMacOSXEventsCheckProc( ClientData clientData, @@ -267,31 +256,23 @@ TkMacOSXEventsCheckProc( if (flags & TCL_WINDOW_EVENTS && ![[NSRunLoop currentRunLoop] currentMode]) { NSEvent *currentEvent = nil; - NSAutoreleasePool *pool = nil; NSModalSession modalSession; - TSD_INIT(); - if (tsdPtr->currentEvent) { - currentEvent = tsdPtr->currentEvent; - [currentEvent autorelease]; - } do { modalSession = TkMacOSXGetModalSession(); + currentEvent = [NSApp nextEventMatchingMask:NSAnyEventMask + untilDate:[NSDate distantPast] + inMode:GetRunLoopMode(modalSession) + dequeue:YES]; if (!currentEvent) { - currentEvent = [NSApp nextEventMatchingMask:NSAnyEventMask - untilDate:[NSDate distantPast] - inMode:GetRunLoopMode(modalSession) dequeue:YES]; - } - if (!currentEvent) { - break; + break; /* No more events. */ } - [currentEvent retain]; - pool = [NSAutoreleasePool new]; - if (![NSApp tkProcessEvent:currentEvent]) { - [currentEvent release]; - currentEvent = nil; - } - if (currentEvent) { + NSAutoreleasePool *pool = [NSAutoreleasePool new]; + /* Generate Xevents. */ + int oldServiceMode = Tcl_SetServiceMode(TCL_SERVICE_ALL); + NSEvent *processedEvent = [NSApp tkProcessEvent:currentEvent]; + Tcl_SetServiceMode(oldServiceMode); + if (processedEvent) { /* Should always be non-NULL. */ #ifdef TK_MAC_DEBUG_EVENTS TKLog(@" event: %@", currentEvent); #endif @@ -300,14 +281,12 @@ TkMacOSXEventsCheckProc( } else { [NSApp sendEvent:currentEvent]; } - [currentEvent release]; - currentEvent = nil; } [pool drain]; - pool = nil; } while (1); } } + /* * Local Variables: |