diff options
author | culler <culler> | 2019-07-01 20:00:46 (GMT) |
---|---|---|
committer | culler <culler> | 2019-07-01 20:00:46 (GMT) |
commit | 4d37dc35b57252cbd904008b843dce0354c01669 (patch) | |
tree | 7e8d01921b4479ece74999b6ec1732f0924aae4b | |
parent | 007c334e52bc3b088269275f91961dbffeecf9d2 (diff) | |
parent | 865691668477d52f751cefbf0c2c6bc5059d2ddd (diff) | |
download | tk-4d37dc35b57252cbd904008b843dce0354c01669.zip tk-4d37dc35b57252cbd904008b843dce0354c01669.tar.gz tk-4d37dc35b57252cbd904008b843dce0354c01669.tar.bz2 |
Fix bug [8476b75781], including the Aqua tk scrollbar.
-rw-r--r-- | doc/tk_mac.n | 16 | ||||
-rw-r--r-- | macosx/tkMacOSXScrlbr.c | 136 | ||||
-rw-r--r-- | macosx/ttkMacOSXTheme.c | 47 |
3 files changed, 154 insertions, 45 deletions
diff --git a/doc/tk_mac.n b/doc/tk_mac.n index 1694385..e4ca695 100644 --- a/doc/tk_mac.n +++ b/doc/tk_mac.n @@ -13,6 +13,8 @@ tk::mac \- Access Mac-Specific Functionality on OS X from Tk .SH SYNOPSIS .nf +\fB::tk::mac::DoScriptFile\fR +\fB::tk::mac::DoScriptText\fR \fB::tk::mac::ShowPreferences\fR \fB::tk::mac::OpenApplication\fR \fB::tk::mac::ReopenApplication\fR @@ -44,6 +46,20 @@ events that applications should respond to. These events are mapped by Tk to calls to commands in the \fB::tk::mac\fR namespace; unless otherwise noted, if the command is absent, no action will be taken. .TP +\fB::tk::mac::DoScriptFile\fR +. +The default Apple Event handler for AEDoScriptHandler. This command, +if defined, executes a Tcl file when an AppleScript sends a +.QW "do script" +command to Wish with a file path as a parameter. +.TP +\fB::tk::mac::DoScriptText\fR +. +The default Apple Event handler for AEDoScriptHandler. This command, +if defined, executes Tcl code when an AppleScript sends a +.QW "do script" +command to Wish with Tcl code or a Tcl procedure as a parameter. +.TP \fB::tk::mac::ShowPreferences\fR . The default Apple Event handler for kAEShowPreferences, diff --git a/macosx/tkMacOSXScrlbr.c b/macosx/tkMacOSXScrlbr.c index 06e0a64..0f92c70 100644 --- a/macosx/tkMacOSXScrlbr.c +++ b/macosx/tkMacOSXScrlbr.c @@ -8,7 +8,7 @@ * Copyright 2001-2009, Apple Inc. * Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net> * Copyright (c) 2015 Kevin Walzer/WordTech Commununications LLC. - * Copyright (c) 2018 Marc Culler + * Copyright (c) 2018-2019 Marc Culler * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. @@ -18,14 +18,13 @@ #include "tkScrollbar.h" #include "tkMacOSXPrivate.h" -#define MIN_SCROLLBAR_VALUE 0 - /* * Minimum slider length, in pixels (designed to make sure that the slider is * always easy to grab with the mouse). */ -#define MIN_SLIDER_LENGTH 5 +#define MIN_SLIDER_LENGTH 18 +#define MIN_GAP 4 /* * Borrowed from ttkMacOSXTheme.c to provide appropriate scaling. @@ -88,7 +87,8 @@ typedef struct ScrollbarMetrics { } ScrollbarMetrics; static ScrollbarMetrics metrics = { - 15, 54, 26, 14, 14, kControlSizeNormal /* kThemeScrollBarMedium */ + /* kThemeScrollBarMedium */ + 15, MIN_SLIDER_LENGTH, 26, 14, 14, kControlSizeNormal }; /* @@ -160,6 +160,80 @@ TkpCreateScrollbar( *-------------------------------------------------------------- */ +#if MAC_OS_X_VERSION_MAX_ALLOWED > 1080 + +/* + * This stand-alone drawing function is used on macOS 10.9 and newer because + * the HIToolbox does not draw the scrollbar thumb at the expected size on + * those systems. The thumb is drawn too large, causing a mouse click on the + * thumb to be interpreted as a mouse click in the trough. + */ + +static void drawMacScrollbar( + TkScrollbar *scrollPtr, + MacScrollbar *msPtr, + CGContextRef context) +{ + MacDrawable *macWin = (MacDrawable *) Tk_WindowId(scrollPtr->tkwin); + NSView *view = TkMacOSXDrawableView(macWin); + CGPathRef path; + CGPoint inner[2], outer[2], thumbOrigin; + CGSize thumbSize; + CGRect troughBounds = msPtr->info.bounds; + troughBounds.origin.y = [view bounds].size.height - + (troughBounds.origin.y + troughBounds.size.height); + if (scrollPtr->vertical) { + thumbOrigin.x = troughBounds.origin.x + MIN_GAP; + thumbOrigin.y = troughBounds.origin.y + scrollPtr->sliderFirst; + thumbSize.width = troughBounds.size.width - 2*MIN_GAP + 1; + thumbSize.height = scrollPtr->sliderLast - scrollPtr->sliderFirst; + inner[0] = troughBounds.origin; + inner[1] = CGPointMake(inner[0].x, + inner[0].y + troughBounds.size.height); + outer[0] = CGPointMake(inner[0].x + troughBounds.size.width - 1, + inner[0].y); + outer[1] = CGPointMake(outer[0].x, inner[1].y); + } else { + thumbOrigin.x = troughBounds.origin.x + scrollPtr->sliderFirst; + thumbOrigin.y = troughBounds.origin.y + MIN_GAP; + thumbSize.width = scrollPtr->sliderLast - scrollPtr->sliderFirst; + thumbSize.height = troughBounds.size.height - 2*MIN_GAP + 1; + inner[0] = troughBounds.origin; + inner[1] = CGPointMake(inner[0].x + troughBounds.size.width, + inner[0].y + 1); + outer[0] = CGPointMake(inner[0].x, + inner[0].y + troughBounds.size.height); + outer[1] = CGPointMake(inner[1].x, outer[0].y); + } + CGContextSetShouldAntialias(context, false); + CGContextSetGrayFillColor(context, 250.0 / 255, 1.0); + CGContextFillRect(context, troughBounds); + CGContextSetGrayStrokeColor(context, 232.0 / 255, 1.0); + CGContextStrokeLineSegments(context, inner, 2); + CGContextSetGrayStrokeColor(context, 238.0 / 255, 1.0); + CGContextStrokeLineSegments(context, outer, 2); + + /* + * Do not display the thumb unless scrolling is possible. + */ + + if (scrollPtr->firstFraction > 0.0 || scrollPtr->lastFraction < 1.0) { + CGRect thumbBounds = {thumbOrigin, thumbSize}; + path = CGPathCreateWithRoundedRect(thumbBounds, 4, 4, NULL); + CGContextBeginPath(context); + CGContextAddPath(context, path); + if (msPtr->info.trackInfo.scrollbar.pressState != 0) { + CGContextSetGrayFillColor(context, 133.0 / 255, 1.0); + } else { + CGContextSetGrayFillColor(context, 200.0 / 255, 1.0); + } + CGContextSetShouldAntialias(context, true); + CGContextFillPath(context); + CFRelease(path); + } +} +#endif + void TkpDisplayScrollbar( ClientData clientData) /* Information about window. */ @@ -185,6 +259,10 @@ TkpDisplayScrollbar( return; } + /* + * Transform NSView coordinates to CoreGraphics coordinates. + */ + CGFloat viewHeight = [view bounds].size.height; CGAffineTransform t = { .a = 1, .b = 0, @@ -229,13 +307,22 @@ TkpDisplayScrollbar( if (SNOW_LEOPARD_STYLE) { HIThemeDrawTrack(&msPtr->info, 0, dc.context, - kHIThemeOrientationInverted); - } else { + kHIThemeOrientationInverted); + } else if ([NSApp macMinorVersion] <= 8) { HIThemeDrawTrack(&msPtr->info, 0, dc.context, - kHIThemeOrientationNormal); + kHIThemeOrientationNormal); + } else { +#if MAC_OS_X_VERSION_MAX_ALLOWED > 1080 + + /* + * Switch back to NSView coordinates and draw a modern scrollbar. + */ + + CGContextConcatCTM(dc.context, t); + drawMacScrollbar(scrollPtr, msPtr, dc.context); +#endif } TkMacOSXRestoreDrawingContext(&dc); - scrollPtr->flags &= ~REDRAW_PENDING; } @@ -297,23 +384,24 @@ TkpComputeScrollbarGeometry( scrollPtr->sliderLast = fieldLength*scrollPtr->lastFraction; /* - * Adjust the slider so that some piece of it is always displayed in the - * scrollbar and so that it has at least a minimal width (so it can be - * grabbed with the mouse). + * Adjust the slider so that it has at least a minimal size and so there + * is a small gap on either end which can be used to scroll by one page. */ + if (scrollPtr->sliderFirst < MIN_GAP) { + scrollPtr->sliderFirst = MIN_GAP; + scrollPtr->sliderLast += MIN_GAP; + } + if (scrollPtr->sliderLast > fieldLength - MIN_GAP) { + scrollPtr->sliderLast = fieldLength - MIN_GAP; + scrollPtr->sliderFirst -= MIN_GAP; + } if (scrollPtr->sliderFirst > fieldLength - MIN_SLIDER_LENGTH) { scrollPtr->sliderFirst = fieldLength - MIN_SLIDER_LENGTH; } - if (scrollPtr->sliderFirst < 0) { - scrollPtr->sliderFirst = 0; - } if (scrollPtr->sliderLast < scrollPtr->sliderFirst + MIN_SLIDER_LENGTH) { scrollPtr->sliderLast = scrollPtr->sliderFirst + MIN_SLIDER_LENGTH; } - if (scrollPtr->sliderLast > fieldLength) { - scrollPtr->sliderLast = fieldLength; - } scrollPtr->sliderFirst += -scrollPtr->arrowLength + scrollPtr->inset; scrollPtr->sliderLast += scrollPtr->inset; @@ -511,7 +599,7 @@ UpdateControlValues( msPtr->info.bounds = contrlRect; width = contrlRect.size.width; - height = contrlRect.size.height; + height = contrlRect.size.height - scrollPtr->arrowLength; /* * Ensure we set scrollbar control bounds only once all size adjustments @@ -535,10 +623,9 @@ UpdateControlValues( * the view area. */ - double maximum = 100, factor = RangeToFactor(maximum); - + double factor = RangeToFactor(100.0); dViewSize = (scrollPtr->lastFraction - scrollPtr->firstFraction) * factor; - msPtr->info.max = MIN_SCROLLBAR_VALUE + factor - dViewSize; + msPtr->info.max = factor - dViewSize; msPtr->info.trackInfo.scrollbar.viewsize = dViewSize; if (scrollPtr->vertical) { if (SNOW_LEOPARD_STYLE) { @@ -548,8 +635,7 @@ UpdateControlValues( factor * scrollPtr->firstFraction; } } else { - msPtr->info.value = MIN_SCROLLBAR_VALUE + - factor * scrollPtr->firstFraction; + msPtr->info.value = factor * scrollPtr->firstFraction; } if ((scrollPtr->firstFraction <= 0.0 && scrollPtr->lastFraction >= 1.0) @@ -616,6 +702,7 @@ ScrollbarEvent( kThemeBottomTrackPressed; break; case TOP_ARROW: + /* * This looks wrong and the docs say it is wrong but it works. */ @@ -647,6 +734,7 @@ ScrollbarEvent( msPtr->info.trackInfo.scrollbar.pressState = 0; } } + TkScrollbarEventuallyRedraw(scrollPtr); return TCL_OK; } diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index 7ea9448..b58a743 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -2347,7 +2347,13 @@ static void ThumbElementSize( int orientation = TTK_ORIENT_HORIZONTAL; Ttk_GetOrientFromObj(NULL, scrollbar->orientObj, &orientation); - *minHeight = *minWidth = 8; + if (orientation == TTK_ORIENT_VERTICAL) { + *minHeight = 18; + *minWidth = 8; + } else { + *minHeight = 8; + *minWidth = 18; + } } static void ThumbElementDraw( @@ -2368,15 +2374,11 @@ static void ThumbElementDraw( * able to display the thumb element at the size and location which the ttk * scrollbar widget requests. The algorithm that HIToolbox uses to * determine the thumb geometry from the input values of min, max, value - * and viewSize is, of course, undocumented. And this turns out to be a - * hard reverse engineering problem. A seemingly natural algorithm is - * implemented below, but it does not correctly compute the same thumb - * geometry as HITools (which also apparently does not agree with - * NSScrollbar). This code uses that algorithm for older OS versions, + * and viewSize is undocumented. A seemingly natural algorithm is + * implemented below. This code uses that algorithm for older OS versions, * because using HITools also handles drawing the buttons and 3D thumb used - * on those systems. The incorrect geometry is annoying but not completely - * unusable. For newer systems the cleanest approach is to just draw the - * thumb directly. + * on those systems. For newer systems the cleanest approach is to just + * draw the thumb directly. */ if ([NSApp macMinorVersion] > 8) { @@ -2404,7 +2406,7 @@ static void ThumbElementDraw( SolidFillRoundedRectangle(dc.context, thumbBounds, 4, thumbColor); END_DRAWING } else { - double thumbSize, trackSize, visibleSize, viewSize; + double thumbSize, trackSize, visibleSize, factor, fraction; MacDrawable *macWin = (MacDrawable *) Tk_WindowId(tkwin); CGRect troughBounds = {{macWin->xOff, macWin->yOff}, {Tk_Width(tkwin), Tk_Height(tkwin)}}; @@ -2418,7 +2420,6 @@ static void ThumbElementDraw( * largest int. */ - viewSize = RangeToFactor(100.0); HIThemeTrackDrawInfo info = { .version = 0, .bounds = troughBounds, @@ -2427,19 +2428,24 @@ static void ThumbElementDraw( kThemeTrackThumbRgnIsNotGhost, .enableState = kThemeTrackActive }; - info.trackInfo.scrollbar.viewsize = viewSize * .8; + factor = RangeToFactor(100.0); if (orientation == TTK_ORIENT_HORIZONTAL) { trackSize = troughBounds.size.width; thumbSize = b.width; - visibleSize = (thumbSize / trackSize) * viewSize; - info.max = viewSize - visibleSize; - info.value = info.max * (b.x / (trackSize - thumbSize)); + fraction = b.x / trackSize; } else { - thumbSize = b.height; trackSize = troughBounds.size.height; - visibleSize = (thumbSize / trackSize) * viewSize; - info.max = viewSize - visibleSize; - info.value = info.max * (b.y / (trackSize - thumbSize)); + thumbSize = b.height; + fraction = b.y / trackSize; + } + visibleSize = (thumbSize / trackSize) * factor; + info.max = factor - visibleSize; + info.trackInfo.scrollbar.viewsize = visibleSize; + if ([NSApp macMinorVersion] < 8 || + orientation == TTK_ORIENT_HORIZONTAL) { + info.value = factor * fraction; + } else { + info.value = info.max - factor * fraction; } if ((state & TTK_STATE_PRESSED) || (state & TTK_STATE_HOVER)) { @@ -3117,8 +3123,7 @@ static int AquaTheme_Init( /* * <<NOTE-TRACKS>> - * In some themes the Layouts for a progress bar has a trough element and - *a + * In some themes the Layouts for a progress bar has a trough element and a * pbar element. But in our case the appearance manager draws both parts * of the progress bar, so we just have a single element called ".track". */ |