diff options
author | marc_culler <marc.culler@gmail.com> | 2020-06-03 03:23:12 (GMT) |
---|---|---|
committer | marc_culler <marc.culler@gmail.com> | 2020-06-03 03:23:12 (GMT) |
commit | 876fc6d65e63ae72fe52d8435ef703efa50fe814 (patch) | |
tree | c4fbfa804523b101ed086d4a5ea89f787ae08735 | |
parent | aeb89ef62c14b00be0853a7539e807bb3937a6f8 (diff) | |
download | tk-876fc6d65e63ae72fe52d8435ef703efa50fe814.zip tk-876fc6d65e63ae72fe52d8435ef703efa50fe814.tar.gz tk-876fc6d65e63ae72fe52d8435ef703efa50fe814.tar.bz2 |
Do not draw in the setup proc. Fix the heartbeat so it can wake up Tcl_WaitForEvent. Handle the first drawing of a window.
-rw-r--r-- | macosx/tkMacOSXDraw.c | 22 | ||||
-rw-r--r-- | macosx/tkMacOSXNotify.c | 84 | ||||
-rw-r--r-- | macosx/tkMacOSXWindowEvent.c | 21 |
3 files changed, 71 insertions, 56 deletions
diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c index 1ec2cfe..6a63449 100644 --- a/macosx/tkMacOSXDraw.c +++ b/macosx/tkMacOSXDraw.c @@ -1658,19 +1658,19 @@ TkMacOSXSetupDrawingContext( } else if (dc.clipRgn) { /* - * Drawing can also fail when we are being called from drawRect but - * the clipping region set by drawRect does not contain the clipping - * region of our drawing context. See bug [2a61eca3a8]. + * Drawing will also fail if we are being called from drawRect but + * the clipping rectangle set by drawRect does not contain the + * clipping region of our drawing context. See bug [2a61eca3a8]. + * If we can't draw all of the clipping region of the drawing + * context then we draw whatever we can, but we also add a dirty + * rectangle so the entire widget will get redrawn in the next + * cycle. */ CGRect currentClip = CGContextGetClipBoundingBox( [NSGraphicsContext currentContext].CGContext); if (!NSContainsRect(currentClip, clipBounds)) { [view addTkDirtyRect:clipBounds]; - // XXXX we should be able to skip drawing but sometimes the clipBounds - // are wrong. - //canDraw = false; - //goto end; } } @@ -1715,10 +1715,10 @@ TkMacOSXSetupDrawingContext( CGRect r; if (!HIShapeIsRectangular(dc.clipRgn) || !CGRectContainsRect( - *HIShapeGetBounds(dc.clipRgn, &r), - CGRectApplyAffineTransform(clipBounds, t))) { - ChkErr(HIShapeReplacePathInCGContext, dc.clipRgn, dc.context); - CGContextEOClip(dc.context); + *HIShapeGetBounds(dc.clipRgn, &r), + CGRectApplyAffineTransform(clipBounds, t))) { + ChkErr(HIShapeReplacePathInCGContext, dc.clipRgn, dc.context); + CGContextEOClip(dc.context); } } if (gc) { diff --git a/macosx/tkMacOSXNotify.c b/macosx/tkMacOSXNotify.c index 7de6bec..8bf5e66 100644 --- a/macosx/tkMacOSXNotify.c +++ b/macosx/tkMacOSXNotify.c @@ -398,12 +398,24 @@ TkMacOSXDrawAllViews( *---------------------------------------------------------------------- */ +#define TICK 100 +static Tcl_TimerToken ticker = NULL; + +static void +Heartbeat( + ClientData clientData) +{ + + if (ticker) { + ticker = Tcl_CreateTimerHandler(TICK, Heartbeat, NULL); + } +} + static void TkMacOSXEventsSetupProc( ClientData clientData, int flags) { - static Bool havePeriodicEvents = NO; NSString *runloopMode = [[NSRunLoop currentRunLoop] currentMode]; /* @@ -412,6 +424,7 @@ TkMacOSXEventsSetupProc( if (flags & TCL_WINDOW_EVENTS && !runloopMode) { static const Tcl_Time zeroBlockTime = { 0, 0 }; + [NSApp _resetAutoreleasePool]; /* @@ -427,26 +440,21 @@ TkMacOSXEventsSetupProc( untilDate:[NSDate distantPast] inMode:GetRunLoopMode(TkMacOSXGetModalSession()) dequeue:NO]; - if (currentEvent) { - if (currentEvent.type > 0) { + if (currentEvent && currentEvent.type > 0) { Tcl_SetMaxBlockTime(&zeroBlockTime); - [NSEvent stopPeriodicEvents]; - havePeriodicEvents = NO; - } - } else if (!havePeriodicEvents){ - - /* - * When the user is not generating events we schedule a "heartbeat" - * event to fire every 0.1 seconds. This helps to make the vwait - * command more responsive when there is no user input, e.g. when - * running the test suite. - */ - - havePeriodicEvents = YES; - [NSEvent startPeriodicEventsAfterDelay:0.0 withPeriod:0.1]; - } - while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {}; - TkMacOSXDrawAllViews(NULL); + Tcl_DeleteTimerHandler(ticker); + ticker = NULL; + } else if (ticker == NULL) { + + /* + * When the user is not generating events we schedule a "heartbeat" + * TimerHandler to fire every 200 milliseconds. The handler does + * nothing, but when its timer fires TclWaitForEvent will return, + * causing TkMacOSXCheckProc to be called. + */ + + ticker = Tcl_CreateTimerHandler(TICK, Heartbeat, NULL); + } } } @@ -543,28 +551,24 @@ TkMacOSXEventsCheckProc( */ [NSApp _unlockAutoreleasePool]; - if (eventsFound == 0) { - /* - * We found no events for Tcl in this iteration of the Tcl event - * loop, so it should proceed to servicing idle tasks. We add an - * idle task to the end of the idle queue which will redisplay all - * of our dirty windows. We want this to happen after all other - * idle tasks have run so that all widgets will be configured - * before they are displayed. The drawRect method "borrows" the - * idle queue while drawing views. That is, it sends expose events - * which cause display procs to be posted as idle tasks and then - * runs an inner event loop to processes those idle tasks. We are - * trying to arrange for the idle queue to be empty when it starts - * that process and empty when it finishes. - */ + /* + * Add an idle task to the end of the idle queue which will redisplay + * all of our dirty windows. We want this to happen after all other + * idle tasks have run so that all widgets will be configured before + * they are displayed. The drawRect method "borrows" the idle queue + * while drawing views. That is, it sends expose events which cause + * display procs to be posted as idle tasks and then runs an inner + * event loop to processes those idle tasks. We are trying to arrange + * for the idle queue to be empty when it starts that process and empty + * when it finishes. + */ - int dirtyCount = 0; - TkMacOSXDrawAllViews(&dirtyCount); - if (dirtyCount > 0) { - Tcl_CancelIdleCall(TkMacOSXDrawAllViews, NULL); - Tcl_DoWhenIdle(TkMacOSXDrawAllViews, NULL); - } + int dirtyCount = 0; + TkMacOSXDrawAllViews(&dirtyCount); + if (dirtyCount > 0) { + Tcl_CancelIdleCall(TkMacOSXDrawAllViews, NULL); + Tcl_DoWhenIdle(TkMacOSXDrawAllViews, NULL); } } } diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c index 0f58c70..d052005 100644 --- a/macosx/tkMacOSXWindowEvent.c +++ b/macosx/tkMacOSXWindowEvent.c @@ -38,6 +38,8 @@ static void DoWindowActivate(ClientData clientData); #pragma mark TKApplication(TKWindowEvent) +extern NSString *NSWindowDidOrderOnScreenNotification; + #ifdef TK_MAC_DEBUG_NOTIFICATIONS extern NSString *NSWindowWillOrderOnScreenNotification; extern NSString *NSWindowDidOrderOnScreenNotification; @@ -208,6 +210,18 @@ extern NSString *NSWindowDidOrderOffScreenNotification; return (winPtr ? NO : YES); } +- (void) windowBecameVisible: (NSNotification *) notification +{ + NSWindow *window = [notification object]; + TkWindow *winPtr = TkMacOSXGetTkWindow(window); + if (winPtr) { + TKContentView *view = [window contentView]; + while(Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {}; + [view setTkDirtyRect:[view bounds]]; + TkMacOSXDrawAllViews(NULL); + } +} + #ifdef TK_MAC_DEBUG_NOTIFICATIONS - (void) windowDragStart: (NSNotification *) notification @@ -227,16 +241,12 @@ extern NSString *NSWindowDidOrderOffScreenNotification; NSWindow *w = [notification object]; TkWindow *winPtr = TkMacOSXGetTkWindow(w); + printf("windowMapped\n"); if (winPtr) { //Tk_MapWindow((Tk_Window) winPtr); } } -- (void) windowBecameVisible: (NSNotification *) notification -{ - TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification); -} - - (void) windowUnmapped: (NSNotification *) notification { TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification); @@ -263,6 +273,7 @@ extern NSString *NSWindowDidOrderOffScreenNotification; observe(NSWindowDidResizeNotification, windowBoundsChanged:); observe(NSWindowDidDeminiaturizeNotification, windowExpanded:); observe(NSWindowDidMiniaturizeNotification, windowCollapsed:); + observe(NSWindowDidOrderOnScreenNotification, windowBecameVisible:); #if !(MAC_OS_X_VERSION_MAX_ALLOWED < 1070) observe(NSWindowDidEnterFullScreenNotification, windowEnteredFullScreen:); |