summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorculler <culler>2019-07-01 20:00:46 (GMT)
committerculler <culler>2019-07-01 20:00:46 (GMT)
commit4d37dc35b57252cbd904008b843dce0354c01669 (patch)
tree7e8d01921b4479ece74999b6ec1732f0924aae4b
parent007c334e52bc3b088269275f91961dbffeecf9d2 (diff)
parent865691668477d52f751cefbf0c2c6bc5059d2ddd (diff)
downloadtk-4d37dc35b57252cbd904008b843dce0354c01669.zip
tk-4d37dc35b57252cbd904008b843dce0354c01669.tar.gz
tk-4d37dc35b57252cbd904008b843dce0354c01669.tar.bz2
Fix bug [8476b75781], including the Aqua tk scrollbar.
-rw-r--r--doc/tk_mac.n16
-rw-r--r--macosx/tkMacOSXScrlbr.c136
-rw-r--r--macosx/ttkMacOSXTheme.c47
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".
*/