summaryrefslogtreecommitdiffstats
path: root/macosx/tkMacOSXNotify.c
diff options
context:
space:
mode:
Diffstat (limited to 'macosx/tkMacOSXNotify.c')
-rw-r--r--macosx/tkMacOSXNotify.c157
1 files changed, 73 insertions, 84 deletions
diff --git a/macosx/tkMacOSXNotify.c b/macosx/tkMacOSXNotify.c
index 3e0dfde..1455688 100644
--- a/macosx/tkMacOSXNotify.c
+++ b/macosx/tkMacOSXNotify.c
@@ -7,6 +7,7 @@
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
* Copyright 2001-2009, Apple Inc.
* Copyright (c) 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ * Copyright 2015 Marc Culler.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -18,9 +19,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 +35,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,41 +50,27 @@ static void TkMacOSXEventsCheckProc(ClientData clientData, int flags);
@end
@implementation TKApplication(TKNotify)
+/* Display all windows each time an event is removed from the queue.*/
- (NSEvent *) nextEventMatchingMask: (NSUInteger) mask
untilDate: (NSDate *) expiration inMode: (NSString *) mode
dequeue: (BOOL) deqFlag
{
- NSAutoreleasePool *pool = [NSAutoreleasePool new];
-
+ NSEvent *event = [super nextEventMatchingMask:mask
+ untilDate:expiration
+ inMode:mode
+ dequeue:deqFlag];
+ /* Retain this event for later use. Must be released.*/
+ [event retain];
[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];
+ return event;
}
+/*
+ * Call super then check the pasteboard.
+ */
- (void) sendEvent: (NSEvent *) theEvent
{
- TSD_INIT();
- int oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
-
- tsdPtr->sendEventNestingLevel++;
[super sendEvent:theEvent];
- tsdPtr->sendEventNestingLevel--;
- Tcl_SetServiceMode(oldMode);
[NSApp tkCheckPasteboard];
}
@end
@@ -161,7 +149,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 +183,8 @@ TkMacOSXNotifyExitHandler(
TSD_INIT();
Tcl_DeleteEventSource(TkMacOSXEventsSetupProc,
- TkMacOSXEventsCheckProc, GetMainEventQueue());
+ TkMacOSXEventsCheckProc,
+ GetMainEventQueue());
tsdPtr->initialized = 0;
}
@@ -203,16 +193,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.
*
*----------------------------------------------------------------------
*/
@@ -222,24 +215,20 @@ TkMacOSXEventsSetupProc(
ClientData clientData,
int flags)
{
- if (flags & TCL_WINDOW_EVENTS &&
- ![[NSRunLoop currentRunLoop] currentMode]) {
+ NSString *runloopMode = [[NSRunLoop currentRunLoop] currentMode];
+ /* runloopMode will be nil if we are in the Tcl event loop. */
+ if (flags & TCL_WINDOW_EVENTS && !runloopMode) {
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 =
- TkMacOSXMakeUncollectableAndRetain(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) {
+ if (currentEvent.type > 0) {
+ Tcl_SetMaxBlockTime(&zeroBlockTime);
}
- }
- if (tsdPtr->currentEvent) {
- Tcl_SetMaxBlockTime(&zeroBlockTime);
+ [currentEvent release];
}
}
}
@@ -249,69 +238,69 @@ 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,
int flags)
{
- if (flags & TCL_WINDOW_EVENTS &&
- ![[NSRunLoop currentRunLoop] currentMode]) {
+ NSString *runloopMode = [[NSRunLoop currentRunLoop] currentMode];
+ /* runloopMode will be nil if we are in the Tcl event loop. */
+ if (flags & TCL_WINDOW_EVENTS && !runloopMode) {
NSEvent *currentEvent = nil;
- NSAutoreleasePool *pool = nil;
+ NSEvent *testEvent = nil;
NSModalSession modalSession;
- TSD_INIT();
- if (tsdPtr->currentEvent) {
- currentEvent = TkMacOSXMakeCollectableAndAutorelease(
- tsdPtr->currentEvent);
- }
do {
+ [NSApp _resetAutoreleasePool];
modalSession = TkMacOSXGetModalSession();
- if (!currentEvent) {
- currentEvent = [NSApp nextEventMatchingMask:NSAnyEventMask
- untilDate:[NSDate distantPast]
- inMode:GetRunLoopMode(modalSession) dequeue:YES];
- }
- if (!currentEvent) {
+ testEvent = [NSApp nextEventMatchingMask:NSAnyEventMask
+ untilDate:[NSDate distantPast]
+ inMode:GetRunLoopMode(modalSession)
+ dequeue:NO];
+ /* We must not steal any events during LiveResize. */
+ if (testEvent && [[testEvent window] inLiveResize]) {
break;
}
- [currentEvent retain];
- pool = [NSAutoreleasePool new];
- if (tkMacOSXGCEnabled) {
- objc_clear_stack(0);
- }
- if (![NSApp tkProcessEvent:currentEvent]) {
- [currentEvent release];
- currentEvent = nil;
- }
+
+ currentEvent = [NSApp nextEventMatchingMask:NSAnyEventMask
+ untilDate:[NSDate distantPast]
+ inMode:GetRunLoopMode(modalSession)
+ dequeue:YES];
if (currentEvent) {
+ /* 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);
+ TKLog(@" event: %@", currentEvent);
#endif
- if (modalSession) {
- [NSApp _modalSession:modalSession sendEvent:currentEvent];
- } else {
- [NSApp sendEvent:currentEvent];
+ if (modalSession) {
+ [NSApp _modalSession:modalSession sendEvent:currentEvent];
+ } else {
+ [NSApp sendEvent:currentEvent];
+ }
}
[currentEvent release];
- currentEvent = nil;
+ } else {
+ break;
}
- [pool drain];
- pool = nil;
} while (1);
}
}
+
/*
* Local Variables: