Tk Source Code

Artifact [8a884d87]
Login

Artifact 8a884d87a9828456df218e490943e258701e1595b7442c9e18a6a60f9ce5554b:

Attachment "idle_curiosity_2.diff" to ticket [06d8246b] added by chrstphrchvz 2020-05-24 16:02:56.
diff --git macosx/tkMacOSXDraw.c macosx/tkMacOSXDraw.c
index e56e6665d..728033464 100644
--- macosx/tkMacOSXDraw.c
+++ macosx/tkMacOSXDraw.c
@@ -1649,18 +1649,14 @@ TkMacOSXSetupDrawingContext(
 	if (![NSApp isDrawing] || view != [NSView focusView]) {
 	    NSRect bounds = [view bounds];
 	    NSRect dirtyNS = bounds;
-	    if ([NSEvent pressedMouseButtons]) {
-		[view setNeedsDisplay:YES];
-	    } else {
-		CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1, .tx = 0,
-					.ty = dirtyNS.size.height};
-		if (dc.clipRgn) {
-		    CGRect dirtyCG = NSRectToCGRect(dirtyNS);
-		    HIShapeGetBounds(dc.clipRgn, &dirtyCG);
-		    dirtyNS = NSRectToCGRect(CGRectApplyAffineTransform(dirtyCG, t));
-		}
-		[view setNeedsDisplayInRect:dirtyNS];
-	    }
+	    CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1, .tx = 0,
+				    .ty = dirtyNS.size.height};
+	    if (dc.clipRgn) {
+		CGRect dirtyCG;
+		HIShapeGetBounds(dc.clipRgn, &dirtyCG);
+		dirtyNS = NSRectToCGRect(CGRectApplyAffineTransform(dirtyCG, t));
+	    }
+	    [view setNeedsDisplayInRect:dirtyNS];
 	    canDraw = false;
 	    goto end;
 	}
diff --git macosx/tkMacOSXNotify.c macosx/tkMacOSXNotify.c
index 985d7bcb0..00331166c 100644
--- macosx/tkMacOSXNotify.c
+++ macosx/tkMacOSXNotify.c
@@ -32,6 +32,15 @@ static void TkMacOSXNotifyExitHandler(ClientData clientData);
 static void TkMacOSXEventsSetupProc(ClientData clientData, int flags);
 static void TkMacOSXEventsCheckProc(ClientData clientData, int flags);
 
+/*
+ * Flag that is set by the first drawRect call, just to have a way to know when
+ * Tk is sufficiently initialized to begin using temoprary idle event loops in
+ * TkMacOSXEventsSetupProc and TkMacOSXEventsCheckProc. Enabling the temporary
+ * loops too early may lead to an empty toplevel appearing for about one second
+ * when Tk is started. See ticket 06d8246baf.
+ */
+bool tkMacOSXHasEnteredDrawRectAtLeastOnce = false;
+
 #ifdef TK_MAC_DEBUG_EVENTS
 static const char *Tk_EventName[39] = {
     "",
@@ -335,10 +344,17 @@ TkMacOSXEventsSetupProc(
 	[NSApp _resetAutoreleasePool];
 
 	/*
-	 * Call this with dequeue=NO -- just checking if the queue is empty.
+	 * Temporary idle event loop (1 of 3): queued idle events are
+	 * handled now in order to avoid handling them during drawRect;
+	 * otherwise widgets can fail to redraw. See ticket 06d8246baf.
 	 */
+	if (tkMacOSXHasEnteredDrawRectAtLeastOnce) {
+	    while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {}
+	}
 
-	while (Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_DONT_WAIT)) {}
+	/*
+	 * Call this with dequeue=NO -- just checking if the queue is empty.
+	 */
 	NSEvent *currentEvent =
 	        [NSApp nextEventMatchingMask:NSAnyEventMask
 			untilDate:[NSDate distantPast]
@@ -408,7 +424,16 @@ TkMacOSXEventsCheckProc(
 
 	[NSApp _lockAutoreleasePool];
 	do {
-	    while (Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_DONT_WAIT)) {}
+
+	    /*
+	     * Temporary idle event loop (2 of 3): queued idle events are
+	     * handled now in order to avoid handling them during drawRect;
+	     * otherwise widgets can fail to redraw. See ticket 06d8246baf.
+	     */
+	    if (tkMacOSXHasEnteredDrawRectAtLeastOnce) {
+		while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {}
+	    }
+
 	    modalSession = TkMacOSXGetModalSession();
 	    testEvent = [NSApp nextEventMatchingMask:NSAnyEventMask
 		    untilDate:[NSDate distantPast]
@@ -422,7 +447,16 @@ TkMacOSXEventsCheckProc(
 	    if (testEvent && [[testEvent window] inLiveResize]) {
 		break;
 	    }
-	    while (Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_DONT_WAIT)) {}
+
+	    /*
+	     * Temporary idle event loop (3 of 3): queued idle events are
+	     * handled now in order to avoid handling them during drawRect;
+	     * otherwise widgets can fail to redraw. See ticket 06d8246baf.
+	     */
+	    if (tkMacOSXHasEnteredDrawRectAtLeastOnce) {
+		while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {}
+	    }
+
 	    currentEvent = [NSApp nextEventMatchingMask:NSAnyEventMask
 		    untilDate:[NSDate distantPast]
 		    inMode:GetRunLoopMode(modalSession)
diff --git macosx/tkMacOSXPrivate.h macosx/tkMacOSXPrivate.h
index a0645f785..cd5ccca13 100644
--- macosx/tkMacOSXPrivate.h
+++ macosx/tkMacOSXPrivate.h
@@ -210,6 +210,7 @@ typedef struct TkMacOSXDrawingContext {
  */
 
 MODULE_SCOPE long tkMacOSXMacOSXVersion;
+MODULE_SCOPE bool tkMacOSXHasEnteredDrawRectAtLeastOnce;
 
 /*
  * Prototypes for TkMacOSXRegion.c.
diff --git macosx/tkMacOSXWindowEvent.c macosx/tkMacOSXWindowEvent.c
index cb4ffd193..5ea82dcd0 100644
--- macosx/tkMacOSXWindowEvent.c
+++ macosx/tkMacOSXWindowEvent.c
@@ -938,6 +938,7 @@ RedisplayView(
 {
     const NSRect *rectsBeingDrawn;
     NSInteger rectsBeingDrawnCount;
+    tkMacOSXHasEnteredDrawRectAtLeastOnce = true;
 
 #ifdef TK_MAC_DEBUG_DRAWING
     TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);