summaryrefslogtreecommitdiffstats
path: root/macosx/tkMacOSXColor.c
diff options
context:
space:
mode:
Diffstat (limited to 'macosx/tkMacOSXColor.c')
-rw-r--r--macosx/tkMacOSXColor.c824
1 files changed, 393 insertions, 431 deletions
diff --git a/macosx/tkMacOSXColor.c b/macosx/tkMacOSXColor.c
index 40b537e..acbfa0e 100644
--- a/macosx/tkMacOSXColor.c
+++ b/macosx/tkMacOSXColor.c
@@ -1,5 +1,5 @@
/*
- * tkMacOSXColor.c --
+ * TkMacOSXColor.c --
*
* This file maintains a database of color values for the Tk
* toolkit, in order to avoid round-trips to the server to
@@ -9,6 +9,7 @@
* Copyright (c) 1994-1996 Sun Microsystems, Inc.
* Copyright 2001-2009, Apple Inc.
* Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ * Copyright (c) 2020 Marc Culler
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -16,286 +17,272 @@
#include "tkMacOSXPrivate.h"
#include "tkColor.h"
+#include "tkMacOSXColor.h"
+
+static Tcl_HashTable systemColors;
+static int numSystemColors;
+static int rgbColorIndex;
+static int controlAccentIndex;
+static int selectedTabTextIndex;
+static Bool useFakeAccentColor = NO;
+static SystemColorDatum **systemColorIndex;
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400
+static NSAppearance *lightAqua = nil;
+static NSAppearance *darkAqua = nil;
+#endif
+static NSColorSpace* sRGB = NULL;
+static const CGFloat WINDOWBACKGROUND[4] =
+ {236.0 / 255, 236.0 / 255, 236.0 / 255, 1.0};
-/*
- * The colorType specifies how the color value should be interpreted. For the
- * unique rgbColor entry, the RGB values are generated from the pixel value of
- * an XColor. The ttkBackground and semantic types are dynamic, meaning
- * that they change when dark mode is enabled on OSX 10.13 and later.
- */
+void initColorTable()
+{
+ NSAutoreleasePool *pool = [NSAutoreleasePool new];
+ Tcl_InitHashTable(&systemColors, TCL_STRING_KEYS);
+ SystemColorDatum *entry, *oldEntry;
+ Tcl_HashSearch search;
+ Tcl_HashEntry *hPtr;
+ int newPtr, index = 0;
+ NSColorList *systemColorList = [NSColorList colorListNamed:@"System"];
+ NSString *key;
-enum colorType {
- clearColor, /* There should be only one of these. */
- rgbColor, /* There should be only one of these. */
- appearance, /* There should be only one of these. */
- HIBrush, /* The value is a HITheme brush color table index. */
- HIText, /* The value is a HITheme text color table index. */
- HIBackground, /* The value is a HITheme background color table index. */
- ttkBackground, /* The value can be used as a parameter.*/
- semantic, /* The value can be used as a parameter.*/
-};
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400
+ if (@available(macOS 10.14, *)) {
+ darkAqua = [NSAppearance appearanceNamed:NSAppearanceNameDarkAqua];
+ lightAqua = [NSAppearance appearanceNamed:NSAppearanceNameAqua];
+ }
+#endif
-/*
+ /*
+ * Build a hash table for looking up a color by its name.
+ * First add all of the static entries from tkMacOSXColor.h
+ */
- */
+ for (entry = systemColorData; entry->name != NULL; entry++) {
+ hPtr = Tcl_CreateHashEntry(&systemColors, entry->name, &newPtr);
+ if (entry->type == semantic) {
+ NSString *colorName = [[NSString alloc]
+ initWithCString:entry->macName
+ encoding:NSUTF8StringEncoding];
+ SEL colorSelector = NSSelectorFromString(colorName);
+ if (![NSColor respondsToSelector:colorSelector]) {
+ if ([colorName isEqualToString:@"controlAccentColor"]) {
+ useFakeAccentColor = YES;
+ } else if (![colorName isEqualToString:@"selectedTabTextColor"]) {
+ /* Uncomment to print all unsupported colors: */
+ /* printf("Unsupported color %s\n", colorName.UTF8String); */
+ continue;
+ }
+ }
+ entry->selector = [colorName retain];
+ }
+ if (newPtr == 0) {
+ oldEntry = (SystemColorDatum *) Tcl_GetHashValue(hPtr);
+ entry->index = oldEntry->index;
+ [oldEntry->selector release];
+ } else {
+ entry->index = index++;
+ }
+ Tcl_SetHashValue(hPtr, entry);
+ }
-struct SystemColorMapEntry {
- const char *name;
- enum colorType type;
- long value;
-}; /* unsigned char pixelCode; */
+ /*
+ * Add all of the colors in the System ColorList.
+ */
-/*
- * Array of system color definitions: the array index is required to equal the
- * color's (pixelCode - MIN_PIXELCODE), i.e. the array order needs to be kept
- * in sync with the public pixel code values in tkMacOSXPort.h !
- */
+ for (key in [systemColorList allKeys]) {
+ int length = [key lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
+ char *name;
+ entry = (SystemColorDatum *)ckalloc(sizeof(SystemColorDatum));
+ bzero(entry, sizeof(SystemColorDatum));
+ name = (char *)ckalloc(length + 1);
+ strcpy(name, key.UTF8String);
+ name[0] = toupper(name[0]);
+ if (!strcmp(name, "WindowBackgroundColor")) {
+
+ /*
+ * Avoid black windows on old systems.
+ */
+
+ continue;
+ }
+ entry->type=semantic;
+ entry->name = name;
+ entry->selector = [key retain];
+ hPtr = Tcl_CreateHashEntry(&systemColors, entry->name, &newPtr);
+ if (newPtr == 0) {
+ oldEntry = (SystemColorDatum *) Tcl_GetHashValue(hPtr);
+ entry->index = oldEntry->index;
+ [oldEntry->selector release];
+ } else {
+ entry->index = index++;
+ }
+ Tcl_SetHashValue(hPtr, entry);
+ }
-#define MIN_PIXELCODE 30
-static const struct SystemColorMapEntry systemColorMap[] = {
- { "Transparent", clearColor, 0 }, /* 30: TRANSPARENT_PIXEL */
- { "Highlight", HIBrush, kThemeBrushPrimaryHighlightColor }, /* 31 */
- { "HighlightSecondary", HIBrush, kThemeBrushSecondaryHighlightColor }, /* 32 */
- { "HighlightText", HIBrush, kThemeBrushBlack }, /* 33 */
- { "HighlightAlternate", HIBrush, kThemeBrushAlternatePrimaryHighlightColor }, /* 34 */
- { "ButtonText", HIText, kThemeTextColorPushButtonActive }, /* 35 */
- { "PrimaryHighlightColor", HIBrush, kThemeBrushPrimaryHighlightColor }, /* 36 */
- { "ButtonFace", HIBrush, kThemeBrushButtonFaceActive }, /* 37 */
- { "SecondaryHighlightColor", HIBrush, kThemeBrushSecondaryHighlightColor }, /* 38 */
- { "ButtonFrame", HIBrush, kThemeBrushButtonFrameActive }, /* 39 */
- { "AlternatePrimaryHighlightColor", HIBrush, kThemeBrushAlternatePrimaryHighlightColor }, /* 40 */
- { "WindowBody", HIBrush, kThemeBrushDocumentWindowBackground }, /* 41 */
- { "SheetBackground", HIBrush, kThemeBrushSheetBackground }, /* 42 */
- { "MenuActive", HIBrush, kThemeBrushMenuBackgroundSelected }, /* 43 */
- { "Black", HIBrush, kThemeBrushBlack }, /* 44 */
- { "MenuActiveText", HIText, kThemeTextColorMenuItemSelected }, /* 45 */
- { "White", HIBrush, kThemeBrushWhite }, /* 46 */
- { "Menu", HIBrush, kThemeBrushMenuBackground }, /* 47 */
- { "DialogBackgroundActive", HIBrush, kThemeBrushDialogBackgroundActive }, /* 48 */
- { "MenuDisabled", HIText, kThemeTextColorMenuItemDisabled }, /* 49 */
- { "DialogBackgroundInactive", HIBrush, kThemeBrushDialogBackgroundInactive }, /* 50 */
- { "MenuText", HIText, kThemeTextColorMenuItemActive }, /* 51 */
- { "AppearanceColor", appearance, 0 }, /* 52: APPEARANCE_PIXEL */
- { "AlertBackgroundActive", HIBrush, kThemeBrushAlertBackgroundActive }, /* 53 */
- { "AlertBackgroundInactive", HIBrush, kThemeBrushAlertBackgroundInactive }, /* 54 */
- { "ModelessDialogBackgroundActive", HIBrush, kThemeBrushModelessDialogBackgroundActive }, /* 55 */
- { "ModelessDialogBackgroundInactive", HIBrush, kThemeBrushModelessDialogBackgroundInactive }, /* 56 */
- { "UtilityWindowBackgroundActive", HIBrush, kThemeBrushUtilityWindowBackgroundActive }, /* 57 */
- { "UtilityWindowBackgroundInactive", HIBrush, kThemeBrushUtilityWindowBackgroundInactive }, /* 58 */
- { "ListViewSortColumnBackground", HIBrush, kThemeBrushListViewSortColumnBackground }, /* 59 */
- { "ListViewBackground", HIBrush, kThemeBrushListViewBackground }, /* 60 */
- { "IconLabelBackground", HIBrush, kThemeBrushIconLabelBackground }, /* 61 */
- { "ListViewSeparator", HIBrush, kThemeBrushListViewSeparator }, /* 62 */
- { "ChasingArrows", HIBrush, kThemeBrushChasingArrows }, /* 63 */
- { "DragHilite", HIBrush, kThemeBrushDragHilite }, /* 64 */
- { "DocumentWindowBackground", HIBrush, kThemeBrushDocumentWindowBackground }, /* 65 */
- { "FinderWindowBackground", HIBrush, kThemeBrushFinderWindowBackground }, /* 66 */
- { "ScrollBarDelimiterActive", HIBrush, kThemeBrushScrollBarDelimiterActive }, /* 67 */
- { "ScrollBarDelimiterInactive", HIBrush, kThemeBrushScrollBarDelimiterInactive }, /* 68 */
- { "FocusHighlight", HIBrush, kThemeBrushFocusHighlight }, /* 69 */
- { "PopupArrowActive", HIBrush, kThemeBrushPopupArrowActive }, /* 70 */
- { "PopupArrowPressed", HIBrush, kThemeBrushPopupArrowPressed }, /* 71 */
- { "PopupArrowInactive", HIBrush, kThemeBrushPopupArrowInactive }, /* 72 */
- { "AppleGuideCoachmark", HIBrush, kThemeBrushAppleGuideCoachmark }, /* 73 */
- { "IconLabelBackgroundSelected", HIBrush, kThemeBrushIconLabelBackgroundSelected }, /* 74 */
- { "StaticAreaFill", HIBrush, kThemeBrushStaticAreaFill }, /* 75 */
- { "ActiveAreaFill", HIBrush, kThemeBrushActiveAreaFill }, /* 76 */
- { "ButtonFrameActive", HIBrush, kThemeBrushButtonFrameActive }, /* 77 */
- { "ButtonFrameInactive", HIBrush, kThemeBrushButtonFrameInactive }, /* 78 */
- { "ButtonFaceActive", HIBrush, kThemeBrushButtonFaceActive }, /* 79 */
- { "ButtonFaceInactive", HIBrush, kThemeBrushButtonFaceInactive }, /* 80 */
- { "ButtonFacePressed", HIBrush, kThemeBrushButtonFacePressed }, /* 81 */
- { "ButtonActiveDarkShadow", HIBrush, kThemeBrushButtonActiveDarkShadow }, /* 82 */
- { "ButtonActiveDarkHighlight", HIBrush, kThemeBrushButtonActiveDarkHighlight }, /* 83 */
- { "ButtonActiveLightShadow", HIBrush, kThemeBrushButtonActiveLightShadow }, /* 84 */
- { "ButtonActiveLightHighlight", HIBrush, kThemeBrushButtonActiveLightHighlight }, /* 85 */
- { "ButtonInactiveDarkShadow", HIBrush, kThemeBrushButtonInactiveDarkShadow }, /* 86 */
- { "ButtonInactiveDarkHighlight", HIBrush, kThemeBrushButtonInactiveDarkHighlight }, /* 87 */
- { "ButtonInactiveLightShadow", HIBrush, kThemeBrushButtonInactiveLightShadow }, /* 88 */
- { "ButtonInactiveLightHighlight", HIBrush, kThemeBrushButtonInactiveLightHighlight }, /* 89 */
- { "ButtonPressedDarkShadow", HIBrush, kThemeBrushButtonPressedDarkShadow }, /* 90 */
- { "ButtonPressedDarkHighlight", HIBrush, kThemeBrushButtonPressedDarkHighlight }, /* 91 */
- { "ButtonPressedLightShadow", HIBrush, kThemeBrushButtonPressedLightShadow }, /* 92 */
- { "ButtonPressedLightHighlight", HIBrush, kThemeBrushButtonPressedLightHighlight }, /* 93 */
- { "BevelActiveLight", HIBrush, kThemeBrushBevelActiveLight }, /* 94 */
- { "BevelActiveDark", HIBrush, kThemeBrushBevelActiveDark }, /* 95 */
- { "BevelInactiveLight", HIBrush, kThemeBrushBevelInactiveLight }, /* 96 */
- { "BevelInactiveDark", HIBrush, kThemeBrushBevelInactiveDark }, /* 97 */
- { "NotificationWindowBackground", HIBrush, kThemeBrushNotificationWindowBackground }, /* 98 */
- { "MovableModalBackground", HIBrush, kThemeBrushMovableModalBackground }, /* 99 */
- { "SheetBackgroundOpaque", HIBrush, kThemeBrushSheetBackgroundOpaque }, /* 100 */
- { "DrawerBackground", HIBrush, kThemeBrushDrawerBackground }, /* 101 */
- { "ToolbarBackground", HIBrush, kThemeBrushToolbarBackground }, /* 102 */
- { "SheetBackgroundTransparent", HIBrush, kThemeBrushSheetBackgroundTransparent }, /* 103 */
- { "MenuBackground", HIBrush, kThemeBrushMenuBackground }, /* 104 */
- { "Pixel", rgbColor, 0 }, /* 105: PIXEL_MAGIC */
- { "MenuBackgroundSelected", HIBrush, kThemeBrushMenuBackgroundSelected }, /* 106 */
- { "ListViewOddRowBackground", HIBrush, kThemeBrushListViewOddRowBackground }, /* 107 */
- { "ListViewEvenRowBackground", HIBrush, kThemeBrushListViewEvenRowBackground }, /* 108 */
- { "ListViewColumnDivider", HIBrush, kThemeBrushListViewColumnDivider }, /* 109 */
- { "BlackText", HIText, kThemeTextColorBlack }, /* 110 */
- { "DialogActiveText", HIText, kThemeTextColorDialogActive }, /* 111 */
- { "DialogInactiveText", HIText, kThemeTextColorDialogInactive }, /* 112 */
- { "AlertActiveText", HIText, kThemeTextColorAlertActive }, /* 113 */
- { "AlertInactiveText", HIText, kThemeTextColorAlertInactive }, /* 114 */
- { "ModelessDialogActiveText", HIText, kThemeTextColorModelessDialogActive }, /* 115 */
- { "ModelessDialogInactiveText", HIText, kThemeTextColorModelessDialogInactive }, /* 116 */
- { "WindowHeaderActiveText", HIText, kThemeTextColorWindowHeaderActive }, /* 117 */
- { "WindowHeaderInactiveText", HIText, kThemeTextColorWindowHeaderInactive }, /* 118 */
- { "PlacardActiveText", HIText, kThemeTextColorPlacardActive }, /* 119 */
- { "PlacardInactiveText", HIText, kThemeTextColorPlacardInactive }, /* 120 */
- { "PlacardPressedText", HIText, kThemeTextColorPlacardPressed }, /* 121 */
- { "PushButtonActiveText", HIText, kThemeTextColorPushButtonActive }, /* 122 */
- { "PushButtonInactiveText", HIText, kThemeTextColorPushButtonInactive }, /* 123 */
- { "PushButtonPressedText", HIText, kThemeTextColorPushButtonPressed }, /* 124 */
- { "BevelButtonActiveText", HIText, kThemeTextColorBevelButtonActive }, /* 125 */
- { "BevelButtonInactiveText", HIText, kThemeTextColorBevelButtonInactive }, /* 126 */
- { "BevelButtonPressedText", HIText, kThemeTextColorBevelButtonPressed }, /* 127 */
- { "PopupButtonActiveText", HIText, kThemeTextColorPopupButtonActive }, /* 128 */
- { "PopupButtonInactiveText", HIText, kThemeTextColorPopupButtonInactive }, /* 129 */
- { "PopupButtonPressedText", HIText, kThemeTextColorPopupButtonPressed }, /* 130 */
- { "IconLabelText", HIText, kThemeTextColorIconLabel }, /* 131 */
- { "ListViewText", HIText, kThemeTextColorListView }, /* 132 */
- { "DocumentWindowTitleActiveText", HIText, kThemeTextColorDocumentWindowTitleActive }, /* 133 */
- { "DocumentWindowTitleInactiveText", HIText, kThemeTextColorDocumentWindowTitleInactive }, /* 134 */
- { "MovableModalWindowTitleActiveText", HIText, kThemeTextColorMovableModalWindowTitleActive }, /* 135 */
- { "MovableModalWindowTitleInactiveText",HIText, kThemeTextColorMovableModalWindowTitleInactive }, /* 136 */
- { "UtilityWindowTitleActiveText", HIText, kThemeTextColorUtilityWindowTitleActive }, /* 137 */
- { "UtilityWindowTitleInactiveText", HIText, kThemeTextColorUtilityWindowTitleInactive }, /* 138 */
- { "PopupWindowTitleActiveText", HIText, kThemeTextColorPopupWindowTitleActive }, /* 139 */
- { "PopupWindowTitleInactiveText", HIText, kThemeTextColorPopupWindowTitleInactive }, /* 140 */
- { "RootMenuActiveText", HIText, kThemeTextColorRootMenuActive }, /* 141 */
- { "RootMenuSelectedText", HIText, kThemeTextColorRootMenuSelected }, /* 142 */
- { "RootMenuDisabledText", HIText, kThemeTextColorRootMenuDisabled }, /* 143 */
- { "MenuItemActiveText", HIText, kThemeTextColorMenuItemActive }, /* 144 */
- { "MenuItemSelectedText", HIText, kThemeTextColorMenuItemSelected }, /* 145 */
- { "MenuItemDisabledText", HIText, kThemeTextColorMenuItemDisabled }, /* 146 */
- { "PopupLabelActiveText", HIText, kThemeTextColorPopupLabelActive }, /* 147 */
- { "PopupLabelInactiveText", HIText, kThemeTextColorPopupLabelInactive }, /* 148 */
- { "TabFrontActiveText", HIText, kThemeTextColorTabFrontActive }, /* 149 */
- { "TabNonFrontActiveText", HIText, kThemeTextColorTabNonFrontActive }, /* 150 */
- { "TabNonFrontPressedText", HIText, kThemeTextColorTabNonFrontPressed }, /* 151 */
- { "TabFrontInactiveText", HIText, kThemeTextColorTabFrontInactive }, /* 152 */
- { "TabNonFrontInactiveText", HIText, kThemeTextColorTabNonFrontInactive }, /* 153 */
- { "IconLabelSelectedText", HIText, kThemeTextColorIconLabelSelected }, /* 154 */
- { "BevelButtonStickyActiveText", HIText, kThemeTextColorBevelButtonStickyActive }, /* 155 */
- { "BevelButtonStickyInactiveText", HIText, kThemeTextColorBevelButtonStickyInactive }, /* 156 */
- { "NotificationText", HIText, kThemeTextColorNotification }, /* 157 */
- { "SystemDetailText", HIText, kThemeTextColorSystemDetail }, /* 158 */
- { "WhiteText", HIText, kThemeTextColorWhite }, /* 159 */
- { "TabPaneBackground", HIBackground, kThemeBackgroundTabPane }, /* 160 */
- { "PlacardBackground", HIBackground, kThemeBackgroundPlacard }, /* 161 */
- { "WindowHeaderBackground", HIBackground, kThemeBackgroundWindowHeader }, /* 162 */
- { "ListViewWindowHeaderBackground", HIBackground, kThemeBackgroundListViewWindowHeader }, /* 163 */
- { "SecondaryGroupBoxBackground", HIBackground, kThemeBackgroundSecondaryGroupBox }, /* 164 */
- { "MetalBackground", HIBackground, kThemeBackgroundMetal }, /* 165 */
+ /*
+ * Build an array for looking up a color by its index.
+ */
+
+ numSystemColors = index;
+ systemColorIndex = (SystemColorDatum **)ckalloc(numSystemColors * sizeof(SystemColorDatum *));
+ for (hPtr = Tcl_FirstHashEntry(&systemColors, &search); hPtr != NULL;
+ hPtr = Tcl_NextHashEntry(&search)) {
+ entry = (SystemColorDatum *) Tcl_GetHashValue(hPtr);
+ if (entry == NULL) {
+ Tcl_Panic("Unsupported semantic color with no supported backup!");
+ }
+ systemColorIndex[entry->index] = entry;
+ }
/*
- * Colors based on "semantic" NSColors.
+ * Remember the indexes of some special entries.
*/
- { "WindowBackgroundColor", ttkBackground, 0 }, /* 166 */
- { "WindowBackgroundColor1", ttkBackground, 1 }, /* 167 */
- { "WindowBackgroundColor2", ttkBackground, 2 }, /* 168 */
- { "WindowBackgroundColor3", ttkBackground, 3 }, /* 169 */
- { "WindowBackgroundColor4", ttkBackground, 4 }, /* 170 */
- { "WindowBackgroundColor5", ttkBackground, 5 }, /* 171 */
- { "WindowBackgroundColor6", ttkBackground, 6 }, /* 172 */
- { "WindowBackgroundColor7", ttkBackground, 7 }, /* 173 */
- { "TextColor", semantic, 0 }, /* 174 */
- { "SelectedTextColor", semantic, 1 }, /* 175 */
- { "LabelColor", semantic, 2 }, /* 176 */
- { "ControlTextColor", semantic, 3 }, /* 177 */
- { "DisabledControlTextColor", semantic, 4 }, /* 178 */
- { "SelectedTabTextColor", semantic, 5 }, /* 179 */
- { "TextBackgroundColor", semantic, 6 }, /* 180 */
- { "SelectedTextBackgroundColor", semantic, 7 }, /* 181 */
- { "ControlAccentColor", semantic, 8 }, /* 182 */
- /* Apple's SecondaryLabelColor is the same as their LabelColor so we roll our own. */
- { "SecondaryLabelColor", ttkBackground, 14 }, /* 183 */
- { "LinkColor", semantic, 9 }, /* 184 */
- { NULL, 0, 0 }
-};
-#define FIRST_SEMANTIC_COLOR 166
-#define MAX_PIXELCODE 184
+ hPtr = Tcl_FindHashEntry(&systemColors, "Pixel");
+ entry = (SystemColorDatum *) Tcl_GetHashValue(hPtr);
+ rgbColorIndex = entry->index;
+ hPtr = Tcl_FindHashEntry(&systemColors, "ControlAccentColor");
+ entry = (SystemColorDatum *) Tcl_GetHashValue(hPtr);
+ controlAccentIndex = entry->index;
+ hPtr = Tcl_FindHashEntry(&systemColors, "SelectedTabTextColor");
+ entry = (SystemColorDatum *) Tcl_GetHashValue(hPtr);
+ selectedTabTextIndex = entry->index;
+ [pool drain];
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXRGBPixel --
+ *
+ * Return an unsigned long value suitable for use in the pixel
+ * field of an XColor with the specified red, green and blue
+ * intensities. The inputs are cast as unsigned longs but are
+ * expected to have values representable by an unsigned char.
+ *
+ * This is called in the TkpGetPixel macro, used in xcolor.c,
+ * and in ImageGetPixel.
+ *
+ * Results:
+ * An unsigned long that can be used as the pixel field of an XColor.
+ *
+ * Side effects:
+ * None.
+ *----------------------------------------------------------------------
+ */
+MODULE_SCOPE
+unsigned long
+TkMacOSXRGBPixel(
+ unsigned long red,
+ unsigned long green,
+ unsigned long blue)
+{
+ MacPixel p;
+ p.pixel.colortype = rgbColor;
+ p.pixel.value = ((red & 0xff) << 16) |
+ ((green & 0xff) << 8) |
+ (blue & 0xff);
+ return p.ulong;
+}
/*
*----------------------------------------------------------------------
*
- * GetEntryFromPixelCode --
+ * TkMacOSXClearPixel --
*
- * Extract a SystemColorMapEntry from the table.
+ * Return the unsigned long value that appears in the pixel
+ * field of the XColor for systemTransparentColor.
+ *
+ * This is used in tkMacOSXImage.c.
*
* Results:
- * Returns false if the code is out of bounds.
+ * The unsigned long that appears in the pixel field of the XColor
+ * for systemTransparentPixel.
*
* Side effects:
* None.
+ *----------------------------------------------------------------------
+ */
+MODULE_SCOPE
+unsigned long TkMacOSXClearPixel(
+ void)
+{
+ MacPixel p;
+ p.pixel.value = 0;
+ p.pixel.colortype = clearColor;
+ return p.ulong;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetEntryFromPixel --
+ *
+ * Look up a SystemColorDatum which describes the XColor with
+ * the specified value as its pixel field.
+ *
+ * Results:
+ * A pointer to a SystemColorDatum, or NULL if the pixel value is
+ * invalid.
+ *
+ * Side effects:
+ * None
*
*----------------------------------------------------------------------
*/
-static bool
-GetEntryFromPixelCode(
- unsigned char code,
- struct SystemColorMapEntry *entry)
+SystemColorDatum*
+GetEntryFromPixel(
+ unsigned long pixel)
{
- if (code >= MIN_PIXELCODE && code <= MAX_PIXELCODE) {
- *entry = systemColorMap[code - MIN_PIXELCODE];
- return true;
+ MacPixel p;
+ int index = rgbColorIndex;
+
+ p.ulong = pixel;
+ if (p.pixel.colortype != rgbColor) {
+ index = p.pixel.value;
+ }
+ if (index < numSystemColors) {
+ return systemColorIndex[index];
} else {
- return false;
+ return NULL;
}
}
+
/*
*----------------------------------------------------------------------
*
- * SetCGColorComponents --
+ * GetRGBA --
*
- * Set the components of a CGColorRef from an XColor pixel value and a
- * system color map entry. The pixel value is only used in the case where
- * the color is of type rgbColor. In that case the normalized XColor RGB
- * values are copied into the CGColorRef.
+ * Given a SystemColorDatum and a pointer to an array of 4 CGFloats, store
+ * the associated RGBA color values in the array. In the case of the
+ * RGBColor datum, the unsigned long pixel value containing the RGB values
+ * must also be provided as the pixel parameter. Otherwise the pixel
+ * parameter is ignored.
*
* Results:
- * OSStatus
+ * None
*
* Side effects:
- * None.
+ * The array rgba is filled in.
*
*----------------------------------------------------------------------
*/
-static NSColorSpace* sRGB = NULL;
-static CGFloat windowBackground[4] =
- {236.0 / 255, 236.0 / 255, 236.0 / 255, 1.0};
-
-static OSStatus
-SetCGColorComponents(
- struct SystemColorMapEntry entry,
+static void
+GetRGBA(
+ SystemColorDatum *entry,
unsigned long pixel,
- CGColorRef *c)
+ CGFloat *rgba)
{
- OSStatus err = noErr;
NSColor *bgColor, *color = nil;
- CGFloat rgba[4] = {0, 0, 0, 1};
if (!sRGB) {
sRGB = [NSColorSpace sRGBColorSpace];
}
-
- /*
- * This function is called before our autorelease pool is set up,
- * so it needs its own pool.
- */
-
- NSAutoreleasePool *pool = [NSAutoreleasePool new];
-
- switch (entry.type) {
- case HIBrush:
- err = ChkErr(HIThemeBrushCreateCGColor, entry.value, c);
- return err;
+ switch (entry->type) {
case rgbColor:
rgba[0] = ((pixel >> 16) & 0xff) / 255.0;
rgba[1] = ((pixel >> 8) & 0xff) / 255.0;
@@ -308,9 +295,9 @@ SetCGColorComponents(
* windowBackGroundColor.
*/
- if ([NSApp macMinorVersion] < 14) {
- for (int i=0; i<3; i++) {
- rgba[i] = windowBackground[i];
+ if ([NSApp macOSVersion] < 101400) {
+ for (int i = 0; i < 3; i++) {
+ rgba[i] = WINDOWBACKGROUND[i];
}
} else {
bgColor = [[NSColor windowBackgroundColor] colorUsingColorSpace:sRGB];
@@ -318,104 +305,80 @@ SetCGColorComponents(
}
if (rgba[0] + rgba[1] + rgba[2] < 1.5) {
for (int i=0; i<3; i++) {
- rgba[i] += entry.value*8.0 / 255.0;
+ rgba[i] += entry->value*8.0 / 255.0;
}
} else {
for (int i=0; i<3; i++) {
- rgba[i] -= entry.value*8.0 / 255.0;
+ rgba[i] -= entry->value*8.0 / 255.0;
}
}
break;
case semantic:
- switch (entry.value) {
- case 0:
- color = [[NSColor textColor] colorUsingColorSpace:sRGB];
- break;
- case 1:
- color = [[NSColor selectedTextColor] colorUsingColorSpace:sRGB];
- break;
- case 2:
- if ([NSApp macMinorVersion] > 9) {
-#if MAC_OS_X_VERSION_MAX_ALLOWED > 1090
- color = [[NSColor labelColor] colorUsingColorSpace:sRGB];
+ if (entry->index == controlAccentIndex && useFakeAccentColor) {
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 101400
+ color = [[NSColor colorForControlTint: [NSColor currentControlTint]]
+ colorUsingColorSpace:sRGB];
#endif
- } else {
- color = [[NSColor textColor] colorUsingColorSpace:sRGB];
- }
- break;
- case 3:
- color = [[NSColor controlTextColor] colorUsingColorSpace:sRGB];
- break;
- case 4:
- color = [[NSColor disabledControlTextColor]
- colorUsingColorSpace:sRGB];
- break;
- case 5:
- if ([NSApp macMinorVersion] > 6) {
+ } else if (entry->index == selectedTabTextIndex) {
+ int OSVersion = [NSApp macOSVersion];
+ if (OSVersion > 100600 && OSVersion < 110000) {
color = [[NSColor whiteColor] colorUsingColorSpace:sRGB];
- } else {
- color = [[NSColor blackColor] colorUsingColorSpace:sRGB];
}
- break;
- case 6:
- color = [[NSColor textBackgroundColor] colorUsingColorSpace:sRGB];
- break;
- case 7:
- color = [[NSColor selectedTextBackgroundColor]
- colorUsingColorSpace:sRGB];
- break;
- case 8:
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400
- if (@available(macOS 14, *)) {
- color = [[NSColor controlAccentColor] colorUsingColorSpace:sRGB];
-#else
- if(false) {
-#endif
- } else {
- color = [[NSColor
- colorForControlTint:[NSColor currentControlTint]]
- colorUsingColorSpace: sRGB];
- }
- break;
- case 9:
- if ([NSApp macMinorVersion] >= 10) {
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
- color = [[NSColor linkColor] colorUsingColorSpace:sRGB];
-#endif
- } else {
- color = [[NSColor blueColor] colorUsingColorSpace:sRGB];
- }
- break;
- default:
- if ([NSApp macMinorVersion] >= 10) {
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
- color = [[NSColor labelColor] colorUsingColorSpace:sRGB];
-#endif
- } else {
- color = [[NSColor textColor] colorUsingColorSpace:sRGB];
- }
- break;
+ } else {
+ color = [[NSColor valueForKey:entry->selector] colorUsingColorSpace:sRGB];
}
[color getComponents: rgba];
break;
case clearColor:
- rgba[3] = 0.0;
+ rgba[3] = 0;
+ default:
break;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetCGColorComponents --
+ *
+ * Set the components of a CGColorRef from an XColor pixel value and a
+ * SystemColorDatum. The pixel value is only used in the case where
+ * the color is of type rgbColor. In that case the normalized XColor RGB
+ * values are copied into the CGColorRef. Otherwise the components are
+ * computed from the SystemColorDatum.
+ *
+ * Results:
+ * True if the function succeeds, false otherwise.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Bool
+SetCGColorComponents(
+ SystemColorDatum *entry,
+ unsigned long pixel,
+ CGColorRef *c)
+{
+ CGFloat rgba[4] = {0, 0, 0, 1};
/*
- * There are no HITheme functions which convert Text or background colors
- * to CGColors. (GetThemeTextColor has been removed, and it was never
- * possible with backgrounds.) If we get one of these we return black.
+ * This function is called before our autorelease pool is set up,
+ * so it needs its own pool.
*/
- case HIText:
- case HIBackground:
- default:
- break;
+ NSAutoreleasePool *pool = [NSAutoreleasePool new];
+
+ if (entry->type == HIBrush) {
+ OSStatus err = ChkErr(HIThemeBrushCreateCGColor, entry->value, c);
+ return err == noErr;
}
+ GetRGBA(entry, pixel, rgba);
*c = CGColorCreate(sRGB.CGColorSpace, rgba);
[pool drain];
- return err;
+ return true;
}
/*
@@ -437,27 +400,24 @@ SetCGColorComponents(
MODULE_SCOPE Bool
TkMacOSXInDarkMode(Tk_Window tkwin)
{
- int result = false;
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400
- static NSAppearanceName darkAqua = @"NSAppearanceNameDarkAqua";
-
- if ([NSApp macMinorVersion] >= 14) {
+ if (@available(macOS 10.14, *)) {
TkWindow *winPtr = (TkWindow*) tkwin;
+ NSAppearanceName name;
NSView *view = nil;
if (winPtr && winPtr->privatePtr) {
- view = TkMacOSXDrawableView(winPtr->privatePtr);
+ view = TkMacOSXGetNSViewForDrawable((Drawable)winPtr->privatePtr);
}
if (view) {
- result = [view.effectiveAppearance.name isEqualToString:darkAqua];
+ name = [[view effectiveAppearance] name];
} else {
- result = [[NSAppearance currentAppearance].name
- isEqualToString:darkAqua];
+ name = [[NSAppearance currentAppearance] name];
}
+ return (name == NSAppearanceNameDarkAqua);
}
#endif
-
- return result;
+ return false;
}
/*
@@ -465,14 +425,13 @@ TkMacOSXInDarkMode(Tk_Window tkwin)
*
* TkSetMacColor --
*
- * Sets the components of a CGColorRef from an XColor pixel value.
- * The high order byte of the pixel value is used as an index into
- * the system color table, and then SetCGColorComponents is called
- * with the table entry and the pixel value.
+ * Sets the components of a CGColorRef from an XColor pixel value. The
+ * pixel value is used to look up the color in the system color table, and
+ * then SetCGColorComponents is called with the table entry and the pixel
+ * value.
*
* Results:
- * Returns false if the high order byte is not a valid index, true
- * otherwise.
+ * Returns false if the color is not found, true otherwise.
*
* Side effects:
* The variable macColor is set to a new CGColorRef, the caller is
@@ -487,13 +446,13 @@ TkSetMacColor(
void *macColor) /* CGColorRef to modify. */
{
CGColorRef *color = (CGColorRef*)macColor;
- OSStatus err = -1;
- struct SystemColorMapEntry entry;
+ SystemColorDatum *entry = GetEntryFromPixel(pixel);
- if (GetEntryFromPixelCode((pixel >> 24) & 0xff, &entry)) {
- err = ChkErr(SetCGColorComponents, entry, pixel, color);
+ if (entry) {
+ return SetCGColorComponents(entry, pixel, color);
+ } else {
+ return false;
}
- return (err == noErr);
}
/*
@@ -506,7 +465,7 @@ TkSetMacColor(
* Results:
* None resp. retained CGColorRef for CopyCachedColor()
*
- * Side effects:M
+ * Side effects:
* None.
*
*----------------------------------------------------------------------
@@ -614,9 +573,10 @@ TkMacOSXCreateCGColor(
* TkMacOSXGetNSColor --
*
* Creates an autoreleased NSColor from a X style pixel value.
+ * The return value is nil if the pixel value is invalid.
*
* Results:
- * Returns nil if not a real pixel, NSColor* otherwise.
+ * A possibly nil pointer to an NSColor.
*
* Side effects:
* None
@@ -650,10 +610,9 @@ TkMacOSXGetNSColor(
*
* TkMacOSXSetColorInContext --
*
- * Sets fill and stroke color in the given CG context from an X
- * pixel value, or if the pixel code indicates a system color,
- * sets the corresponding brush, textColor or background via
- * HITheme APIs if available or Appearance mgr APIs.
+ * Sets the fill and stroke colors in the given CGContext to the CGColor
+ * which corresponds to the XColor having the specified value for its pixel
+ * field.
*
* Results:
* None.
@@ -672,37 +631,20 @@ TkMacOSXSetColorInContext(
{
OSStatus err = noErr;
CGColorRef cgColor = nil;
- struct SystemColorMapEntry entry;
- CGRect rect;
- int code = (pixel >> 24) & 0xff;
- HIThemeBackgroundDrawInfo info = {0, kThemeStateActive, 0};;
+ SystemColorDatum *entry = GetEntryFromPixel(pixel);
- if (code < FIRST_SEMANTIC_COLOR) {
- cgColor = CopyCachedColor(gc, pixel);
- }
- if (!cgColor && GetEntryFromPixelCode(code, &entry)) {
- switch (entry.type) {
+ if (entry) {
+ switch (entry->type) {
case HIBrush:
- err = ChkErr(HIThemeSetFill, entry.value, NULL, context,
+ err = ChkErr(HIThemeSetFill, entry->value, NULL, context,
kHIThemeOrientationNormal);
if (err == noErr) {
- err = ChkErr(HIThemeSetStroke, entry.value, NULL, context,
+ err = ChkErr(HIThemeSetStroke, entry->value, NULL, context,
kHIThemeOrientationNormal);
}
break;
- case HIText:
- err = ChkErr(HIThemeSetTextFill, entry.value, NULL, context,
- kHIThemeOrientationNormal);
- break;
- case HIBackground:
- info.kind = entry.value;
- rect = CGContextGetClipBoundingBox(context);
- err = ChkErr(HIThemeApplyBackground, &rect, &info,
- context, kHIThemeOrientationNormal);
- break;
default:
- err = ChkErr(SetCGColorComponents, entry, pixel, &cgColor);
- if (err == noErr) {
+ if (SetCGColorComponents(entry, pixel, &cgColor)){
SetCachedColor(gc, pixel, cgColor);
}
break;
@@ -723,15 +665,20 @@ TkMacOSXSetColorInContext(
*
* TkpGetColor --
*
- * Allocate a new TkColor for the color with the given name.
+ * Create a new TkColor for the color with the given name, for use in the
+ * specified window. The colormap field is set to lightColormap if the
+ * window has a LightAqua appearance, or darkColormap if the window has a
+ * DarkAqua appearance. TkColors with different colormaps are managed
+ * separately in the per-display table of TkColors maintained by Tk.
+ *
+ * This function is called by Tk_GetColor.
*
* Results:
* Returns a newly allocated TkColor, or NULL on failure.
*
* Side effects:
- * May invalidate the colormap cache associated with tkwin upon
- * allocating a new colormap entry. Allocates a new TkColor
- * structure.
+ *
+ * Allocates memory for the TkColor structure.
*
*----------------------------------------------------------------------
*/
@@ -742,31 +689,68 @@ TkpGetColor(
Tk_Uid name) /* Name of color to be allocated (in form
* suitable for passing to XParseColor). */
{
- Display *display = tkwin != None ? Tk_Display(tkwin) : NULL;
- Colormap colormap = tkwin!= None ? Tk_Colormap(tkwin) : None;
+ Display *display = NULL;
TkColor *tkColPtr;
XColor color;
+ Colormap colormap = tkwin ? Tk_Colormap(tkwin) : noColormap;
+ NSView *view = nil;
+ static Bool initialized = NO;
+ static NSColorSpace* sRGB = NULL;
+
+ if (!initialized) {
+ initialized = YES;
+ sRGB = [NSColorSpace sRGBColorSpace];
+ initColorTable();
+ }
+ if (tkwin) {
+ display = Tk_Display(tkwin);
+ Drawable d = Tk_WindowId(tkwin);
+ view = TkMacOSXGetNSViewForDrawable(d);
+ }
/*
- * Check to see if this is a system color. Otherwise, XParseColor
- * will do all the work.
+ * Check to see if this is a system color. If not, just call XParseColor.
*/
if (strncasecmp(name, "system", 6) == 0) {
- Tcl_Obj *strPtr = Tcl_NewStringObj(name+6, -1);
- int idx, result;
-
- result = Tcl_GetIndexFromObjStruct(NULL, strPtr, systemColorMap,
- sizeof(struct SystemColorMapEntry), NULL, TCL_EXACT, &idx);
- Tcl_DecrRefCount(strPtr);
- if (result == TCL_OK) {
- OSStatus err;
+ Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&systemColors, name + 6);
+ MacPixel p;
+
+ if (hPtr != NULL) {
+ SystemColorDatum *entry = (SystemColorDatum *)Tcl_GetHashValue(hPtr);
CGColorRef c;
- unsigned char pixelCode = idx + MIN_PIXELCODE;
- struct SystemColorMapEntry entry = systemColorMap[idx];
- err = ChkErr(SetCGColorComponents, entry, 0, &c);
- if (err == noErr) {
+ p.pixel.colortype = entry->type;
+ p.pixel.value = entry->index;
+ color.pixel = p.ulong;
+ if (entry->type == semantic) {
+ CGFloat rgba[4];
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400
+ if (@available(macOS 10.14, *)) {
+ NSAppearance *savedAppearance = [NSAppearance currentAppearance];
+ NSAppearance *windowAppearance = savedAppearance;
+ if (view) {
+ windowAppearance = [view effectiveAppearance];
+ }
+ if ([windowAppearance name] == NSAppearanceNameDarkAqua) {
+ colormap = darkColormap;
+ } else {
+ colormap = lightColormap;
+ }
+ [NSAppearance setCurrentAppearance:windowAppearance];
+ GetRGBA(entry, p.ulong, rgba);
+ [NSAppearance setCurrentAppearance:savedAppearance];
+ } else {
+ GetRGBA(entry, p.ulong, rgba);
+ }
+#else
+ GetRGBA(entry, p.ulong, rgba);
+#endif
+ color.red = rgba[0] * 65535.0;
+ color.green = rgba[1] * 65535.0;
+ color.blue = rgba[2] * 65535.0;
+ goto validXColor;
+ } else if (SetCGColorComponents(entry, 0, &c)) {
const size_t n = CGColorGetNumberOfComponents(c);
const CGFloat *rgba = CGColorGetComponents(c);
@@ -782,25 +766,19 @@ TkpGetColor(
default:
Tcl_Panic("CGColor with %d components", (int) n);
}
- color.pixel = ((((((pixelCode << 8)
- | ((color.red >> 8) & 0xff)) << 8)
- | ((color.green >> 8) & 0xff)) << 8)
- | ((color.blue >> 8) & 0xff));
CGColorRelease(c);
goto validXColor;
}
- CGColorRelease(c);
}
}
-
if (TkParseColor(display, colormap, name, &color) == 0) {
return NULL;
}
validXColor:
tkColPtr = (TkColor *)ckalloc(sizeof(TkColor));
+ tkColPtr->colormap = colormap;
tkColPtr->color = color;
-
return tkColPtr;
}
@@ -809,36 +787,35 @@ validXColor:
*
* TkpGetColorByValue --
*
- * Given a desired set of red-green-blue intensities for a color,
- * locate a pixel value to use to draw that color in a given
- * window.
+ * Given an pointer to an XColor, construct a TkColor whose red, green and
+ * blue intensities match those of the XColor as closely as possible. For
+ * the Macintosh, this means that the colortype bitfield of the pixel
+ * value will be RGBColor and that the color intensities stored in its
+ * 24-bit value bitfield are computed from the 16-bit red green and blue
+ * values in the XColor by dividing by 256.
*
* Results:
- * The return value is a pointer to an TkColor structure that
- * indicates the closest red, blue, and green intensities available
- * to those specified in colorPtr, and also specifies a pixel
- * value to use to draw in that color.
+ * A pointer to a newly allocated TkColor structure.
*
* Side effects:
* May invalidate the colormap cache for the specified window.
- * Allocates a new TkColor structure.
+ * Allocates memory for a TkColor structure.
*
*----------------------------------------------------------------------
*/
TkColor *
TkpGetColorByValue(
- Tk_Window tkwin, /* Window in which color will be used. */
+ TCL_UNUSED(Tk_Window), /* Window in which color will be used. */
XColor *colorPtr) /* Red, green, and blue fields indicate
* desired color. */
{
TkColor *tkColPtr = (TkColor *)ckalloc(sizeof(TkColor));
- (void)tkwin;
tkColPtr->color.red = colorPtr->red;
tkColPtr->color.green = colorPtr->green;
tkColPtr->color.blue = colorPtr->blue;
- tkColPtr->color.pixel = TkpGetPixel(&tkColPtr->color);
+ tkColPtr->color.pixel = TkpGetPixel(colorPtr);
return tkColPtr;
}
@@ -862,11 +839,9 @@ TkpGetColorByValue(
Status
XAllocColor(
Display *display, /* Display. */
- Colormap map, /* Not used. */
+ TCL_UNUSED(Colormap), /* Not used. */
XColor *colorPtr) /* XColor struct to modify. */
{
- (void)map;
-
display->request++;
colorPtr->pixel = TkpGetPixel(colorPtr);
return 1;
@@ -874,52 +849,39 @@ XAllocColor(
Colormap
XCreateColormap(
- Display *display, /* Display. */
- Window window, /* X window. */
- Visual *visual, /* Not used. */
- int alloc) /* Not used. */
+ TCL_UNUSED(Display *), /* Display. */
+ TCL_UNUSED(Window), /* X window. */
+ TCL_UNUSED(Visual *), /* Not used. */
+ TCL_UNUSED(int)) /* Not used. */
{
- static Colormap index = 1;
- (void)display;
- (void)window;
- (void)visual;
- (void)alloc;
+ static Colormap index = 16;
/*
- * Just return a new value each time.
+ * Just return a new value each time, large enough that it will not
+ * conflict with any value of the macColormap enum.
*/
return index++;
}
int
XFreeColormap(
- Display* display, /* Display. */
- Colormap colormap) /* Colormap. */
+ TCL_UNUSED(Display *), /* Display. */
+ TCL_UNUSED(Colormap)) /* Colormap. */
{
- (void)display;
- (void)colormap;
-
return Success;
}
int
XFreeColors(
- Display* display, /* Display. */
- Colormap colormap, /* Colormap. */
- unsigned long* pixels, /* Array of pixels. */
- int npixels, /* Number of pixels. */
- unsigned long planes) /* Number of pixel planes. */
+ TCL_UNUSED(Display *), /* Display. */
+ TCL_UNUSED(Colormap), /* Colormap. */
+ TCL_UNUSED(unsigned long *), /* Array of pixels. */
+ TCL_UNUSED(int), /* Number of pixels. */
+ TCL_UNUSED(unsigned long)) /* Number of pixel planes. */
{
- (void)display;
- (void)colormap;
- (void)pixels;
- (void)npixels;
- (void)planes;
-
/*
- * The Macintosh version of Tk uses TrueColor. Nothing
- * needs to be done to release colors as there really is
- * no colormap in the Tk sense.
+ * Nothing needs to be done to release colors as there really is no
+ * colormap in the Tk sense.
*/
return Success;
}