From d2ef41555d8bb64bf21f2065a56365aa840cda77 Mon Sep 17 00:00:00 2001 From: culler Date: Sun, 19 May 2024 02:41:36 +0000 Subject: Attempt to fix [22349fc78a] for macOS. Currently only event-9.16 fails unless there is a timeout waiting for an enter or leave event. --- generic/tkGrab.c | 16 ++ generic/tkPointer.c | 5 +- generic/tkWindow.c | 51 +++++++ macosx/tkMacOSXInit.c | 12 ++ macosx/tkMacOSXMouseEvent.c | 20 ++- macosx/tkMacOSXSubwindows.c | 1 + macosx/tkMacOSXWindowEvent.c | 2 + macosx/tkMacOSXWm.c | 71 ++++++--- tests/event.test | 350 +++++++++++++++++++++++++++++++++++++------ 9 files changed, 454 insertions(+), 74 deletions(-) diff --git a/generic/tkGrab.c b/generic/tkGrab.c index 2232ba5..c5f2a3b 100644 --- a/generic/tkGrab.c +++ b/generic/tkGrab.c @@ -998,6 +998,10 @@ TkInOutEvents( { TkWindow *winPtr; int upLevels, downLevels, i, j, focus; + //fprintf(stderr, "TkInOutEvents: source is %s, destination is %s, leaveType is %d, enterType is %d\n", + // sourcePtr ? Tk_PathName(sourcePtr) : "NULL", + // destPtr ? Tk_PathName(destPtr) : "NULL", + // leaveType, enterType); /* * There are four possible cases to deal with: @@ -1025,6 +1029,7 @@ TkInOutEvents( focus = 0; } FindCommonAncestor(sourcePtr, destPtr, &upLevels, &downLevels); + //fprintf(stderr, "upLevels = %d, downLevels = %d\n", upLevels, downLevels); /* * Generate enter/leave events and add them to the grab event queue. @@ -1083,10 +1088,15 @@ TkInOutEvents( * Non-linear: neither window is an inferior of the other. */ + //fprintf(stderr, " Nonlinear path\n"); if (leaveType != 0) { + //fprintf(stderr, " Queueing leave event for %s\n", + // Tk_PathName(sourcePtr)); QUEUE(sourcePtr, leaveType, NotifyNonlinear); for (winPtr = sourcePtr->parentPtr, i = upLevels-1; i > 0; winPtr = winPtr->parentPtr, i--) { + //fprintf(stderr, " Queueing Virtual leave event for %s\n", + // Tk_PathName(winPtr)); QUEUE(winPtr, leaveType, NotifyNonlinearVirtual); } } @@ -1095,13 +1105,18 @@ TkInOutEvents( for (winPtr = destPtr->parentPtr, j = 1; j < i; winPtr = winPtr->parentPtr, j++) { } + //fprintf(stderr, " Queueing Virtual enter event for %s\n", + // Tk_PathName(winPtr)); QUEUE(winPtr, enterType, NotifyNonlinearVirtual); } if (destPtr != NULL) { + //fprintf(stderr, " Queueing enter event for %s\n", + // Tk_PathName(destPtr)); QUEUE(destPtr, enterType, NotifyNonlinear); } } } + fflush(stderr); } /* @@ -1167,6 +1182,7 @@ MovePointer2( TkInOutEvents(&event, sourcePtr, destPtr, (leaveEvents) ? LeaveNotify : 0, (enterEvents) ? EnterNotify : 0, TCL_QUEUE_MARK); } + /* *---------------------------------------------------------------------- diff --git a/generic/tkPointer.c b/generic/tkPointer.c index 905489a..2b5b40e 100644 --- a/generic/tkPointer.c +++ b/generic/tkPointer.c @@ -183,7 +183,6 @@ GenerateEnterLeave( InitializeEvent(&event, targetPtr, LeaveNotify, x, y, state, NotifyNormal); - TkInOutEvents(&event, lastWinPtr, winPtr, LeaveNotify, EnterNotify, TCL_QUEUE_TAIL); crossed = 1; @@ -228,6 +227,10 @@ Tk_UpdatePointer( unsigned changes = (state ^ tsdPtr->lastState) & ALL_BUTTONS; int type, b; unsigned mask; + //fprintf(stderr, " Tk_UpdatePointer: %s %d %d %x --> %s %d %d %x\n", + // tsdPtr->lastWinPtr ? Tk_PathName(tsdPtr->lastWinPtr): "NULL", + // tsdPtr->lastPos.x, tsdPtr->lastPos.y, tsdPtr->lastState, + // tkwin ? Tk_PathName(tkwin) : "NULL", x, y, state); pos.x = x; pos.y = y; diff --git a/generic/tkWindow.c b/generic/tkWindow.c index 5d664b9..5c3700b 100644 --- a/generic/tkWindow.c +++ b/generic/tkWindow.c @@ -1322,6 +1322,33 @@ Tk_CreateWindowFromPath( *-------------------------------------------------------------- */ + +static void SendEnterLeaveForDestroy( + Tk_Window tkwin) +{ + int x, y; + unsigned int state; + Tk_Window pointerWin; + TkWindow *containerPtr; + + XQueryPointer(NULL, None, NULL, NULL, &x, &y, NULL, NULL, &state); + pointerWin = Tk_CoordsToWindow(x, y, tkwin); + if (pointerWin == tkwin) { + //fprintf(stderr, " Pointer window is being destroyed\n"); + if (!Tk_IsTopLevel(tkwin)) { + containerPtr = TkGetContainer((TkWindow *)pointerWin); + //fprintf(stderr, " Moving pointer from topmost %s to container %s\n", + // pointerWin ? Tk_PathName(pointerWin) : "NULL", + // containerPtr ? Tk_PathName(containerPtr) : "NULL"); + Tk_UpdatePointer((Tk_Window) containerPtr, x, y, state); + } + // else { + //fprintf(stderr, " Pointer window is a toplevel\n"); + // } + } + // fflush(stderr); +} + void Tk_DestroyWindow( Tk_Window tkwin) /* Window to destroy. */ @@ -1341,6 +1368,10 @@ Tk_DestroyWindow( return; } + //fprintf(stderr, "Tk_DestroyWindow: destroying %s\n", Tk_PathName(tkwin)); + //fflush(stderr); + SendEnterLeaveForDestroy(tkwin); + winPtr->flags |= TK_ALREADY_DEAD; /* @@ -1711,6 +1742,22 @@ Tk_DestroyWindow( *-------------------------------------------------------------- */ +static void SendEnterLeaveForMap( + Tk_Window tkwin) +{ + int x, y; + unsigned int state; + Tk_Window pointerWin; + + XQueryPointer(NULL, None, NULL, NULL, &x, &y, NULL, NULL, &state); + pointerWin = Tk_CoordsToWindow(x, y, tkwin); + if (pointerWin == tkwin) { + //fprintf(stderr, " New window contains pointer.\n"); + //fflush(stderr); + Tk_UpdatePointer(tkwin, x, y, state); + } +} + void Tk_MapWindow( Tk_Window tkwin) /* Token for window to map. */ @@ -1740,6 +1787,7 @@ Tk_MapWindow( TkWmMapWindow(winPtr); return; } + winPtr->flags |= TK_MAPPED; XMapWindow(winPtr->display, winPtr->window); event.type = MapNotify; @@ -1750,6 +1798,9 @@ Tk_MapWindow( event.xmap.window = winPtr->window; event.xmap.override_redirect = winPtr->atts.override_redirect; Tk_HandleEvent(&event); + //fprintf(stderr, "Tk_MapWindow: mapped %s\n", Tk_PathName(tkwin)); + //fflush(stderr); + SendEnterLeaveForMap(tkwin); } /* diff --git a/macosx/tkMacOSXInit.c b/macosx/tkMacOSXInit.c index e6a6835..aa3cd7a 100644 --- a/macosx/tkMacOSXInit.c +++ b/macosx/tkMacOSXInit.c @@ -425,6 +425,18 @@ TCL_NORETURN void TkpExitProc( } /* + * At this point it is too late to be looking up the Tk window associated + * to any NSWindows, but it can happen. This makes sure the answer is None + * if such a query is attempted. + */ + + for (TKWindow *w in [NSApp orderedWindows]) { + if ([w respondsToSelector: @selector (tkWindow)]) { + [w setTkWindow: None]; + } + } + + /* * Tcl_Exit does not call Tcl_Finalize if there is an exit proc installed. */ diff --git a/macosx/tkMacOSXMouseEvent.c b/macosx/tkMacOSXMouseEvent.c index 9b88eb9..8d94300 100644 --- a/macosx/tkMacOSXMouseEvent.c +++ b/macosx/tkMacOSXMouseEvent.c @@ -199,6 +199,7 @@ enum { int fakeState = [NSApp tkButtonState] & ~TkGetButtonMask(Button1); int x = location.x; int y = floor(TkMacOSXZeroScreenHeight() - location.y); + //fprintf(stderr, "(1) calling Tk_UpdatePointer)\n"); fflush(stderr); Tk_UpdatePointer((Tk_Window) [NSApp tkEventTarget], x, y, fakeState); } @@ -500,18 +501,31 @@ enum { state |= TkGetButtonMask(Button1); } if (eventType == NSMouseEntered) { - Tk_UpdatePointer((Tk_Window) [NSApp tkPointerWindow], - global.x, global.y, state); + //fprintf(stderr, "handling NSMouseEntered for %s\n", + //Tk_PathName([NSApp tkPointerWindow])); + //fflush(stderr); + Tk_Window new_win = Tk_CoordsToWindow(global.x, global.y, + (Tk_Window) [NSApp tkPointerWindow]); + // WHEN SHOULD THIS CALL HAPPEN? + // It only happens for toplevels, but can happen when a window is + // deiconified, in which case the highest Tk window containing the + // mouse should be the target. + //fprintf(stderr, "(2) calling Tk_UpdatePointer)\n"); fflush(stderr); + Tk_UpdatePointer(new_win, global.x, global.y, state); } else if (eventType == NSMouseExited) { + //fprintf(stderr, "handling NSMouseExited\n"); fflush(stderr); if ([NSApp tkDragTarget]) { + //fprintf(stderr, "(3) calling Tk_UpdatePointer)\n"); fflush(stderr); Tk_UpdatePointer((Tk_Window) [NSApp tkDragTarget], global.x, global.y, state); } else { + //fprintf(stderr, "(4) calling Tk_UpdatePointer)\n"); fflush(stderr); Tk_UpdatePointer(NULL, global.x, global.y, state); } } else if (eventType == NSMouseMoved || eventType == NSLeftMouseDragged) { if ([NSApp tkPointerWindow]) { + //fprintf(stderr, "(5) calling Tk_UpdatePointer)\n"); fflush(stderr); Tk_UpdatePointer(target, global.x, global.y, state); } else { XEvent xEvent = {0}; @@ -536,6 +550,7 @@ enum { } } else { + //fprintf(stderr, "(6) calling Tk_UpdatePointer)\n"); fflush(stderr); Tk_UpdatePointer(target, global.x, global.y, state); } } else { @@ -825,6 +840,7 @@ GenerateButtonEvent( tkwin = Tk_TopCoordsToWindow(tkwin, medPtr->local.h, medPtr->local.v, &dummy, &dummy); } + //fprintf(stderr, "(7) calling Tk_UpdatePointer)\n"); fflush(stderr); Tk_UpdatePointer(tkwin, medPtr->global.h, medPtr->global.v, medPtr->state); return true; } diff --git a/macosx/tkMacOSXSubwindows.c b/macosx/tkMacOSXSubwindows.c index fb71a0c..732ed1d 100644 --- a/macosx/tkMacOSXSubwindows.c +++ b/macosx/tkMacOSXSubwindows.c @@ -197,6 +197,7 @@ XMapWindow( NSPoint viewLocation = [view convertPoint:mouse fromView:nil]; if (NSPointInRect(viewLocation, NSInsetRect([view bounds], 2, 2))) { + fprintf(stderr, "XMapWindow: calling Tk_UpdatePointer\n"); Tk_UpdatePointer((Tk_Window) winPtr, x, y, [NSApp tkButtonState]); } } else { diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c index 09112ee..4e40bb6 100644 --- a/macosx/tkMacOSXWindowEvent.c +++ b/macosx/tkMacOSXWindowEvent.c @@ -74,6 +74,8 @@ extern NSString *NSWindowDidOrderOffScreenNotification; NSView *view = [w contentView]; NSPoint viewLocation = [view convertPoint:location fromView:nil]; if (NSPointInRect(viewLocation, NSInsetRect([view bounds], 2, 2))) { + fprintf(stderr, "windowActivation calling TkUpdatePointer\n"); + fflush(stderr); Tk_UpdatePointer((Tk_Window) winPtr, x, y, [NSApp tkButtonState]); } } diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index 2fa9434..1ada289 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -911,13 +911,17 @@ void TkWmDeadWindow( TkWindow *winPtr) /* Top-level window that's being deleted. */ { + TkWindow *winPtr2; WmInfo *wmPtr = winPtr->wmInfoPtr, *wmPtr2; - TKWindow *deadNSWindow; - if (wmPtr == NULL) { return; } - + TKWindow *deadNSWindow = (TKWindow *)TkMacOSXGetNSWindowForDrawable( + Tk_WindowId(winPtr)); + //fprintf(stderr, "TkWmDeadWindow: will destroy %s\n", Tk_PathName(winPtr)); + if (deadNSWindow == NULL) { + return; + } /* *If the dead window is a transient, remove it from the container's list. */ @@ -985,31 +989,49 @@ 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. + * state which is recorded in the NSApplication object and notify Tk + * of the new pointer window. */ - 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; - } + NSPoint mouse = [NSEvent mouseLocation]; + NSWindow *w; + [NSApp setTkPointerWindow:nil]; + //fprintf(stderr, " Looking for new pointer window\n"); + winPtr2 = NULL; + + for (w in [NSApp orderedWindows]) { + if (w == deadNSWindow || w == NULL) { + continue; + } + winPtr2 = TkMacOSXGetTkWindow(w); + if (winPtr2 == NULL) { + continue; + } + if (NSPointInRect(mouse, [w frame])) { + [NSApp setTkPointerWindow: winPtr2]; + break; } } + if (winPtr2) { + /* + * We now know which toplevel will contain the pointer when the window + * is destroyed. We need to know which Tk window within the + * toplevel will contain the pointer. + */ + NSPoint local = [w tkConvertPointFromScreen: mouse]; + int top_x = floor(local.x), + top_y = floor(w.frame.size.height - local.y); + int root_x = floor(mouse.x), + root_y = floor(TkMacOSXZeroScreenHeight() - mouse.y); + int win_x, win_y; + Tk_Window target = Tk_TopCoordsToWindow((Tk_Window) winPtr2, top_x, top_y, &win_x, &win_y); + //fprintf(stderr, " new mouseWindow is %s\n", + // target ? Tk_PathName(target) : "NULL"); + Tk_UpdatePointer((Tk_Window) target, root_x, root_y, [NSApp tkButtonState]); + } +// fflush(stderr); /* * Unregister the NSWindow and remove all references to it from the Tk @@ -1017,7 +1039,7 @@ TkWmDeadWindow( * the parent. Then close and release the NSWindow. */ - if (deadNSWindow && !Tk_IsEmbedded(winPtr)) { + if (0 && deadNSWindow && winPtr && !Tk_IsEmbedded(winPtr)) { NSWindow *parent = [deadNSWindow parentWindow]; [deadNSWindow setTkWindow:None]; if (winPtr->window) { @@ -1059,9 +1081,10 @@ TkWmDeadWindow( * set tkEventTarget to NULL when there is no window to send Tk events to. */ TkWindow *newTkEventTarget = NULL; + winPtr2 = NULL; for (NSWindow *w in [NSApp orderedWindows]) { - TkWindow *winPtr2 = TkMacOSXGetTkWindow(w); + winPtr2 = TkMacOSXGetTkWindow(w); BOOL isOnScreen; if (!winPtr2 || !winPtr2->wmInfoPtr) { diff --git a/tests/event.test b/tests/event.test index 015720e..e398b87 100644 --- a/tests/event.test +++ b/tests/event.test @@ -311,6 +311,7 @@ test event-2.5(keypress) {type into text widget and then delete some text} -setu test event-2.6(keypress) {type into text widget, triple click, hit Delete key, and then type some more} -setup { deleteWindows + update idletasks } -body { set t [toplevel .t] set e [text $t.e] @@ -861,60 +862,313 @@ test event-8 {event generate with keysyms corresponding to deleteWindows } -result {OK} -test event-9.1 {enter . window by destroying a toplevel - bug b1d115fa60} -setup { - set EnterBind [bind . ] -} -body { - wm geometry . 200x200+300+300 - wm deiconify . +proc waitForWindowEvent {w event {timeout 1000}} { +# This proc is intended to overcome latency of windowing system +# notifications when toplevel windows are involved. These latencies vary +# considerably with the window manager in use, with the system load, +# with configured scheduling priorities for processes, etc ... +# Waiting for the corresponding window events evades the trouble that is +# associated with the alternative: waiting or halting the Tk process for a +# fixed amount of time (using "after ms"). With the latter strategy it's +# always a gamble how much waiting time is enough on an end user's system. +# It also leads to long fixed waiting times in order to be on the safe side. + + variable _windowEvent + + # Use counter as a unique ID to prevent subsequent waits + # from interfering with each other. + set counter [incr _windowEvent(counter)] + set _windowEvent($counter) 1 + set savedBinding [bind $w $event] + bind $w $event [list +waitForWindowEvent.signal $counter] + set afterID [after $timeout [list set _windowEvent($counter) -1]] + vwait _windowEvent($counter) + set late [expr {$_windowEvent($counter) == -1}] + bind $w $event $savedBinding + unset _windowEvent($counter) + if {$late} { + puts "waiting for $event event on $w timed out (> $timeout ms)" + } else { + after cancel $afterID + } +} +proc waitForWindowEvent.signal {counter} { +# Helper proc that records the triggering of a window event. + incr ::_windowEvent($counter) +} + +proc create_and_pack_frames {{w {}}} { + frame $w.f1 -bg blue -width 200 -height 200 + pack propagate $w.f1 0 + frame $w.f1.f2 -bg yellow -width 100 -height 100 + pack $w.f1.f2 $w.f1 -side bottom -anchor se +} + +proc setup_win_mousepointer {w} { +# Position the window and the mouse pointer as an initial state for some tests. +# The so-called "pointer window" is the $w window that will now contain the mouse pointer. + wm geometry . +700+700; # root window out of our way - must not cover windows from event-9.1* + toplevel $w + pack propagate $w 0 + wm geometry $w 300x300+100+100 + tkwait visibility $w + update; # service remaining screen drawing events (e.g. ) + set pointerWin [winfo containing [winfo pointerx $w] [winfo pointery $w]] + event generate $w -warp 1 -x 250 -y 250 +# if {[tk windowingsystem] eq "aqua"} { +# # Generate a NSMouseMoved NSevent with no mouse pointer position change. +# # This is to let event-9.1? tests pass on macOS aqua and is only a workaround +# # since macOS aqua should send the adequate NSevent by itself. +# movemouse [expr {[winfo rootx $w] + 250}] [expr {[winfo rooty $w] + 250}] +# } + if {($pointerWin ne $w) && ([tk windowingsystem] ne "aqua")} { + waitForWindowEvent $w + } else { + controlPointerWarpTiming + } +} + +test event-9.11 {pointer window container = parent} -setup { + setup_win_mousepointer .one + wm withdraw .one + create_and_pack_frames .one + wm deiconify .one + tkwait visibility .one.f1.f2 _pause 200 - toplevel .top2 -width 200 -height 200 - wm geometry .top2 +[expr {[winfo rootx .]+50}]+[expr {[winfo rooty .]+50}] - wm deiconify .top2 - raise .top2 - _pause 400 - event generate .top2 -warp 1 -x 50 -y 50 - _pause 100 - bind . {lappend res %W} - set res [list ] - destroy .top2 + bind all {append result " %d %W|"} + bind all {append result " %d %W|"} + set result "|" +} -body { + destroy .one.f1.f2 +# if {[tk windowingsystem] eq "aqua"} { +# # Generate a NSMouseMoved NSevent with no mouse pointer position change. +# # This is to let event-9.1? tests pass on macOS aqua and is only a workaround +# # since macOS aqua should send the adequate NSevent by itself. +# movemouse [expr {[winfo rootx .one] + 250}] [expr {[winfo rooty .one] + 250}] +# } + _pause 200; # service crossing events + set result +} -cleanup { + bind all {} + bind all {} + destroy .one + unset result +} -result {| NotifyInferior .one.f1|} + +test event-9.12 {pointer window container != parent} -setup { + setup_win_mousepointer .one + wm withdraw .one + create_and_pack_frames .one + pack propagate .one.f1.f2 0 + pack [frame .one.g -bg orange -width 80 -height 80] -anchor se -side bottom -in .one.f1.f2 + wm deiconify .one + tkwait visibility .one.g + event generate .one -warp 1 -x 250 -y 250 _pause 200 - set res + bind all {append result " %d %W|"} + bind all {append result " %d %W|"} + set result "|" +} -body { + destroy .one.g + _pause 200; # service crossing events -- crashes without this + set result } -cleanup { - deleteWindows - bind . $EnterBind -} -result {.} -test event-9.2 {enter toplevel window by destroying a toplevel - bug b1d115fa60} -setup { - set iconified false - if {[winfo ismapped .]} { - wm iconify . - update - set iconified true - } + bind all {} + bind all {} + destroy .one + unset result +} -result {| NotifyNonlinearVirtual .one.f1| NotifyNonlinear .one.f1.f2|} + +test event-9.13 {pointer window is a toplevel, toplevel destination} -setup { + setup_win_mousepointer .one + wm withdraw .one + toplevel .two + wm geometry .two 300x300+150+150 + wm withdraw .two + wm deiconify .one + wm deiconify .two + waitForWindowEvent .two + bind all {append result " %d %W|"} + bind all {append result " %d %W|"} + set result "|" } -body { - toplevel .top1 - wm geometry .top1 200x200+300+300 - wm deiconify .top1 - _pause 200 - toplevel .top2 -width 200 -height 200 - wm geometry .top2 +[expr {[winfo rootx .top1]+50}]+[expr {[winfo rooty .top1]+50}] + destroy .two + waitForWindowEvent .one + set result +} -cleanup { + bind all {} + bind all {} + destroy .one + unset result +} -result {| NotifyNonlinear .one|} + +test event-9.14 {pointer window is a toplevel, tk internal destination} -setup { + setup_win_mousepointer .one + wm withdraw .one + create_and_pack_frames .one + toplevel .two + wm geometry .two 300x300+150+150 + wm withdraw .two + wm deiconify .one + wm deiconify .two + waitForWindowEvent .two + bind all {append result " %d %W|"} + bind all {append result " %d %W|"} + set result "|" +} -body { + destroy .two + waitForWindowEvent .one.f1.f2 + set result +} -cleanup { + bind all {} + bind all {} + destroy .one + unset result +} -result {| NotifyNonlinearVirtual .one| NotifyNonlinearVirtual .one.f1| NotifyNonlinear .one.f1.f2|} + +test event-9.15 {pointer window is a toplevel, destination is screen root} -setup { + setup_win_mousepointer .one; # ensure the mouse pointer is where we want it to be (the .one toplevel is not itself used in this test) + toplevel .two + wm geometry .two 300x300+150+150 + wm deiconify .two + waitForWindowEvent .two + event generate .two -warp 1 -x 275 -y 275 + controlPointerWarpTiming + bind all {append result " %d %W|"} + bind all {append result " %d %W|"} + set result "|" +} -body { + destroy .two + _pause 200; # ensure servicing of all scheduled events (only events expected) + set result +} -cleanup { + bind all {} + bind all {} + destroy .one + unset result +} -result {|} + +test event-9.16 {Successive destructions (pointer window + parent), single generation of crossing events} -setup { + # Tests correctness of overwriting the dead window struct in + # TkPointerDeadWindow() and subsequent reading in GenerateEnterLeave(). + setup_win_mousepointer .one + wm withdraw .one + create_and_pack_frames .one + wm deiconify .one + tkwait visibility .one.f1.f2 _pause 200 - wm deiconify .top2 - raise .top2 - _pause 400 - event generate .top2 -warp 1 -x 50 -y 50 - _pause 100 - bind .top1 {lappend res %W} - set res [list ] - destroy .top2 + bind all {append result " %d %W|"} + bind all {append result " %d %W|"} + set result "|" +} -body { + destroy .one.f1 + _pause 200; # service crossing events + set result +} -cleanup { + bind all {} + bind all {} + destroy .one + unset result +} -result {| NotifyInferior .one|} + +test event-9.17 {Successive destructions (pointer window + parent), separate crossing events} -setup { + # Tests correctness of overwriting the dead window struct in + # TkPointerDeadWindow() and subsequent reading in GenerateEnterLeave(). + setup_win_mousepointer .one + wm withdraw .one + create_and_pack_frames .one + wm deiconify .one + tkwait visibility .one.f1.f2 _pause 200 - set res + bind all {append result " %d %W|"} + bind all {append result " %d %W|"} + set result "|" +} -body { + destroy .one.f1.f2 + _pause 200; # service crossing events + destroy .one.f1 + _pause 200; # service crossing events + set result } -cleanup { - deleteWindows ; # destroy all children of ".", this already includes .top1 - if {$iconified} { - wm deiconify . - update - } -} -result {.top1} + bind all {} + bind all {} + destroy .one + unset result +} -result {| NotifyInferior .one.f1| NotifyInferior .one|} + +test event-9.18 {Successive destructions (pointer window + ancestors including its toplevel), destination is non-root toplevel} -setup { + setup_win_mousepointer .one + toplevel .two + pack propagate .two 0 + wm geometry .two 300x300+100+100 + create_and_pack_frames .two + wm deiconify .two + waitForWindowEvent .two.f1.f2 + bind all {append result " %d %W|"} + bind all {append result " %d %W|"} + set result "|" +} -body { + destroy .two + waitForWindowEvent .one + set result +} -cleanup { + bind all {} + bind all {} + destroy .one + unset result +} -result {| NotifyNonlinear .one|} + +test event-9.19 {Successive destructions (pointer window + ancestors including its toplevel), destination is internal window, bypass root win} -setup { + setup_win_mousepointer .one; # ensure the mouse pointer is where we want it to be (the .one toplevel is not itself used in this test) + toplevel .two + pack propagate .two 0 + wm geometry .two 300x300+100+100 + create_and_pack_frames .two + wm deiconify .two + waitForWindowEvent .two.f1.f2 + toplevel .three + pack propagate .three 0 + wm geometry .three 300x300+110+110 + create_and_pack_frames .three + wm deiconify .three + waitForWindowEvent .three.f1.f2 + bind all {append result " %d %W|"} + bind all {append result " %d %W|"} + set result "|" +} -body { + destroy .three + waitForWindowEvent .two.f1.f2 + set result +} -cleanup { + bind all {} + bind all {} + destroy .two + destroy .one + unset result +} -result {| NotifyNonlinearVirtual .two| NotifyNonlinearVirtual .two.f1| NotifyNonlinear .two.f1.f2|} + +test event-9.20 {Successive destructions (pointer window + ancestors including its toplevel), destination is screen root} -setup { + setup_win_mousepointer .one; # ensure the mouse pointer is where we want it to be (the .one toplevel is not itself used in this test) + wm withdraw .one + toplevel .two + pack propagate .two 0 + wm geometry .two 300x300+100+100 + create_and_pack_frames .two + wm deiconify .two + waitForWindowEvent .two.f1.f2 + bind all {append result " %d %W|"} + bind all {append result " %d %W|"} + set result "|" +} -body { + destroy .two + _pause 200; # service events (only screen drawing events expected) + set result +} -cleanup { + bind all {} + bind all {} + destroy .one + unset result +} -result {|} # cleanup update @@ -925,6 +1179,8 @@ rename _keypress {} rename _pause {} rename _text_ind_to_x_y {} rename _get_selection {} +rename create_and_pack_frames {} +rename setup_win_mousepointer {} cleanupTests return -- cgit v0.12 From c9eed3be52a8f16837c1aaf6099edc1668739832 Mon Sep 17 00:00:00 2001 From: culler Date: Sun, 19 May 2024 03:08:05 +0000 Subject: Remove debugging print statements. --- generic/tkGrab.c | 15 --------------- generic/tkPointer.c | 4 ---- generic/tkWindow.c | 14 -------------- macosx/tkMacOSXMouseEvent.c | 15 --------------- macosx/tkMacOSXSubwindows.c | 1 - macosx/tkMacOSXWm.c | 5 ----- 6 files changed, 54 deletions(-) diff --git a/generic/tkGrab.c b/generic/tkGrab.c index c5f2a3b..c8e5253 100644 --- a/generic/tkGrab.c +++ b/generic/tkGrab.c @@ -998,10 +998,6 @@ TkInOutEvents( { TkWindow *winPtr; int upLevels, downLevels, i, j, focus; - //fprintf(stderr, "TkInOutEvents: source is %s, destination is %s, leaveType is %d, enterType is %d\n", - // sourcePtr ? Tk_PathName(sourcePtr) : "NULL", - // destPtr ? Tk_PathName(destPtr) : "NULL", - // leaveType, enterType); /* * There are four possible cases to deal with: @@ -1029,7 +1025,6 @@ TkInOutEvents( focus = 0; } FindCommonAncestor(sourcePtr, destPtr, &upLevels, &downLevels); - //fprintf(stderr, "upLevels = %d, downLevels = %d\n", upLevels, downLevels); /* * Generate enter/leave events and add them to the grab event queue. @@ -1088,15 +1083,10 @@ TkInOutEvents( * Non-linear: neither window is an inferior of the other. */ - //fprintf(stderr, " Nonlinear path\n"); if (leaveType != 0) { - //fprintf(stderr, " Queueing leave event for %s\n", - // Tk_PathName(sourcePtr)); QUEUE(sourcePtr, leaveType, NotifyNonlinear); for (winPtr = sourcePtr->parentPtr, i = upLevels-1; i > 0; winPtr = winPtr->parentPtr, i--) { - //fprintf(stderr, " Queueing Virtual leave event for %s\n", - // Tk_PathName(winPtr)); QUEUE(winPtr, leaveType, NotifyNonlinearVirtual); } } @@ -1105,18 +1095,13 @@ TkInOutEvents( for (winPtr = destPtr->parentPtr, j = 1; j < i; winPtr = winPtr->parentPtr, j++) { } - //fprintf(stderr, " Queueing Virtual enter event for %s\n", - // Tk_PathName(winPtr)); QUEUE(winPtr, enterType, NotifyNonlinearVirtual); } if (destPtr != NULL) { - //fprintf(stderr, " Queueing enter event for %s\n", - // Tk_PathName(destPtr)); QUEUE(destPtr, enterType, NotifyNonlinear); } } } - fflush(stderr); } /* diff --git a/generic/tkPointer.c b/generic/tkPointer.c index 2b5b40e..ae3bef9 100644 --- a/generic/tkPointer.c +++ b/generic/tkPointer.c @@ -227,10 +227,6 @@ Tk_UpdatePointer( unsigned changes = (state ^ tsdPtr->lastState) & ALL_BUTTONS; int type, b; unsigned mask; - //fprintf(stderr, " Tk_UpdatePointer: %s %d %d %x --> %s %d %d %x\n", - // tsdPtr->lastWinPtr ? Tk_PathName(tsdPtr->lastWinPtr): "NULL", - // tsdPtr->lastPos.x, tsdPtr->lastPos.y, tsdPtr->lastState, - // tkwin ? Tk_PathName(tkwin) : "NULL", x, y, state); pos.x = x; pos.y = y; diff --git a/generic/tkWindow.c b/generic/tkWindow.c index 5c3700b..3703d36 100644 --- a/generic/tkWindow.c +++ b/generic/tkWindow.c @@ -1334,19 +1334,11 @@ static void SendEnterLeaveForDestroy( XQueryPointer(NULL, None, NULL, NULL, &x, &y, NULL, NULL, &state); pointerWin = Tk_CoordsToWindow(x, y, tkwin); if (pointerWin == tkwin) { - //fprintf(stderr, " Pointer window is being destroyed\n"); if (!Tk_IsTopLevel(tkwin)) { containerPtr = TkGetContainer((TkWindow *)pointerWin); - //fprintf(stderr, " Moving pointer from topmost %s to container %s\n", - // pointerWin ? Tk_PathName(pointerWin) : "NULL", - // containerPtr ? Tk_PathName(containerPtr) : "NULL"); Tk_UpdatePointer((Tk_Window) containerPtr, x, y, state); } - // else { - //fprintf(stderr, " Pointer window is a toplevel\n"); - // } } - // fflush(stderr); } void @@ -1368,8 +1360,6 @@ Tk_DestroyWindow( return; } - //fprintf(stderr, "Tk_DestroyWindow: destroying %s\n", Tk_PathName(tkwin)); - //fflush(stderr); SendEnterLeaveForDestroy(tkwin); winPtr->flags |= TK_ALREADY_DEAD; @@ -1752,8 +1742,6 @@ static void SendEnterLeaveForMap( XQueryPointer(NULL, None, NULL, NULL, &x, &y, NULL, NULL, &state); pointerWin = Tk_CoordsToWindow(x, y, tkwin); if (pointerWin == tkwin) { - //fprintf(stderr, " New window contains pointer.\n"); - //fflush(stderr); Tk_UpdatePointer(tkwin, x, y, state); } } @@ -1798,8 +1786,6 @@ Tk_MapWindow( event.xmap.window = winPtr->window; event.xmap.override_redirect = winPtr->atts.override_redirect; Tk_HandleEvent(&event); - //fprintf(stderr, "Tk_MapWindow: mapped %s\n", Tk_PathName(tkwin)); - //fflush(stderr); SendEnterLeaveForMap(tkwin); } diff --git a/macosx/tkMacOSXMouseEvent.c b/macosx/tkMacOSXMouseEvent.c index 8d94300..f942485 100644 --- a/macosx/tkMacOSXMouseEvent.c +++ b/macosx/tkMacOSXMouseEvent.c @@ -199,7 +199,6 @@ enum { int fakeState = [NSApp tkButtonState] & ~TkGetButtonMask(Button1); int x = location.x; int y = floor(TkMacOSXZeroScreenHeight() - location.y); - //fprintf(stderr, "(1) calling Tk_UpdatePointer)\n"); fflush(stderr); Tk_UpdatePointer((Tk_Window) [NSApp tkEventTarget], x, y, fakeState); } @@ -501,31 +500,19 @@ enum { state |= TkGetButtonMask(Button1); } if (eventType == NSMouseEntered) { - //fprintf(stderr, "handling NSMouseEntered for %s\n", - //Tk_PathName([NSApp tkPointerWindow])); - //fflush(stderr); Tk_Window new_win = Tk_CoordsToWindow(global.x, global.y, (Tk_Window) [NSApp tkPointerWindow]); - // WHEN SHOULD THIS CALL HAPPEN? - // It only happens for toplevels, but can happen when a window is - // deiconified, in which case the highest Tk window containing the - // mouse should be the target. - //fprintf(stderr, "(2) calling Tk_UpdatePointer)\n"); fflush(stderr); Tk_UpdatePointer(new_win, global.x, global.y, state); } else if (eventType == NSMouseExited) { - //fprintf(stderr, "handling NSMouseExited\n"); fflush(stderr); if ([NSApp tkDragTarget]) { - //fprintf(stderr, "(3) calling Tk_UpdatePointer)\n"); fflush(stderr); Tk_UpdatePointer((Tk_Window) [NSApp tkDragTarget], global.x, global.y, state); } else { - //fprintf(stderr, "(4) calling Tk_UpdatePointer)\n"); fflush(stderr); Tk_UpdatePointer(NULL, global.x, global.y, state); } } else if (eventType == NSMouseMoved || eventType == NSLeftMouseDragged) { if ([NSApp tkPointerWindow]) { - //fprintf(stderr, "(5) calling Tk_UpdatePointer)\n"); fflush(stderr); Tk_UpdatePointer(target, global.x, global.y, state); } else { XEvent xEvent = {0}; @@ -550,7 +537,6 @@ enum { } } else { - //fprintf(stderr, "(6) calling Tk_UpdatePointer)\n"); fflush(stderr); Tk_UpdatePointer(target, global.x, global.y, state); } } else { @@ -840,7 +826,6 @@ GenerateButtonEvent( tkwin = Tk_TopCoordsToWindow(tkwin, medPtr->local.h, medPtr->local.v, &dummy, &dummy); } - //fprintf(stderr, "(7) calling Tk_UpdatePointer)\n"); fflush(stderr); Tk_UpdatePointer(tkwin, medPtr->global.h, medPtr->global.v, medPtr->state); return true; } diff --git a/macosx/tkMacOSXSubwindows.c b/macosx/tkMacOSXSubwindows.c index 732ed1d..fb71a0c 100644 --- a/macosx/tkMacOSXSubwindows.c +++ b/macosx/tkMacOSXSubwindows.c @@ -197,7 +197,6 @@ XMapWindow( NSPoint viewLocation = [view convertPoint:mouse fromView:nil]; if (NSPointInRect(viewLocation, NSInsetRect([view bounds], 2, 2))) { - fprintf(stderr, "XMapWindow: calling Tk_UpdatePointer\n"); Tk_UpdatePointer((Tk_Window) winPtr, x, y, [NSApp tkButtonState]); } } else { diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index 1ada289..952da39 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -918,7 +918,6 @@ TkWmDeadWindow( } TKWindow *deadNSWindow = (TKWindow *)TkMacOSXGetNSWindowForDrawable( Tk_WindowId(winPtr)); - //fprintf(stderr, "TkWmDeadWindow: will destroy %s\n", Tk_PathName(winPtr)); if (deadNSWindow == NULL) { return; } @@ -998,7 +997,6 @@ TkWmDeadWindow( NSPoint mouse = [NSEvent mouseLocation]; NSWindow *w; [NSApp setTkPointerWindow:nil]; - //fprintf(stderr, " Looking for new pointer window\n"); winPtr2 = NULL; for (w in [NSApp orderedWindows]) { @@ -1027,11 +1025,8 @@ TkWmDeadWindow( root_y = floor(TkMacOSXZeroScreenHeight() - mouse.y); int win_x, win_y; Tk_Window target = Tk_TopCoordsToWindow((Tk_Window) winPtr2, top_x, top_y, &win_x, &win_y); - //fprintf(stderr, " new mouseWindow is %s\n", - // target ? Tk_PathName(target) : "NULL"); Tk_UpdatePointer((Tk_Window) target, root_x, root_y, [NSApp tkButtonState]); } -// fflush(stderr); /* * Unregister the NSWindow and remove all references to it from the Tk -- cgit v0.12 From 7312614099fe545740036db6a632e1cdebc04e88 Mon Sep 17 00:00:00 2001 From: culler Date: Sun, 19 May 2024 21:07:21 +0000 Subject: All event-9.xy tests now pass, but 9.13 fails one time out of five. --- generic/tkPointer.c | 1 + generic/tkWindow.c | 23 ++++++++++++++++++----- macosx/tkMacOSXWindowEvent.c | 20 +++++++++----------- macosx/tkMacOSXWm.c | 10 +++++----- tests/event.test | 6 +++--- 5 files changed, 36 insertions(+), 24 deletions(-) diff --git a/generic/tkPointer.c b/generic/tkPointer.c index ae3bef9..be05b06 100644 --- a/generic/tkPointer.c +++ b/generic/tkPointer.c @@ -45,6 +45,7 @@ static int GenerateEnterLeave(TkWindow *winPtr, int x, int y, static void InitializeEvent(XEvent *eventPtr, TkWindow *winPtr, int type, int x, int y, int state, int detail); static void UpdateCursor(TkWindow *winPtr); + /* *---------------------------------------------------------------------- diff --git a/generic/tkWindow.c b/generic/tkWindow.c index 3703d36..90a20f2 100644 --- a/generic/tkWindow.c +++ b/generic/tkWindow.c @@ -215,6 +215,7 @@ static int Initialize(Tcl_Interp *interp); static int NameWindow(Tcl_Interp *interp, TkWindow *winPtr, TkWindow *parentPtr, const char *name); static void UnlinkWindow(TkWindow *winPtr); + /* *---------------------------------------------------------------------- @@ -1322,15 +1323,15 @@ Tk_CreateWindowFromPath( *-------------------------------------------------------------- */ - static void SendEnterLeaveForDestroy( Tk_Window tkwin) { +#if defined(MAC_OSX_TK) || defined(_WIN32) int x, y; unsigned int state; Tk_Window pointerWin; TkWindow *containerPtr; - + XQueryPointer(NULL, None, NULL, NULL, &x, &y, NULL, NULL, &state); pointerWin = Tk_CoordsToWindow(x, y, tkwin); if (pointerWin == tkwin) { @@ -1338,7 +1339,15 @@ static void SendEnterLeaveForDestroy( containerPtr = TkGetContainer((TkWindow *)pointerWin); Tk_UpdatePointer((Tk_Window) containerPtr, x, y, state); } + else if (pointerWin) { + TkWmDeadWindow((TkWindow *) pointerWin); + } } + + if (pointerWin && (tkwin == Tk_Parent(pointerWin))) { + Tk_UpdatePointer(Tk_Parent(tkwin), x, y, state); + } +#endif } void @@ -1360,7 +1369,9 @@ Tk_DestroyWindow( return; } - SendEnterLeaveForDestroy(tkwin); + if ((winPtr->flags & TK_DONT_DESTROY_WINDOW) == 0) { + SendEnterLeaveForDestroy(tkwin); + } winPtr->flags |= TK_ALREADY_DEAD; @@ -1532,7 +1543,7 @@ Tk_DestroyWindow( * Cleanup the data structures associated with this window. */ - if (winPtr->flags & TK_WIN_MANAGED) { + if (winPtr->wmInfoPtr && (winPtr->flags & TK_WIN_MANAGED)) { TkWmDeadWindow(winPtr); } else if (winPtr->flags & TK_WM_COLORMAP_WINDOW) { TkWmRemoveFromColormapWindows(winPtr); @@ -1735,6 +1746,7 @@ Tk_DestroyWindow( static void SendEnterLeaveForMap( Tk_Window tkwin) { +#if defined(MAC_OSX_TK) || defined(_WIN32) int x, y; unsigned int state; Tk_Window pointerWin; @@ -1744,6 +1756,7 @@ static void SendEnterLeaveForMap( if (pointerWin == tkwin) { Tk_UpdatePointer(tkwin, x, y, state); } +#endif } void @@ -2634,7 +2647,7 @@ Tk_RestackWindow( TkWindow *otherPtr = (TkWindow *) other; /* - * Special case: if winPtr is a top-level window then just find the + * Special case: if winPtr is a toplevel window then just find the * top-level ancestor of otherPtr and restack winPtr above otherPtr * without changing any of Tk's childLists. */ diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c index 4e40bb6..41c9ede 100644 --- a/macosx/tkMacOSXWindowEvent.c +++ b/macosx/tkMacOSXWindowEvent.c @@ -74,8 +74,6 @@ extern NSString *NSWindowDidOrderOffScreenNotification; NSView *view = [w contentView]; NSPoint viewLocation = [view convertPoint:location fromView:nil]; if (NSPointInRect(viewLocation, NSInsetRect([view bounds], 2, 2))) { - fprintf(stderr, "windowActivation calling TkUpdatePointer\n"); - fflush(stderr); Tk_UpdatePointer((Tk_Window) winPtr, x, y, [NSApp tkButtonState]); } } @@ -252,15 +250,15 @@ extern NSString *NSWindowDidOrderOffScreenNotification; } } -- (void) windowMapped: (NSNotification *) notification -{ - NSWindow *w = [notification object]; - TkWindow *winPtr = TkMacOSXGetTkWindow(w); +//- (void) windowMapped: (NSNotification *) notification +//{ +// NSWindow *w = [notification object]; +// TkWindow *winPtr = TkMacOSXGetTkWindow(w); - if (winPtr) { - while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {} - } -} +// if (winPtr) { +// while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {} +// } +//} - (void) windowLiveResize: (NSNotification *) notification { @@ -306,7 +304,7 @@ extern NSString *NSWindowDidOrderOffScreenNotification; observe(NSWindowDidResizeNotification, windowBoundsChanged:); observe(NSWindowDidDeminiaturizeNotification, windowExpanded:); observe(NSWindowDidMiniaturizeNotification, windowCollapsed:); - observe(NSWindowWillOrderOnScreenNotification, windowMapped:); + //observe(NSWindowWillOrderOnScreenNotification, windowMapped:); observe(NSWindowDidOrderOnScreenNotification, windowBecameVisible:); observe(NSWindowWillStartLiveResizeNotification, windowLiveResize:); observe(NSWindowDidEndLiveResizeNotification, windowLiveResize:); diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index 952da39..c771ec3 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -897,12 +897,15 @@ TkWmUnmapWindow( * * This procedure is invoked when a top-level window is about to be * deleted. It cleans up the wm-related data structures for the window. + * If the dead window contains the pointer, TkUpdatePointer is called + * to tell Tk which window will be the new pointer window. * * Results: * None. * * Side effects: - * The WmInfo structure for winPtr gets freed up. + * The WmInfo structure for winPtr gets freed. Tk's cached pointer + * window may change. * *---------------------------------------------------------------------- */ @@ -913,9 +916,6 @@ TkWmDeadWindow( { TkWindow *winPtr2; WmInfo *wmPtr = winPtr->wmInfoPtr, *wmPtr2; - if (wmPtr == NULL) { - return; - } TKWindow *deadNSWindow = (TKWindow *)TkMacOSXGetNSWindowForDrawable( Tk_WindowId(winPtr)); if (deadNSWindow == NULL) { @@ -2037,7 +2037,7 @@ WmForgetCmd( macWin->toplevel->referenceCount++; macWin->flags &= ~TK_HOST_EXISTS; - TkWmDeadWindow(winPtr); + //TkWmDeadWindow(winPtr); RemapWindows(winPtr, (MacDrawable *)winPtr->parentPtr->window); /* diff --git a/tests/event.test b/tests/event.test index e398b87..2958850 100644 --- a/tests/event.test +++ b/tests/event.test @@ -887,7 +887,7 @@ proc waitForWindowEvent {w event {timeout 1000}} { bind $w $event $savedBinding unset _windowEvent($counter) if {$late} { - puts "waiting for $event event on $w timed out (> $timeout ms)" + puts stderr "wait for $event event on $w timed out (> $timeout ms)" } else { after cancel $afterID } @@ -902,6 +902,7 @@ proc create_and_pack_frames {{w {}}} { pack propagate $w.f1 0 frame $w.f1.f2 -bg yellow -width 100 -height 100 pack $w.f1.f2 $w.f1 -side bottom -anchor se + update idletasks } proc setup_win_mousepointer {w} { @@ -1149,7 +1150,7 @@ test event-9.19 {Successive destructions (pointer window + ancestors including i test event-9.20 {Successive destructions (pointer window + ancestors including its toplevel), destination is screen root} -setup { setup_win_mousepointer .one; # ensure the mouse pointer is where we want it to be (the .one toplevel is not itself used in this test) - wm withdraw .one + destroy .one toplevel .two pack propagate .two 0 wm geometry .two 300x300+100+100 @@ -1166,7 +1167,6 @@ test event-9.20 {Successive destructions (pointer window + ancestors including i } -cleanup { bind all {} bind all {} - destroy .one unset result } -result {|} -- cgit v0.12 From 5a43993cb3259453bb802dfbb09cd9d88afd3201 Mon Sep 17 00:00:00 2001 From: culler Date: Sun, 19 May 2024 21:38:16 +0000 Subject: Remove call to TkPointerDeadWindow in macOS and simplify 9.13 so it tests the same thing but fails less often. --- macosx/tkMacOSXSubwindows.c | 1 - tests/event.test | 2 -- 2 files changed, 3 deletions(-) diff --git a/macosx/tkMacOSXSubwindows.c b/macosx/tkMacOSXSubwindows.c index fb71a0c..b3eab4a 100644 --- a/macosx/tkMacOSXSubwindows.c +++ b/macosx/tkMacOSXSubwindows.c @@ -62,7 +62,6 @@ XDestroyWindow( * deleting is being tracked by the grab code. */ - TkPointerDeadWindow(macWin->winPtr); TkMacOSXSelDeadWindow(macWin->winPtr); macWin->toplevel->referenceCount--; diff --git a/tests/event.test b/tests/event.test index 2958850..6388533 100644 --- a/tests/event.test +++ b/tests/event.test @@ -982,11 +982,9 @@ test event-9.12 {pointer window container != parent} -setup { test event-9.13 {pointer window is a toplevel, toplevel destination} -setup { setup_win_mousepointer .one - wm withdraw .one toplevel .two wm geometry .two 300x300+150+150 wm withdraw .two - wm deiconify .one wm deiconify .two waitForWindowEvent .two bind all {append result " %d %W|"} -- cgit v0.12 From 32eb23bc4d60fab1c8691f1afce5a10a05c70365 Mon Sep 17 00:00:00 2001 From: culler Date: Mon, 20 May 2024 15:41:09 +0000 Subject: Don't pass a NULL display and None window to XQueryPointer. --- generic/tkWindow.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/generic/tkWindow.c b/generic/tkWindow.c index 90a20f2..e322bb4 100644 --- a/generic/tkWindow.c +++ b/generic/tkWindow.c @@ -1332,7 +1332,8 @@ static void SendEnterLeaveForDestroy( Tk_Window pointerWin; TkWindow *containerPtr; - XQueryPointer(NULL, None, NULL, NULL, &x, &y, NULL, NULL, &state); + XQueryPointer(Tk_Display(tkwin), None, NULL, NULL, &x, &y, + NULL, NULL, &state); pointerWin = Tk_CoordsToWindow(x, y, tkwin); if (pointerWin == tkwin) { if (!Tk_IsTopLevel(tkwin)) { @@ -1751,7 +1752,8 @@ static void SendEnterLeaveForMap( unsigned int state; Tk_Window pointerWin; - XQueryPointer(NULL, None, NULL, NULL, &x, &y, NULL, NULL, &state); + XQueryPointer(Tk_Display(tkwin), None, NULL, NULL, &x, &y, + NULL, NULL, &state); pointerWin = Tk_CoordsToWindow(x, y, tkwin); if (pointerWin == tkwin) { Tk_UpdatePointer(tkwin, x, y, state); -- cgit v0.12 From 080aeeed22a914bdf8f1de650e6a4f2c34824104 Mon Sep 17 00:00:00 2001 From: culler Date: Mon, 20 May 2024 23:04:54 +0000 Subject: Restore the call to TkPointerDeadWindow - Windows needs it; probably macOS does too. --- macosx/tkMacOSXSubwindows.c | 1 + 1 file changed, 1 insertion(+) diff --git a/macosx/tkMacOSXSubwindows.c b/macosx/tkMacOSXSubwindows.c index b3eab4a..0e4820e 100644 --- a/macosx/tkMacOSXSubwindows.c +++ b/macosx/tkMacOSXSubwindows.c @@ -63,6 +63,7 @@ XDestroyWindow( */ TkMacOSXSelDeadWindow(macWin->winPtr); + TkPointerDeadWindow(macWin->winPtr); macWin->toplevel->referenceCount--; if (!Tk_IsTopLevel(macWin->winPtr)) { -- cgit v0.12 From e4fbaea258605ad01892f783375433c8bf613270 Mon Sep 17 00:00:00 2001 From: culler Date: Tue, 21 May 2024 22:42:45 +0000 Subject: Only 9.13, 9.14. and 9.19 fail on windows. Debug output included. --- generic/tkGrab.c | 21 +++++++++++++++++++-- generic/tkPointer.c | 11 +++++++++-- generic/tkWindow.c | 5 ++--- tests/event.test | 11 ++++++++++- win/tkWinWm.c | 39 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 79 insertions(+), 8 deletions(-) diff --git a/generic/tkGrab.c b/generic/tkGrab.c index c8e5253..b4228bd 100644 --- a/generic/tkGrab.c +++ b/generic/tkGrab.c @@ -998,6 +998,10 @@ TkInOutEvents( { TkWindow *winPtr; int upLevels, downLevels, i, j, focus; +#define NAME(w) (w ? Tk_PathName(w) : "NULL") + + fprintf(stderr, "TkInOutEvents: %s -> %s\n", + NAME(sourcePtr), NAME(destPtr)); /* * There are four possible cases to deal with: @@ -1029,7 +1033,7 @@ TkInOutEvents( /* * Generate enter/leave events and add them to the grab event queue. */ - + #define QUEUE(w, t, d) \ if (w->window != None) { \ eventPtr->type = t; \ @@ -1043,19 +1047,24 @@ TkInOutEvents( Tk_QueueWindowEvent(eventPtr, position); \ } +#define DBGEV(w, t, d) fprintf(stderr, " Queueing %s %s for %s\n", t, d, NAME(w)) + if (downLevels == 0) { /* * SourcePtr is an inferior of destPtr. */ if (leaveType != 0) { + DBGEV(sourcePtr, "", "NotifyAncestor"); QUEUE(sourcePtr, leaveType, NotifyAncestor); for (winPtr = sourcePtr->parentPtr, i = upLevels-1; i > 0; winPtr = winPtr->parentPtr, i--) { + DBGEV(winPtr, "", "NotifyVirtual"); QUEUE(winPtr, leaveType, NotifyVirtual); } } if ((enterType != 0) && (destPtr != NULL)) { + DBGEV(destPtr, "", "NotifyVirtual"); QUEUE(destPtr, enterType, NotifyInferior); } } else if (upLevels == 0) { @@ -1064,6 +1073,7 @@ TkInOutEvents( */ if ((leaveType != 0) && (sourcePtr != NULL)) { + DBGEV(sourcePtr, "", "NotifyInferior"); QUEUE(sourcePtr, leaveType, NotifyInferior); } if (enterType != 0) { @@ -1072,9 +1082,11 @@ TkInOutEvents( winPtr = winPtr->parentPtr, j++) { /* empty */ } + DBGEV(winPtr, "", "NotifyVirtual"); QUEUE(winPtr, enterType, NotifyVirtual); } if (destPtr != NULL) { + DBGEV(winPtr, "", "NotifyVirtual"); QUEUE(destPtr, enterType, NotifyAncestor); } } @@ -1084,10 +1096,12 @@ TkInOutEvents( */ if (leaveType != 0) { + DBGEV(sourcePtr, "", "NotifyNonlinear"); QUEUE(sourcePtr, leaveType, NotifyNonlinear); for (winPtr = sourcePtr->parentPtr, i = upLevels-1; i > 0; winPtr = winPtr->parentPtr, i--) { - QUEUE(winPtr, leaveType, NotifyNonlinearVirtual); + DBGEV(winPtr, "", "NotifyNonlinearVirtual"); + QUEUE(winPtr, leaveType, NotifyNonlinearVirtual); } } if (enterType != 0) { @@ -1095,13 +1109,16 @@ TkInOutEvents( for (winPtr = destPtr->parentPtr, j = 1; j < i; winPtr = winPtr->parentPtr, j++) { } + DBGEV(winPtr, "", "NotifyNonlinearVirtual"); QUEUE(winPtr, enterType, NotifyNonlinearVirtual); } if (destPtr != NULL) { + DBGEV(destPtr, "", "NotifyNonlinear"); QUEUE(destPtr, enterType, NotifyNonlinear); } } } + fflush(stderr); } /* diff --git a/generic/tkPointer.c b/generic/tkPointer.c index be05b06..df26de1 100644 --- a/generic/tkPointer.c +++ b/generic/tkPointer.c @@ -228,7 +228,10 @@ Tk_UpdatePointer( unsigned changes = (state ^ tsdPtr->lastState) & ALL_BUTTONS; int type, b; unsigned mask; - + fprintf(stderr, "TkUpdatePointer: %s -> %s\n", + tsdPtr->lastWinPtr ? Tk_PathName(tsdPtr->lastWinPtr) : "NULL", + tkwin ? Tk_PathName(tkwin) : "NULL"); + fflush(stderr); pos.x = x; pos.y = y; @@ -493,8 +496,11 @@ TkPointerDeadWindow( { ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - + fprintf(stderr, "TkPointerDeadWindow: %s\n", winPtr ? Tk_PathName(winPtr) : "NULL"); if (winPtr == tsdPtr->lastWinPtr) { + //This fails on Windows because the windows version of TkWnDeadWindow + //does not (yet) call TkUpdatePointer when a dead toplevel contains the + //pointer. tsdPtr->lastWinPtr = TkGetContainer(winPtr); } if (winPtr == tsdPtr->grabWinPtr) { @@ -514,6 +520,7 @@ TkPointerDeadWindow( TkpSetCapture(NULL); } } + fflush(stderr); } /* diff --git a/generic/tkWindow.c b/generic/tkWindow.c index e322bb4..e8c56dd 100644 --- a/generic/tkWindow.c +++ b/generic/tkWindow.c @@ -1328,12 +1328,11 @@ static void SendEnterLeaveForDestroy( { #if defined(MAC_OSX_TK) || defined(_WIN32) int x, y; - unsigned int state; + unsigned int state = TkWinGetModifierState(); Tk_Window pointerWin; TkWindow *containerPtr; - XQueryPointer(Tk_Display(tkwin), None, NULL, NULL, &x, &y, - NULL, NULL, &state); + TkGetPointerCoords(NULL, &x, &y); pointerWin = Tk_CoordsToWindow(x, y, tkwin); if (pointerWin == tkwin) { if (!Tk_IsTopLevel(tkwin)) { diff --git a/tests/event.test b/tests/event.test index 6388533..42f28f5 100644 --- a/tests/event.test +++ b/tests/event.test @@ -873,6 +873,7 @@ proc waitForWindowEvent {w event {timeout 1000}} { # always a gamble how much waiting time is enough on an end user's system. # It also leads to long fixed waiting times in order to be on the safe side. + puts stderr "Waiting for $event on $w" variable _windowEvent # Use counter as a unique ID to prevent subsequent waits @@ -890,6 +891,7 @@ proc waitForWindowEvent {w event {timeout 1000}} { puts stderr "wait for $event event on $w timed out (> $timeout ms)" } else { after cancel $afterID + puts stderr "Event received" } } proc waitForWindowEvent.signal {counter} { @@ -981,6 +983,7 @@ test event-9.12 {pointer window container != parent} -setup { } -result {| NotifyNonlinearVirtual .one.f1| NotifyNonlinear .one.f1.f2|} test event-9.13 {pointer window is a toplevel, toplevel destination} -setup { + puts stderr "9.13 setup started" setup_win_mousepointer .one toplevel .two wm geometry .two 300x300+150+150 @@ -989,11 +992,14 @@ test event-9.13 {pointer window is a toplevel, toplevel destination} -setup { waitForWindowEvent .two bind all {append result " %d %W|"} bind all {append result " %d %W|"} - set result "|" + set result | + puts stderr "9.13 setup done" } -body { + puts stderr "9.13 body started - destroying .two" destroy .two waitForWindowEvent .one set result + puts stderr "9.13 body finished" } -cleanup { bind all {} bind all {} @@ -1002,6 +1008,7 @@ test event-9.13 {pointer window is a toplevel, toplevel destination} -setup { } -result {| NotifyNonlinear .one|} test event-9.14 {pointer window is a toplevel, tk internal destination} -setup { + puts stderr "9.14 setup" setup_win_mousepointer .one wm withdraw .one create_and_pack_frames .one @@ -1015,9 +1022,11 @@ test event-9.14 {pointer window is a toplevel, tk internal destination} -setup { bind all {append result " %d %W|"} set result "|" } -body { + puts stderr "9.14 body" destroy .two waitForWindowEvent .one.f1.f2 set result + puts stderr "9.14 body finished" } -cleanup { bind all {} bind all {} diff --git a/win/tkWinWm.c b/win/tkWinWm.c index 90503a6..146b82b 100644 --- a/win/tkWinWm.c +++ b/win/tkWinWm.c @@ -2577,6 +2577,36 @@ TkpWmGetState( *-------------------------------------------------------------- */ +static void CheckForPointer(TkWindow *winPtr) +{ + Display *display = Tk_Display(winPtr); + POINT mouse; + unsigned int state = TkWinGetModifierState(); + TkWindow **windows = TkWmStackorderToplevel(winPtr->mainPtr->winPtr); + TkWindow **w; + TkGetPointerCoords(NULL, &mouse.x, &mouse.y); + fprintf(stderr, "CheckForPointer: %s with mouse @(%d, %d)\n", + Tk_PathName(winPtr), mouse.x, mouse.y); + if (windows != NULL) { + for (w = windows; *w ; w++) { + RECT windowRect; + HWND hwnd = Tk_GetHWND(Tk_WindowId((Tk_Window) *w)); + fprintf(stderr, " Checking %s\n", Tk_PathName(*w)); + if (GetWindowRect(hwnd, &windowRect) == 0) { + continue; + } + if (winPtr != *w && PtInRect(&windowRect, mouse)) { + fprintf(stderr, "Pointer is in %s. Calling Tk_UpdatePointer\n", + Tk_PathName(*w)); + Tk_UpdatePointer((Tk_Window) *w, mouse.x, mouse.y, state); + break; + } + } + ckfree(windows); + } + fflush(stderr); +} + void TkWmDeadWindow( TkWindow *winPtr) /* Top-level window that's being deleted. */ @@ -2715,6 +2745,15 @@ TkWmDeadWindow( DecrIconRefCount(wmPtr->iconPtr); } + /* + * Check if the dead window is a toplevel containing the pointer. If so, + * find the window which will inherit the pointer and call + * TkUpdatePointer. + */ + + CheckForPointer(winPtr); + //TkPointerDeadWindow(winPtr); + ckfree(wmPtr); winPtr->wmInfoPtr = NULL; } -- cgit v0.12 From ec44aa0c277d6c671ec0024785197e2f2619993a Mon Sep 17 00:00:00 2001 From: culler Date: Wed, 22 May 2024 02:44:54 +0000 Subject: All event tests now pass on Windows --- tests/event.test | 20 ++++++-------------- win/tkWinWm.c | 12 ++++-------- 2 files changed, 10 insertions(+), 22 deletions(-) diff --git a/tests/event.test b/tests/event.test index 42f28f5..f24c3c6 100644 --- a/tests/event.test +++ b/tests/event.test @@ -873,7 +873,6 @@ proc waitForWindowEvent {w event {timeout 1000}} { # always a gamble how much waiting time is enough on an end user's system. # It also leads to long fixed waiting times in order to be on the safe side. - puts stderr "Waiting for $event on $w" variable _windowEvent # Use counter as a unique ID to prevent subsequent waits @@ -891,7 +890,6 @@ proc waitForWindowEvent {w event {timeout 1000}} { puts stderr "wait for $event event on $w timed out (> $timeout ms)" } else { after cancel $afterID - puts stderr "Event received" } } proc waitForWindowEvent.signal {counter} { @@ -983,32 +981,28 @@ test event-9.12 {pointer window container != parent} -setup { } -result {| NotifyNonlinearVirtual .one.f1| NotifyNonlinear .one.f1.f2|} test event-9.13 {pointer window is a toplevel, toplevel destination} -setup { - puts stderr "9.13 setup started" setup_win_mousepointer .one toplevel .two wm geometry .two 300x300+150+150 wm withdraw .two wm deiconify .two waitForWindowEvent .two - bind all {append result " %d %W|"} - bind all {append result " %d %W|"} + bind all {append result " %d %W|" ; puts stderr "=leave=" } + bind all {append result " %d %W|" ; puts stderr "-enter=" } set result | - puts stderr "9.13 setup done" } -body { - puts stderr "9.13 body started - destroying .two" destroy .two waitForWindowEvent .one + # destroying .one here instead of in cleanup makes the test pass + destroy .one set result - puts stderr "9.13 body finished" } -cleanup { bind all {} bind all {} - destroy .one unset result } -result {| NotifyNonlinear .one|} test event-9.14 {pointer window is a toplevel, tk internal destination} -setup { - puts stderr "9.14 setup" setup_win_mousepointer .one wm withdraw .one create_and_pack_frames .one @@ -1022,15 +1016,13 @@ test event-9.14 {pointer window is a toplevel, tk internal destination} -setup { bind all {append result " %d %W|"} set result "|" } -body { - puts stderr "9.14 body" destroy .two waitForWindowEvent .one.f1.f2 - set result - puts stderr "9.14 body finished" -} -cleanup { bind all {} bind all {} destroy .one + set result +} -cleanup { unset result } -result {| NotifyNonlinearVirtual .one| NotifyNonlinearVirtual .one.f1| NotifyNonlinear .one.f1.f2|} diff --git a/win/tkWinWm.c b/win/tkWinWm.c index 146b82b..a550302 100644 --- a/win/tkWinWm.c +++ b/win/tkWinWm.c @@ -2585,20 +2585,18 @@ static void CheckForPointer(TkWindow *winPtr) TkWindow **windows = TkWmStackorderToplevel(winPtr->mainPtr->winPtr); TkWindow **w; TkGetPointerCoords(NULL, &mouse.x, &mouse.y); - fprintf(stderr, "CheckForPointer: %s with mouse @(%d, %d)\n", - Tk_PathName(winPtr), mouse.x, mouse.y); if (windows != NULL) { for (w = windows; *w ; w++) { RECT windowRect; HWND hwnd = Tk_GetHWND(Tk_WindowId((Tk_Window) *w)); - fprintf(stderr, " Checking %s\n", Tk_PathName(*w)); if (GetWindowRect(hwnd, &windowRect) == 0) { continue; } if (winPtr != *w && PtInRect(&windowRect, mouse)) { - fprintf(stderr, "Pointer is in %s. Calling Tk_UpdatePointer\n", - Tk_PathName(*w)); - Tk_UpdatePointer((Tk_Window) *w, mouse.x, mouse.y, state); + Tk_Window target = Tk_CoordsToWindow(mouse.x, mouse.y, + (Tk_Window) *w); + Tk_UpdatePointer((Tk_Window) target, + mouse.x, mouse.y, state); break; } } @@ -6710,8 +6708,6 @@ TkWmStackorderToplevelEnumProc( TkWmStackorderToplevelPair *pair = (TkWmStackorderToplevelPair *) lParam; - /*fprintf(stderr, "Looking up HWND %d\n", hwnd);*/ - hPtr = Tcl_FindHashEntry(pair->table, (char *) hwnd); if (hPtr != NULL) { childWinPtr = (TkWindow *)Tcl_GetHashValue(hPtr); -- cgit v0.12 From 9a54c3a18c796aa1ec12622752092c15a85b2e54 Mon Sep 17 00:00:00 2001 From: culler Date: Wed, 22 May 2024 03:16:50 +0000 Subject: Remove debugging code. Issues remain with macOS for other tests in event.test. --- generic/tkGrab.c | 16 ---------------- generic/tkPointer.c | 9 +-------- generic/tkWindow.c | 5 +++-- tests/event.test | 4 ++-- 4 files changed, 6 insertions(+), 28 deletions(-) diff --git a/generic/tkGrab.c b/generic/tkGrab.c index b4228bd..2c7c6ab 100644 --- a/generic/tkGrab.c +++ b/generic/tkGrab.c @@ -998,10 +998,6 @@ TkInOutEvents( { TkWindow *winPtr; int upLevels, downLevels, i, j, focus; -#define NAME(w) (w ? Tk_PathName(w) : "NULL") - - fprintf(stderr, "TkInOutEvents: %s -> %s\n", - NAME(sourcePtr), NAME(destPtr)); /* * There are four possible cases to deal with: @@ -1047,24 +1043,19 @@ TkInOutEvents( Tk_QueueWindowEvent(eventPtr, position); \ } -#define DBGEV(w, t, d) fprintf(stderr, " Queueing %s %s for %s\n", t, d, NAME(w)) - if (downLevels == 0) { /* * SourcePtr is an inferior of destPtr. */ if (leaveType != 0) { - DBGEV(sourcePtr, "", "NotifyAncestor"); QUEUE(sourcePtr, leaveType, NotifyAncestor); for (winPtr = sourcePtr->parentPtr, i = upLevels-1; i > 0; winPtr = winPtr->parentPtr, i--) { - DBGEV(winPtr, "", "NotifyVirtual"); QUEUE(winPtr, leaveType, NotifyVirtual); } } if ((enterType != 0) && (destPtr != NULL)) { - DBGEV(destPtr, "", "NotifyVirtual"); QUEUE(destPtr, enterType, NotifyInferior); } } else if (upLevels == 0) { @@ -1073,7 +1064,6 @@ TkInOutEvents( */ if ((leaveType != 0) && (sourcePtr != NULL)) { - DBGEV(sourcePtr, "", "NotifyInferior"); QUEUE(sourcePtr, leaveType, NotifyInferior); } if (enterType != 0) { @@ -1082,11 +1072,9 @@ TkInOutEvents( winPtr = winPtr->parentPtr, j++) { /* empty */ } - DBGEV(winPtr, "", "NotifyVirtual"); QUEUE(winPtr, enterType, NotifyVirtual); } if (destPtr != NULL) { - DBGEV(winPtr, "", "NotifyVirtual"); QUEUE(destPtr, enterType, NotifyAncestor); } } @@ -1096,11 +1084,9 @@ TkInOutEvents( */ if (leaveType != 0) { - DBGEV(sourcePtr, "", "NotifyNonlinear"); QUEUE(sourcePtr, leaveType, NotifyNonlinear); for (winPtr = sourcePtr->parentPtr, i = upLevels-1; i > 0; winPtr = winPtr->parentPtr, i--) { - DBGEV(winPtr, "", "NotifyNonlinearVirtual"); QUEUE(winPtr, leaveType, NotifyNonlinearVirtual); } } @@ -1109,11 +1095,9 @@ TkInOutEvents( for (winPtr = destPtr->parentPtr, j = 1; j < i; winPtr = winPtr->parentPtr, j++) { } - DBGEV(winPtr, "", "NotifyNonlinearVirtual"); QUEUE(winPtr, enterType, NotifyNonlinearVirtual); } if (destPtr != NULL) { - DBGEV(destPtr, "", "NotifyNonlinear"); QUEUE(destPtr, enterType, NotifyNonlinear); } } diff --git a/generic/tkPointer.c b/generic/tkPointer.c index df26de1..9f88d2f 100644 --- a/generic/tkPointer.c +++ b/generic/tkPointer.c @@ -228,10 +228,7 @@ Tk_UpdatePointer( unsigned changes = (state ^ tsdPtr->lastState) & ALL_BUTTONS; int type, b; unsigned mask; - fprintf(stderr, "TkUpdatePointer: %s -> %s\n", - tsdPtr->lastWinPtr ? Tk_PathName(tsdPtr->lastWinPtr) : "NULL", - tkwin ? Tk_PathName(tkwin) : "NULL"); - fflush(stderr); + pos.x = x; pos.y = y; @@ -496,11 +493,7 @@ TkPointerDeadWindow( { ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - fprintf(stderr, "TkPointerDeadWindow: %s\n", winPtr ? Tk_PathName(winPtr) : "NULL"); if (winPtr == tsdPtr->lastWinPtr) { - //This fails on Windows because the windows version of TkWnDeadWindow - //does not (yet) call TkUpdatePointer when a dead toplevel contains the - //pointer. tsdPtr->lastWinPtr = TkGetContainer(winPtr); } if (winPtr == tsdPtr->grabWinPtr) { diff --git a/generic/tkWindow.c b/generic/tkWindow.c index e8c56dd..e322bb4 100644 --- a/generic/tkWindow.c +++ b/generic/tkWindow.c @@ -1328,11 +1328,12 @@ static void SendEnterLeaveForDestroy( { #if defined(MAC_OSX_TK) || defined(_WIN32) int x, y; - unsigned int state = TkWinGetModifierState(); + unsigned int state; Tk_Window pointerWin; TkWindow *containerPtr; - TkGetPointerCoords(NULL, &x, &y); + XQueryPointer(Tk_Display(tkwin), None, NULL, NULL, &x, &y, + NULL, NULL, &state); pointerWin = Tk_CoordsToWindow(x, y, tkwin); if (pointerWin == tkwin) { if (!Tk_IsTopLevel(tkwin)) { diff --git a/tests/event.test b/tests/event.test index f24c3c6..a099b5a 100644 --- a/tests/event.test +++ b/tests/event.test @@ -987,8 +987,8 @@ test event-9.13 {pointer window is a toplevel, toplevel destination} -setup { wm withdraw .two wm deiconify .two waitForWindowEvent .two - bind all {append result " %d %W|" ; puts stderr "=leave=" } - bind all {append result " %d %W|" ; puts stderr "-enter=" } + bind all {append result " %d %W|"} + bind all {append result " %d %W|"} set result | } -body { destroy .two -- cgit v0.12 From 26ddf13d3772b5ac21eab4f997628305d5622543 Mon Sep 17 00:00:00 2001 From: culler Date: Wed, 22 May 2024 04:22:40 +0000 Subject: Make destruction of windows on macOS work again. But more issues remain. --- macosx/tkMacOSXWm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index c771ec3..810b700 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -1034,7 +1034,7 @@ TkWmDeadWindow( * the parent. Then close and release the NSWindow. */ - if (0 && deadNSWindow && winPtr && !Tk_IsEmbedded(winPtr)) { + if (deadNSWindow && !Tk_IsEmbedded(winPtr)) { NSWindow *parent = [deadNSWindow parentWindow]; [deadNSWindow setTkWindow:None]; if (winPtr->window) { @@ -2037,7 +2037,6 @@ WmForgetCmd( macWin->toplevel->referenceCount++; macWin->flags &= ~TK_HOST_EXISTS; - //TkWmDeadWindow(winPtr); RemapWindows(winPtr, (MacDrawable *)winPtr->parentPtr->window); /* -- cgit v0.12 From 000fab56ad22db72cc7b854e859cc8597bac1575 Mon Sep 17 00:00:00 2001 From: culler Date: Wed, 22 May 2024 16:58:35 +0000 Subject: Add some update hacks to defer macOS crashes until xmfbox.test. --- tests/unixWm.test | 8 ++++++++ tests/wm.test | 2 ++ 2 files changed, 10 insertions(+) diff --git a/tests/unixWm.test b/tests/unixWm.test index 4bf466c..472db21 100644 --- a/tests/unixWm.test +++ b/tests/unixWm.test @@ -641,6 +641,8 @@ test unixWm-16.1 {Tk_WmCmd procedure, "deiconify" option} unix { test unixWm-16.2 {Tk_WmCmd procedure, "deiconify" option} unix { destroy .icon toplevel .icon -width 50 -height 50 -bg red + # calling update here prevents a crash in 16.3 on macOS + update wm iconwindow .t .icon set result [list [catch {wm deiconify .icon} msg] $msg] destroy .icon @@ -1352,8 +1354,12 @@ test unixWm-38.2 {Tk_WmCmd procedure, "withdraw" option} unix { test unixWm-38.3 {Tk_WmCmd procedure, "withdraw" option} unix { set result {} wm withdraw .t + #added to avoid a crash on macOS + update idletasks lappend result [wm state .t] [winfo ismapped .t] wm deiconify .t + #added to avoid a crash on macOS + update idletasks lappend result [wm state .t] [winfo ismapped .t] } {withdrawn 0 normal 1} @@ -1373,7 +1379,9 @@ test unixWm-40.1 {Tk_SetGrid procedure, set grid dimensions before turning on gr wm geometry .t } {30x10+0+0} test unixWm-40.2 {Tk_SetGrid procedure, turning on grid when dimensions already set} unix { + update destroy .t + update toplevel .t wm geometry .t 200x100+100+$Y0 listbox .t.l -height 20 -width 20 diff --git a/tests/wm.test b/tests/wm.test index 6f6dc80..926615e 100644 --- a/tests/wm.test +++ b/tests/wm.test @@ -947,6 +947,8 @@ test wm-iconwindow-2.1 {setting and reading values} -setup { destroy .icon set result {} } -body { + #added to avoid a crash on macOS + deiconify .t; update lappend result [wm iconwindow .t] toplevel .icon -width 50 -height 50 -bg green wm iconwindow .t .icon -- cgit v0.12 From 338f1ec85f66ca2e6643e65ae85a94cdc0fb7679 Mon Sep 17 00:00:00 2001 From: culler Date: Wed, 22 May 2024 18:45:38 +0000 Subject: xmfbox now passes - the crash occurs at the end of the tk tests, before the ttk tests --- macosx/tkMacOSXWm.c | 15 ++++----------- tests/xmfbox.test | 7 +++++++ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index 810b700..6c7468a 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -623,24 +623,17 @@ FrontWindowAtPoint( for (NSWindow *w in windows) { winPtr = TkMacOSXGetTkWindow(w); if (winPtr) { - WmInfo *wmPtr = winPtr->wmInfoPtr; NSRect windowFrame = [w frame]; - NSRect contentFrame = [w frame]; - - contentFrame.size.height = [[w contentView] frame].size.height; + NSRect contentFrame = windowFrame; /* * For consistency with other platforms, points in the * title bar are not considered to be contained in the * window. */ - if ((wmPtr->hints.initial_state == NormalState || - wmPtr->hints.initial_state == ZoomState)) { - if (NSMouseInRect(p, contentFrame, NO)) { - return winPtr; - } else if (NSMouseInRect(p, windowFrame, NO)) { - return NULL; - } + contentFrame.size.height = [[w contentView] frame].size.height; + if (NSMouseInRect(p, contentFrame, NO)) { + return winPtr; } } } diff --git a/tests/xmfbox.test b/tests/xmfbox.test index f50329c..cef9910 100644 --- a/tests/xmfbox.test +++ b/tests/xmfbox.test @@ -54,6 +54,7 @@ proc cleanup {} { } catch {unset foo} destroy .foo + update } # ---------------------------------------------------------------------- @@ -76,6 +77,7 @@ test xmfbox-1.2 {tk::MotifFDialog_Create, -parent switch} -constraints { } -body { toplevel .bar wm geometry .bar +0+0 + update set x [tk::MotifFDialog_Create foo open {-parent .bar}] } -cleanup { destroy $x @@ -89,6 +91,7 @@ test xmfbox-2.1 {tk::MotifFDialog_InterpFilter, ~ in dir names} -constraints { cleanup file mkdir ./~nosuchuser1 set x [tk::MotifFDialog_Create foo open {}] + update $::tk::dialog::file::foo(fEnt) delete 0 end $::tk::dialog::file::foo(fEnt) insert 0 [pwd]/~nosuchuser1 set kk [tk::MotifFDialog_InterpFilter $x] @@ -100,6 +103,7 @@ test xmfbox-2.2 {tk::MotifFDialog_InterpFilter, ~ in file names} -constraints { cleanup close [open ./~nosuchuser1 {CREAT TRUNC WRONLY}] set x [tk::MotifFDialog_Create foo open {}] + update $::tk::dialog::file::foo(fEnt) delete 0 end $::tk::dialog::file::foo(fEnt) insert 0 [pwd]/~nosuchuser1 set kk [tk::MotifFDialog_InterpFilter $x] @@ -111,6 +115,7 @@ test xmfbox-2.3 {tk::MotifFDialog_Update, ~ in file names} -constraints { cleanup close [open ./~nosuchuser1 {CREAT TRUNC WRONLY}] set x [tk::MotifFDialog_Create foo open {}] + update $::tk::dialog::file::foo(fEnt) delete 0 end $::tk::dialog::file::foo(fEnt) insert 0 [pwd]/~nosuchuser1 tk::MotifFDialog_InterpFilter $x @@ -124,6 +129,7 @@ test xmfbox-2.4 {tk::MotifFDialog_LoadFile, ~ in file names} -constraints { cleanup close [open ./~nosuchuser1 {CREAT TRUNC WRONLY}] set x [tk::MotifFDialog_Create foo open {}] + update set i [lsearch [$::tk::dialog::file::foo(fList) get 0 end] ~nosuchuser1] expr {$i >= 0} } -result 1 @@ -134,6 +140,7 @@ test xmfbox-2.5 {tk::MotifFDialog_BrowseFList, ~ in file names} -constraints { cleanup close [open ./~nosuchuser1 {CREAT TRUNC WRONLY}] set x [tk::MotifFDialog_Create foo open {}] + update set i [lsearch [$::tk::dialog::file::foo(fList) get 0 end] ~nosuchuser1] $::tk::dialog::file::foo(fList) selection clear 0 end $::tk::dialog::file::foo(fList) selection set $i -- cgit v0.12 From e85680bb451049993bad99dc1e47ec9b58da680a Mon Sep 17 00:00:00 2001 From: culler Date: Wed, 22 May 2024 19:00:35 +0000 Subject: Readjust event-9.15 and event-9.19 --- tests/event.test | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/tests/event.test b/tests/event.test index a099b5a..f35e5a2 100644 --- a/tests/event.test +++ b/tests/event.test @@ -916,12 +916,6 @@ proc setup_win_mousepointer {w} { update; # service remaining screen drawing events (e.g. ) set pointerWin [winfo containing [winfo pointerx $w] [winfo pointery $w]] event generate $w -warp 1 -x 250 -y 250 -# if {[tk windowingsystem] eq "aqua"} { -# # Generate a NSMouseMoved NSevent with no mouse pointer position change. -# # This is to let event-9.1? tests pass on macOS aqua and is only a workaround -# # since macOS aqua should send the adequate NSevent by itself. -# movemouse [expr {[winfo rootx $w] + 250}] [expr {[winfo rooty $w] + 250}] -# } if {($pointerWin ne $w) && ([tk windowingsystem] ne "aqua")} { waitForWindowEvent $w } else { @@ -1038,8 +1032,8 @@ test event-9.15 {pointer window is a toplevel, destination is screen root} -setu bind all {append result " %d %W|"} set result "|" } -body { - destroy .two _pause 200; # ensure servicing of all scheduled events (only events expected) + destroy .two set result } -cleanup { bind all {} @@ -1138,12 +1132,12 @@ test event-9.19 {Successive destructions (pointer window + ancestors including i } -body { destroy .three waitForWindowEvent .two.f1.f2 - set result -} -cleanup { bind all {} bind all {} destroy .two destroy .one + set result +} -cleanup { unset result } -result {| NotifyNonlinearVirtual .two| NotifyNonlinearVirtual .two.f1| NotifyNonlinear .two.f1.f2|} -- cgit v0.12 From 6704a6d04762b9963ce78a778ff706b3e7a90d61 Mon Sep 17 00:00:00 2001 From: culler Date: Thu, 23 May 2024 15:08:00 +0000 Subject: Prevent crash at exit on macOS --- generic/tkWindow.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/event.test | 6 +++--- 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/generic/tkWindow.c b/generic/tkWindow.c index e322bb4..cbbdafe 100644 --- a/generic/tkWindow.c +++ b/generic/tkWindow.c @@ -215,6 +215,19 @@ static int Initialize(Tcl_Interp *interp); static int NameWindow(Tcl_Interp *interp, TkWindow *winPtr, TkWindow *parentPtr, const char *name); static void UnlinkWindow(TkWindow *winPtr); +#if 0 +static Bool HasValidDisplay(Tk_Window tkwin); +#endif + +/* + * This static variable only makes sense for macOS and Windows, which never + * have more than one display. It is set by TkCloseDisplay, and when set + * prevents sending Enter and Leave events when all of the windows in the + * display are being destroyed. Tk does not send those events on X11; that + * job is handled by the X server. + */ + +static int displayBeingClosed = 0; /* @@ -240,6 +253,7 @@ static void TkCloseDisplay( TkDisplay *dispPtr) { + displayBeingClosed = 1; TkClipCleanup(dispPtr); TkpCancelWarp(dispPtr); @@ -509,7 +523,40 @@ GetScreen( *screenPtr = screenId; return dispPtr; } +#if 0 +/* + *-------------------------------------------------------------- + * + * HasValidDisplay -- + * + * Given a Tk window, returns True if the window's display is still on + * the display list. + * + * Results: + * + * True if the display is on the display list, False otherwise/ + * + * Side effects: + * None + * + *-------------------------------------------------------------- + */ + +static Bool HasValidDisplay( + Tk_Window tkwin) +{ + TkWindow *winPtr = (TkWindow *) tkwin; + TkDisplay *dispPtr = (TkDisplay *) winPtr->display, *dispPtr2; + + for (dispPtr2 = TkGetDisplayList(); dispPtr2; dispPtr2 = dispPtr2->nextPtr) { + if (dispPtr2 == dispPtr) { + return True; + } + } + return False; +} +#endif /* *---------------------------------------------------------------------- * @@ -1332,6 +1379,13 @@ static void SendEnterLeaveForDestroy( Tk_Window pointerWin; TkWindow *containerPtr; + if (displayBeingClosed) { + return; + } + // if (!HasValidDisplay(tkwin)) { + // return; + // } + XQueryPointer(Tk_Display(tkwin), None, NULL, NULL, &x, &y, NULL, NULL, &state); pointerWin = Tk_CoordsToWindow(x, y, tkwin); @@ -1752,6 +1806,13 @@ static void SendEnterLeaveForMap( unsigned int state; Tk_Window pointerWin; + if (displayBeingClosed) { + return; + } + // if (!HasValidDisplay(tkwin)) { + // return; + // } + XQueryPointer(Tk_Display(tkwin), None, NULL, NULL, &x, &y, NULL, NULL, &state); pointerWin = Tk_CoordsToWindow(x, y, tkwin); diff --git a/tests/event.test b/tests/event.test index f35e5a2..d2f65e5 100644 --- a/tests/event.test +++ b/tests/event.test @@ -1104,16 +1104,17 @@ test event-9.18 {Successive destructions (pointer window + ancestors including i } -body { destroy .two waitForWindowEvent .one - set result -} -cleanup { bind all {} bind all {} destroy .one + set result +} -cleanup { unset result } -result {| NotifyNonlinear .one|} test event-9.19 {Successive destructions (pointer window + ancestors including its toplevel), destination is internal window, bypass root win} -setup { setup_win_mousepointer .one; # ensure the mouse pointer is where we want it to be (the .one toplevel is not itself used in this test) + destroy .one toplevel .two pack propagate .two 0 wm geometry .two 300x300+100+100 @@ -1135,7 +1136,6 @@ test event-9.19 {Successive destructions (pointer window + ancestors including i bind all {} bind all {} destroy .two - destroy .one set result } -cleanup { unset result -- cgit v0.12 From 00623999b20177be1ce0a6ca8c83dd0d9269e9d2 Mon Sep 17 00:00:00 2001 From: culler Date: Thu, 23 May 2024 15:22:01 +0000 Subject: Remove general code for checking if a display is valid because it affects timing, which breaks all of the event-9 tests. --- generic/tkWindow.c | 44 -------------------------------------------- 1 file changed, 44 deletions(-) diff --git a/generic/tkWindow.c b/generic/tkWindow.c index cbbdafe..644fea3 100644 --- a/generic/tkWindow.c +++ b/generic/tkWindow.c @@ -215,9 +215,6 @@ static int Initialize(Tcl_Interp *interp); static int NameWindow(Tcl_Interp *interp, TkWindow *winPtr, TkWindow *parentPtr, const char *name); static void UnlinkWindow(TkWindow *winPtr); -#if 0 -static Bool HasValidDisplay(Tk_Window tkwin); -#endif /* * This static variable only makes sense for macOS and Windows, which never @@ -523,40 +520,7 @@ GetScreen( *screenPtr = screenId; return dispPtr; } -#if 0 -/* - *-------------------------------------------------------------- - * - * HasValidDisplay -- - * - * Given a Tk window, returns True if the window's display is still on - * the display list. - * - * Results: - * - * True if the display is on the display list, False otherwise/ - * - * Side effects: - * None - * - *-------------------------------------------------------------- - */ - -static Bool HasValidDisplay( - Tk_Window tkwin) -{ - TkWindow *winPtr = (TkWindow *) tkwin; - TkDisplay *dispPtr = (TkDisplay *) winPtr->display, *dispPtr2; - - for (dispPtr2 = TkGetDisplayList(); dispPtr2; dispPtr2 = dispPtr2->nextPtr) { - if (dispPtr2 == dispPtr) { - return True; - } - } - return False; -} -#endif /* *---------------------------------------------------------------------- * @@ -1382,10 +1346,6 @@ static void SendEnterLeaveForDestroy( if (displayBeingClosed) { return; } - // if (!HasValidDisplay(tkwin)) { - // return; - // } - XQueryPointer(Tk_Display(tkwin), None, NULL, NULL, &x, &y, NULL, NULL, &state); pointerWin = Tk_CoordsToWindow(x, y, tkwin); @@ -1809,10 +1769,6 @@ static void SendEnterLeaveForMap( if (displayBeingClosed) { return; } - // if (!HasValidDisplay(tkwin)) { - // return; - // } - XQueryPointer(Tk_Display(tkwin), None, NULL, NULL, &x, &y, NULL, NULL, &state); pointerWin = Tk_CoordsToWindow(x, y, tkwin); -- cgit v0.12 From c03a103ca11b8710b13b35b4bf5de0b46379d89c Mon Sep 17 00:00:00 2001 From: culler Date: Thu, 23 May 2024 16:55:00 +0000 Subject: Clean up. --- generic/tkGrab.c | 1 - generic/tkPointer.c | 1 - macosx/tkMacOSXWindowEvent.c | 22 ++++++++++++---------- win/tkWinWm.c | 2 -- 4 files changed, 12 insertions(+), 14 deletions(-) diff --git a/generic/tkGrab.c b/generic/tkGrab.c index 2c7c6ab..d4ecdb0 100644 --- a/generic/tkGrab.c +++ b/generic/tkGrab.c @@ -1102,7 +1102,6 @@ TkInOutEvents( } } } - fflush(stderr); } /* diff --git a/generic/tkPointer.c b/generic/tkPointer.c index 9f88d2f..c2ba29f 100644 --- a/generic/tkPointer.c +++ b/generic/tkPointer.c @@ -513,7 +513,6 @@ TkPointerDeadWindow( TkpSetCapture(NULL); } } - fflush(stderr); } /* diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c index 41c9ede..fc7acfd 100644 --- a/macosx/tkMacOSXWindowEvent.c +++ b/macosx/tkMacOSXWindowEvent.c @@ -250,15 +250,15 @@ extern NSString *NSWindowDidOrderOffScreenNotification; } } -//- (void) windowMapped: (NSNotification *) notification -//{ -// NSWindow *w = [notification object]; -// TkWindow *winPtr = TkMacOSXGetTkWindow(w); +- (void) windowMapped: (NSNotification *) notification +{ + NSWindow *w = [notification object]; + TkWindow *winPtr = TkMacOSXGetTkWindow(w); -// if (winPtr) { -// while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {} -// } -//} + if (winPtr) { + while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {} + } +} - (void) windowLiveResize: (NSNotification *) notification { @@ -284,9 +284,11 @@ extern NSString *NSWindowDidOrderOffScreenNotification; NSWindow *w = [notification object]; TkWindow *winPtr = TkMacOSXGetTkWindow(w); +#if 0 if (winPtr) { - //Tk_UnmapWindow((Tk_Window)winPtr); + Tk_UnmapWindow((Tk_Window)winPtr); } +#endif } #endif /* TK_MAC_DEBUG_NOTIFICATIONS */ @@ -304,7 +306,7 @@ extern NSString *NSWindowDidOrderOffScreenNotification; observe(NSWindowDidResizeNotification, windowBoundsChanged:); observe(NSWindowDidDeminiaturizeNotification, windowExpanded:); observe(NSWindowDidMiniaturizeNotification, windowCollapsed:); - //observe(NSWindowWillOrderOnScreenNotification, windowMapped:); + observe(NSWindowWillOrderOnScreenNotification, windowMapped:); observe(NSWindowDidOrderOnScreenNotification, windowBecameVisible:); observe(NSWindowWillStartLiveResizeNotification, windowLiveResize:); observe(NSWindowDidEndLiveResizeNotification, windowLiveResize:); diff --git a/win/tkWinWm.c b/win/tkWinWm.c index a550302..df9b1ce 100644 --- a/win/tkWinWm.c +++ b/win/tkWinWm.c @@ -2750,8 +2750,6 @@ TkWmDeadWindow( */ CheckForPointer(winPtr); - //TkPointerDeadWindow(winPtr); - ckfree(wmPtr); winPtr->wmInfoPtr = NULL; } -- cgit v0.12 From 0a51685f4bf2ef83d5ef6e3a32be16f7f34d86aa Mon Sep 17 00:00:00 2001 From: culler Date: Thu, 23 May 2024 17:43:55 +0000 Subject: White space. --- generic/tkGrab.c | 5 ++--- generic/tkPointer.c | 3 ++- generic/tkWindow.c | 1 - macosx/tkMacOSXWindowEvent.c | 8 ++++---- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/generic/tkGrab.c b/generic/tkGrab.c index d4ecdb0..2232ba5 100644 --- a/generic/tkGrab.c +++ b/generic/tkGrab.c @@ -1029,7 +1029,7 @@ TkInOutEvents( /* * Generate enter/leave events and add them to the grab event queue. */ - + #define QUEUE(w, t, d) \ if (w->window != None) { \ eventPtr->type = t; \ @@ -1087,7 +1087,7 @@ TkInOutEvents( QUEUE(sourcePtr, leaveType, NotifyNonlinear); for (winPtr = sourcePtr->parentPtr, i = upLevels-1; i > 0; winPtr = winPtr->parentPtr, i--) { - QUEUE(winPtr, leaveType, NotifyNonlinearVirtual); + QUEUE(winPtr, leaveType, NotifyNonlinearVirtual); } } if (enterType != 0) { @@ -1167,7 +1167,6 @@ MovePointer2( TkInOutEvents(&event, sourcePtr, destPtr, (leaveEvents) ? LeaveNotify : 0, (enterEvents) ? EnterNotify : 0, TCL_QUEUE_MARK); } - /* *---------------------------------------------------------------------- diff --git a/generic/tkPointer.c b/generic/tkPointer.c index c2ba29f..905489a 100644 --- a/generic/tkPointer.c +++ b/generic/tkPointer.c @@ -45,7 +45,6 @@ static int GenerateEnterLeave(TkWindow *winPtr, int x, int y, static void InitializeEvent(XEvent *eventPtr, TkWindow *winPtr, int type, int x, int y, int state, int detail); static void UpdateCursor(TkWindow *winPtr); - /* *---------------------------------------------------------------------- @@ -184,6 +183,7 @@ GenerateEnterLeave( InitializeEvent(&event, targetPtr, LeaveNotify, x, y, state, NotifyNormal); + TkInOutEvents(&event, lastWinPtr, winPtr, LeaveNotify, EnterNotify, TCL_QUEUE_TAIL); crossed = 1; @@ -493,6 +493,7 @@ TkPointerDeadWindow( { ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + if (winPtr == tsdPtr->lastWinPtr) { tsdPtr->lastWinPtr = TkGetContainer(winPtr); } diff --git a/generic/tkWindow.c b/generic/tkWindow.c index 644fea3..44f27f7 100644 --- a/generic/tkWindow.c +++ b/generic/tkWindow.c @@ -1807,7 +1807,6 @@ Tk_MapWindow( TkWmMapWindow(winPtr); return; } - winPtr->flags |= TK_MAPPED; XMapWindow(winPtr->display, winPtr->window); event.type = MapNotify; diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c index fc7acfd..68ec369 100644 --- a/macosx/tkMacOSXWindowEvent.c +++ b/macosx/tkMacOSXWindowEvent.c @@ -252,12 +252,12 @@ extern NSString *NSWindowDidOrderOffScreenNotification; - (void) windowMapped: (NSNotification *) notification { - NSWindow *w = [notification object]; - TkWindow *winPtr = TkMacOSXGetTkWindow(w); + NSWindow *w = [notification object]; + TkWindow *winPtr = TkMacOSXGetTkWindow(w); - if (winPtr) { + if (winPtr) { while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {} - } + } } - (void) windowLiveResize: (NSNotification *) notification -- cgit v0.12 From 012c6e1a16eb7548e1d804b07740458d6328dfb8 Mon Sep 17 00:00:00 2001 From: culler Date: Thu, 23 May 2024 19:53:24 +0000 Subject: Schedule a CI run --- .github/workflows/linux-build.yml | 1 + .github/workflows/mac-build.yml | 1 + .github/workflows/win-build.yml | 1 + 3 files changed, 3 insertions(+) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index 9414037..15a1a48 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -5,6 +5,7 @@ on: - "main" - "core-8-branch" - "core-8-6-branch" + - "bug-22349fc78a-v2" tags: - "core-**" permissions: diff --git a/.github/workflows/mac-build.yml b/.github/workflows/mac-build.yml index 9fd297a..b5f077f 100644 --- a/.github/workflows/mac-build.yml +++ b/.github/workflows/mac-build.yml @@ -5,6 +5,7 @@ on: - "main" - "core-8-branch" - "core-8-6-branch" + - "bug-22349fc78a-v2" tags: - "core-**" permissions: diff --git a/.github/workflows/win-build.yml b/.github/workflows/win-build.yml index 6642a8d..c1a44e5 100644 --- a/.github/workflows/win-build.yml +++ b/.github/workflows/win-build.yml @@ -5,6 +5,7 @@ on: - "main" - "core-8-branch" - "core-8-6-branch" + - "bug-22349fc78a-v2" tags: - "core-**" permissions: -- cgit v0.12 From ba5defb6f8c03eb5f52b6641bf002059467df4a1 Mon Sep 17 00:00:00 2001 From: culler Date: Thu, 23 May 2024 23:32:31 +0000 Subject: fix wm-iconwindow-2.1 --- tests/wm.test | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/wm.test b/tests/wm.test index 926615e..2b31e5e 100644 --- a/tests/wm.test +++ b/tests/wm.test @@ -945,10 +945,11 @@ test wm-iconwindow-1.5 {usage} -setup { test wm-iconwindow-2.1 {setting and reading values} -setup { destroy .icon + # Destroying and creating .t prevents a segfault on macOS + destroy .t + toplevel .t set result {} } -body { - #added to avoid a crash on macOS - deiconify .t; update lappend result [wm iconwindow .t] toplevel .icon -width 50 -height 50 -bg green wm iconwindow .t .icon -- cgit v0.12 From f0a5f7aa739d4042b0718f644987e04e1166b3f1 Mon Sep 17 00:00:00 2001 From: culler Date: Fri, 24 May 2024 01:54:08 +0000 Subject: Simpler fix for wm-iconwindow-2.1 which still does not explain the crash. --- tests/wm.test | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/wm.test b/tests/wm.test index 2b31e5e..9cb402a 100644 --- a/tests/wm.test +++ b/tests/wm.test @@ -944,10 +944,9 @@ test wm-iconwindow-1.5 {usage} -setup { } -result {.icon is already an icon for .t2} test wm-iconwindow-2.1 {setting and reading values} -setup { + # without this macOS crashes for unknown reasons + wm iconwindow .t {} destroy .icon - # Destroying and creating .t prevents a segfault on macOS - destroy .t - toplevel .t set result {} } -body { lappend result [wm iconwindow .t] -- cgit v0.12 From c4c94b611dab530185007be10efece9695dcdb72 Mon Sep 17 00:00:00 2001 From: fvogel Date: Fri, 24 May 2024 03:44:47 +0000 Subject: Remove leftover debugging code. --- win/tkWinWm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/win/tkWinWm.c b/win/tkWinWm.c index df9b1ce..c387111 100644 --- a/win/tkWinWm.c +++ b/win/tkWinWm.c @@ -2602,7 +2602,6 @@ static void CheckForPointer(TkWindow *winPtr) } ckfree(windows); } - fflush(stderr); } void -- cgit v0.12 From 285f6cdbf8bad836d1de14c2dd11f7e86daeeb8e Mon Sep 17 00:00:00 2001 From: culler Date: Fri, 24 May 2024 15:30:48 +0000 Subject: Fix bug introduced in FrontWindowAtPoint which causes unixWm-50.1 to fail by ignoring that the pointer is in a titlebar. Also, make the unixWm-50 tests more robust by ensuring that the root window is out of the way. (This matters for macOS 14, not 11). --- macosx/tkMacOSXWm.c | 13 +++++++++++-- tests/unixWm.test | 2 ++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index 6c7468a..e782dda 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -623,17 +623,26 @@ FrontWindowAtPoint( for (NSWindow *w in windows) { winPtr = TkMacOSXGetTkWindow(w); if (winPtr) { + // WmInfo *wmPtr = winPtr->wmInfoPtr; NSRect windowFrame = [w frame]; - NSRect contentFrame = windowFrame; + NSRect contentFrame = [w frame]; + + contentFrame.size.height = [[w contentView] frame].size.height; /* * For consistency with other platforms, points in the * title bar are not considered to be contained in the * window. */ - contentFrame.size.height = [[w contentView] frame].size.height; if (NSMouseInRect(p, contentFrame, NO)) { return winPtr; + } else if (NSMouseInRect(p, windowFrame, NO)) { + /* + * The pointer is in the title bar of the highest NSWindow + * containing it, and therefore is should not be considered + * to be contained in any Tk window. + */ + return NULL; } } } diff --git a/tests/unixWm.test b/tests/unixWm.test index 472db21..65561d4 100644 --- a/tests/unixWm.test +++ b/tests/unixWm.test @@ -1806,6 +1806,8 @@ test unixWm-49.2 {Tk_GetRootCoords procedure, menubars} {unix testmenubar} { } {52 7 12 62} deleteWindows +# Make sure that the root window is out of the way! +wm geom . +700+700 wm withdraw . if {[tk windowingsystem] eq "aqua"} { # Modern mac windows have no border. -- cgit v0.12 From 9317a30b3627fcf0010375bf708cc3fb5432a915 Mon Sep 17 00:00:00 2001 From: culler Date: Fri, 24 May 2024 19:46:55 +0000 Subject: Deal with compiler warnings when building with mingw gcc on Windows. --- win/tkWinWm.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/win/tkWinWm.c b/win/tkWinWm.c index c387111..31fa03f 100644 --- a/win/tkWinWm.c +++ b/win/tkWinWm.c @@ -2579,12 +2579,14 @@ TkpWmGetState( static void CheckForPointer(TkWindow *winPtr) { - Display *display = Tk_Display(winPtr); POINT mouse; + int x, y; unsigned int state = TkWinGetModifierState(); TkWindow **windows = TkWmStackorderToplevel(winPtr->mainPtr->winPtr); TkWindow **w; - TkGetPointerCoords(NULL, &mouse.x, &mouse.y); + x = (int) mouse.x; + y = (int) mouse.y; + TkGetPointerCoords(NULL, &x, &y); if (windows != NULL) { for (w = windows; *w ; w++) { RECT windowRect; @@ -2593,10 +2595,8 @@ static void CheckForPointer(TkWindow *winPtr) continue; } if (winPtr != *w && PtInRect(&windowRect, mouse)) { - Tk_Window target = Tk_CoordsToWindow(mouse.x, mouse.y, - (Tk_Window) *w); - Tk_UpdatePointer((Tk_Window) target, - mouse.x, mouse.y, state); + Tk_Window target = Tk_CoordsToWindow(x, y, (Tk_Window) *w); + Tk_UpdatePointer((Tk_Window) target, x, y, state); break; } } -- cgit v0.12 From c7a1c8ab1b6d29b631d2b77c3ddf3159b191000e Mon Sep 17 00:00:00 2001 From: culler Date: Sat, 25 May 2024 13:19:06 +0000 Subject: Fix silly error. --- win/tkWinWm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/win/tkWinWm.c b/win/tkWinWm.c index 31fa03f..6d72009 100644 --- a/win/tkWinWm.c +++ b/win/tkWinWm.c @@ -2584,9 +2584,9 @@ static void CheckForPointer(TkWindow *winPtr) unsigned int state = TkWinGetModifierState(); TkWindow **windows = TkWmStackorderToplevel(winPtr->mainPtr->winPtr); TkWindow **w; - x = (int) mouse.x; - y = (int) mouse.y; TkGetPointerCoords(NULL, &x, &y); + mouse.x = x; + mouse.y = y; if (windows != NULL) { for (w = windows; *w ; w++) { RECT windowRect; -- cgit v0.12 From 596308daa8e8f621aafc4849bd0a98842a15402f Mon Sep 17 00:00:00 2001 From: culler Date: Sun, 26 May 2024 01:26:05 +0000 Subject: Try macOS 12 --- .github/workflows/mac-build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/mac-build.yml b/.github/workflows/mac-build.yml index b5f077f..7f07669 100644 --- a/.github/workflows/mac-build.yml +++ b/.github/workflows/mac-build.yml @@ -14,7 +14,7 @@ env: ERROR_ON_FAILURES: 1 jobs: xcode: - runs-on: macos-11 + runs-on: macos-12 defaults: run: shell: bash @@ -49,7 +49,7 @@ jobs: } - name: Run Tests run: | - make test | tee out.txt + make TESTFLAGS="-verbose bpest" test | tee out.txt nmatches=$( grep -c "Failed 0" out.txt ) if [ $nmatches -lt 4 ] then @@ -58,7 +58,7 @@ jobs: fi timeout-minutes: 30 clang: - runs-on: macos-11 + runs-on: macos-12 strategy: matrix: symbols: -- cgit v0.12 From 10156faa8f5ac4df59f0e7e6356dc1262bd1e3c5 Mon Sep 17 00:00:00 2001 From: fvogel Date: Sun, 26 May 2024 18:38:52 +0000 Subject: Remove commented statements in event.test. --- tests/event.test | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tests/event.test b/tests/event.test index d2f65e5..7fcdab3 100644 --- a/tests/event.test +++ b/tests/event.test @@ -935,12 +935,6 @@ test event-9.11 {pointer window container = parent} -setup { set result "|" } -body { destroy .one.f1.f2 -# if {[tk windowingsystem] eq "aqua"} { -# # Generate a NSMouseMoved NSevent with no mouse pointer position change. -# # This is to let event-9.1? tests pass on macOS aqua and is only a workaround -# # since macOS aqua should send the adequate NSevent by itself. -# movemouse [expr {[winfo rootx .one] + 250}] [expr {[winfo rooty .one] + 250}] -# } _pause 200; # service crossing events set result } -cleanup { -- cgit v0.12 From 1bb534ff3475c78cff17d791f2d046490b1fcd1e Mon Sep 17 00:00:00 2001 From: culler Date: Sun, 26 May 2024 20:17:58 +0000 Subject: Remove unneeded call to TkWmDeadWindow --- generic/tkWindow.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/generic/tkWindow.c b/generic/tkWindow.c index 44f27f7..c411bd3 100644 --- a/generic/tkWindow.c +++ b/generic/tkWindow.c @@ -1354,9 +1354,6 @@ static void SendEnterLeaveForDestroy( containerPtr = TkGetContainer((TkWindow *)pointerWin); Tk_UpdatePointer((Tk_Window) containerPtr, x, y, state); } - else if (pointerWin) { - TkWmDeadWindow((TkWindow *) pointerWin); - } } if (pointerWin && (tkwin == Tk_Parent(pointerWin))) { -- cgit v0.12 From d2d0cce3dd0d647a9744613bff159313ff486260 Mon Sep 17 00:00:00 2001 From: culler Date: Mon, 27 May 2024 16:07:10 +0000 Subject: Don't call tkUpdatePointer from TkWmDeadWindow unless it is necessary. --- macosx/tkMacOSXWm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index e782dda..96478f4 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -1027,7 +1027,9 @@ TkWmDeadWindow( root_y = floor(TkMacOSXZeroScreenHeight() - mouse.y); int win_x, win_y; Tk_Window target = Tk_TopCoordsToWindow((Tk_Window) winPtr2, top_x, top_y, &win_x, &win_y); - Tk_UpdatePointer((Tk_Window) target, root_x, root_y, [NSApp tkButtonState]); + if (target != (Tk_Window) winPtr) { + Tk_UpdatePointer((Tk_Window) target, root_x, root_y, [NSApp tkButtonState]); + } } /* -- cgit v0.12 From d0863507871c8c40fefb431343082e2607e2f583 Mon Sep 17 00:00:00 2001 From: culler Date: Tue, 28 May 2024 03:35:38 +0000 Subject: Avoid calling TkUpdatePointer for a window which is being destroyed by a child's binding script. --- macosx/tkMacOSXWm.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index 96478f4..d5575cc 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -1027,8 +1027,11 @@ TkWmDeadWindow( root_y = floor(TkMacOSXZeroScreenHeight() - mouse.y); int win_x, win_y; Tk_Window target = Tk_TopCoordsToWindow((Tk_Window) winPtr2, top_x, top_y, &win_x, &win_y); - if (target != (Tk_Window) winPtr) { - Tk_UpdatePointer((Tk_Window) target, root_x, root_y, [NSApp tkButtonState]); + /* A non-toplevel window can have a NULL parent while it is in the process of + * being destroyed. We should not call Tk_UpdatePointer in that case. + */ + if (Tk_Parent(target) != NULL || Tk_IsTopLevel(target)) { + Tk_UpdatePointer(target, root_x, root_y, [NSApp tkButtonState]); } } -- cgit v0.12 From 4e2ce7f2c671d121814f282afbe74d72a6bdd217 Mon Sep 17 00:00:00 2001 From: culler Date: Tue, 28 May 2024 16:10:46 +0000 Subject: Adjust some tests and schedule a CI run on macOS 14. --- .github/workflows/mac-build.yml | 3 ++- tests/font.test | 13 +++++++------ tests/unixWm.test | 1 + 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/.github/workflows/mac-build.yml b/.github/workflows/mac-build.yml index 9fd297a..cb4b6f7 100644 --- a/.github/workflows/mac-build.yml +++ b/.github/workflows/mac-build.yml @@ -5,6 +5,7 @@ on: - "main" - "core-8-branch" - "core-8-6-branch" + - "macOS-14-CI" tags: - "core-**" permissions: @@ -13,7 +14,7 @@ env: ERROR_ON_FAILURES: 1 jobs: xcode: - runs-on: macos-11 + runs-on: macos-14 defaults: run: shell: bash diff --git a/tests/font.test b/tests/font.test index 4a264f8..5ceb1ee 100644 --- a/tests/font.test +++ b/tests/font.test @@ -2427,15 +2427,15 @@ test font-47.2 {Bug 3049518 - Canvas} -body { set twidth [font measure MyFont $text] set theight [font metrics MyFont -linespace] set circid [$c create polygon \ - 15 15 \ - [expr {15 + $twidth}] 15 \ - [expr {15 + $twidth}] [expr {15 + $theight}] \ - 15 [expr {15 + $theight}] \ - -width 1 -joinstyle round -smooth true -fill {} -outline blue] + 15 15 \ + [expr {15 + $twidth}] 15 \ + [expr {15 + $twidth}] [expr {15 + $theight}] \ + 15 [expr {15 + $theight}] \ + -width 1 -joinstyle round -smooth true -fill {} -outline blue] pack $c -fill both -expand 1 -side top update - # Lamda test functions + # Lambda test functions set circle_text {{w user_data text circ} { if {[winfo class $w] ne "Canvas"} { puts "Wrong widget type: $w" @@ -2461,6 +2461,7 @@ test font-47.2 {Bug 3049518 - Canvas} -body { apply $circle_text $c FontChanged $textid $circid update bind $c <> [list apply $circle_text %W %d $textid $circid] + update idletasks # Begin test: set results {} diff --git a/tests/unixWm.test b/tests/unixWm.test index 4bf466c..2898d19 100644 --- a/tests/unixWm.test +++ b/tests/unixWm.test @@ -105,6 +105,7 @@ foreach geom "+20+80 +80+$Y0 +0+$Y0 -0-0 +0-0 -0+$Y0 -10-5 -10+$Y5 +10-5" { set i 1 foreach geom "+20+80 +80+$Y0 +0+$Y0 -0-0 +0-0 -0+$Y0 -10-5 -10+$Y5 +10-5" { test unixWm-3.$i {moving window while iconified} unix { + update wm iconify .t update idletasks wm geom .t $geom -- cgit v0.12 From 5c57addb770317e6c2acafffbed2f3d51485bcfd Mon Sep 17 00:00:00 2001 From: culler Date: Tue, 28 May 2024 22:28:13 +0000 Subject: fix wm-manage-1.8 (without fixing wm manage) --- macosx/tkMacOSXWm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index d5575cc..50ff5f8 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -2922,6 +2922,7 @@ WmManageCmd( } else if (Tk_IsTopLevel(frameWin)) { /* Already managed by wm - ignore it */ } + winPtr->geomMgrPtr = &wmMgrType; return TCL_OK; } -- cgit v0.12 From 65eb0c8c381b378de6ac9095d2b5549078b4eee5 Mon Sep 17 00:00:00 2001 From: culler Date: Wed, 29 May 2024 01:20:07 +0000 Subject: Use Tk_ManageGeometry here too. --- macosx/tkMacOSXWm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index 50ff5f8..b154f18 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -2922,7 +2922,7 @@ WmManageCmd( } else if (Tk_IsTopLevel(frameWin)) { /* Already managed by wm - ignore it */ } - winPtr->geomMgrPtr = &wmMgrType; + Tk_ManageGeometry((Tk_Window)winPtr, &wmMgrType, NULL); return TCL_OK; } -- cgit v0.12 From b39986a99d587498f5ba40e71cddf6ea0360b89f Mon Sep 17 00:00:00 2001 From: culler Date: Wed, 29 May 2024 16:18:42 +0000 Subject: Add a simple version of the processevents test command and use it for the event-9* tests. --- generic/tkTest.c | 46 ++++++++++++++++++++++++++++++ tests/event.test | 85 ++++++++++++++++++++++++++++++-------------------------- 2 files changed, 91 insertions(+), 40 deletions(-) diff --git a/generic/tkTest.c b/generic/tkTest.c index 755a6be..4fc6a80 100644 --- a/generic/tkTest.c +++ b/generic/tkTest.c @@ -147,6 +147,9 @@ typedef struct TrivialCommandHeader { static int ImageObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj * const objv[]); +static int ProcessEventsObjCmd(ClientData dummy, + Tcl_Interp *interp, int objc, + Tcl_Obj * const objv[]); static int TestbitmapObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj * const objv[]); @@ -247,6 +250,7 @@ Tktest_Init( return TCL_ERROR; } + Tcl_CreateObjCommand(interp, "processevents", ProcessEventsObjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "square", SquareObjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testbitmap", TestbitmapObjCmd, (ClientData) Tk_MainWindow(interp), NULL); @@ -1682,6 +1686,48 @@ ImageDelete( /* *---------------------------------------------------------------------- * + * ProcessEventsObjCmd -- + * + * This function implements the "processevents" command. Currently + * It processes all or events on the queue. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * Events are processed + * + *---------------------------------------------------------------------- + */ + +static Tk_RestrictAction +CrossingRestrictProc( + ClientData arg, + XEvent *eventPtr) +{ + if (eventPtr->type == EnterNotify || eventPtr->type == LeaveNotify) { + return TK_PROCESS_EVENT; + } + return TK_DEFER_EVENT; +} + +static int ProcessEventsObjCmd(ClientData dummy, + Tcl_Interp *interp, + int objc, + Tcl_Obj * const objv[]) +{ + ClientData oldArg; + Tk_RestrictProc *oldProc; + int count = 0; + oldProc = Tk_RestrictEvents(CrossingRestrictProc, NULL, &oldArg); + while (Tcl_ServiceEvent(TCL_WINDOW_EVENTS|TCL_DONT_WAIT)) {}; + Tk_RestrictEvents(oldProc, oldArg, &oldArg); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * * TestmakeexistObjCmd -- * * This function implements the "testmakeexist" command. It calls diff --git a/tests/event.test b/tests/event.test index 7fcdab3..10dcf07 100644 --- a/tests/event.test +++ b/tests/event.test @@ -929,13 +929,13 @@ test event-9.11 {pointer window container = parent} -setup { create_and_pack_frames .one wm deiconify .one tkwait visibility .one.f1.f2 - _pause 200 - bind all {append result " %d %W|"} - bind all {append result " %d %W|"} + update; # finish display of window set result "|" } -body { + bind all {append result " %d %W|"} + bind all {append result " %d %W|"} destroy .one.f1.f2 - _pause 200; # service crossing events + processevents end set result } -cleanup { bind all {} @@ -953,13 +953,13 @@ test event-9.12 {pointer window container != parent} -setup { wm deiconify .one tkwait visibility .one.g event generate .one -warp 1 -x 250 -y 250 - _pause 200 - bind all {append result " %d %W|"} - bind all {append result " %d %W|"} + update; # finish mouse warp set result "|" } -body { + bind all {append result " %d %W|"} + bind all {append result " %d %W|"} destroy .one.g - _pause 200; # service crossing events -- crashes without this + processevents end set result } -cleanup { bind all {} @@ -975,18 +975,19 @@ test event-9.13 {pointer window is a toplevel, toplevel destination} -setup { wm withdraw .two wm deiconify .two waitForWindowEvent .two - bind all {append result " %d %W|"} - bind all {append result " %d %W|"} + update; # finish displaying windows set result | } -body { + bind all {append result " %d %W|"} + bind all {append result " %d %W|"} destroy .two waitForWindowEvent .one - # destroying .one here instead of in cleanup makes the test pass - destroy .one + processevents end set result } -cleanup { bind all {} bind all {} + destroy .one unset result } -result {| NotifyNonlinear .one|} @@ -1000,17 +1001,18 @@ test event-9.14 {pointer window is a toplevel, tk internal destination} -setup { wm deiconify .one wm deiconify .two waitForWindowEvent .two - bind all {append result " %d %W|"} - bind all {append result " %d %W|"} set result "|" } -body { + bind all {append result " %d %W|"} + bind all {append result " %d %W|"} destroy .two waitForWindowEvent .one.f1.f2 + processevents end + set result +} -cleanup { bind all {} bind all {} destroy .one - set result -} -cleanup { unset result } -result {| NotifyNonlinearVirtual .one| NotifyNonlinearVirtual .one.f1| NotifyNonlinear .one.f1.f2|} @@ -1022,12 +1024,12 @@ test event-9.15 {pointer window is a toplevel, destination is screen root} -setu waitForWindowEvent .two event generate .two -warp 1 -x 275 -y 275 controlPointerWarpTiming - bind all {append result " %d %W|"} - bind all {append result " %d %W|"} set result "|" } -body { - _pause 200; # ensure servicing of all scheduled events (only events expected) + bind all {append result " %d %W|"} + bind all {append result " %d %W|"} destroy .two + processevents end set result } -cleanup { bind all {} @@ -1044,13 +1046,13 @@ test event-9.16 {Successive destructions (pointer window + parent), single gener create_and_pack_frames .one wm deiconify .one tkwait visibility .one.f1.f2 - _pause 200 - bind all {append result " %d %W|"} - bind all {append result " %d %W|"} + update; # finish displaying window set result "|" } -body { + bind all {append result " %d %W|"} + bind all {append result " %d %W|"} destroy .one.f1 - _pause 200; # service crossing events + processevents end set result } -cleanup { bind all {} @@ -1067,15 +1069,16 @@ test event-9.17 {Successive destructions (pointer window + parent), separate cro create_and_pack_frames .one wm deiconify .one tkwait visibility .one.f1.f2 - _pause 200 - bind all {append result " %d %W|"} - bind all {append result " %d %W|"} + update; # finish displaying window set result "|" } -body { + bind all {append result " %d %W|"} + bind all {append result " %d %W|"} destroy .one.f1.f2 - _pause 200; # service crossing events + update; # make sure window is gone destroy .one.f1 - _pause 200; # service crossing events + update; # make sure window is gone + processevents end set result } -cleanup { bind all {} @@ -1092,17 +1095,18 @@ test event-9.18 {Successive destructions (pointer window + ancestors including i create_and_pack_frames .two wm deiconify .two waitForWindowEvent .two.f1.f2 - bind all {append result " %d %W|"} - bind all {append result " %d %W|"} set result "|" } -body { + bind all {append result " %d %W|"} + bind all {append result " %d %W|"} destroy .two waitForWindowEvent .one + processevents end + set result +} -cleanup { bind all {} bind all {} destroy .one - set result -} -cleanup { unset result } -result {| NotifyNonlinear .one|} @@ -1114,24 +1118,25 @@ test event-9.19 {Successive destructions (pointer window + ancestors including i wm geometry .two 300x300+100+100 create_and_pack_frames .two wm deiconify .two - waitForWindowEvent .two.f1.f2 toplevel .three pack propagate .three 0 wm geometry .three 300x300+110+110 create_and_pack_frames .three wm deiconify .three waitForWindowEvent .three.f1.f2 - bind all {append result " %d %W|"} - bind all {append result " %d %W|"} + update; # finish displaying windows set result "|" } -body { + bind all {append result " %d %W|"} + bind all {append result " %d %W|"} destroy .three waitForWindowEvent .two.f1.f2 + processevents end + set result +} -cleanup { bind all {} bind all {} destroy .two - set result -} -cleanup { unset result } -result {| NotifyNonlinearVirtual .two| NotifyNonlinearVirtual .two.f1| NotifyNonlinear .two.f1.f2|} @@ -1144,12 +1149,12 @@ test event-9.20 {Successive destructions (pointer window + ancestors including i create_and_pack_frames .two wm deiconify .two waitForWindowEvent .two.f1.f2 - bind all {append result " %d %W|"} - bind all {append result " %d %W|"} set result "|" } -body { + bind all {append result " %d %W|"} + bind all {append result " %d %W|"} destroy .two - _pause 200; # service events (only screen drawing events expected) + processevents end set result } -cleanup { bind all {} -- cgit v0.12 From c333b6fa71d92be0364b3ed3b7ecd9af3c58f3cc Mon Sep 17 00:00:00 2001 From: culler Date: Wed, 29 May 2024 16:23:21 +0000 Subject: remove unused variable; forgot to save events.test --- generic/tkTest.c | 1 - tests/event.test | 20 ++++++++++---------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/generic/tkTest.c b/generic/tkTest.c index 4fc6a80..a5f1c34 100644 --- a/generic/tkTest.c +++ b/generic/tkTest.c @@ -1718,7 +1718,6 @@ static int ProcessEventsObjCmd(ClientData dummy, { ClientData oldArg; Tk_RestrictProc *oldProc; - int count = 0; oldProc = Tk_RestrictEvents(CrossingRestrictProc, NULL, &oldArg); while (Tcl_ServiceEvent(TCL_WINDOW_EVENTS|TCL_DONT_WAIT)) {}; Tk_RestrictEvents(oldProc, oldArg, &oldArg); diff --git a/tests/event.test b/tests/event.test index 10dcf07..65208b1 100644 --- a/tests/event.test +++ b/tests/event.test @@ -935,7 +935,7 @@ test event-9.11 {pointer window container = parent} -setup { bind all {append result " %d %W|"} bind all {append result " %d %W|"} destroy .one.f1.f2 - processevents end + processevents set result } -cleanup { bind all {} @@ -959,7 +959,7 @@ test event-9.12 {pointer window container != parent} -setup { bind all {append result " %d %W|"} bind all {append result " %d %W|"} destroy .one.g - processevents end + processevents set result } -cleanup { bind all {} @@ -982,7 +982,7 @@ test event-9.13 {pointer window is a toplevel, toplevel destination} -setup { bind all {append result " %d %W|"} destroy .two waitForWindowEvent .one - processevents end + processevents set result } -cleanup { bind all {} @@ -1007,7 +1007,7 @@ test event-9.14 {pointer window is a toplevel, tk internal destination} -setup { bind all {append result " %d %W|"} destroy .two waitForWindowEvent .one.f1.f2 - processevents end + processevents set result } -cleanup { bind all {} @@ -1029,7 +1029,7 @@ test event-9.15 {pointer window is a toplevel, destination is screen root} -setu bind all {append result " %d %W|"} bind all {append result " %d %W|"} destroy .two - processevents end + processevents set result } -cleanup { bind all {} @@ -1052,7 +1052,7 @@ test event-9.16 {Successive destructions (pointer window + parent), single gener bind all {append result " %d %W|"} bind all {append result " %d %W|"} destroy .one.f1 - processevents end + processevents set result } -cleanup { bind all {} @@ -1078,7 +1078,7 @@ test event-9.17 {Successive destructions (pointer window + parent), separate cro update; # make sure window is gone destroy .one.f1 update; # make sure window is gone - processevents end + processevents set result } -cleanup { bind all {} @@ -1101,7 +1101,7 @@ test event-9.18 {Successive destructions (pointer window + ancestors including i bind all {append result " %d %W|"} destroy .two waitForWindowEvent .one - processevents end + processevents set result } -cleanup { bind all {} @@ -1131,7 +1131,7 @@ test event-9.19 {Successive destructions (pointer window + ancestors including i bind all {append result " %d %W|"} destroy .three waitForWindowEvent .two.f1.f2 - processevents end + processevents set result } -cleanup { bind all {} @@ -1154,7 +1154,7 @@ test event-9.20 {Successive destructions (pointer window + ancestors including i bind all {append result " %d %W|"} bind all {append result " %d %W|"} destroy .two - processevents end + processevents set result } -cleanup { bind all {} -- cgit v0.12 From 79c9294609224f128ca3f4b901ecefbf444955fd Mon Sep 17 00:00:00 2001 From: culler Date: Wed, 29 May 2024 16:50:18 +0000 Subject: Restore some calls to _pause, needed by Windows. --- tests/event.test | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/event.test b/tests/event.test index 65208b1..8a69104 100644 --- a/tests/event.test +++ b/tests/event.test @@ -929,9 +929,11 @@ test event-9.11 {pointer window container = parent} -setup { create_and_pack_frames .one wm deiconify .one tkwait visibility .one.f1.f2 + _pause 200; # needed for Windows update; # finish display of window set result "|" } -body { + processevents bind all {append result " %d %W|"} bind all {append result " %d %W|"} destroy .one.f1.f2 @@ -954,6 +956,7 @@ test event-9.12 {pointer window container != parent} -setup { tkwait visibility .one.g event generate .one -warp 1 -x 250 -y 250 update; # finish mouse warp + _pause 200; # needed for Windows set result "|" } -body { bind all {append result " %d %W|"} @@ -1046,7 +1049,8 @@ test event-9.16 {Successive destructions (pointer window + parent), single gener create_and_pack_frames .one wm deiconify .one tkwait visibility .one.f1.f2 - update; # finish displaying window + update; # finish displaying window + _pause 200; # needed for Windows set result "|" } -body { bind all {append result " %d %W|"} @@ -1070,6 +1074,7 @@ test event-9.17 {Successive destructions (pointer window + parent), separate cro wm deiconify .one tkwait visibility .one.f1.f2 update; # finish displaying window + _pause 200; # needed for Windows set result "|" } -body { bind all {append result " %d %W|"} -- cgit v0.12 From 7555afa81653a8967d77ef4697b1d4b0f5d25e30 Mon Sep 17 00:00:00 2001 From: culler Date: Wed, 29 May 2024 18:11:08 +0000 Subject: Make the processevents command general. --- generic/tkTest.c | 41 +++++++++++++++++++++++++++++++++-------- tests/event.test | 22 +++++++++++----------- 2 files changed, 44 insertions(+), 19 deletions(-) diff --git a/generic/tkTest.c b/generic/tkTest.c index a5f1c34..2eaa4de 100644 --- a/generic/tkTest.c +++ b/generic/tkTest.c @@ -1688,14 +1688,16 @@ ImageDelete( * * ProcessEventsObjCmd -- * - * This function implements the "processevents" command. Currently - * It processes all or events on the queue. + * This function implements the "processevents" command which processes + * all queued events of a type specified by one of the arguments to the + * command. Currently the supported arguments are leave, enter, and + * motion. Others could be added if needed. * * Results: - * A standard Tcl result. + * A standard Tcl result. * * Side effects: - * Events are processed + * Events are processed * *---------------------------------------------------------------------- */ @@ -1705,20 +1707,43 @@ CrossingRestrictProc( ClientData arg, XEvent *eventPtr) { - if (eventPtr->type == EnterNotify || eventPtr->type == LeaveNotify) { - return TK_PROCESS_EVENT; + int *eventTypes = (int *) arg; + for (int *t = eventTypes; *t != 0; t++) { + if (eventPtr->type == *t) { + return TK_PROCESS_EVENT; + } } return TK_DEFER_EVENT; } -static int ProcessEventsObjCmd(ClientData dummy, +static int ProcessEventsObjCmd( + ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj * const objv[]) { ClientData oldArg; Tk_RestrictProc *oldProc; - oldProc = Tk_RestrictEvents(CrossingRestrictProc, NULL, &oldArg); + int index; + static const char *const eventTypeNames[] = { + "leave", "enter", "motion", NULL}; + static const int eventTypes[] = { + LeaveNotify, EnterNotify, MotionNotify}; + int whichEvents[100]; + if (objc < 2) { + Tcl_WrongNumArgs(interp, 1, objv, "eventtype ?eventtype ...?"); + return TCL_ERROR; + } + for (int n = 1; n < objc; n++) { + if (Tcl_GetIndexFromObj(interp, objv[n], eventTypeNames, "eventtype", 0, + &index) != TCL_OK) { + return TCL_ERROR; + } + whichEvents[n - 1] = eventTypes[index]; + } + whichEvents[objc - 1] = 0; + oldProc = Tk_RestrictEvents(CrossingRestrictProc, (void *) whichEvents, + &oldArg); while (Tcl_ServiceEvent(TCL_WINDOW_EVENTS|TCL_DONT_WAIT)) {}; Tk_RestrictEvents(oldProc, oldArg, &oldArg); return TCL_OK; diff --git a/tests/event.test b/tests/event.test index 8a69104..7bdf57c 100644 --- a/tests/event.test +++ b/tests/event.test @@ -933,11 +933,11 @@ test event-9.11 {pointer window container = parent} -setup { update; # finish display of window set result "|" } -body { - processevents + processevents enter leave bind all {append result " %d %W|"} bind all {append result " %d %W|"} destroy .one.f1.f2 - processevents + processevents enter leave set result } -cleanup { bind all {} @@ -962,7 +962,7 @@ test event-9.12 {pointer window container != parent} -setup { bind all {append result " %d %W|"} bind all {append result " %d %W|"} destroy .one.g - processevents + processevents enter leave set result } -cleanup { bind all {} @@ -985,7 +985,7 @@ test event-9.13 {pointer window is a toplevel, toplevel destination} -setup { bind all {append result " %d %W|"} destroy .two waitForWindowEvent .one - processevents + processevents enter leave set result } -cleanup { bind all {} @@ -1010,7 +1010,7 @@ test event-9.14 {pointer window is a toplevel, tk internal destination} -setup { bind all {append result " %d %W|"} destroy .two waitForWindowEvent .one.f1.f2 - processevents + processevents enter leave set result } -cleanup { bind all {} @@ -1032,7 +1032,7 @@ test event-9.15 {pointer window is a toplevel, destination is screen root} -setu bind all {append result " %d %W|"} bind all {append result " %d %W|"} destroy .two - processevents + processevents enter leave set result } -cleanup { bind all {} @@ -1056,7 +1056,7 @@ test event-9.16 {Successive destructions (pointer window + parent), single gener bind all {append result " %d %W|"} bind all {append result " %d %W|"} destroy .one.f1 - processevents + processevents enter leave set result } -cleanup { bind all {} @@ -1083,7 +1083,7 @@ test event-9.17 {Successive destructions (pointer window + parent), separate cro update; # make sure window is gone destroy .one.f1 update; # make sure window is gone - processevents + processevents enter leave set result } -cleanup { bind all {} @@ -1106,7 +1106,7 @@ test event-9.18 {Successive destructions (pointer window + ancestors including i bind all {append result " %d %W|"} destroy .two waitForWindowEvent .one - processevents + processevents enter leave set result } -cleanup { bind all {} @@ -1136,7 +1136,7 @@ test event-9.19 {Successive destructions (pointer window + ancestors including i bind all {append result " %d %W|"} destroy .three waitForWindowEvent .two.f1.f2 - processevents + processevents enter leave set result } -cleanup { bind all {} @@ -1159,7 +1159,7 @@ test event-9.20 {Successive destructions (pointer window + ancestors including i bind all {append result " %d %W|"} bind all {append result " %d %W|"} destroy .two - processevents + processevents enter leave set result } -cleanup { bind all {} -- cgit v0.12 From cdbcd05743c083c4a28648aaa4c064ccef44b292 Mon Sep 17 00:00:00 2001 From: culler Date: Wed, 29 May 2024 19:07:21 +0000 Subject: Switch back to the macOS-11 runner, for comparison --- .github/workflows/mac-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/mac-build.yml b/.github/workflows/mac-build.yml index d7fd4ba..59b93d3 100644 --- a/.github/workflows/mac-build.yml +++ b/.github/workflows/mac-build.yml @@ -14,7 +14,7 @@ env: ERROR_ON_FAILURES: 1 jobs: xcode: - runs-on: macos-14 + runs-on: macos-11 defaults: run: shell: bash -- cgit v0.12 From 44dc0fba4b17d751ad739e095a0459e69716085b Mon Sep 17 00:00:00 2001 From: culler Date: Thu, 30 May 2024 03:41:42 +0000 Subject: Small adjustments to tests. --- generic/tkTest.c | 4 ++-- tests/event.test | 23 +++++++++++++---------- tests/winfo.test | 2 ++ 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/generic/tkTest.c b/generic/tkTest.c index 2eaa4de..b424a36 100644 --- a/generic/tkTest.c +++ b/generic/tkTest.c @@ -1726,9 +1726,9 @@ static int ProcessEventsObjCmd( Tk_RestrictProc *oldProc; int index; static const char *const eventTypeNames[] = { - "leave", "enter", "motion", NULL}; + "leave", "enter", "motion", "expose", NULL}; static const int eventTypes[] = { - LeaveNotify, EnterNotify, MotionNotify}; + LeaveNotify, EnterNotify, MotionNotify, Expose}; int whichEvents[100]; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "eventtype ?eventtype ...?"); diff --git a/tests/event.test b/tests/event.test index 7bdf57c..292e41e 100644 --- a/tests/event.test +++ b/tests/event.test @@ -930,10 +930,9 @@ test event-9.11 {pointer window container = parent} -setup { wm deiconify .one tkwait visibility .one.f1.f2 _pause 200; # needed for Windows - update; # finish display of window + update idletasks; # finish display of window set result "|" } -body { - processevents enter leave bind all {append result " %d %W|"} bind all {append result " %d %W|"} destroy .one.f1.f2 @@ -955,7 +954,6 @@ test event-9.12 {pointer window container != parent} -setup { wm deiconify .one tkwait visibility .one.g event generate .one -warp 1 -x 250 -y 250 - update; # finish mouse warp _pause 200; # needed for Windows set result "|" } -body { @@ -978,7 +976,7 @@ test event-9.13 {pointer window is a toplevel, toplevel destination} -setup { wm withdraw .two wm deiconify .two waitForWindowEvent .two - update; # finish displaying windows + update idletasks; # finish displaying windows set result | } -body { bind all {append result " %d %W|"} @@ -1021,10 +1019,12 @@ test event-9.14 {pointer window is a toplevel, tk internal destination} -setup { test event-9.15 {pointer window is a toplevel, destination is screen root} -setup { setup_win_mousepointer .one; # ensure the mouse pointer is where we want it to be (the .one toplevel is not itself used in this test) +# destroy .one toplevel .two wm geometry .two 300x300+150+150 wm deiconify .two waitForWindowEvent .two + update idletasks; # finish displaying .two event generate .two -warp 1 -x 275 -y 275 controlPointerWarpTiming set result "|" @@ -1032,7 +1032,7 @@ test event-9.15 {pointer window is a toplevel, destination is screen root} -setu bind all {append result " %d %W|"} bind all {append result " %d %W|"} destroy .two - processevents enter leave +# processevents enter leave set result } -cleanup { bind all {} @@ -1049,7 +1049,7 @@ test event-9.16 {Successive destructions (pointer window + parent), single gener create_and_pack_frames .one wm deiconify .one tkwait visibility .one.f1.f2 - update; # finish displaying window + update idletasks; # finish displaying window _pause 200; # needed for Windows set result "|" } -body { @@ -1073,7 +1073,7 @@ test event-9.17 {Successive destructions (pointer window + parent), separate cro create_and_pack_frames .one wm deiconify .one tkwait visibility .one.f1.f2 - update; # finish displaying window + update idletasks; # finish displaying window _pause 200; # needed for Windows set result "|" } -body { @@ -1117,7 +1117,7 @@ test event-9.18 {Successive destructions (pointer window + ancestors including i test event-9.19 {Successive destructions (pointer window + ancestors including its toplevel), destination is internal window, bypass root win} -setup { setup_win_mousepointer .one; # ensure the mouse pointer is where we want it to be (the .one toplevel is not itself used in this test) - destroy .one +# destroy .one toplevel .two pack propagate .two 0 wm geometry .two 300x300+100+100 @@ -1129,18 +1129,20 @@ test event-9.19 {Successive destructions (pointer window + ancestors including i create_and_pack_frames .three wm deiconify .three waitForWindowEvent .three.f1.f2 - update; # finish displaying windows + update idletasks; # finish displaying windows set result "|" } -body { bind all {append result " %d %W|"} bind all {append result " %d %W|"} destroy .three waitForWindowEvent .two.f1.f2 + update idletasks; #finish destroying .two processevents enter leave set result } -cleanup { bind all {} bind all {} + destroy .one destroy .two unset result } -result {| NotifyNonlinearVirtual .two| NotifyNonlinearVirtual .two.f1| NotifyNonlinear .two.f1.f2|} @@ -1159,7 +1161,8 @@ test event-9.20 {Successive destructions (pointer window + ancestors including i bind all {append result " %d %W|"} bind all {append result " %d %W|"} destroy .two - processevents enter leave + update idletasks; #finish destroying .two +# processevents enter leave set result } -cleanup { bind all {} diff --git a/tests/winfo.test b/tests/winfo.test index ffacf8f..5a7a3ec 100644 --- a/tests/winfo.test +++ b/tests/winfo.test @@ -441,8 +441,10 @@ test winfo-13.3 {destroying container window} -setup { test winfo-13.4 {[winfo containing] with embedded windows} -setup { deleteWindows } -body { + wm geometry . +100+100 frame .con -container 1 pack .con -expand yes -fill both + update toplevel .emb -use [winfo id .con] -bd 0 -highlightthickness 0 button .emb.b pack .emb.b -expand yes -fill both -- cgit v0.12 From 789cd6ea2a3de0e5d19338d594b97c467316d897 Mon Sep 17 00:00:00 2001 From: culler Date: Thu, 30 May 2024 18:51:57 +0000 Subject: Don't use processevents on linux. --- tests/event.test | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/tests/event.test b/tests/event.test index 292e41e..edfddc4 100644 --- a/tests/event.test +++ b/tests/event.test @@ -936,7 +936,7 @@ test event-9.11 {pointer window container = parent} -setup { bind all {append result " %d %W|"} bind all {append result " %d %W|"} destroy .one.f1.f2 - processevents enter leave + if {[tk windowingsystem] ne "x11" }]} {processevents enter leave} set result } -cleanup { bind all {} @@ -960,7 +960,7 @@ test event-9.12 {pointer window container != parent} -setup { bind all {append result " %d %W|"} bind all {append result " %d %W|"} destroy .one.g - processevents enter leave + if {[tk windowingsystem] ne "x11" }]} {processevents enter leave} set result } -cleanup { bind all {} @@ -983,7 +983,7 @@ test event-9.13 {pointer window is a toplevel, toplevel destination} -setup { bind all {append result " %d %W|"} destroy .two waitForWindowEvent .one - processevents enter leave + if {[tk windowingsystem] ne "x11" }]} {processevents enter leave} set result } -cleanup { bind all {} @@ -1032,7 +1032,6 @@ test event-9.15 {pointer window is a toplevel, destination is screen root} -setu bind all {append result " %d %W|"} bind all {append result " %d %W|"} destroy .two -# processevents enter leave set result } -cleanup { bind all {} @@ -1056,7 +1055,7 @@ test event-9.16 {Successive destructions (pointer window + parent), single gener bind all {append result " %d %W|"} bind all {append result " %d %W|"} destroy .one.f1 - processevents enter leave + if {[tk windowingsystem] ne "x11" }]} {processevents enter leave} set result } -cleanup { bind all {} @@ -1083,7 +1082,7 @@ test event-9.17 {Successive destructions (pointer window + parent), separate cro update; # make sure window is gone destroy .one.f1 update; # make sure window is gone - processevents enter leave + if {[tk windowingsystem] ne "x11" }]} {processevents enter leave} set result } -cleanup { bind all {} @@ -1106,7 +1105,7 @@ test event-9.18 {Successive destructions (pointer window + ancestors including i bind all {append result " %d %W|"} destroy .two waitForWindowEvent .one - processevents enter leave + if {[tk windowingsystem] ne "x11" }]} {processevents enter leave} set result } -cleanup { bind all {} @@ -1137,7 +1136,7 @@ test event-9.19 {Successive destructions (pointer window + ancestors including i destroy .three waitForWindowEvent .two.f1.f2 update idletasks; #finish destroying .two - processevents enter leave + if {[tk windowingsystem] ne "x11" }]} {processevents enter leave} set result } -cleanup { bind all {} @@ -1162,7 +1161,6 @@ test event-9.20 {Successive destructions (pointer window + ancestors including i bind all {append result " %d %W|"} destroy .two update idletasks; #finish destroying .two -# processevents enter leave set result } -cleanup { bind all {} -- cgit v0.12 From 7e11e70c9bc4f893b845c39baea7c50cac82ffad Mon Sep 17 00:00:00 2001 From: culler Date: Fri, 31 May 2024 22:01:29 +0000 Subject: Fix typo in event.test; be less lazy in processevents --- generic/tkTest.c | 8 +++++++- tests/event.test | 14 +++++++------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/generic/tkTest.c b/generic/tkTest.c index b424a36..bd6dde3 100644 --- a/generic/tkTest.c +++ b/generic/tkTest.c @@ -1729,11 +1729,17 @@ static int ProcessEventsObjCmd( "leave", "enter", "motion", "expose", NULL}; static const int eventTypes[] = { LeaveNotify, EnterNotify, MotionNotify, Expose}; - int whichEvents[100]; +#define NUM_TYPES (sizeof(eventTypes)/sizeof(int)) + int whichEvents[1 + NUM_TYPES]; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "eventtype ?eventtype ...?"); return TCL_ERROR; } + if (objc > NUM_TYPES + 1) { + Tcl_WrongNumArgs(interp, 1, objv, "too many event types"); + return TCL_ERROR; + } +#undef NUM_TYPES for (int n = 1; n < objc; n++) { if (Tcl_GetIndexFromObj(interp, objv[n], eventTypeNames, "eventtype", 0, &index) != TCL_OK) { diff --git a/tests/event.test b/tests/event.test index edfddc4..585eb96 100644 --- a/tests/event.test +++ b/tests/event.test @@ -936,7 +936,7 @@ test event-9.11 {pointer window container = parent} -setup { bind all {append result " %d %W|"} bind all {append result " %d %W|"} destroy .one.f1.f2 - if {[tk windowingsystem] ne "x11" }]} {processevents enter leave} + if {[tk windowingsystem] ne "x11"} {processevents enter leave} set result } -cleanup { bind all {} @@ -960,7 +960,7 @@ test event-9.12 {pointer window container != parent} -setup { bind all {append result " %d %W|"} bind all {append result " %d %W|"} destroy .one.g - if {[tk windowingsystem] ne "x11" }]} {processevents enter leave} + if {[tk windowingsystem] ne "x11"} {processevents enter leave} set result } -cleanup { bind all {} @@ -983,7 +983,7 @@ test event-9.13 {pointer window is a toplevel, toplevel destination} -setup { bind all {append result " %d %W|"} destroy .two waitForWindowEvent .one - if {[tk windowingsystem] ne "x11" }]} {processevents enter leave} + if {[tk windowingsystem] ne "x11"} {processevents enter leave} set result } -cleanup { bind all {} @@ -1055,7 +1055,7 @@ test event-9.16 {Successive destructions (pointer window + parent), single gener bind all {append result " %d %W|"} bind all {append result " %d %W|"} destroy .one.f1 - if {[tk windowingsystem] ne "x11" }]} {processevents enter leave} + if {[tk windowingsystem] ne "x11"} {processevents enter leave} set result } -cleanup { bind all {} @@ -1082,7 +1082,7 @@ test event-9.17 {Successive destructions (pointer window + parent), separate cro update; # make sure window is gone destroy .one.f1 update; # make sure window is gone - if {[tk windowingsystem] ne "x11" }]} {processevents enter leave} + if {[tk windowingsystem] ne "x11"} {processevents enter leave} set result } -cleanup { bind all {} @@ -1105,7 +1105,7 @@ test event-9.18 {Successive destructions (pointer window + ancestors including i bind all {append result " %d %W|"} destroy .two waitForWindowEvent .one - if {[tk windowingsystem] ne "x11" }]} {processevents enter leave} + if {[tk windowingsystem] ne "x11"} {processevents enter leave} set result } -cleanup { bind all {} @@ -1136,7 +1136,7 @@ test event-9.19 {Successive destructions (pointer window + ancestors including i destroy .three waitForWindowEvent .two.f1.f2 update idletasks; #finish destroying .two - if {[tk windowingsystem] ne "x11" }]} {processevents enter leave} + if {[tk windowingsystem] ne "x11"} {processevents enter leave} set result } -cleanup { bind all {} -- cgit v0.12 From 1419bbfee25ed9da6b99303e536b35dce74d91db Mon Sep 17 00:00:00 2001 From: culler Date: Fri, 31 May 2024 22:26:53 +0000 Subject: Remove commented out code --- macosx/tkMacOSXWm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index b154f18..09a7710 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -623,7 +623,6 @@ FrontWindowAtPoint( for (NSWindow *w in windows) { winPtr = TkMacOSXGetTkWindow(w); if (winPtr) { - // WmInfo *wmPtr = winPtr->wmInfoPtr; NSRect windowFrame = [w frame]; NSRect contentFrame = [w frame]; -- cgit v0.12 From a075e134b1d8a47abdce9fcedf5266529846f271 Mon Sep 17 00:00:00 2001 From: culler Date: Fri, 31 May 2024 22:36:47 +0000 Subject: keep the root on the screen for event tests --- tests/event.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/event.test b/tests/event.test index 585eb96..ea46dd1 100644 --- a/tests/event.test +++ b/tests/event.test @@ -908,7 +908,7 @@ proc create_and_pack_frames {{w {}}} { proc setup_win_mousepointer {w} { # Position the window and the mouse pointer as an initial state for some tests. # The so-called "pointer window" is the $w window that will now contain the mouse pointer. - wm geometry . +700+700; # root window out of our way - must not cover windows from event-9.1* + wm geometry . +700+400; # root window out of our way - must not cover windows from event-9.1* toplevel $w pack propagate $w 0 wm geometry $w 300x300+100+100 -- cgit v0.12 From f1542aec0c1636298ec381a06c196f76a5807085 Mon Sep 17 00:00:00 2001 From: culler Date: Fri, 31 May 2024 23:09:32 +0000 Subject: Restore accidentally deleted linux test code --- tests/event.test | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/tests/event.test b/tests/event.test index ea46dd1..c37fc67 100644 --- a/tests/event.test +++ b/tests/event.test @@ -936,7 +936,11 @@ test event-9.11 {pointer window container = parent} -setup { bind all {append result " %d %W|"} bind all {append result " %d %W|"} destroy .one.f1.f2 - if {[tk windowingsystem] ne "x11"} {processevents enter leave} + if {[tk windowingsystem] ne "x11"} { + processevents enter leave + } else { + update + } set result } -cleanup { bind all {} @@ -960,7 +964,11 @@ test event-9.12 {pointer window container != parent} -setup { bind all {append result " %d %W|"} bind all {append result " %d %W|"} destroy .one.g - if {[tk windowingsystem] ne "x11"} {processevents enter leave} + if {[tk windowingsystem] ne "x11"} { + processevents enter leave + } else { + update + } set result } -cleanup { bind all {} @@ -983,7 +991,11 @@ test event-9.13 {pointer window is a toplevel, toplevel destination} -setup { bind all {append result " %d %W|"} destroy .two waitForWindowEvent .one - if {[tk windowingsystem] ne "x11"} {processevents enter leave} + if {[tk windowingsystem] ne "x11"} { + processevents enter leave + } else { + update + } set result } -cleanup { bind all {} @@ -1055,7 +1067,11 @@ test event-9.16 {Successive destructions (pointer window + parent), single gener bind all {append result " %d %W|"} bind all {append result " %d %W|"} destroy .one.f1 - if {[tk windowingsystem] ne "x11"} {processevents enter leave} + if {[tk windowingsystem] ne "x11"} { + processevents enter leave + } else { + update + } set result } -cleanup { bind all {} -- cgit v0.12 From 5493df5dff50798c087c108676ca372ccc5c86ee Mon Sep 17 00:00:00 2001 From: fvogel Date: Sun, 9 Jun 2024 19:59:50 +0000 Subject: Comments style. --- macosx/tkMacOSXWm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index 09a7710..228ee32 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -1026,7 +1026,8 @@ TkWmDeadWindow( root_y = floor(TkMacOSXZeroScreenHeight() - mouse.y); int win_x, win_y; Tk_Window target = Tk_TopCoordsToWindow((Tk_Window) winPtr2, top_x, top_y, &win_x, &win_y); - /* A non-toplevel window can have a NULL parent while it is in the process of + /* + * A non-toplevel window can have a NULL parent while it is in the process of * being destroyed. We should not call Tk_UpdatePointer in that case. */ if (Tk_Parent(target) != NULL || Tk_IsTopLevel(target)) { -- cgit v0.12 From fe184a24838c9d2e19d239898218a2ef81f516d8 Mon Sep 17 00:00:00 2001 From: fvogel Date: Sun, 9 Jun 2024 20:00:38 +0000 Subject: Remove -verbose option from macOS workflow file. --- .github/workflows/mac-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/mac-build.yml b/.github/workflows/mac-build.yml index 59b93d3..3d8178e 100644 --- a/.github/workflows/mac-build.yml +++ b/.github/workflows/mac-build.yml @@ -49,7 +49,7 @@ jobs: } - name: Run Tests run: | - make TESTFLAGS="-verbose bpest" test | tee out.txt + make | tee out.txt nmatches=$( grep -c "Failed 0" out.txt ) if [ $nmatches -lt 4 ] then -- cgit v0.12 From c9218c7a9dd08f1c281c1ba82cb09cc2d7a9e3f7 Mon Sep 17 00:00:00 2001 From: fvogel Date: Sun, 9 Jun 2024 20:01:04 +0000 Subject: Typo in previous commit. --- .github/workflows/mac-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/mac-build.yml b/.github/workflows/mac-build.yml index 3d8178e..7485ac7 100644 --- a/.github/workflows/mac-build.yml +++ b/.github/workflows/mac-build.yml @@ -49,7 +49,7 @@ jobs: } - name: Run Tests run: | - make | tee out.txt + make test | tee out.txt nmatches=$( grep -c "Failed 0" out.txt ) if [ $nmatches -lt 4 ] then -- cgit v0.12 From bbbd008273a2c030840742cac6b09d596d66ee59 Mon Sep 17 00:00:00 2001 From: fvogel Date: Sun, 9 Jun 2024 20:08:52 +0000 Subject: Rename processevents --> testprocessevents to conform to the widely used convention that commands specific to the test suite start with 'test'. --- generic/tkTest.c | 14 +++++++------- tests/event.test | 16 ++++++++-------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/generic/tkTest.c b/generic/tkTest.c index bd6dde3..85dd664 100644 --- a/generic/tkTest.c +++ b/generic/tkTest.c @@ -147,7 +147,7 @@ typedef struct TrivialCommandHeader { static int ImageObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj * const objv[]); -static int ProcessEventsObjCmd(ClientData dummy, +static int TestProcessEventsObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj * const objv[]); static int TestbitmapObjCmd(ClientData dummy, @@ -250,7 +250,7 @@ Tktest_Init( return TCL_ERROR; } - Tcl_CreateObjCommand(interp, "processevents", ProcessEventsObjCmd, NULL, NULL); + Tcl_CreateObjCommand(interp, "testprocessevents", TestProcessEventsObjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "square", SquareObjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testbitmap", TestbitmapObjCmd, (ClientData) Tk_MainWindow(interp), NULL); @@ -1686,12 +1686,12 @@ ImageDelete( /* *---------------------------------------------------------------------- * - * ProcessEventsObjCmd -- + * TestProcessEventsObjCmd -- * - * This function implements the "processevents" command which processes + * This function implements the "testprocessevents" command which processes * all queued events of a type specified by one of the arguments to the - * command. Currently the supported arguments are leave, enter, and - * motion. Others could be added if needed. + * command. Currently the supported arguments are leave, enter, motion, + * and expose. Others could be added if needed. * * Results: * A standard Tcl result. @@ -1716,7 +1716,7 @@ CrossingRestrictProc( return TK_DEFER_EVENT; } -static int ProcessEventsObjCmd( +static int TestProcessEventsObjCmd( ClientData dummy, Tcl_Interp *interp, int objc, diff --git a/tests/event.test b/tests/event.test index c37fc67..b1c7931 100644 --- a/tests/event.test +++ b/tests/event.test @@ -937,7 +937,7 @@ test event-9.11 {pointer window container = parent} -setup { bind all {append result " %d %W|"} destroy .one.f1.f2 if {[tk windowingsystem] ne "x11"} { - processevents enter leave + testprocessevents enter leave } else { update } @@ -965,7 +965,7 @@ test event-9.12 {pointer window container != parent} -setup { bind all {append result " %d %W|"} destroy .one.g if {[tk windowingsystem] ne "x11"} { - processevents enter leave + testprocessevents enter leave } else { update } @@ -992,7 +992,7 @@ test event-9.13 {pointer window is a toplevel, toplevel destination} -setup { destroy .two waitForWindowEvent .one if {[tk windowingsystem] ne "x11"} { - processevents enter leave + testprocessevents enter leave } else { update } @@ -1020,7 +1020,7 @@ test event-9.14 {pointer window is a toplevel, tk internal destination} -setup { bind all {append result " %d %W|"} destroy .two waitForWindowEvent .one.f1.f2 - processevents enter leave + testprocessevents enter leave set result } -cleanup { bind all {} @@ -1068,7 +1068,7 @@ test event-9.16 {Successive destructions (pointer window + parent), single gener bind all {append result " %d %W|"} destroy .one.f1 if {[tk windowingsystem] ne "x11"} { - processevents enter leave + testprocessevents enter leave } else { update } @@ -1098,7 +1098,7 @@ test event-9.17 {Successive destructions (pointer window + parent), separate cro update; # make sure window is gone destroy .one.f1 update; # make sure window is gone - if {[tk windowingsystem] ne "x11"} {processevents enter leave} + if {[tk windowingsystem] ne "x11"} {testprocessevents enter leave} set result } -cleanup { bind all {} @@ -1121,7 +1121,7 @@ test event-9.18 {Successive destructions (pointer window + ancestors including i bind all {append result " %d %W|"} destroy .two waitForWindowEvent .one - if {[tk windowingsystem] ne "x11"} {processevents enter leave} + if {[tk windowingsystem] ne "x11"} {testprocessevents enter leave} set result } -cleanup { bind all {} @@ -1152,7 +1152,7 @@ test event-9.19 {Successive destructions (pointer window + ancestors including i destroy .three waitForWindowEvent .two.f1.f2 update idletasks; #finish destroying .two - if {[tk windowingsystem] ne "x11"} {processevents enter leave} + if {[tk windowingsystem] ne "x11"} {testprocessevents enter leave} set result } -cleanup { bind all {} -- cgit v0.12 From f05a10a3aca5c7affc50789a2a9a2cae5bb31244 Mon Sep 17 00:00:00 2001 From: fvogel Date: Sun, 9 Jun 2024 20:21:07 +0000 Subject: Document parameters of TestProcessEventsObjCmd. --- generic/tkTest.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/generic/tkTest.c b/generic/tkTest.c index 85dd664..dbf572e 100644 --- a/generic/tkTest.c +++ b/generic/tkTest.c @@ -1717,10 +1717,10 @@ CrossingRestrictProc( } static int TestProcessEventsObjCmd( - ClientData dummy, - Tcl_Interp *interp, - int objc, - Tcl_Obj * const objv[]) + TCL_UNUSED(ClientData), /* Main window for application. */ + Tcl_Interp* interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj* const objv[]) /* Argument objects. */ { ClientData oldArg; Tk_RestrictProc *oldProc; -- cgit v0.12 From d0b47a6ee79bdf4f9b8e40bad1c35c1b95266734 Mon Sep 17 00:00:00 2001 From: fvogel Date: Sun, 9 Jun 2024 20:25:29 +0000 Subject: TCL_UNUSED() parameter in SendEnterLeaveForDestroy() on Linux. --- generic/tkWindow.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/generic/tkWindow.c b/generic/tkWindow.c index 85b5a0b..589a930 100644 --- a/generic/tkWindow.c +++ b/generic/tkWindow.c @@ -1334,10 +1334,10 @@ Tk_CreateWindowFromPath( *-------------------------------------------------------------- */ +#if defined(MAC_OSX_TK) || defined(_WIN32) static void SendEnterLeaveForDestroy( Tk_Window tkwin) { -#if defined(MAC_OSX_TK) || defined(_WIN32) int x, y; unsigned int state; Tk_Window pointerWin; @@ -1359,8 +1359,13 @@ static void SendEnterLeaveForDestroy( if (pointerWin && (tkwin == Tk_Parent(pointerWin))) { Tk_UpdatePointer(Tk_Parent(tkwin), x, y, state); } -#endif } +#else +static void SendEnterLeaveForDestroy( + TCL_UNUSED(Tk_Window) +{ +} +#endif void Tk_DestroyWindow( -- cgit v0.12 From 3f0a126393198d3f6e0dff58e479ee9cab5b213d Mon Sep 17 00:00:00 2001 From: fvogel Date: Sun, 9 Jun 2024 20:29:38 +0000 Subject: Add parenthesis that was missing from previous commit. --- generic/tkWindow.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generic/tkWindow.c b/generic/tkWindow.c index 589a930..fa3885d 100644 --- a/generic/tkWindow.c +++ b/generic/tkWindow.c @@ -1362,7 +1362,7 @@ static void SendEnterLeaveForDestroy( } #else static void SendEnterLeaveForDestroy( - TCL_UNUSED(Tk_Window) + TCL_UNUSED(Tk_Window)) { } #endif -- cgit v0.12