From 0d26ea1e12a28136b3969f44b067df11a2195599 Mon Sep 17 00:00:00 2001 From: Kevin Walzer Date: Wed, 24 Dec 2014 04:44:16 +0000 Subject: All on Tk/Cocoa: Improve view performance during resizing; implement custom drawing of scroller to remove flickering and ghosted appearance during window operations; reduce flickering of menubutton during resizing, but do not completely eliminate ghosted rendering when widget is unmapped --- macosx/tkMacOSXScrlbr.c | 53 +++++++++++++++++++++++++++++++++++++++++++- macosx/tkMacOSXWindowEvent.c | 41 +++++++++++++++------------------- 2 files changed, 70 insertions(+), 24 deletions(-) diff --git a/macosx/tkMacOSXScrlbr.c b/macosx/tkMacOSXScrlbr.c index 3658f7e..a34ce88 100644 --- a/macosx/tkMacOSXScrlbr.c +++ b/macosx/tkMacOSXScrlbr.c @@ -7,6 +7,8 @@ * Copyright (c) 1996 by Sun Microsystems, Inc. * Copyright 2001-2009, Apple Inc. * Copyright (c) 2006-2009 Daniel A. Steffen +* Copyright (c) 2014 Marc Culler. + * Copyright (c) 2014 Kevin Walzer/WordTech Commununications LLC. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. @@ -31,11 +33,22 @@ NSRect TkMacOSXGetScrollFrame(TkScrollbar *scrlPtr); * aware of the state of its Tk parent. This subclass overrides the drawRect * method so that it will not draw itself if the widget is completely outside * of its container. + * + * Custom drawing of the knob seems to work around the flickering visible after + * private API's were removed. Based on technique outlined at + * http://stackoverflow.com/questions/1604682/nsscroller- + * graphical-glitches-lag. Only supported on 10.7 and above. */ + @interface TkNSScroller: NSScroller -(void) drawRect:(NSRect)dirtyRect; - +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 +-(BOOL) isHorizontal; +-(void) drawKnob; +- (void)drawArrow:(NSScrollerArrow)arrow highlightPart:(int)flag; +- (void)drawKnobSlotInRect:(NSRect)rect highlight:(BOOL)highlight; +#endif @end @implementation TkNSScroller @@ -77,6 +90,44 @@ NSRect TkMacOSXGetScrollFrame(TkScrollbar *scrlPtr); } [super drawRect:dirtyRect]; } + + #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 +- (BOOL)isHorizontal { + NSRect bounds = [self bounds]; + return NSWidth(bounds) < NSHeight (bounds); +} + + +- (void)drawKnob +{ + NSRect knobRect = [self rectForPart:NSScrollerKnob]; + + if ([self isHorizontal]) { + NSRect newRect = NSMakeRect(knobRect.origin.x, knobRect.origin.y, knobRect.size.width - 5, knobRect.size.height); + NSBezierPath *path = [NSBezierPath bezierPathWithRoundedRect:newRect xRadius:7 yRadius:7]; + + [[NSColor lightGrayColor] set]; + [path fill]; + } else { + NSRect newRect = NSMakeRect(knobRect.origin.x, knobRect.origin.y, knobRect.size.width, knobRect.size.height - 5); + NSBezierPath *path = [NSBezierPath bezierPathWithRoundedRect:newRect xRadius:7 yRadius:7]; + + [[NSColor lightGrayColor] set]; + [path fill]; + } + +} + +- (void)drawArrow:(NSScrollerArrow)arrow highlightPart:(int)flag +{ + // We don't want arrows +} + +- (void)drawKnobSlotInRect:(NSRect)rect highlight:(BOOL)highlight +{ + +} +#endif @end diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c index f5e506f..13a9f10 100644 --- a/macosx/tkMacOSXWindowEvent.c +++ b/macosx/tkMacOSXWindowEvent.c @@ -771,6 +771,8 @@ Tk_MacOSXIsAppInFront(void) @interface TKContentView(TKWindowEvent) - (void) drawRect: (NSRect) rect; - (void) generateExposeEvents: (HIMutableShapeRef) shape; +- (BOOL) preservesContentDuringLiveResize; +- (void) viewWillStartLiveResize; - (void) viewDidEndLiveResize; - (void) viewWillDraw; - (BOOL) isOpaque; @@ -782,15 +784,6 @@ Tk_MacOSXIsAppInFront(void) @implementation TKContentView @end -double drawTime; - -/* - * Set a minimum time for drawing to render. With removal of private NSView API's, default drawing - * is slower and less responsive. This number, which seems feasible after some experimentatation, skips - * some drawing to avoid lag. - */ - -#define MAX_DYNAMIC_TIME .000000001 /*Restrict event processing to Expose events.*/ static Tk_RestrictAction @@ -818,11 +811,6 @@ ExposeRestrictProc( NSCompositeSourceOver); #endif - NSDate *beginTime=[NSDate date]; - - /*Skip drawing during live resize if redraw is too slow.*/ - if([self inLiveResize] && drawTime>MAX_DYNAMIC_TIME) return; - CGFloat height = [self bounds].size.height; HIMutableShapeRef drawShape = HIShapeCreateMutable(); @@ -842,23 +830,30 @@ ExposeRestrictProc( nil]]; } CFRelease(drawShape); - drawTime=-[beginTime timeIntervalSinceNow]; - [super setNeedsDisplayInRect:rect]; } -/*At conclusion of resize event, send notification and set view for redraw if earlier drawing was skipped because of lagginess.*/ +/*Provide more fine-grained control over resizing of content to reduce flicker after removal of private API's.*/ + +- (BOOL) preservesContentDuringLiveResize +{ + return YES; +} + +- (void)viewWillStartLiveResize +{ + [super viewWillStartLiveResize]; +} + + - (void)viewDidEndLiveResize { - if(drawTime>MAX_DYNAMIC_TIME) { + [self setNeedsDisplay:YES]; + [super setNeedsDisplay:YES]; [super viewDidEndLiveResize]; - } + } --(void) viewWillDraw { - [self setNeedsDisplay:YES]; - } - - (void) generateExposeEvents: (HIMutableShapeRef) shape { -- cgit v0.12