From fe654c46dc6d3fe6d413014093b8430dc05f1276 Mon Sep 17 00:00:00 2001 From: Kevin Walzer Date: Thu, 19 Feb 2015 02:27:14 +0000 Subject: Restore live resize to Cocoa with reduced flickering; addresses most serious issue of Cocoa drawing while preserving user expectations for display during window resize; thanks to Marc Culler for extensive patch --- macosx/tkMacOSXDraw.c | 15 +++----- macosx/tkMacOSXWindowEvent.c | 82 +++++++++++++++++++------------------------- 2 files changed, 41 insertions(+), 56 deletions(-) diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c index 0b39cb4..f94c8af 100644 --- a/macosx/tkMacOSXDraw.c +++ b/macosx/tkMacOSXDraw.c @@ -1508,11 +1508,6 @@ TkScrollWindow( /* Scroll the rectangle. */ [view scrollRect:scrollSrc by:NSMakeSize(dx, -dy)]; - - /* Redisplay the scrolled area; hide to reduce flicker after removal of private API calls. */ - [view setHidden:YES]; - [view displayRect:scrollDst]; - [view setHidden:NO]; } } @@ -1857,9 +1852,9 @@ TkpClipDrawableToRect( macDraw->drawRgn = NULL; } if (width >= 0 && height >= 0) { - CGRect drawRect = CGRectMake(x + macDraw->xOff, y + macDraw->yOff, + CGRect clipRect = CGRectMake(x + macDraw->xOff, y + macDraw->yOff, width, height); - HIShapeRef drawRgn = HIShapeCreateWithRect(&drawRect); + HIShapeRef drawRgn = HIShapeCreateWithRect(&clipRect); if (macDraw->winPtr && macDraw->flags & TK_CLIP_INVALID) { TkMacOSXUpdateClipRgn(macDraw->winPtr); @@ -1872,9 +1867,9 @@ TkpClipDrawableToRect( macDraw->drawRgn = drawRgn; } if (view && view != [NSView focusView] && [view lockFocusIfCanDraw]) { - drawRect.origin.y = [view bounds].size.height - - (drawRect.origin.y + drawRect.size.height); - NSRectClip(NSRectFromCGRect(drawRect)); + clipRect.origin.y = [view bounds].size.height - + (clipRect.origin.y + clipRect.size.height); + NSRectClip(NSRectFromCGRect(clipRect)); macDraw->flags |= TK_FOCUSED_VIEW; } } else { diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c index fea6049..4e51dbf 100644 --- a/macosx/tkMacOSXWindowEvent.c +++ b/macosx/tkMacOSXWindowEvent.c @@ -6,6 +6,8 @@ * * Copyright 2001-2009, Apple Inc. * Copyright (c) 2005-2009 Daniel A. Steffen + * Copyright (c) 2015 Kevin Walzer/WordTech Communications LLC. + * Copyright (c) 2015 Marc Culler. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. @@ -762,19 +764,29 @@ Tk_MacOSXIsAppInFront(void) #import /* - * Custom content view for Tk NSWindows, containing standard NSView subviews. - * The goal is to emulate X11-style drawing in response to Expose events: - * during the normal AppKit drawing cycle, we supress drawing of all subviews - * and instead send Expose events about the subviews that would be redrawn. + * Custom content view for use in Tk NSWindows. + * + * Since Tk handles all drawing of widgets, we only use the AppKit event loop + * as a source of input events. To do this, we overload the NSView drawRect + * method with a method which generates Expose events for Tk but does no + * drawing. The redrawing operations are then done when Tk processes these + * events. + * + * Earlier versions of Mac Tk used subclasses of NSView, e.g. NSButton, as the + * basis for Tk widgets. These would then appear as subviews of the + * TKContentView. To prevent the AppKit from redrawing and corrupting the Tk + * Widgets it was necessary to use Apple private API calls. In order to avoid + * using private API calls, the NSView-based widgets have been replaced with + * normal Tk widgets which draw themselves as native widgets by using the + * HITheme API. + * */ @interface TKContentView(TKWindowEvent) - (void) drawRect: (NSRect) rect; - (void) generateExposeEvents: (HIMutableShapeRef) shape; -- (BOOL) preservesContentDuringLiveResize; -- (void) viewWillStartLiveResize; - (void) viewDidEndLiveResize; -- (void) viewWillDraw; +- (void) tkToolbarButton: (id) sender; - (BOOL) isOpaque; - (BOOL) wantsDefaultClipping; - (BOOL) acceptsFirstResponder; @@ -795,12 +807,10 @@ ExposeRestrictProc( ? TK_PROCESS_EVENT : TK_DEFER_EVENT); } - @implementation TKContentView(TKWindowEvent) - (void) drawRect: (NSRect) rect { - const NSRect *rectsBeingDrawn; NSInteger rectsBeingDrawnCount; @@ -836,39 +846,20 @@ ExposeRestrictProc( } - -/*Provide more fine-grained control over resizing of content to reduce flicker after removal of private API's.*/ - --(void) viewWillDraw -{ - - [super viewWillDraw]; -} - - -- (BOOL) preservesContentDuringLiveResize -{ - return NO; -} - -- (void)viewWillStartLiveResize -{ - [super viewWillStartLiveResize]; - [self setNeedsDisplay:NO]; - [self setHidden:YES]; -} - +/* + * As insurance against bugs that might cause layout glitches during a live + * resize, we redraw the window at the end of the resize operation. + */ - (void)viewDidEndLiveResize { + NSRect bounds = NSRectFromCGRect([self bounds]); + HIShapeRef shape = HIShapeCreateWithRect(&bounds); + [self generateExposeEvents: shape]; - [self setHidden:NO]; - [self setNeedsDisplay:YES]; - [super setNeedsDisplay:YES]; - [super viewDidEndLiveResize]; - } + /*Core function of this class, generates expose events for redrawing.*/ - (void) generateExposeEvents: (HIMutableShapeRef) shape { @@ -888,15 +879,16 @@ ExposeRestrictProc( ![[NSRunLoop currentRunLoop] currentMode] && Tcl_GetServiceMode() != TCL_SERVICE_NONE) { /* - * Ensure there are no pending idle-time redraws that could prevent the - * just posted Expose events from generating new redraws. + * Ensure there are no pending idle-time redraws that could + * prevent the just posted Expose events from generating + * new redraws. */ while (Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_DONT_WAIT)) {} /* - * For smoother drawing, process Expose events and resulting redraws - * immediately instead of at idle time. + * For smoother drawing, process Expose events and resulting + * redraws immediately instead of at idle time. */ ClientData oldArg; @@ -913,7 +905,10 @@ ExposeRestrictProc( } -/*This is no-op on 10.7 and up because Apple has removed this widget, but leaving here for backwards compatibility.*/ +/* + * This is no-op on 10.7 and up because Apple has removed this widget, + * but we are leaving it here for backwards compatibility. + */ - (void) tkToolbarButton: (id) sender { #ifdef TK_MAC_DEBUG_EVENTS @@ -941,11 +936,6 @@ ExposeRestrictProc( Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL); } -- (void) setFrameSize: (NSSize) newSize -{ - [super setFrameSize:newSize]; -} - - (BOOL) isOpaque { NSWindow *w = [self window]; -- cgit v0.12