diff options
author | culler <culler> | 2021-12-20 18:46:13 (GMT) |
---|---|---|
committer | culler <culler> | 2021-12-20 18:46:13 (GMT) |
commit | 2fdb9f02fd6d10fb497634b0ff5acef9dd5350cb (patch) | |
tree | 74dd72f5cdad5ea660010fed3f06624787dc1669 | |
parent | 8b6266dcbcfbfa6036baae36eb6875e31519f9d3 (diff) | |
parent | 774c6317321143cc524d608e9b78e8ee51cfb84e (diff) | |
download | tk-2fdb9f02fd6d10fb497634b0ff5acef9dd5350cb.zip tk-2fdb9f02fd6d10fb497634b0ff5acef9dd5350cb.tar.gz tk-2fdb9f02fd6d10fb497634b0ff5acef9dd5350cb.tar.bz2 |
Fix [6be8b0b48c]: crashes caused by stale pointers stored in static variables in tkMacOSXMouseEvent.c
-rw-r--r-- | macosx/tkMacOSXInit.c | 1 | ||||
-rw-r--r-- | macosx/tkMacOSXMouseEvent.c | 39 | ||||
-rw-r--r-- | macosx/tkMacOSXPrivate.h | 7 | ||||
-rw-r--r-- | macosx/tkMacOSXWm.c | 32 |
4 files changed, 62 insertions, 17 deletions
diff --git a/macosx/tkMacOSXInit.c b/macosx/tkMacOSXInit.c index d44bea3..d9f3d12 100644 --- a/macosx/tkMacOSXInit.c +++ b/macosx/tkMacOSXInit.c @@ -46,6 +46,7 @@ static int TkMacOSXGetAppPathCmd(ClientData cd, Tcl_Interp *ip, @synthesize tkLiveResizeEnded = _tkLiveResizeEnded; @synthesize tkPointerWindow = _tkPointerWindow; @synthesize tkEventTarget = _tkEventTarget; +@synthesize tkDragTarget = _tkDragTarget; @synthesize tkButtonState = _tkButtonState; @end diff --git a/macosx/tkMacOSXMouseEvent.c b/macosx/tkMacOSXMouseEvent.c index faba2dc..4ed954d 100644 --- a/macosx/tkMacOSXMouseEvent.c +++ b/macosx/tkMacOSXMouseEvent.c @@ -83,8 +83,7 @@ enum { NSPoint location = [theEvent locationInWindow]; NSPoint viewLocation = [contentView convertPoint:location fromView:nil]; TkWindow *winPtr = NULL, *grabWinPtr, *scrollTarget = NULL; - Tk_Window tkwin = NULL, capture; - static Tk_Window target = NULL, dragTarget = NULL; + Tk_Window tkwin = NULL, capture, target; NSPoint local, global; NSInteger button; TkWindow *newFocus = NULL; @@ -93,7 +92,6 @@ enum { Bool isTestingEvent = NO; Bool isMotionEvent = NO; Bool isOutside = NO; - static Bool isDragging = NO; static Bool ignoreDrags = NO; static Bool ignoreUpDown = NO; static NSTimeInterval timestamp = 0; @@ -134,14 +132,14 @@ enum { buttonState &= ~TkGetButtonMask(button); break; case NSLeftMouseDragged: - if (isOutside && !isDragging) { + if (isOutside && ![NSApp tkDragTarget]) { ignoreDrags = YES; } if (ignoreDrags) { return theEvent; } - isDragging = YES; - dragTarget = target; + [NSApp setTkDragTarget: [NSApp tkEventTarget]]; + break; case NSRightMouseDragged: case NSOtherMouseDragged: isMotionEvent = YES; @@ -163,8 +161,7 @@ enum { [NSApp setTkPointerWindow:nil]; break; case NSLeftMouseUp: - isDragging = NO; - dragTarget = NULL; + [NSApp setTkDragTarget: nil]; if ([theEvent clickCount] == 2) { ignoreUpDown = NO; } @@ -200,7 +197,6 @@ enum { if ([theEvent timestamp] - timestamp > 1) { ignoreUpDown = NO; } - if ([theEvent clickCount] == 2) { if (ignoreUpDown == YES) { return theEvent; @@ -291,8 +287,19 @@ enum { return theEvent; } } else { - if (isDragging) { - winPtr = TkMacOSXGetHostToplevel((TkWindow *)dragTarget)->winPtr; + if ([NSApp tkDragTarget]) { + TkWindow *dragPtr = (TkWindow *) [NSApp tkDragTarget]; + TKWindow *dragWindow = nil; + if (dragPtr) { + dragWindow = (TKWindow *)TkMacOSXGetNSWindowForDrawable( + dragPtr->window); + } + if (!dragWindow) { + [NSApp setTkDragTarget: nil]; + target = NULL; + return theEvent; + } + winPtr = TkMacOSXGetHostToplevel((TkWindow *) [NSApp tkDragTarget])->winPtr; } else if (eventType == NSScrollWheel) { winPtr = scrollTarget; } else { @@ -355,8 +362,8 @@ enum { * when the mouse is outside of the focused toplevel. */ - if (isDragging) { - TkWindow *w = (TkWindow *) dragTarget; + if ([NSApp tkDragTarget]) { + TkWindow *w = (TkWindow *) [NSApp tkDragTarget]; win_x = global.x; win_y = global.y; for (; w != NULL; w = w->parentPtr) { @@ -373,7 +380,7 @@ enum { break; } } - target = dragTarget; + target = (Tk_Window) [NSApp tkDragTarget]; } else { target = Tk_TopCoordsToWindow(tkwin, local.x, local.y, &win_x, &win_y); } @@ -439,7 +446,7 @@ enum { */ if (eventType != NSScrollWheel) { - if (isDragging) { + if ([NSApp tkDragTarget]) { /* * When dragging the mouse into the resize area Apple shows the @@ -454,7 +461,7 @@ enum { Tk_UpdatePointer((Tk_Window) [NSApp tkPointerWindow], global.x, global.y, state); } else if (eventType == NSMouseExited) { - if (isDragging) { + if ([NSApp tkDragTarget]) { Tk_UpdatePointer((Tk_Window) [NSApp tkPointerWindow], global.x, global.y, state); } else { diff --git a/macosx/tkMacOSXPrivate.h b/macosx/tkMacOSXPrivate.h index de0f5fd..3b03139 100644 --- a/macosx/tkMacOSXPrivate.h +++ b/macosx/tkMacOSXPrivate.h @@ -336,6 +336,7 @@ VISIBILITY_HIDDEN Bool _tkLiveResizeEnded; TkWindow *_tkPointerWindow; TkWindow *_tkEventTarget; + TkWindow *_tkDragTarget; unsigned int _tkButtonState; #endif @@ -345,8 +346,14 @@ VISIBILITY_HIDDEN @property Bool isDrawing; @property Bool needsToDraw; @property Bool tkLiveResizeEnded; + +/* + * Persistent state variables used by processMouseEvent. + */ + @property TkWindow *tkPointerWindow; @property TkWindow *tkEventTarget; +@property TkWindow *tkDragTarget; @property unsigned int tkButtonState; @end diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index c065d6c..0d52e43 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -1050,13 +1050,41 @@ TkWmDeadWindow( ckfree(transientPtr); } + deadNSWindow = (TKWindow *)wmPtr->window; + + /* + * Remove references to the Tk window from the mouse event processing + * state which is recorded in the NSApplication object. + */ + + if (winPtr == [NSApp tkDragTarget]) { + [NSApp setTkDragTarget:nil]; + } + if (winPtr == [NSApp tkPointerWindow]) { + NSWindow *w; + NSPoint mouse = [NSEvent mouseLocation]; + [NSApp setTkPointerWindow:nil]; + for (w in [NSApp orderedWindows]) { + if (w == deadNSWindow) { + continue; + } + if (NSPointInRect(mouse, [w frame])) { + TkWindow *winPtr2 = TkMacOSXGetTkWindow(w); + int x = mouse.x, y = TkMacOSXZeroScreenHeight() - mouse.y; + [NSApp setTkPointerWindow:winPtr2]; + Tk_UpdatePointer((Tk_Window) winPtr2, x, y, + [NSApp tkButtonState]); + break; + } + } + } + /* * Unregister the NSWindow and remove all references to it from the Tk * data structures. If the NSWindow is a child, disassociate it from * the parent. Then close and release the NSWindow. */ - deadNSWindow = (TKWindow *)wmPtr->window; if (deadNSWindow && !Tk_IsEmbedded(winPtr)) { NSWindow *parent = [deadNSWindow parentWindow]; [deadNSWindow setTkWindow:None]; @@ -1105,6 +1133,7 @@ TkWmDeadWindow( wmPtr2->hints.initial_state != WithdrawnState); if (w != deadNSWindow && isOnScreen && [w canBecomeKeyWindow]) { [w makeKeyAndOrderFront:NSApp]; + [NSApp setTkEventTarget:TkMacOSXGetTkWindow(w)]; break; } } @@ -6644,6 +6673,7 @@ TkpChangeFocus( } if (win && [win canBecomeKeyWindow]) { [win makeKeyAndOrderFront:NSApp]; + [NSApp setTkEventTarget:TkMacOSXGetTkWindow(win)]; } } |