From 4f6c1ad7943f8c595d9d539a6c6c33c96832554b Mon Sep 17 00:00:00 2001 From: Kevin Walzer Date: Sat, 21 Mar 2015 00:57:14 +0000 Subject: Cleanup and improvement of tracking of native windows in Cocoa; thanks to Marc Culler for patch --- macosx/tkMacOSXEvent.c | 33 ++++++++++--------- macosx/tkMacOSXKeyEvent.c | 8 +++-- macosx/tkMacOSXMouseEvent.c | 21 +++++------- macosx/tkMacOSXWm.c | 79 +++++++++++++++++++++------------------------ 4 files changed, 66 insertions(+), 75 deletions(-) diff --git a/macosx/tkMacOSXEvent.c b/macosx/tkMacOSXEvent.c index ea262ff..365dc9b 100644 --- a/macosx/tkMacOSXEvent.c +++ b/macosx/tkMacOSXEvent.c @@ -31,18 +31,19 @@ enum { NSEvent *processedEvent = theEvent; NSEventType type = [theEvent type]; NSInteger subtype; - NSUInteger flags; switch ((NSInteger)type) { case NSAppKitDefined: subtype = [theEvent subtype]; switch (subtype) { + /* Ignored at the moment. */ case NSApplicationActivatedEventType: break; case NSApplicationDeactivatedEventType: break; case NSWindowExposedEventType: + break; case NSScreenChangedEventType: break; case NSWindowMovedEventType: @@ -53,13 +54,12 @@ enum { default: break; } - break; + break; /* AppkitEvent. Return theEvent */ case NSKeyUp: case NSKeyDown: case NSFlagsChanged: - flags = [theEvent modifierFlags]; processedEvent = [self tkProcessKeyEvent:theEvent]; - break; + break; /* Key event. Return the processed event. */ case NSLeftMouseDown: case NSLeftMouseUp: case NSRightMouseDown: @@ -76,7 +76,7 @@ enum { case NSTabletPoint: case NSTabletProximity: processedEvent = [self tkProcessMouseEvent:theEvent]; - break; + break; /* Mouse event. Return the processed event. */ #if 0 case NSSystemDefined: subtype = [theEvent subtype]; @@ -100,7 +100,7 @@ enum { #endif default: - break; + break; /* return theEvent */ } return processedEvent; } @@ -113,14 +113,14 @@ enum { * * TkMacOSXFlushWindows -- * - * This routine flushes all the windows of the application. It is + * This routine flushes all the visible windows of the application. It is * called by XSync(). * * Results: * None. * * Side effects: - * Flushes all Carbon windows + * Flushes all visible Cocoa windows * *---------------------------------------------------------------------- */ @@ -128,22 +128,23 @@ enum { MODULE_SCOPE void TkMacOSXFlushWindows(void) { - NSInteger windowCount; - NSInteger *windowNumbers; + /* This can be called from outside the Appkit event loop, + * so it needs its own AutoreleasePool. + */ + NSAutoreleasePool *pool = [NSAutoreleasePool new]; + NSArray *macWindows = [NSApp orderedWindows]; + NSInteger windowCount = [macWindows count]; - NSCountWindows(&windowCount); if(windowCount) { - windowNumbers = ckalloc(windowCount * sizeof(NSInteger)); - NSWindowList(windowCount, windowNumbers); - for (NSInteger index = 0; index < windowCount; index++) { - NSWindow *w = [NSApp windowWithWindowNumber:windowNumbers[index]]; + for (NSWindow *w in macWindows) { if (TkMacOSXGetXWindow(w)) { [w flushWindow]; } } - ckfree(windowNumbers); } + [pool drain]; } + /* * Local Variables: diff --git a/macosx/tkMacOSXKeyEvent.c b/macosx/tkMacOSXKeyEvent.c index c9ad9f1..09cdf94 100644 --- a/macosx/tkMacOSXKeyEvent.c +++ b/macosx/tkMacOSXKeyEvent.c @@ -78,16 +78,18 @@ static unsigned isFunctionKey(unsigned int code); case NSFlagsChanged: modifiers = [theEvent modifierFlags]; keyCode = [theEvent keyCode]; - w = [self windowWithWindowNumber:[theEvent windowNumber]]; + // w = [self windowWithWindowNumber:[theEvent windowNumber]]; + w = [theEvent window]; #if defined(TK_MAC_DEBUG_EVENTS) || NS_KEYLOG == 1 NSLog(@"-[%@(%p) %s] r=%d mods=%u '%@' '%@' code=%u c=%d %@ %d", [self class], self, _cmd, repeat, modifiers, characters, charactersIgnoringModifiers, keyCode,([charactersIgnoringModifiers length] == 0) ? 0 : [charactersIgnoringModifiers characterAtIndex: 0], w, type); #endif break; default: - return theEvent; + return theEvent; /* Unrecognized key event. */ } + /* Create an Xevent to add to the Tk queue. */ if (!processingCompose) { unsigned int state = 0; @@ -128,7 +130,7 @@ static unsigned isFunctionKey(unsigned int code); tkwin = (Tk_Window) winPtr->dispPtr->focusPtr; if (!tkwin) { TkMacOSXDbgMsg("tkwin == NULL"); - return theEvent; + return theEvent; /* Give up. No window for this event. */ } /* diff --git a/macosx/tkMacOSXMouseEvent.c b/macosx/tkMacOSXMouseEvent.c index 90d2d00..95f0021 100644 --- a/macosx/tkMacOSXMouseEvent.c +++ b/macosx/tkMacOSXMouseEvent.c @@ -53,19 +53,17 @@ enum { case NSCursorUpdate: #if 0 trackingArea = [theEvent trackingArea]; -#endif /* fall through */ +#endif case NSLeftMouseDown: case NSLeftMouseUp: case NSRightMouseDown: case NSRightMouseUp: case NSOtherMouseDown: case NSOtherMouseUp: - case NSLeftMouseDragged: case NSRightMouseDragged: case NSOtherMouseDragged: - case NSMouseMoved: #if 0 eventNumber = [theEvent eventNumber]; @@ -73,22 +71,20 @@ enum { clickCount = [theEvent clickCount]; buttonNumber = [theEvent buttonNumber]; } + /* fall through */ #endif - case NSTabletPoint: case NSTabletProximity: - case NSScrollWheel: - win = [self windowWithWindowNumber:[theEvent windowNumber]]; break; - default: + default: /* Unrecognized mouse event. */ return theEvent; - break; } + /* Create an Xevent to add to the Tk queue. */ + win = [theEvent window]; NSPoint global, local = [theEvent locationInWindow]; - if (win) { global = [win convertBaseToScreen:local]; local.y = [win frame].size.height - local.y; @@ -105,7 +101,7 @@ enum { tkwin = TkMacOSXGetCapture(); } if (!tkwin) { - return theEvent; + return theEvent; /* Give up. No window for this event. */ } /* @@ -127,10 +123,10 @@ enum { EventRef eventRef = (EventRef)[theEvent eventRef]; UInt32 buttons; OSStatus err = GetEventParameter(eventRef, kEventParamMouseChord, - typeUInt32, NULL, sizeof(UInt32), NULL, &buttons); + typeUInt32, NULL, sizeof(UInt32), NULL, &buttons); if (err == noErr) { - state |= (buttons & ((1<<5) - 1)) << 8; + state |= (buttons & ((1<<5) - 1)) << 8; } else if (button < 5) { switch (type) { case NSLeftMouseDown: @@ -205,7 +201,6 @@ enum { Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL); } } - return theEvent; } @end diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index fc61c7f..ffb3c34 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -463,25 +463,18 @@ FrontWindowAtPoint( int x, int y) { NSPoint p = NSMakePoint(x, tkMacOSXZeroScreenHeight - y); - NSWindow *win = nil; - NSInteger windowCount; - NSInteger *windowNumbers; - - NSCountWindows(&windowCount); - if (windowCount) { - windowNumbers = ckalloc(windowCount * sizeof(NSInteger)); - NSWindowList(windowCount, windowNumbers); - for (NSInteger index = 0; index < windowCount; index++) { - NSWindow *w = [NSApp windowWithWindowNumber:windowNumbers[index]]; + NSAutoreleasePool *pool = [NSAutoreleasePool new]; + NSArray *windows = [NSApp orderedWindows]; + TkWindow *front = NULL; + for (NSWindow *w in windows) { if (w && NSMouseInRect(p, [w frame], NO)) { - win = w; + front = TkMacOSXGetTkWindow(w); break; } } - ckfree(windowNumbers); - } - return (win ? TkMacOSXGetTkWindow(win) : NULL); + [pool drain]; + return front; } /* @@ -677,6 +670,7 @@ TkWmMapWindow( */ XMapWindow(winPtr->display, winPtr->window); + } /* @@ -699,7 +693,7 @@ TkWmMapWindow( void TkWmUnmapWindow( TkWindow *winPtr) /* Top-level window that's about to be - * mapped. */ + * unmapped. */ { XUnmapWindow(winPtr->display, winPtr->window); } @@ -783,21 +777,26 @@ TkWmDeadWindow( NSWindow *window = wmPtr->window; if (window && !Tk_IsEmbedded(winPtr) ) { - [[window parentWindow] removeChildWindow:window]; + NSWindow *parent = [window parentWindow]; + if (parent) { + [parent removeChildWindow:window]; + } [window setExcludedFromWindowsMenu:YES]; [window close]; TkMacOSXUnregisterMacWindow(window); - if (winPtr->window) { - ((MacDrawable *) winPtr->window)->view = nil; + if (winPtr->window) { + ((MacDrawable *) winPtr->window)->view = nil; } - [window release]; + [window release]; wmPtr->window = NULL; - /* Activate the highest window left on the screen. */ - NSArray *windows = [NSApp orderedWindows]; - NSWindow *front = [windows objectAtIndex:0]; - if ( front && [front canBecomeKeyWindow] ) { - [front makeKeyAndOrderFront:NSApp]; - } + /* Activate the highest window left on the screen. */ + NSArray *windows = [NSApp orderedWindows]; + if ( [windows count] > 0 ) { + NSWindow *front = [windows objectAtIndex:0]; + if ( front && [front canBecomeKeyWindow] ) { + [front makeKeyAndOrderFront:NSApp]; + } + } } ckfree(wmPtr); winPtr->wmInfoPtr = NULL; @@ -5927,6 +5926,7 @@ TkpChangeFocus( if (Tk_IsTopLevel(winPtr) && !Tk_IsEmbedded(winPtr) ){ NSWindow *win = TkMacOSXDrawableWindow(winPtr->window); + NSAutoreleasePool *pool = [NSAutoreleasePool new]; TkWmRestackToplevel(winPtr, Above, NULL); if (force ) { [NSApp activateIgnoringOtherApps:YES]; @@ -5934,6 +5934,7 @@ TkpChangeFocus( if ( win && [win canBecomeKeyWindow] ) { [win makeKeyAndOrderFront:NSApp]; } + [pool drain]; } /* @@ -5952,7 +5953,7 @@ TkpChangeFocus( * WmStackorderToplevelWrapperMap -- * * This procedure will create a table that maps the reparent wrapper X id - * for a toplevel to the TkWindow structure that is wraps. Tk keeps track + * for a toplevel to the TkWindow structure that it wraps. Tk keeps track * of a mapping from the window X id to the TkWindow structure but that * does us no good here since we only get the X id of the wrapper window. * Only those toplevel windows that are mapped have a position in the @@ -6015,8 +6016,6 @@ TkWmStackorderToplevel( Tcl_HashTable table; Tcl_HashEntry *hPtr; Tcl_HashSearch search; - NSInteger windowCount; - NSInteger *windowNumbers; /* * Map mac windows to a TkWindow of the wrapped toplevel. @@ -6043,31 +6042,26 @@ TkWmStackorderToplevel( goto done; } - NSCountWindows(&windowCount); + NSArray *macWindows = [NSApp orderedWindows]; + NSInteger windowCount = [macWindows count]; + if (!windowCount) { ckfree(windows); windows = NULL; } else { windowPtr = windows + table.numEntries; *windowPtr-- = NULL; - windowNumbers = ckalloc(windowCount * sizeof(NSInteger)); - NSWindowList(windowCount, windowNumbers); - for (NSInteger index = 0; index < windowCount; index++) { - NSWindow *w = [NSApp windowWithWindowNumber:windowNumbers[index]]; - - if (w) { - hPtr = Tcl_FindHashEntry(&table, (char*) w); - if (hPtr != NULL) { - childWinPtr = Tcl_GetHashValue(hPtr); - *windowPtr-- = childWinPtr; - } + for (NSWindow *w in macWindows) { + hPtr = Tcl_FindHashEntry(&table, (char*) w); + if (hPtr != NULL) { + childWinPtr = Tcl_GetHashValue(hPtr); + *windowPtr-- = childWinPtr; } } if (windowPtr != windows-1) { Tcl_Panic("num matched toplevel windows does not equal num " - "children"); + "children"); } - ckfree(windowNumbers); } done: @@ -6626,7 +6620,6 @@ RemapWindows( MacDrawable *parentWin) { TkWindow *childPtr; - /* * Remove the OS specific window. It will get rebuilt when the window gets * Mapped. -- cgit v0.12