summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorculler <culler>2021-12-20 18:46:13 (GMT)
committerculler <culler>2021-12-20 18:46:13 (GMT)
commit2fdb9f02fd6d10fb497634b0ff5acef9dd5350cb (patch)
tree74dd72f5cdad5ea660010fed3f06624787dc1669
parent8b6266dcbcfbfa6036baae36eb6875e31519f9d3 (diff)
parent774c6317321143cc524d608e9b78e8ee51cfb84e (diff)
downloadtk-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.c1
-rw-r--r--macosx/tkMacOSXMouseEvent.c39
-rw-r--r--macosx/tkMacOSXPrivate.h7
-rw-r--r--macosx/tkMacOSXWm.c32
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)];
}
}