Tk Source Code

Check-in [476cf7ba]
Login
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2019 Conference, Houston/TX, US, Nov 4-8
Send your abstracts to [email protected]
or submit via the online form by Sep 9.

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:On macOS, edit comments and documentation; fix compiler warnings.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | core-8-6-branch
Files: files | file ages | folders
SHA3-256: 476cf7ba9c77ef97fbb1511e0500314daa734258a2c9ecd2218a0fb565144439
User & Date: culler 2019-04-20 15:03:00
Original Comment: Edit comments and documentation; fix compiler warnings.
Context
2019-04-24
16:04
Fix bug [4d2e8d4d5c]: Aqua notebooks sometimes do not draw a new pane immediately check-in: f656b303 user: culler tags: core-8-6-branch
15:52
Fix bug [4d2e8d4d5c]: Aqua notebooks sometimes do not draw a new pane immediately Closed-Leaf check-in: b1645f5c user: culler tags: bug-4d2e8d4d5c
2019-04-22
22:09
Fix [2513186fff] and [f9343d8f72]: ttk::entry xview sub-command forces use of update idletasks. Thanks to cjmcdonald. check-in: b6f1c7d8 user: fvogel tags: bug-2513186fff, bug-8261c517af
2019-04-20
15:03
On macOS, edit comments and documentation; fix compiler warnings. check-in: 1603d383 user: culler tags: trunk
15:03
On macOS, edit comments and documentation; fix compiler warnings. check-in: 476cf7ba user: culler tags: core-8-6-branch
03:40
On macOS, squelch more availability warnings. Fix a hard to find bug [40ada90762] which could sometimes cause a segfault. check-in: 663e4bc3 user: culler tags: core-8-6-branch
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to doc/colors.n.

897
898
899
900
901
902
903

904
905
906
907
908
909
910
systemRootMenuActiveText
systemRootMenuDisabledText
systemRootMenuSelectedText
systemScrollBarDelimiterActive
systemScrollBarDelimiterInactive
systemSecondaryGroupBoxBackground
systemSecondaryHighlightColor

systemSheetBackground
systemSheetBackgroundOpaque
systemSheetBackgroundTransparent
systemStaticAreaFill
systemSystemDetailText
systemTabFrontActiveText
systemTabFrontInactiveText






>







897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
systemRootMenuActiveText
systemRootMenuDisabledText
systemRootMenuSelectedText
systemScrollBarDelimiterActive
systemScrollBarDelimiterInactive
systemSecondaryGroupBoxBackground
systemSecondaryHighlightColor
systemSelectedTabTextColor
systemSheetBackground
systemSheetBackgroundOpaque
systemSheetBackgroundTransparent
systemStaticAreaFill
systemSystemDetailText
systemTabFrontActiveText
systemTabFrontInactiveText

Changes to macosx/README.

299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314


315
316
317
318
319
320
321
appearance.  Part of the implementation of the Dark Mode was to make
some of the named NSColors have dynamic values.  Apple calls these
"semantic colors" because the name does not specify a specific color,
but rather refers to the context in which the color should be used.
Tk now provides the following semantic colors as system colors:
systemTextColor, systemTextBackgroundColor, systemSelectedTextColor,
systemSelectedTextBackgroundColor, systemControlTextColor,
systemDisabledControlTextColor, systemLabelColor and
systemControlAccentColor.  All of these except the last two were
present in OSX 10.0 (and those two are simulated in systems where they
do not exist).  The change in 10.14 was that the RGB color value of
these colors became dynamic, meaning that the color value can change
when the application appearance changes.  In particular, when a user
selects Dark Mode in the system preferences these colors change
appearance.  For example systemTextColor is dark in Aqua and light in
DarkAqua.



The default background and foreground colors of most of the Tk widgets
have been set to semantic colors, which means that the widgets will change
appearance, and remain usable, when Dark Mode is selected in the system
preferences.  However, to get a close match to the native Dark Mode style it
is recommended to use Ttk widgets when possible.







|







|
>
>







299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
appearance.  Part of the implementation of the Dark Mode was to make
some of the named NSColors have dynamic values.  Apple calls these
"semantic colors" because the name does not specify a specific color,
but rather refers to the context in which the color should be used.
Tk now provides the following semantic colors as system colors:
systemTextColor, systemTextBackgroundColor, systemSelectedTextColor,
systemSelectedTextBackgroundColor, systemControlTextColor,
systemDisabledControlTextColor, systemLabelColor, and
systemControlAccentColor.  All of these except the last two were
present in OSX 10.0 (and those two are simulated in systems where they
do not exist).  The change in 10.14 was that the RGB color value of
these colors became dynamic, meaning that the color value can change
when the application appearance changes.  In particular, when a user
selects Dark Mode in the system preferences these colors change
appearance.  For example systemTextColor is dark in Aqua and light in
DarkAqua.  One additional color, systemSelectedTabTextColor, does not
exist in macOS but is used by Tk to match the different colors used
for Notebook tab text in different OS versions.

The default background and foreground colors of most of the Tk widgets
have been set to semantic colors, which means that the widgets will change
appearance, and remain usable, when Dark Mode is selected in the system
preferences.  However, to get a close match to the native Dark Mode style it
is recommended to use Ttk widgets when possible.

Changes to macosx/tkMacOSXInit.c.

147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
    _mainPool = [NSAutoreleasePool new];
    [NSApp setPoolLock:0];

    /*
     * Record the OS version we are running on.
     */
    int minorVersion;
#if MAC_OS_X_VERSION_MIN_REQUIRED < 101000
    Gestalt(gestaltSystemVersionMinor, (SInt32*)&minorVersion);
#else
    NSOperatingSystemVersion systemVersion;
    systemVersion = [[NSProcessInfo processInfo] operatingSystemVersion];
    minorVersion = systemVersion.minorVersion;
#endif
    [NSApp setMacMinorVersion: minorVersion];






|







147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
    _mainPool = [NSAutoreleasePool new];
    [NSApp setPoolLock:0];

    /*
     * Record the OS version we are running on.
     */
    int minorVersion;
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101000
    Gestalt(gestaltSystemVersionMinor, (SInt32*)&minorVersion);
#else
    NSOperatingSystemVersion systemVersion;
    systemVersion = [[NSProcessInfo processInfo] operatingSystemVersion];
    minorVersion = systemVersion.minorVersion;
#endif
    [NSApp setMacMinorVersion: minorVersion];

Changes to macosx/tkMacOSXTest.c.

14
15
16
17
18
19
20

21
22


23
24
25
26
27
28
29
..
42
43
44
45
46
47
48

49
50

51
52
53
54
55
56
57
58
59
60

61
62
63
64
65
66
67
68
69
70

71
72
73
74
75
76
77
78
79
80

81
82
83
84
85
86
87
#include "tkMacOSXPrivate.h"

/*
 * Forward declarations of procedures defined later in this file:
 */


static int		DebuggerObjCmd (ClientData dummy, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);


 
/*
 *----------------------------------------------------------------------
 *
 * TkplatformtestInit --
 *
 *	Defines commands that test platform specific functionality for
................................................................................
TkplatformtestInit(
    Tcl_Interp *interp)		/* Interpreter to add commands to. */
{
    /*
     * Add commands for platform specific tests on MacOS here.
     */


    Tcl_CreateObjCommand(interp, "debugger", DebuggerObjCmd,
	    (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);


    return TCL_OK;
}
 
/*
 *----------------------------------------------------------------------
 *
 * DebuggerObjCmd --
 *
 *	This procedure simply calls the low level debugger.

 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */


static int
DebuggerObjCmd(
    ClientData clientData,		/* Not used. */
    Tcl_Interp *interp,			/* Not used. */
    int objc,				/* Not used. */
    Tcl_Obj *const objv[])			/* Not used. */
{
    Debugger();
    return TCL_OK;
}

 
/*
 *----------------------------------------------------------------------
 *
 * TkTestAppIsDrawing --
 *
 *      A test widget display procedure which records calls can use this to






>

|
>
>







 







>


>









|
>










>










>







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
..
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include "tkMacOSXPrivate.h"

/*
 * Forward declarations of procedures defined later in this file:
 */

#if MAC_OS_X_VERSION_MAX_ALLOWED < 1080
static int		DebuggerObjCmd (ClientData dummy, Tcl_Interp *interp,
					int objc, Tcl_Obj *const objv[]);
#endif

 
/*
 *----------------------------------------------------------------------
 *
 * TkplatformtestInit --
 *
 *	Defines commands that test platform specific functionality for
................................................................................
TkplatformtestInit(
    Tcl_Interp *interp)		/* Interpreter to add commands to. */
{
    /*
     * Add commands for platform specific tests on MacOS here.
     */

#if MAC_OS_X_VERSION_MAX_ALLOWED < 1080
    Tcl_CreateObjCommand(interp, "debugger", DebuggerObjCmd,
	    (ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
#endif

    return TCL_OK;
}
 
/*
 *----------------------------------------------------------------------
 *
 * DebuggerObjCmd --
 *
 *	This procedure simply calls the low level debugger, which was
 *      deprecated in OSX 10.8.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

#if MAC_OS_X_VERSION_MAX_ALLOWED < 1080
static int
DebuggerObjCmd(
    ClientData clientData,		/* Not used. */
    Tcl_Interp *interp,			/* Not used. */
    int objc,				/* Not used. */
    Tcl_Obj *const objv[])			/* Not used. */
{
    Debugger();
    return TCL_OK;
}
#endif
 
/*
 *----------------------------------------------------------------------
 *
 * TkTestAppIsDrawing --
 *
 *      A test widget display procedure which records calls can use this to

Changes to macosx/tkMacOSXXStubs.c.

174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
	snprintf(vendor, sizeof(vendor), "Apple AppKit %g",
		NSAppKitVersionNumber);
    }
    display->vendor = vendor;
    {
	int major, minor, patch;

#if MAC_OS_X_VERSION_MIN_REQUIRED < 101000
	Gestalt(gestaltSystemVersionMajor, (SInt32*)&major);
	Gestalt(gestaltSystemVersionMinor, (SInt32*)&minor);
	Gestalt(gestaltSystemVersionBugFix, (SInt32*)&patch);
#else
	NSOperatingSystemVersion systemVersion = [[NSProcessInfo processInfo] operatingSystemVersion];
	major = systemVersion.majorVersion;
	minor = systemVersion.minorVersion;






|







174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
	snprintf(vendor, sizeof(vendor), "Apple AppKit %g",
		NSAppKitVersionNumber);
    }
    display->vendor = vendor;
    {
	int major, minor, patch;

#if MAC_OS_X_VERSION_MAX_ALLOWED < 101000
	Gestalt(gestaltSystemVersionMajor, (SInt32*)&major);
	Gestalt(gestaltSystemVersionMinor, (SInt32*)&minor);
	Gestalt(gestaltSystemVersionBugFix, (SInt32*)&patch);
#else
	NSOperatingSystemVersion systemVersion = [[NSProcessInfo processInfo] operatingSystemVersion];
	major = systemVersion.majorVersion;
	minor = systemVersion.minorVersion;

Changes to macosx/ttkMacOSXTheme.c.

97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
...
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
...
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
...
415
416
417
418
419
420
421
422

423
424
425
426
427
428
429
....
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
....
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
....
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
....
2695
2696
2697
2698
2699
2700
2701

2702
2703
2704
2705
2706
2707
2708
....
2723
2724
2725
2726
2727
2728
2729
2730


2731
2732
2733
2734
2735
2736
2737

2738
2739
2740
2741
2742
2743
2744
2745
2746
2747

2748
2749
2750
2751
2752
2753
2754
    20.0 / 255, 94.0 / 255,  206.0 / 255, 1.0
};

/*
 * When building on systems earlier than 10.8 there is no reasonable way to
 * convert an NSColor to a CGColor.  We do run-time checking of the OS version,
 * and never need the CGColor property on older systems, so we can use this
 * CGCOLOR macro, which evaluates to NULL without raising compiler
 * warnings. designed to.  Similarly, we never draw rounded rectangles on older
 * systems which did not have CGPathCreateWithRoundedRect, so we just redefine
 * it to
 */

#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
#define CGCOLOR(nscolor) nscolor.CGColor
#else
#define CGCOLOR(nscolor) (0 ? (CGColorRef) nscolor : NULL)
#define CGPathCreateWithRoundedRect(w, x, y, z) NULL
................................................................................
};
static CGFloat whiteRGBA[4] = {1.0, 1.0, 1.0, 1.0};
static CGFloat blackRGBA[4] = {0.0, 0.0, 0.0, 1.0};

/*----------------------------------------------------------------------
 * GetBackgroundColor --
 *
 *      Fills the array rgba with the color coordinates for a background
 *      color.  Start with the background color of a window's geometry master,
 *      or the standard ttk window background if not. If the contrast
 *      parameter is nonzero modify this color to be darker, for the aqua
 *      appearance, or lighter for the DarkAqua appearance.  This is primarily
 *      used by the Fill and Background elements.
 */

static void GetBackgroundColor(
    CGContextRef context,
    Tk_Window tkwin,
................................................................................
}


/*----------------------------------------------------------------------
 * +++ FillButtonBackground --
 *
 *      Fills a rounded rectangle with a transparent black gradient.
 *      This is a no-op if not building on 10.9 or higher.
 */

static void FillButtonBackground(
    CGContextRef context,
    CGRect bounds,
    CGFloat radius)
{
................................................................................
    CFRelease(topGradient);
}

/*----------------------------------------------------------------------
 * DrawGroupBox --
 *
 *      This is a standalone drawing procedure which draws the contrasting
 *      rounded rectangular box for LabelFrames and Notebook panes.

 */

static void DrawGroupBox(
    CGRect bounds,
    CGContextRef context,
    Tk_Window tkwin)
{
................................................................................
         */

	*minHeight += 2;

        /*
         * The minwidth must be 0 to force the generic ttk code to compute the
         * correct text layout.  For example, a non-zero value will cause the
         * text to be left justified, no matter what -anchor setting is used
         *in
         * the style.
         */

	*minWidth = 0;
    }
}

................................................................................
    ScrollbarElement *scrollbar = elementRecord;
    int orientation = TTK_ORIENT_HORIZONTAL;

    Ttk_GetOrientFromObj(NULL, scrollbar->orientObj, &orientation);

    /*
     * In order to make ttk scrollbars work correctly it is necessary to be
     * 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 viewSizeis, 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,
     * because using HITools also handles drawing the buttons and 3D thumb
     * used on those systems.  The incorrect geometry is annoying but not
     * unusable.  For newer systems the cleanest approach is to just draw the
     * thumb directly.
     */

    if ([NSApp macMinorVersion] > 8) {
	CGRect thumbBounds = BoxToRect(d, b);
	NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
................................................................................
 *
 *      This job is made more complicated in recent versions of macOS by the
 *      fact that the Appkit GroupBox (used for ttk LabelFrames) and
 *      TabbedPane (used for the Notebook widget) both place their content
 *      inside a rectangle with rounded corners that has a color which
 *      contrasts with the dialog background color.  Moreover, although the
 *      Apple human interface guidelines recommend against doing so, there are
 *      times when one wants to nest these widgets, for example having a
 *      GroupBox inside of a TabbedPane.  To have the right contrast, each
 *      level of nesting requires a different color.
 *
 *      Previous Tk releases used the HIThemeDrawGroupBox routine to draw
 *      GroupBoxes and TabbedPanes. This meant that the best that could be
 *      done was to set the GroupBox to be of kind
 *      kHIThemeGroupBoxKindPrimaryOpaque, and set its fill color to be the
................................................................................
} FieldElement;

static Ttk_ElementOptionSpec FieldElementOptions[] = {
    {"-fieldbackground", TK_OPTION_BORDER,
     Tk_Offset(FieldElement, backgroundObj), "white"},
    {NULL, 0, 0, NULL}
};

static void FieldElementDraw(
    void *clientData,
    void *elementRecord,
    Tk_Window tkwin,
    Drawable d,
    Ttk_Box b,
    Ttk_State state)
................................................................................
    TtkNullElementSize,
    FieldElementDraw
};

/*----------------------------------------------------------------------
 * +++ Treeview headers --
 *
 *    Redefine the header to use a kThemeListHeaderButton.


 */

static Ttk_StateTable TreeHeaderValueTable[] = {
    {kThemeButtonOn, TTK_STATE_ALTERNATE},
    {kThemeButtonOn, TTK_STATE_SELECTED},
    {kThemeButtonOff, 0}
};

static Ttk_StateTable TreeHeaderAdornmentTable[] = {
    {kThemeAdornmentHeaderButtonSortUp,
     TTK_STATE_ALTERNATE | TTK_TREEVIEW_STATE_SORTARROW},
    {kThemeAdornmentDefault,
     TTK_STATE_SELECTED | TTK_TREEVIEW_STATE_SORTARROW},
    {kThemeAdornmentHeaderButtonNoSortArrow, TTK_STATE_ALTERNATE},
    {kThemeAdornmentHeaderButtonNoSortArrow, TTK_STATE_SELECTED},
    {kThemeAdornmentFocus, TTK_STATE_FOCUS},
    {kThemeAdornmentNone, 0}
};

static void TreeAreaElementSize (
    void *clientData,
    void *elementRecord,
    Tk_Window tkwin,
    int *minWidth,
    int *minHeight,
    Ttk_Padding *paddingPtr)






|
|
|
<







 







|
|
|
|







 







|







 







|
>







 







|
<







 







|
|

|




|
|







 







|







 







>







 







|
>
>







>










>







97
98
99
100
101
102
103
104
105
106

107
108
109
110
111
112
113
...
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
...
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
...
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
....
1221
1222
1223
1224
1225
1226
1227
1228

1229
1230
1231
1232
1233
1234
1235
....
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
....
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
....
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
....
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
    20.0 / 255, 94.0 / 255,  206.0 / 255, 1.0
};

/*
 * When building on systems earlier than 10.8 there is no reasonable way to
 * convert an NSColor to a CGColor.  We do run-time checking of the OS version,
 * and never need the CGColor property on older systems, so we can use this
 * CGCOLOR macro, which evaluates to NULL without raising compiler warnings.
 * Similarly, we never draw rounded rectangles on older systems which did not
 * have CGPathCreateWithRoundedRect, so we just redefine it to return NULL.

 */

#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
#define CGCOLOR(nscolor) nscolor.CGColor
#else
#define CGCOLOR(nscolor) (0 ? (CGColorRef) nscolor : NULL)
#define CGPathCreateWithRoundedRect(w, x, y, z) NULL
................................................................................
};
static CGFloat whiteRGBA[4] = {1.0, 1.0, 1.0, 1.0};
static CGFloat blackRGBA[4] = {0.0, 0.0, 0.0, 1.0};

/*----------------------------------------------------------------------
 * GetBackgroundColor --
 *
 *      Fills the array rgba with the color coordinates for a background color.
 *      Start with the background color of a window's geometry master, or the
 *      standard ttk window background if there is no master. If the contrast
 *      parameter is nonzero, modify this color to be darker, for the aqua
 *      appearance, or lighter for the DarkAqua appearance.  This is primarily
 *      used by the Fill and Background elements.
 */

static void GetBackgroundColor(
    CGContextRef context,
    Tk_Window tkwin,
................................................................................
}


/*----------------------------------------------------------------------
 * +++ FillButtonBackground --
 *
 *      Fills a rounded rectangle with a transparent black gradient.
 *      This is a no-op if building on 10.8 or older.
 */

static void FillButtonBackground(
    CGContextRef context,
    CGRect bounds,
    CGFloat radius)
{
................................................................................
    CFRelease(topGradient);
}

/*----------------------------------------------------------------------
 * DrawGroupBox --
 *
 *      This is a standalone drawing procedure which draws the contrasting
 *      rounded rectangular box for LabelFrames and Notebook panes used in
 *      more recent versions of macOS.
 */

static void DrawGroupBox(
    CGRect bounds,
    CGContextRef context,
    Tk_Window tkwin)
{
................................................................................
         */

	*minHeight += 2;

        /*
         * The minwidth must be 0 to force the generic ttk code to compute the
         * correct text layout.  For example, a non-zero value will cause the
         * text to be left justified, no matter what -anchor setting is used in

         * the style.
         */

	*minWidth = 0;
    }
}

................................................................................
    ScrollbarElement *scrollbar = elementRecord;
    int orientation = TTK_ORIENT_HORIZONTAL;

    Ttk_GetOrientFromObj(NULL, scrollbar->orientObj, &orientation);

    /*
     * In order to make ttk scrollbars work correctly it is necessary to be
     * 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,
     * 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.
     */

    if ([NSApp macMinorVersion] > 8) {
	CGRect thumbBounds = BoxToRect(d, b);
	NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
................................................................................
 *
 *      This job is made more complicated in recent versions of macOS by the
 *      fact that the Appkit GroupBox (used for ttk LabelFrames) and
 *      TabbedPane (used for the Notebook widget) both place their content
 *      inside a rectangle with rounded corners that has a color which
 *      contrasts with the dialog background color.  Moreover, although the
 *      Apple human interface guidelines recommend against doing so, there are
 *      times when one wants to nest these widgets, for example placing a
 *      GroupBox inside of a TabbedPane.  To have the right contrast, each
 *      level of nesting requires a different color.
 *
 *      Previous Tk releases used the HIThemeDrawGroupBox routine to draw
 *      GroupBoxes and TabbedPanes. This meant that the best that could be
 *      done was to set the GroupBox to be of kind
 *      kHIThemeGroupBoxKindPrimaryOpaque, and set its fill color to be the
................................................................................
} FieldElement;

static Ttk_ElementOptionSpec FieldElementOptions[] = {
    {"-fieldbackground", TK_OPTION_BORDER,
     Tk_Offset(FieldElement, backgroundObj), "white"},
    {NULL, 0, 0, NULL}
};

static void FieldElementDraw(
    void *clientData,
    void *elementRecord,
    Tk_Window tkwin,
    Drawable d,
    Ttk_Box b,
    Ttk_State state)
................................................................................
    TtkNullElementSize,
    FieldElementDraw
};

/*----------------------------------------------------------------------
 * +++ Treeview headers --
 *
 *    On systems older than 10.9 The header is a kThemeListHeaderButton drawn
 *    by HIToolbox.  On newer systems those buttons do not match the Apple
 *    buttons, so we draw them from scratch.
 */

static Ttk_StateTable TreeHeaderValueTable[] = {
    {kThemeButtonOn, TTK_STATE_ALTERNATE},
    {kThemeButtonOn, TTK_STATE_SELECTED},
    {kThemeButtonOff, 0}
};

static Ttk_StateTable TreeHeaderAdornmentTable[] = {
    {kThemeAdornmentHeaderButtonSortUp,
     TTK_STATE_ALTERNATE | TTK_TREEVIEW_STATE_SORTARROW},
    {kThemeAdornmentDefault,
     TTK_STATE_SELECTED | TTK_TREEVIEW_STATE_SORTARROW},
    {kThemeAdornmentHeaderButtonNoSortArrow, TTK_STATE_ALTERNATE},
    {kThemeAdornmentHeaderButtonNoSortArrow, TTK_STATE_SELECTED},
    {kThemeAdornmentFocus, TTK_STATE_FOCUS},
    {kThemeAdornmentNone, 0}
};

static void TreeAreaElementSize (
    void *clientData,
    void *elementRecord,
    Tk_Window tkwin,
    int *minWidth,
    int *minHeight,
    Ttk_Padding *paddingPtr)