From 7ee00057db4a080edfaf39bc921f7eb58d64a459 Mon Sep 17 00:00:00 2001 From: oehhar Date: Sun, 3 Feb 2019 11:21:11 +0000 Subject: gif read not complete on overflow image - information missinterpreted if following subimage is querried [4da2191b] --- generic/tkImgGIF.c | 21 ++++++++++++++++++++- tests/imgPhoto.test | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/generic/tkImgGIF.c b/generic/tkImgGIF.c index 7c4872b..fa4b728 100644 --- a/generic/tkImgGIF.c +++ b/generic/tkImgGIF.c @@ -1034,7 +1034,7 @@ ReadImage( int transparent) { unsigned char initialCodeSize; - int xpos = 0, ypos = 0, pass = 0, i; + int xpos = 0, ypos = 0, pass = 0, i, count; register unsigned char *pixelPtr; static const int interlaceStep[] = { 8, 8, 4, 2 }; static const int interlaceStart[] = { 0, 4, 2, 1 }; @@ -1252,6 +1252,25 @@ ReadImage( } pixelPtr = imagePtr + (ypos) * len * ((transparent>=0)?4:3); } + + /* + * Now read until the final zero byte. + * It was observed that there might be 1 length blocks + * (test imgPhoto-14.1) which are not read. + * + * The field "stack" is abused for temporary buffer. it has 4096 bytes + * and we need 256. + * + * Loop until we hit a 0 length block which is the end sign. + */ + while ( 0 < (count = GetDataBlock(gifConfPtr, chan, stack))) + { + if (-1 == count ) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "error reading GIF image: %s", Tcl_PosixError(interp))); + return TCL_ERROR; + } + } return TCL_OK; } diff --git a/tests/imgPhoto.test b/tests/imgPhoto.test index 97fb7ae..c45c5fb 100644 --- a/tests/imgPhoto.test +++ b/tests/imgPhoto.test @@ -1212,6 +1212,39 @@ test imgPhoto-14.5 {Bug [fbaed1f66b] - GIF decoder with deferred clear code} -se image create photo -file $fileName -format "gif -index 2" } -returnCodes error -result {no image data for this index} +test imgPhoto-14.6 {Access Subimage after Subimage with buffer overflow. Ticket 4da2191b} -setup { + set data { + R0lGODlhYwA5APcAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgAysnGy8hKzM + hASs3MTcjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDAwP8AAAD/ + AP//AAAA//8A/wD//////ywAAAAAYwA5AAAI/wAZCBxIsKDBgwgTKlzIsKHD + hxAjSpxIsaLFixgzatzIsaPHjyBDihxJsqTJkyhTqlzJsqXLlzBjypxJs6bN + mzhz6tzJs6fPn0CDCh1KtKhRiwoSKEXAtGlTpUqPGkyagOmCq1edNsWalWkC + BUSXIuDqFepBqFWtZv3KU+zYrkrBSqT6dgECtjOTbu16NwFHvV3lshRLti/J + qlgRCE6ZuO9ik4Dt+k0ZVyZiyVIvXr77ODPEy5g9T4zMWfTEzXdNz1VbWvXn + uqldP1TAOrbshqBb314Y2W7n3Qdpv7UNPCHpycUVbv6dnODy5sqzQldIe8H0 + hciva9/Ovbv37+BzBgE7ACH5BAFkAAMALAAAAAAEAAQAAAMEKLrckgA7 + } +} -body { + image create photo photo1 -data $data -format "GIF -index 1" +} -cleanup { + catch {image delete photo1} +} -result photo1 + test imgPhoto-15.1 {photo images can fail to allocate memory gracefully} -constraints { nonPortable } -body { -- cgit v0.12 From 31b66a6295cd71b19bc085fd8c1b6b660c327ad3 Mon Sep 17 00:00:00 2001 From: jal_frezie Date: Wed, 20 Feb 2019 11:51:53 +0000 Subject: Eliminate trailing zeros from scale tick values. This is done by calculating a separate format string for these values, rather than using the same format string as for the current value. The basis is the same, i.e., enough digits are displayed to distinguish any pair of adjacent tick values, and all tick values have the same number of decimals so some may still have trailing zeros. Code for laying out vertical scales has been adjusted to take account of the fact that the tick column may now be narrower than the value column. --- generic/tkScale.c | 148 ++++++++++++++++++++++++++++++++++------------------- generic/tkScale.h | 4 +- unix/tkUnixScale.c | 28 +++++----- 3 files changed, 114 insertions(+), 66 deletions(-) diff --git a/generic/tkScale.c b/generic/tkScale.c index 29f8722..455c656 100644 --- a/generic/tkScale.c +++ b/generic/tkScale.c @@ -157,7 +157,7 @@ enum command { * Forward declarations for procedures defined later in this file: */ -static void ComputeFormat(TkScale *scalePtr); +static void ComputeFormat(TkScale *scalePtr, int forTicks); static void ComputeScaleGeometry(TkScale *scalePtr); static int ConfigureScale(Tcl_Interp *interp, TkScale *scalePtr, int objc, Tcl_Obj *const objv[]); @@ -430,7 +430,7 @@ ScaleWidgetObjCmd( } value = TkScalePixelToValue(scalePtr, x, y); } - Tcl_SetObjResult(interp, Tcl_ObjPrintf(scalePtr->format, value)); + Tcl_SetObjResult(interp, Tcl_ObjPrintf(scalePtr->valueFormat, value)); break; } case COMMAND_IDENTIFY: { @@ -636,7 +636,8 @@ ConfigureScale( scalePtr->tickInterval = -scalePtr->tickInterval; } - ComputeFormat(scalePtr); + ComputeFormat(scalePtr, 0); + ComputeFormat(scalePtr, 1); scalePtr->labelLength = scalePtr->label ? (int)strlen(scalePtr->label) : 0; @@ -764,22 +765,22 @@ ScaleWorldChanged( * * ComputeFormat -- * - * This procedure is invoked to recompute the "format" field of a scale's - * widget record, which determines how the value of the scale is - * converted to a string. + * This procedure is invoked to recompute the "valueFormat" or + * "tickFormat" field of a scale's widget record, which determines how + * the value of the scale or one of its ticks is converted to a string. * * Results: * None. * - * Side effects: - * The format field of scalePtr is modified. + * Side effects: The valueFormat or tickFormat field of scalePtr is modified. * *---------------------------------------------------------------------- */ static void ComputeFormat( - TkScale *scalePtr) /* Information about scale widget. */ + TkScale *scalePtr, /* Information about scale widget. */ + int forTicks) /* Do for ticks rather than value */ { double maxValue, x; int mostSigDigit, numDigits, leastSigDigit, afterDecimal; @@ -800,46 +801,60 @@ ComputeFormat( } mostSigDigit = (int) floor(log10(maxValue)); - /* - * If the number of significant digits wasn't specified explicitly, - * compute it. It's the difference between the most significant digit - * needed to represent any number on the scale and the most significant - * digit of the smallest difference between numbers on the scale. In other - * words, display enough digits so that at least one digit will be - * different between any two adjacent positions of the scale. - */ - - numDigits = scalePtr->digits; - if (numDigits > TCL_MAX_PREC) { - numDigits = 0; - } - if (numDigits <= 0) { - if (scalePtr->resolution > 0) { - /* - * A resolution was specified for the scale, so just use it. - */ + if (forTicks) { + /* + * Display only enough digits to ensure adjacent ticks have different + * values + */ - leastSigDigit = (int) floor(log10(scalePtr->resolution)); + if (scalePtr->tickInterval > 0) { + numDigits = 1 + mostSigDigit - (int) floor(log10(scalePtr->tickInterval)); } else { - /* - * No resolution was specified, so compute the difference in value - * between adjacent pixels and use it for the least significant - * digit. - */ + numDigits = 1; + } + } else { + /* + * If the number of significant digits wasn't specified explicitly, + * compute it. It's the difference between the most significant digit + * needed to represent any number on the scale and the most + * significant digit of the smallest difference between numbers on the + * scale. In other words, display enough digits so that at least one + * digit will be different between any two adjacent positions of the + * scale. + */ - x = fabs(scalePtr->fromValue - scalePtr->toValue); - if (scalePtr->length > 0) { - x /= scalePtr->length; - } - if (x > 0){ - leastSigDigit = (int) floor(log10(x)); + numDigits = scalePtr->digits; + if (numDigits > TCL_MAX_PREC) { + numDigits = 0; + } + if (numDigits <= 0) { + if (scalePtr->resolution > 0) { + /* + * A resolution was specified for the scale, so just use it. + */ + + leastSigDigit = (int) floor(log10(scalePtr->resolution)); } else { - leastSigDigit = 0; + /* + * No resolution was specified, so compute the difference in + * value between adjacent pixels and use it for the least + * significant digit. + */ + + x = fabs(scalePtr->fromValue - scalePtr->toValue); + if (scalePtr->length > 0) { + x /= scalePtr->length; + } + if (x > 0){ + leastSigDigit = (int) floor(log10(x)); + } else { + leastSigDigit = 0; + } + } + numDigits = mostSigDigit - leastSigDigit + 1; + if (numDigits < 1) { + numDigits = 1; } - } - numDigits = mostSigDigit - leastSigDigit + 1; - if (numDigits < 1) { - numDigits = 1; } } @@ -863,10 +878,18 @@ ComputeFormat( if (mostSigDigit < 0) { fDigits++; /* Zero to left of decimal point. */ } - if (fDigits <= eDigits) { - sprintf(scalePtr->format, "%%.%df", afterDecimal); + if (forTicks) { + if (fDigits <= eDigits) { + sprintf(scalePtr->tickFormat, "%%.%df", afterDecimal); + } else { + sprintf(scalePtr->tickFormat, "%%.%de", numDigits-1); + } } else { - sprintf(scalePtr->format, "%%.%de", numDigits-1); + if (fDigits <= eDigits) { + sprintf(scalePtr->valueFormat, "%%.%df", afterDecimal); + } else { + sprintf(scalePtr->valueFormat, "%%.%de", numDigits-1); + } } } @@ -894,7 +917,7 @@ ComputeScaleGeometry( register TkScale *scalePtr) /* Information about widget. */ { char valueString[TCL_DOUBLE_SPACE]; - int tmp, valuePixels, x, y, extraSpace; + int tmp, valuePixels, tickPixels, x, y, extraSpace; Tk_FontMetrics fm; Tk_GetFontMetrics(scalePtr->tkfont, &fm); @@ -940,13 +963,13 @@ ComputeScaleGeometry( * whichever length is longer. */ - if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->format, + if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->valueFormat, scalePtr->fromValue) < 0) { valueString[TCL_DOUBLE_SPACE - 1] = '\0'; } valuePixels = Tk_TextWidth(scalePtr->tkfont, valueString, -1); - if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->format, + if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->valueFormat, scalePtr->toValue) < 0) { valueString[TCL_DOUBLE_SPACE - 1] = '\0'; } @@ -956,18 +979,37 @@ ComputeScaleGeometry( } /* + * Now do the same thing for the tick values + */ + + if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->tickFormat, + scalePtr->fromValue) < 0) { + valueString[TCL_DOUBLE_SPACE - 1] = '\0'; + } + tickPixels = Tk_TextWidth(scalePtr->tkfont, valueString, -1); + + if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->tickFormat, + scalePtr->toValue) < 0) { + valueString[TCL_DOUBLE_SPACE - 1] = '\0'; + } + tmp = Tk_TextWidth(scalePtr->tkfont, valueString, -1); + if (tickPixels < tmp) { + tickPixels = tmp; + } + + /* * Assign x-locations to the elements of the scale, working from left to * right. */ x = scalePtr->inset; if ((scalePtr->tickInterval != 0) && (scalePtr->showValue)) { - scalePtr->vertTickRightX = x + SPACING + valuePixels; + scalePtr->vertTickRightX = x + SPACING + tickPixels; scalePtr->vertValueRightX = scalePtr->vertTickRightX + valuePixels + fm.ascent/2; x = scalePtr->vertValueRightX + SPACING; } else if (scalePtr->tickInterval != 0) { - scalePtr->vertTickRightX = x + SPACING + valuePixels; + scalePtr->vertTickRightX = x + SPACING + tickPixels; scalePtr->vertValueRightX = scalePtr->vertTickRightX; x = scalePtr->vertTickRightX + SPACING; } else if (scalePtr->showValue) { @@ -1350,7 +1392,7 @@ ScaleSetVariable( if (scalePtr->varNamePtr != NULL) { char string[TCL_DOUBLE_SPACE]; - if (snprintf(string, TCL_DOUBLE_SPACE, scalePtr->format, + if (snprintf(string, TCL_DOUBLE_SPACE, scalePtr->valueFormat, scalePtr->value) < 0) { string[TCL_DOUBLE_SPACE - 1] = '\0'; } diff --git a/generic/tkScale.h b/generic/tkScale.h index d44e65b..4250b06 100644 --- a/generic/tkScale.h +++ b/generic/tkScale.h @@ -73,8 +73,10 @@ typedef struct TkScale { * values. 0 means we get to choose the number * based on resolution and/or the range of the * scale. */ - char format[16]; /* Sprintf conversion specifier computed from + char valueFormat[16]; /* Sprintf conversion specifier computed from * digits and other information. */ + char tickFormat[16]; /* Sprintf conversion specifier computed from + * tick interval. */ double bigIncrement; /* Amount to use for large increments to scale * value. (0 means we pick a value). */ char *command; /* Command prefix to use when invoking Tcl diff --git a/unix/tkUnixScale.c b/unix/tkUnixScale.c index 2009288..f5e3fc2 100644 --- a/unix/tkUnixScale.c +++ b/unix/tkUnixScale.c @@ -24,11 +24,13 @@ static void DisplayHorizontalScale(TkScale *scalePtr, Drawable drawable, XRectangle *drawnAreaPtr); static void DisplayHorizontalValue(TkScale *scalePtr, - Drawable drawable, double value, int top); + Drawable drawable, double value, + int top, char* format); static void DisplayVerticalScale(TkScale *scalePtr, Drawable drawable, XRectangle *drawnAreaPtr); static void DisplayVerticalValue(TkScale *scalePtr, - Drawable drawable, double value, int rightEdge); + Drawable drawable, double value, + int rightEdge, char* format); /* *---------------------------------------------------------------------- @@ -165,7 +167,7 @@ DisplayVerticalScale( } } DisplayVerticalValue(scalePtr, drawable, tickValue, - scalePtr->vertTickRightX); + scalePtr->vertTickRightX, scalePtr->tickFormat); } } } @@ -176,7 +178,7 @@ DisplayVerticalScale( if (scalePtr->showValue) { DisplayVerticalValue(scalePtr, drawable, scalePtr->value, - scalePtr->vertValueRightX); + scalePtr->vertValueRightX, scalePtr->valueFormat); } /* @@ -261,8 +263,9 @@ DisplayVerticalValue( double value, /* Y-coordinate of number to display, * specified in application coords, not in * pixels (we'll compute pixels). */ - int rightEdge) /* X-coordinate of right edge of text, + int rightEdge, /* X-coordinate of right edge of text, * specified in pixels. */ + char* format) /* Format string to use for the value */ { register Tk_Window tkwin = scalePtr->tkwin; int y, width, length; @@ -271,7 +274,7 @@ DisplayVerticalValue( Tk_GetFontMetrics(scalePtr->tkfont, &fm); y = TkScaleValueToPixel(scalePtr, value) + fm.ascent/2; - if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->format, value) < 0) { + if (snprintf(valueString, TCL_DOUBLE_SPACE, format, value) < 0) { valueString[TCL_DOUBLE_SPACE - 1] = '\0'; } length = (int) strlen(valueString); @@ -358,7 +361,7 @@ DisplayHorizontalScale( ticks = fabs((scalePtr->toValue - scalePtr->fromValue) / tickInterval); - if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->format, + if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->tickFormat, scalePtr->fromValue) < 0) { valueString[TCL_DOUBLE_SPACE - 1] = '\0'; } @@ -385,7 +388,7 @@ DisplayHorizontalScale( } } DisplayHorizontalValue(scalePtr, drawable, tickValue, - scalePtr->horizTickY); + scalePtr->horizTickY, scalePtr->tickFormat); } } } @@ -396,7 +399,7 @@ DisplayHorizontalScale( if (scalePtr->showValue) { DisplayHorizontalValue(scalePtr, drawable, scalePtr->value, - scalePtr->horizValueY); + scalePtr->horizValueY, scalePtr->valueFormat); } /* @@ -482,8 +485,9 @@ DisplayHorizontalValue( double value, /* X-coordinate of number to display, * specified in application coords, not in * pixels (we'll compute pixels). */ - int top) /* Y-coordinate of top edge of text, specified + int top, /* Y-coordinate of top edge of text, specified * in pixels. */ + char* format) /* Format string to use for the value */ { register Tk_Window tkwin = scalePtr->tkwin; int x, y, length, width; @@ -493,7 +497,7 @@ DisplayHorizontalValue( x = TkScaleValueToPixel(scalePtr, value); Tk_GetFontMetrics(scalePtr->tkfont, &fm); y = top + fm.ascent; - if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->format, value) < 0) { + if (snprintf(valueString, TCL_DOUBLE_SPACE, format, value) < 0) { valueString[TCL_DOUBLE_SPACE - 1] = '\0'; } length = (int) strlen(valueString); @@ -562,7 +566,7 @@ TkpDisplayScale( Tcl_Preserve(scalePtr); if ((scalePtr->flags & INVOKE_COMMAND) && (scalePtr->command != NULL)) { Tcl_Preserve(interp); - if (snprintf(string, TCL_DOUBLE_SPACE, scalePtr->format, + if (snprintf(string, TCL_DOUBLE_SPACE, scalePtr->valueFormat, scalePtr->value) < 0) { string[TCL_DOUBLE_SPACE - 1] = '\0'; } -- cgit v0.12 From df6b431de5bfd967f436105572e5853b478cc21c Mon Sep 17 00:00:00 2001 From: culler Date: Sun, 24 Feb 2019 17:08:37 +0000 Subject: Fix bug [0d63621b6c]: Aqua ttk uses incorrect background colors. --- macosx/tkMacOSXColor.c | 396 ++++++++++++++++++++++++------------------------ macosx/tkMacOSXInt.h | 1 + macosx/ttkMacOSXTheme.c | 153 +++++++++++++------ 3 files changed, 309 insertions(+), 241 deletions(-) diff --git a/macosx/tkMacOSXColor.c b/macosx/tkMacOSXColor.c index 459ca47..b90fae3 100644 --- a/macosx/tkMacOSXColor.c +++ b/macosx/tkMacOSXColor.c @@ -22,6 +22,7 @@ struct SystemColorMapEntry { ThemeBrush brush; ThemeTextColor textColor; ThemeBackgroundKind background; + int depth; }; /* unsigned char pixelCode; */ /* @@ -32,145 +33,153 @@ struct SystemColorMapEntry { #define MIN_PIXELCODE 30 static const struct SystemColorMapEntry systemColorMap[] = { - { "Transparent", 0, 0, 0 }, /* 30: TRANSPARENT_PIXEL */ - { "Highlight", kThemeBrushPrimaryHighlightColor, 0, 0 }, /* 31: HIGHLIGHT_PIXEL */ - { "HighlightSecondary", kThemeBrushSecondaryHighlightColor, 0, 0 }, /* 32: HIGHLIGHT_SECONDARY_PIXEL */ - { "HighlightText", kThemeBrushBlack, 0, 0 }, /* 33: HIGHLIGHT_TEXT_PIXEL */ - { "HighlightAlternate", kThemeBrushAlternatePrimaryHighlightColor, 0, 0 }, /* 34: HIGHLIGHT_ALTERNATE_PIXEL */ - { "ButtonText", 0, kThemeTextColorPushButtonActive, 0 }, /* 35: CONTROL_TEXT_PIXEL */ - { "PrimaryHighlightColor", kThemeBrushPrimaryHighlightColor, 0, 0 }, /* 36 */ - { "ButtonFace", kThemeBrushButtonFaceActive, 0, 0 }, /* 37: CONTROL_BODY_PIXEL */ - { "SecondaryHighlightColor", kThemeBrushSecondaryHighlightColor, 0, 0 }, /* 38 */ - { "ButtonFrame", kThemeBrushButtonFrameActive, 0, 0 }, /* 39: CONTROL_FRAME_PIXEL */ - { "AlternatePrimaryHighlightColor", kThemeBrushAlternatePrimaryHighlightColor, 0, 0 }, /* 40 */ - { "WindowBody", kThemeBrushDocumentWindowBackground, 0, 0 }, /* 41: WINDOW_BODY_PIXEL */ - { "SheetBackground", kThemeBrushSheetBackground, 0, 0 }, /* 42 */ - { "MenuActive", kThemeBrushMenuBackgroundSelected, 0, 0 }, /* 43: MENU_ACTIVE_PIXEL */ - { "Black", kThemeBrushBlack, 0, 0 }, /* 44 */ - { "MenuActiveText", 0, kThemeTextColorMenuItemSelected, 0 }, /* 45: MENU_ACTIVE_TEXT_PIXEL */ - { "White", kThemeBrushWhite, 0, 0 }, /* 46 */ - { "Menu", kThemeBrushMenuBackground, 0, 0 }, /* 47: MENU_BACKGROUND_PIXEL */ - { "DialogBackgroundActive", kThemeBrushDialogBackgroundActive, 0, 0 }, /* 48 */ - { "MenuDisabled", 0, kThemeTextColorMenuItemDisabled, 0 }, /* 49: MENU_DISABLED_PIXEL */ - { "DialogBackgroundInactive", kThemeBrushDialogBackgroundInactive, 0, 0 }, /* 50 */ - { "MenuText", 0, kThemeTextColorMenuItemActive, 0 }, /* 51: MENU_TEXT_PIXEL */ - { "AppearanceColor", 0, 0, 0 }, /* 52: APPEARANCE_PIXEL */ - { "AlertBackgroundActive", kThemeBrushAlertBackgroundActive, 0, 0 }, /* 53 */ - { "AlertBackgroundInactive", kThemeBrushAlertBackgroundInactive, 0, 0 }, /* 54 */ - { "ModelessDialogBackgroundActive", kThemeBrushModelessDialogBackgroundActive, 0, 0 }, /* 55 */ - { "ModelessDialogBackgroundInactive", kThemeBrushModelessDialogBackgroundInactive, 0, 0 }, /* 56 */ - { "UtilityWindowBackgroundActive", kThemeBrushUtilityWindowBackgroundActive, 0, 0 }, /* 57 */ - { "UtilityWindowBackgroundInactive", kThemeBrushUtilityWindowBackgroundInactive, 0, 0 }, /* 58 */ - { "ListViewSortColumnBackground", kThemeBrushListViewSortColumnBackground, 0, 0 }, /* 59 */ - { "ListViewBackground", kThemeBrushListViewBackground, 0, 0 }, /* 60 */ - { "IconLabelBackground", kThemeBrushIconLabelBackground, 0, 0 }, /* 61 */ - { "ListViewSeparator", kThemeBrushListViewSeparator, 0, 0 }, /* 62 */ - { "ChasingArrows", kThemeBrushChasingArrows, 0, 0 }, /* 63 */ - { "DragHilite", kThemeBrushDragHilite, 0, 0 }, /* 64 */ - { "DocumentWindowBackground", kThemeBrushDocumentWindowBackground, 0, 0 }, /* 65 */ - { "FinderWindowBackground", kThemeBrushFinderWindowBackground, 0, 0 }, /* 66 */ - { "ScrollBarDelimiterActive", kThemeBrushScrollBarDelimiterActive, 0, 0 }, /* 67 */ - { "ScrollBarDelimiterInactive", kThemeBrushScrollBarDelimiterInactive, 0, 0 }, /* 68 */ - { "FocusHighlight", kThemeBrushFocusHighlight, 0, 0 }, /* 69 */ - { "PopupArrowActive", kThemeBrushPopupArrowActive, 0, 0 }, /* 70 */ - { "PopupArrowPressed", kThemeBrushPopupArrowPressed, 0, 0 }, /* 71 */ - { "PopupArrowInactive", kThemeBrushPopupArrowInactive, 0, 0 }, /* 72 */ - { "AppleGuideCoachmark", kThemeBrushAppleGuideCoachmark, 0, 0 }, /* 73 */ - { "IconLabelBackgroundSelected", kThemeBrushIconLabelBackgroundSelected, 0, 0 }, /* 74 */ - { "StaticAreaFill", kThemeBrushStaticAreaFill, 0, 0 }, /* 75 */ - { "ActiveAreaFill", kThemeBrushActiveAreaFill, 0, 0 }, /* 76 */ - { "ButtonFrameActive", kThemeBrushButtonFrameActive, 0, 0 }, /* 77 */ - { "ButtonFrameInactive", kThemeBrushButtonFrameInactive, 0, 0 }, /* 78 */ - { "ButtonFaceActive", kThemeBrushButtonFaceActive, 0, 0 }, /* 79 */ - { "ButtonFaceInactive", kThemeBrushButtonFaceInactive, 0, 0 }, /* 80 */ - { "ButtonFacePressed", kThemeBrushButtonFacePressed, 0, 0 }, /* 81 */ - { "ButtonActiveDarkShadow", kThemeBrushButtonActiveDarkShadow, 0, 0 }, /* 82 */ - { "ButtonActiveDarkHighlight", kThemeBrushButtonActiveDarkHighlight, 0, 0 }, /* 83 */ - { "ButtonActiveLightShadow", kThemeBrushButtonActiveLightShadow, 0, 0 }, /* 84 */ - { "ButtonActiveLightHighlight", kThemeBrushButtonActiveLightHighlight, 0, 0 }, /* 85 */ - { "ButtonInactiveDarkShadow", kThemeBrushButtonInactiveDarkShadow, 0, 0 }, /* 86 */ - { "ButtonInactiveDarkHighlight", kThemeBrushButtonInactiveDarkHighlight, 0, 0 }, /* 87 */ - { "ButtonInactiveLightShadow", kThemeBrushButtonInactiveLightShadow, 0, 0 }, /* 88 */ - { "ButtonInactiveLightHighlight", kThemeBrushButtonInactiveLightHighlight, 0, 0 }, /* 89 */ - { "ButtonPressedDarkShadow", kThemeBrushButtonPressedDarkShadow, 0, 0 }, /* 90 */ - { "ButtonPressedDarkHighlight", kThemeBrushButtonPressedDarkHighlight, 0, 0 }, /* 91 */ - { "ButtonPressedLightShadow", kThemeBrushButtonPressedLightShadow, 0, 0 }, /* 92 */ - { "ButtonPressedLightHighlight", kThemeBrushButtonPressedLightHighlight, 0, 0 }, /* 93 */ - { "BevelActiveLight", kThemeBrushBevelActiveLight, 0, 0 }, /* 94 */ - { "BevelActiveDark", kThemeBrushBevelActiveDark, 0, 0 }, /* 95 */ - { "BevelInactiveLight", kThemeBrushBevelInactiveLight, 0, 0 }, /* 96 */ - { "BevelInactiveDark", kThemeBrushBevelInactiveDark, 0, 0 }, /* 97 */ - { "NotificationWindowBackground", kThemeBrushNotificationWindowBackground, 0, 0 }, /* 98 */ - { "MovableModalBackground", kThemeBrushMovableModalBackground, 0, 0 }, /* 99 */ - { "SheetBackgroundOpaque", kThemeBrushSheetBackgroundOpaque, 0, 0 }, /* 100 */ - { "DrawerBackground", kThemeBrushDrawerBackground, 0, 0 }, /* 101 */ - { "ToolbarBackground", kThemeBrushToolbarBackground, 0, 0 }, /* 102 */ - { "SheetBackgroundTransparent", kThemeBrushSheetBackgroundTransparent, 0, 0 }, /* 103 */ - { "MenuBackground", kThemeBrushMenuBackground, 0, 0 }, /* 104 */ - { "Pixel", 0, 0, 0 }, /* 105: PIXEL_MAGIC */ - { "MenuBackgroundSelected", kThemeBrushMenuBackgroundSelected, 0, 0 }, /* 106 */ - { "ListViewOddRowBackground", kThemeBrushListViewOddRowBackground, 0, 0 }, /* 107 */ - { "ListViewEvenRowBackground", kThemeBrushListViewEvenRowBackground, 0, 0 }, /* 108 */ - { "ListViewColumnDivider", kThemeBrushListViewColumnDivider, 0, 0 }, /* 109 */ - { "BlackText", 0, kThemeTextColorBlack, 0 }, /* 110 */ - { "DialogActiveText", 0, kThemeTextColorDialogActive, 0 }, /* 111 */ - { "DialogInactiveText", 0, kThemeTextColorDialogInactive, 0 }, /* 112 */ - { "AlertActiveText", 0, kThemeTextColorAlertActive, 0 }, /* 113 */ - { "AlertInactiveText", 0, kThemeTextColorAlertInactive, 0 }, /* 114 */ - { "ModelessDialogActiveText", 0, kThemeTextColorModelessDialogActive, 0 }, /* 115 */ - { "ModelessDialogInactiveText", 0, kThemeTextColorModelessDialogInactive, 0 }, /* 116 */ - { "WindowHeaderActiveText", 0, kThemeTextColorWindowHeaderActive, 0 }, /* 117 */ - { "WindowHeaderInactiveText", 0, kThemeTextColorWindowHeaderInactive, 0 }, /* 118 */ - { "PlacardActiveText", 0, kThemeTextColorPlacardActive, 0 }, /* 119 */ - { "PlacardInactiveText", 0, kThemeTextColorPlacardInactive, 0 }, /* 120 */ - { "PlacardPressedText", 0, kThemeTextColorPlacardPressed, 0 }, /* 121 */ - { "PushButtonActiveText", 0, kThemeTextColorPushButtonActive, 0 }, /* 122 */ - { "PushButtonInactiveText", 0, kThemeTextColorPushButtonInactive, 0 }, /* 123 */ - { "PushButtonPressedText", 0, kThemeTextColorPushButtonPressed, 0 }, /* 124 */ - { "BevelButtonActiveText", 0, kThemeTextColorBevelButtonActive, 0 }, /* 125 */ - { "BevelButtonInactiveText", 0, kThemeTextColorBevelButtonInactive, 0 }, /* 126 */ - { "BevelButtonPressedText", 0, kThemeTextColorBevelButtonPressed, 0 }, /* 127 */ - { "PopupButtonActiveText", 0, kThemeTextColorPopupButtonActive, 0 }, /* 128 */ - { "PopupButtonInactiveText", 0, kThemeTextColorPopupButtonInactive, 0 }, /* 129 */ - { "PopupButtonPressedText", 0, kThemeTextColorPopupButtonPressed, 0 }, /* 130 */ - { "IconLabelText", 0, kThemeTextColorIconLabel, 0 }, /* 131 */ - { "ListViewText", 0, kThemeTextColorListView, 0 }, /* 132 */ - { "DocumentWindowTitleActiveText", 0, kThemeTextColorDocumentWindowTitleActive, 0 }, /* 133 */ - { "DocumentWindowTitleInactiveText", 0, kThemeTextColorDocumentWindowTitleInactive, 0 }, /* 134 */ - { "MovableModalWindowTitleActiveText", 0, kThemeTextColorMovableModalWindowTitleActive, 0 }, /* 135 */ - { "MovableModalWindowTitleInactiveText",0, kThemeTextColorMovableModalWindowTitleInactive, 0 }, /* 136 */ - { "UtilityWindowTitleActiveText", 0, kThemeTextColorUtilityWindowTitleActive, 0 }, /* 137 */ - { "UtilityWindowTitleInactiveText", 0, kThemeTextColorUtilityWindowTitleInactive, 0 }, /* 138 */ - { "PopupWindowTitleActiveText", 0, kThemeTextColorPopupWindowTitleActive, 0 }, /* 139 */ - { "PopupWindowTitleInactiveText", 0, kThemeTextColorPopupWindowTitleInactive, 0 }, /* 140 */ - { "RootMenuActiveText", 0, kThemeTextColorRootMenuActive, 0 }, /* 141 */ - { "RootMenuSelectedText", 0, kThemeTextColorRootMenuSelected, 0 }, /* 142 */ - { "RootMenuDisabledText", 0, kThemeTextColorRootMenuDisabled, 0 }, /* 143 */ - { "MenuItemActiveText", 0, kThemeTextColorMenuItemActive, 0 }, /* 144 */ - { "MenuItemSelectedText", 0, kThemeTextColorMenuItemSelected, 0 }, /* 145 */ - { "MenuItemDisabledText", 0, kThemeTextColorMenuItemDisabled, 0 }, /* 146 */ - { "PopupLabelActiveText", 0, kThemeTextColorPopupLabelActive, 0 }, /* 147 */ - { "PopupLabelInactiveText", 0, kThemeTextColorPopupLabelInactive, 0 }, /* 148 */ - { "TabFrontActiveText", 0, kThemeTextColorTabFrontActive, 0 }, /* 149 */ - { "TabNonFrontActiveText", 0, kThemeTextColorTabNonFrontActive, 0 }, /* 150 */ - { "TabNonFrontPressedText", 0, kThemeTextColorTabNonFrontPressed, 0 }, /* 151 */ - { "TabFrontInactiveText", 0, kThemeTextColorTabFrontInactive, 0 }, /* 152 */ - { "TabNonFrontInactiveText", 0, kThemeTextColorTabNonFrontInactive, 0 }, /* 153 */ - { "IconLabelSelectedText", 0, kThemeTextColorIconLabelSelected, 0 }, /* 154 */ - { "BevelButtonStickyActiveText", 0, kThemeTextColorBevelButtonStickyActive, 0 }, /* 155 */ - { "BevelButtonStickyInactiveText", 0, kThemeTextColorBevelButtonStickyInactive, 0 }, /* 156 */ - { "NotificationText", 0, kThemeTextColorNotification, 0 }, /* 157 */ - { "SystemDetailText", 0, kThemeTextColorSystemDetail, 0 }, /* 158 */ - { "WhiteText", 0, kThemeTextColorWhite, 0 }, /* 159 */ - { "TabPaneBackground", 0, 0, kThemeBackgroundTabPane }, /* 160 */ - { "PlacardBackground", 0, 0, kThemeBackgroundPlacard }, /* 161 */ - { "WindowHeaderBackground", 0, 0, kThemeBackgroundWindowHeader }, /* 162 */ - { "ListViewWindowHeaderBackground", 0, 0, kThemeBackgroundListViewWindowHeader }, /* 163 */ - { "SecondaryGroupBoxBackground", 0, 0, kThemeBackgroundSecondaryGroupBox }, /* 164 */ - { "MetalBackground", 0, 0, kThemeBackgroundMetal }, /* 165 */ - { NULL, 0, 0, 0 } + { "Transparent", 0, 0, 0, 0 }, /* 30: TRANSPARENT_PIXEL */ + { "Highlight", kThemeBrushPrimaryHighlightColor, 0, 0, 0 }, /* 31: HIGHLIGHT_PIXEL */ + { "HighlightSecondary", kThemeBrushSecondaryHighlightColor, 0, 0, 0 }, /* 32: HIGHLIGHT_SECONDARY_PIXEL */ + { "HighlightText", kThemeBrushBlack, 0, 0, 0 }, /* 33: HIGHLIGHT_TEXT_PIXEL */ + { "HighlightAlternate", kThemeBrushAlternatePrimaryHighlightColor, 0, 0, 0 }, /* 34: HIGHLIGHT_ALTERNATE_PIXEL */ + { "ButtonText", 0, kThemeTextColorPushButtonActive, 0, 0 }, /* 35: CONTROL_TEXT_PIXEL */ + { "PrimaryHighlightColor", kThemeBrushPrimaryHighlightColor, 0, 0, 0 }, /* 36 */ + { "ButtonFace", kThemeBrushButtonFaceActive, 0, 0, 0 }, /* 37: CONTROL_BODY_PIXEL */ + { "SecondaryHighlightColor", kThemeBrushSecondaryHighlightColor, 0, 0, 0 }, /* 38 */ + { "ButtonFrame", kThemeBrushButtonFrameActive, 0, 0, 0 }, /* 39: CONTROL_FRAME_PIXEL */ + { "AlternatePrimaryHighlightColor", kThemeBrushAlternatePrimaryHighlightColor, 0, 0, 0 }, /* 40 */ + { "WindowBody", kThemeBrushDocumentWindowBackground, 0, 0, 0 }, /* 41: WINDOW_BODY_PIXEL */ + { "SheetBackground", kThemeBrushSheetBackground, 0, 0, 0 }, /* 42 */ + { "MenuActive", kThemeBrushMenuBackgroundSelected, 0, 0, 0 }, /* 43: MENU_ACTIVE_PIXEL */ + { "Black", kThemeBrushBlack, 0, 0, 0 }, /* 44 */ + { "MenuActiveText", 0, kThemeTextColorMenuItemSelected, 0, 0 }, /* 45: MENU_ACTIVE_TEXT_PIXEL */ + { "White", kThemeBrushWhite, 0, 0, 0 }, /* 46 */ + { "Menu", kThemeBrushMenuBackground, 0, 0, 0 }, /* 47: MENU_BACKGROUND_PIXEL */ + { "DialogBackgroundActive", kThemeBrushDialogBackgroundActive, 0, 0, 0 }, /* 48 */ + { "MenuDisabled", 0, kThemeTextColorMenuItemDisabled, 0, 0 }, /* 49: MENU_DISABLED_PIXEL */ + { "DialogBackgroundInactive", kThemeBrushDialogBackgroundInactive, 0, 0, 0 }, /* 50 */ + { "MenuText", 0, kThemeTextColorMenuItemActive, 0, 0 }, /* 51: MENU_TEXT_PIXEL */ + { "AppearanceColor", 0, 0, 0, 0 }, /* 52: APPEARANCE_PIXEL */ + { "AlertBackgroundActive", kThemeBrushAlertBackgroundActive, 0, 0, 0 }, /* 53 */ + { "AlertBackgroundInactive", kThemeBrushAlertBackgroundInactive, 0, 0, 0 }, /* 54 */ + { "ModelessDialogBackgroundActive", kThemeBrushModelessDialogBackgroundActive, 0, 0, 0 }, /* 55 */ + { "ModelessDialogBackgroundInactive", kThemeBrushModelessDialogBackgroundInactive, 0, 0, 0 }, /* 56 */ + { "UtilityWindowBackgroundActive", kThemeBrushUtilityWindowBackgroundActive, 0, 0, 0 }, /* 57 */ + { "UtilityWindowBackgroundInactive", kThemeBrushUtilityWindowBackgroundInactive, 0, 0, 0 }, /* 58 */ + { "ListViewSortColumnBackground", kThemeBrushListViewSortColumnBackground, 0, 0, 0 }, /* 59 */ + { "ListViewBackground", kThemeBrushListViewBackground, 0, 0, 0 }, /* 60 */ + { "IconLabelBackground", kThemeBrushIconLabelBackground, 0, 0, 0 }, /* 61 */ + { "ListViewSeparator", kThemeBrushListViewSeparator, 0, 0, 0 }, /* 62 */ + { "ChasingArrows", kThemeBrushChasingArrows, 0, 0, 0 }, /* 63 */ + { "DragHilite", kThemeBrushDragHilite, 0, 0, 0 }, /* 64 */ + { "DocumentWindowBackground", kThemeBrushDocumentWindowBackground, 0, 0, 0 }, /* 65 */ + { "FinderWindowBackground", kThemeBrushFinderWindowBackground, 0, 0, 0 }, /* 66 */ + { "ScrollBarDelimiterActive", kThemeBrushScrollBarDelimiterActive, 0, 0, 0 }, /* 67 */ + { "ScrollBarDelimiterInactive", kThemeBrushScrollBarDelimiterInactive, 0, 0, 0 }, /* 68 */ + { "FocusHighlight", kThemeBrushFocusHighlight, 0, 0, 0 }, /* 69 */ + { "PopupArrowActive", kThemeBrushPopupArrowActive, 0, 0, 0 }, /* 70 */ + { "PopupArrowPressed", kThemeBrushPopupArrowPressed, 0, 0, 0 }, /* 71 */ + { "PopupArrowInactive", kThemeBrushPopupArrowInactive, 0, 0, 0 }, /* 72 */ + { "AppleGuideCoachmark", kThemeBrushAppleGuideCoachmark, 0, 0, 0 }, /* 73 */ + { "IconLabelBackgroundSelected", kThemeBrushIconLabelBackgroundSelected, 0, 0, 0 }, /* 74 */ + { "StaticAreaFill", kThemeBrushStaticAreaFill, 0, 0, 0 }, /* 75 */ + { "ActiveAreaFill", kThemeBrushActiveAreaFill, 0, 0, 0 }, /* 76 */ + { "ButtonFrameActive", kThemeBrushButtonFrameActive, 0, 0, 0 }, /* 77 */ + { "ButtonFrameInactive", kThemeBrushButtonFrameInactive, 0, 0, 0 }, /* 78 */ + { "ButtonFaceActive", kThemeBrushButtonFaceActive, 0, 0, 0 }, /* 79 */ + { "ButtonFaceInactive", kThemeBrushButtonFaceInactive, 0, 0, 0 }, /* 80 */ + { "ButtonFacePressed", kThemeBrushButtonFacePressed, 0, 0, 0 }, /* 81 */ + { "ButtonActiveDarkShadow", kThemeBrushButtonActiveDarkShadow, 0, 0, 0 }, /* 82 */ + { "ButtonActiveDarkHighlight", kThemeBrushButtonActiveDarkHighlight, 0, 0, 0 }, /* 83 */ + { "ButtonActiveLightShadow", kThemeBrushButtonActiveLightShadow, 0, 0, 0 }, /* 84 */ + { "ButtonActiveLightHighlight", kThemeBrushButtonActiveLightHighlight, 0, 0, 0 }, /* 85 */ + { "ButtonInactiveDarkShadow", kThemeBrushButtonInactiveDarkShadow, 0, 0, 0 }, /* 86 */ + { "ButtonInactiveDarkHighlight", kThemeBrushButtonInactiveDarkHighlight, 0, 0, 0 }, /* 87 */ + { "ButtonInactiveLightShadow", kThemeBrushButtonInactiveLightShadow, 0, 0, 0 }, /* 88 */ + { "ButtonInactiveLightHighlight", kThemeBrushButtonInactiveLightHighlight, 0, 0, 0 }, /* 89 */ + { "ButtonPressedDarkShadow", kThemeBrushButtonPressedDarkShadow, 0, 0, 0 }, /* 90 */ + { "ButtonPressedDarkHighlight", kThemeBrushButtonPressedDarkHighlight, 0, 0, 0 }, /* 91 */ + { "ButtonPressedLightShadow", kThemeBrushButtonPressedLightShadow, 0, 0, 0 }, /* 92 */ + { "ButtonPressedLightHighlight", kThemeBrushButtonPressedLightHighlight, 0, 0, 0 }, /* 93 */ + { "BevelActiveLight", kThemeBrushBevelActiveLight, 0, 0, 0 }, /* 94 */ + { "BevelActiveDark", kThemeBrushBevelActiveDark, 0, 0, 0 }, /* 95 */ + { "BevelInactiveLight", kThemeBrushBevelInactiveLight, 0, 0, 0 }, /* 96 */ + { "BevelInactiveDark", kThemeBrushBevelInactiveDark, 0, 0, 0 }, /* 97 */ + { "NotificationWindowBackground", kThemeBrushNotificationWindowBackground, 0, 0, 0 }, /* 98 */ + { "MovableModalBackground", kThemeBrushMovableModalBackground, 0, 0, 0 }, /* 99 */ + { "SheetBackgroundOpaque", kThemeBrushSheetBackgroundOpaque, 0, 0, 0 }, /* 100 */ + { "DrawerBackground", kThemeBrushDrawerBackground, 0, 0, 0 }, /* 101 */ + { "ToolbarBackground", kThemeBrushToolbarBackground, 0, 0, 0 }, /* 102 */ + { "SheetBackgroundTransparent", kThemeBrushSheetBackgroundTransparent, 0, 0, 0 }, /* 103 */ + { "MenuBackground", kThemeBrushMenuBackground, 0, 0, 0 }, /* 104 */ + { "Pixel", 0, 0, 0, 0 }, /* 105: PIXEL_MAGIC */ + { "MenuBackgroundSelected", kThemeBrushMenuBackgroundSelected, 0, 0, 0 }, /* 106 */ + { "ListViewOddRowBackground", kThemeBrushListViewOddRowBackground, 0, 0, 0 }, /* 107 */ + { "ListViewEvenRowBackground", kThemeBrushListViewEvenRowBackground, 0, 0, 0 }, /* 108 */ + { "ListViewColumnDivider", kThemeBrushListViewColumnDivider, 0, 0, 0 }, /* 109 */ + { "BlackText", 0, kThemeTextColorBlack, 0, 0 }, /* 110 */ + { "DialogActiveText", 0, kThemeTextColorDialogActive, 0, 0 }, /* 111 */ + { "DialogInactiveText", 0, kThemeTextColorDialogInactive, 0, 0 }, /* 112 */ + { "AlertActiveText", 0, kThemeTextColorAlertActive, 0, 0 }, /* 113 */ + { "AlertInactiveText", 0, kThemeTextColorAlertInactive, 0, 0 }, /* 114 */ + { "ModelessDialogActiveText", 0, kThemeTextColorModelessDialogActive, 0, 0 }, /* 115 */ + { "ModelessDialogInactiveText", 0, kThemeTextColorModelessDialogInactive, 0, 0 }, /* 116 */ + { "WindowHeaderActiveText", 0, kThemeTextColorWindowHeaderActive, 0, 0 }, /* 117 */ + { "WindowHeaderInactiveText", 0, kThemeTextColorWindowHeaderInactive, 0, 0 }, /* 118 */ + { "PlacardActiveText", 0, kThemeTextColorPlacardActive, 0, 0 }, /* 119 */ + { "PlacardInactiveText", 0, kThemeTextColorPlacardInactive, 0, 0 }, /* 120 */ + { "PlacardPressedText", 0, kThemeTextColorPlacardPressed, 0, 0 }, /* 121 */ + { "PushButtonActiveText", 0, kThemeTextColorPushButtonActive, 0, 0 }, /* 122 */ + { "PushButtonInactiveText", 0, kThemeTextColorPushButtonInactive, 0, 0 }, /* 123 */ + { "PushButtonPressedText", 0, kThemeTextColorPushButtonPressed, 0, 0 }, /* 124 */ + { "BevelButtonActiveText", 0, kThemeTextColorBevelButtonActive, 0, 0 }, /* 125 */ + { "BevelButtonInactiveText", 0, kThemeTextColorBevelButtonInactive, 0, 0 }, /* 126 */ + { "BevelButtonPressedText", 0, kThemeTextColorBevelButtonPressed, 0, 0 }, /* 127 */ + { "PopupButtonActiveText", 0, kThemeTextColorPopupButtonActive, 0, 0 }, /* 128 */ + { "PopupButtonInactiveText", 0, kThemeTextColorPopupButtonInactive, 0, 0 }, /* 129 */ + { "PopupButtonPressedText", 0, kThemeTextColorPopupButtonPressed, 0, 0 }, /* 130 */ + { "IconLabelText", 0, kThemeTextColorIconLabel, 0, 0 }, /* 131 */ + { "ListViewText", 0, kThemeTextColorListView, 0, 0 }, /* 132 */ + { "DocumentWindowTitleActiveText", 0, kThemeTextColorDocumentWindowTitleActive, 0, 0 }, /* 133 */ + { "DocumentWindowTitleInactiveText", 0, kThemeTextColorDocumentWindowTitleInactive, 0, 0 }, /* 134 */ + { "MovableModalWindowTitleActiveText", 0, kThemeTextColorMovableModalWindowTitleActive, 0, 0 }, /* 135 */ + { "MovableModalWindowTitleInactiveText",0, kThemeTextColorMovableModalWindowTitleInactive, 0, 0 }, /* 136 */ + { "UtilityWindowTitleActiveText", 0, kThemeTextColorUtilityWindowTitleActive, 0, 0 }, /* 137 */ + { "UtilityWindowTitleInactiveText", 0, kThemeTextColorUtilityWindowTitleInactive, 0, 0 }, /* 138 */ + { "PopupWindowTitleActiveText", 0, kThemeTextColorPopupWindowTitleActive, 0, 0 }, /* 139 */ + { "PopupWindowTitleInactiveText", 0, kThemeTextColorPopupWindowTitleInactive, 0, 0 }, /* 140 */ + { "RootMenuActiveText", 0, kThemeTextColorRootMenuActive, 0, 0 }, /* 141 */ + { "RootMenuSelectedText", 0, kThemeTextColorRootMenuSelected, 0, 0 }, /* 142 */ + { "RootMenuDisabledText", 0, kThemeTextColorRootMenuDisabled, 0, 0 }, /* 143 */ + { "MenuItemActiveText", 0, kThemeTextColorMenuItemActive, 0, 0 }, /* 144 */ + { "MenuItemSelectedText", 0, kThemeTextColorMenuItemSelected, 0, 0 }, /* 145 */ + { "MenuItemDisabledText", 0, kThemeTextColorMenuItemDisabled, 0, 0 }, /* 146 */ + { "PopupLabelActiveText", 0, kThemeTextColorPopupLabelActive, 0, 0 }, /* 147 */ + { "PopupLabelInactiveText", 0, kThemeTextColorPopupLabelInactive, 0, 0 }, /* 148 */ + { "TabFrontActiveText", 0, kThemeTextColorTabFrontActive, 0, 0 }, /* 149 */ + { "TabNonFrontActiveText", 0, kThemeTextColorTabNonFrontActive, 0, 0 }, /* 150 */ + { "TabNonFrontPressedText", 0, kThemeTextColorTabNonFrontPressed, 0, 0 }, /* 151 */ + { "TabFrontInactiveText", 0, kThemeTextColorTabFrontInactive, 0, 0 }, /* 152 */ + { "TabNonFrontInactiveText", 0, kThemeTextColorTabNonFrontInactive, 0, 0 }, /* 153 */ + { "IconLabelSelectedText", 0, kThemeTextColorIconLabelSelected, 0, 0 }, /* 154 */ + { "BevelButtonStickyActiveText", 0, kThemeTextColorBevelButtonStickyActive, 0, 0 }, /* 155 */ + { "BevelButtonStickyInactiveText", 0, kThemeTextColorBevelButtonStickyInactive, 0, 0 }, /* 156 */ + { "NotificationText", 0, kThemeTextColorNotification, 0, 0 }, /* 157 */ + { "SystemDetailText", 0, kThemeTextColorSystemDetail, 0, 0 }, /* 158 */ + { "WhiteText", 0, kThemeTextColorWhite, 0, 0 }, /* 159 */ + { "TabPaneBackground", 0, 0, kThemeBackgroundTabPane, 0 }, /* 160 */ + { "PlacardBackground", 0, 0, kThemeBackgroundPlacard, 0 }, /* 161 */ + { "WindowHeaderBackground", 0, 0, kThemeBackgroundWindowHeader, 0 }, /* 162 */ + { "ListViewWindowHeaderBackground", 0, 0, kThemeBackgroundListViewWindowHeader, 0 }, /* 163 */ + { "SecondaryGroupBoxBackground", 0, 0, kThemeBackgroundSecondaryGroupBox, 0 }, /* 164 */ + { "MetalBackground", 0, 0, kThemeBackgroundMetal, 0 }, /* 165 */ + { "TtkBackground", kThemeBrushModelessDialogBackgroundActive, 0, 0, 0 }, /* 166 */ + { "TtkBackground1", 0, 0, 0, 1 }, /* 167 */ + { "TtkBackground2", 0, 0, 0, 2 }, /* 168 */ + { "TtkBackground3", 0, 0, 0, 3 }, /* 169 */ + { "TtkBackground4", 0, 0, 0, 4 }, /* 170 */ + { "TtkBackground5", 0, 0, 0, 5 }, /* 171 */ + { "TtkBackground6", 0, 0, 0, 6 }, /* 172 */ + { "TtkBackground7", 0, 0, 0, 7 }, /* 173 */ + { NULL, 0, 0, 0, 0 } }; -#define MAX_PIXELCODE 165 +#define MAX_PIXELCODE 173 /* *---------------------------------------------------------------------- @@ -193,21 +202,19 @@ static const struct SystemColorMapEntry systemColorMap[] = { static int GetThemeFromPixelCode( unsigned char code, - ThemeBrush *brush, - ThemeTextColor *textColor, - ThemeBackgroundKind *background) + struct SystemColorMapEntry *entry) { + bool zeroEntry = false; if (code >= MIN_PIXELCODE && code <= MAX_PIXELCODE) { - *brush = systemColorMap[code - MIN_PIXELCODE].brush; - *textColor = systemColorMap[code - MIN_PIXELCODE].textColor; - *background = systemColorMap[code - MIN_PIXELCODE].background; + *entry = systemColorMap[code - MIN_PIXELCODE]; } else { - *brush = 0; - *textColor = 0; - *background = 0; + entry->brush=0; + entry->textColor=0; + entry->background=0; + entry->depth=0; + zeroEntry = true; } - if (!*brush && !*textColor && !*background && code != PIXEL_MAGIC && - code != TRANSPARENT_PIXEL) { + if (zeroEntry && code != PIXEL_MAGIC && code != TRANSPARENT_PIXEL) { return false; } else { return true; @@ -233,39 +240,44 @@ GetThemeFromPixelCode( static OSStatus GetThemeColor( unsigned long pixel, - ThemeBrush brush, - ThemeTextColor textColor, - ThemeBackgroundKind background, + struct SystemColorMapEntry entry, CGColorRef *c) { OSStatus err = noErr; + static double RB1 = 0.8897365196078432; + static double G1 = 0.8936734068627451; + static double DELTA = 0.031495098039215685; - if (brush) { - err = ChkErr(HIThemeBrushCreateCGColor, brush, c); + if (entry.brush) { + err = ChkErr(HIThemeBrushCreateCGColor, entry.brush, c); /*} else if (textColor) { err = ChkErr(GetThemeTextColor, textColor, 32, true, c);*/ } else { CGFloat rgba[4] = {0, 0, 0, 1}; - - switch ((pixel >> 24) & 0xff) { - case PIXEL_MAGIC: { - unsigned short red, green, blue; - red = (pixel >> 16) & 0xff; - green = (pixel >> 8) & 0xff; - blue = (pixel ) & 0xff; - red |= red << 8; - green |= green << 8; - blue |= blue << 8; - rgba[0] = red / 65535.0; - rgba[1] = green / 65535.0; - rgba[2] = blue / 65535.0; - break; + if (entry.depth) { + rgba[0] = RB1 - DELTA*(entry.depth - 1); + rgba[1] = G1 - DELTA*(entry.depth - 1); + rgba[2] = RB1 - DELTA*(entry.depth - 1); + } else { + switch ((pixel >> 24) & 0xff) { + case PIXEL_MAGIC: { + unsigned short red, green, blue; + red = (pixel >> 16) & 0xff; + green = (pixel >> 8) & 0xff; + blue = (pixel ) & 0xff; + red |= red << 8; + green |= green << 8; + blue |= blue << 8; + rgba[0] = red / 65535.0; + rgba[1] = green / 65535.0; + rgba[2] = blue / 65535.0; + break; + } + case TRANSPARENT_PIXEL: + rgba[3] = 0.0; + break; } - case TRANSPARENT_PIXEL: - rgba[3] = 0.0; - break; } - static CGColorSpaceRef deviceRGBSpace = NULL; if (!deviceRGBSpace) { deviceRGBSpace = CGColorSpaceCreateDeviceRGB(); @@ -299,14 +311,10 @@ TkSetMacColor( { CGColorRef *color = (CGColorRef*)macColor; OSStatus err = -1; - ThemeBrush brush; - ThemeTextColor textColor; - ThemeBackgroundKind background; + struct SystemColorMapEntry entry; - if (GetThemeFromPixelCode((pixel >> 24) & 0xff, &brush, &textColor, - &background)) { - err = ChkErr(GetThemeColor, pixel, brush, textColor, background, - color); + if (GetThemeFromPixelCode((pixel >> 24) & 0xff, &entry)) { + err = ChkErr(GetThemeColor, pixel, entry, color); } return (err == noErr); } @@ -486,26 +494,23 @@ TkMacOSXSetColorInContext( { OSStatus err = -1; CGColorRef cgColor = CopyCachedColor(gc, pixel); - ThemeBrush brush; - ThemeTextColor textColor; - ThemeBackgroundKind background; + struct SystemColorMapEntry entry; - if (!cgColor && GetThemeFromPixelCode((pixel >> 24) & 0xff, &brush, - &textColor, &background)) { - if (brush) { - err = ChkErr(HIThemeSetFill, brush, NULL, context, + if (!cgColor && GetThemeFromPixelCode((pixel >> 24) & 0xff, &entry)) { + if (entry.brush) { + err = ChkErr(HIThemeSetFill, entry.brush, NULL, context, kHIThemeOrientationNormal); if (err == noErr) { - err = ChkErr(HIThemeSetStroke, brush, NULL, context, + err = ChkErr(HIThemeSetStroke, entry.brush, NULL, context, kHIThemeOrientationNormal); } - } else if (textColor) { - err = ChkErr(HIThemeSetTextFill, textColor, NULL, context, + } else if (entry.textColor) { + err = ChkErr(HIThemeSetTextFill, entry.textColor, NULL, context, kHIThemeOrientationNormal); - } else if (background) { + } else if (entry.background) { CGRect rect = CGContextGetClipBoundingBox(context); HIThemeBackgroundDrawInfo info = { 0, kThemeStateActive, - background }; + entry.background }; err = ChkErr(HIThemeApplyBackground, &rect, &info, context, kHIThemeOrientationNormal); @@ -513,8 +518,7 @@ TkMacOSXSetColorInContext( if (err == noErr) { return; } - err = ChkErr(GetThemeColor, pixel, brush, textColor, background, - &cgColor); + err = ChkErr(GetThemeColor, pixel, entry, &cgColor); if (err == noErr) { SetCachedColor(gc, pixel, cgColor); } @@ -572,11 +576,9 @@ TkpGetColor( OSStatus err; CGColorRef c; unsigned char pixelCode = idx + MIN_PIXELCODE; - ThemeBrush brush = systemColorMap[idx].brush; - ThemeTextColor textColor = systemColorMap[idx].textColor; - ThemeBackgroundKind background = systemColorMap[idx].background; + struct SystemColorMapEntry entry = systemColorMap[idx]; - err = ChkErr(GetThemeColor, 0, brush, textColor, background, &c); + err = ChkErr(GetThemeColor, 0, entry, &c); if (err == noErr) { const size_t n = CGColorGetNumberOfComponents(c); const CGFloat *rgba = CGColorGetComponents(c); diff --git a/macosx/tkMacOSXInt.h b/macosx/tkMacOSXInt.h index d942286..a137724 100644 --- a/macosx/tkMacOSXInt.h +++ b/macosx/tkMacOSXInt.h @@ -86,6 +86,7 @@ typedef struct TkWindowPrivate MacDrawable; #define TK_IS_PIXMAP 0x10 #define TK_IS_BW_PIXMAP 0x20 #define TK_DO_NOT_DRAW 0x40 +#define TTK_HAS_DARKER_BG 0x80 /* * I am reserving TK_EMBEDDED = 0x100 in the MacDrawable flags diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index f9611c5..68ff87c 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -32,15 +32,15 @@ #include "tkMacOSXPrivate.h" #include "ttk/ttkTheme.h" - +#include /* * Use this version in the core: */ #define BEGIN_DRAWING(d) { \ - TkMacOSXDrawingContext dc; \ - if (!TkMacOSXSetupDrawingContext((d), NULL, 1, &dc)) {return;} + TkMacOSXDrawingContext dc; \ + if (!TkMacOSXSetupDrawingContext((d), NULL, 1, &dc)) {return;} #define END_DRAWING \ - TkMacOSXRestoreDrawingContext(&dc); } + TkMacOSXRestoreDrawingContext(&dc); } #define HIOrientation kHIThemeOrientationNormal @@ -56,8 +56,8 @@ /* * BoxToRect -- - * Convert a Ttk_Box in Tk coordinates relative to the given Drawable - * to a native Rect relative to the containing port. + * Convert a Ttk_Box in Tk coordinates relative to the given Drawable + * to a native Rect relative to the containing port. */ static inline CGRect BoxToRect(Drawable d, Ttk_Box b) { @@ -135,10 +135,10 @@ static Ttk_StateTable ButtonAdornmentTable[] = { /* * computeButtonDrawInfo -- - * Fill in an appearance manager HIThemeButtonDrawInfo record. + * Fill in an appearance manager HIThemeButtonDrawInfo record. */ static inline HIThemeButtonDrawInfo computeButtonDrawInfo( - ThemeButtonParams *params, Ttk_State state) + ThemeButtonParams *params, Ttk_State state) { const HIThemeButtonDrawInfo info = { .version = 0, @@ -317,7 +317,6 @@ static void TabElementDraw( .kind = kHIThemeTabKindNormal, .position = Ttk_StateTableLookup(TabPositionTable, state), }; - BEGIN_DRAWING(d) ChkErr(HIThemeDrawTab, &bounds, &info, dc.context, HIOrientation, NULL); END_DRAWING @@ -345,6 +344,7 @@ static void PaneElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) { + TkWindow *winPtr = (TkWindow *)tkwin; CGRect bounds = BoxToRect(d, b); HIThemeTabPaneDrawInfo info = { .version = 1, @@ -354,12 +354,14 @@ static void PaneElementDraw( .kind = kHIThemeTabKindNormal, .adornment = kHIThemeTabPaneAdornmentNormal, }; - bounds.origin.y -= kThemeMetricTabFrameOverlap; bounds.size.height += kThemeMetricTabFrameOverlap; BEGIN_DRAWING(d) ChkErr(HIThemeDrawTabPane, &bounds, &info, dc.context, HIOrientation); END_DRAWING + if (winPtr->privatePtr != NULL) { + winPtr->privatePtr->flags |= TTK_HAS_DARKER_BG; + } } static Ttk_ElementSpec PaneElementSpec = { @@ -391,16 +393,19 @@ static void GroupElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) { + TkWindow *winPtr = (TkWindow *)tkwin; CGRect bounds = BoxToRect(d, b); const HIThemeGroupBoxDrawInfo info = { .version = 0, .state = Ttk_StateTableLookup(ThemeStateTable, state), - .kind = kHIThemeGroupBoxKindPrimaryOpaque, + .kind = kHIThemeGroupBoxKindPrimary, }; - BEGIN_DRAWING(d) ChkErr(HIThemeDrawGroupBox, &bounds, &info, dc.context, HIOrientation); END_DRAWING + if (winPtr->privatePtr != NULL) { + winPtr->privatePtr->flags |= TTK_HAS_DARKER_BG; + } } static Ttk_ElementSpec GroupElementSpec = { @@ -413,8 +418,8 @@ static Ttk_ElementSpec GroupElementSpec = { /*---------------------------------------------------------------------- * +++ Entry element -- - * 3 pixels padding for focus rectangle - * 2 pixels padding for EditTextFrame + * 3 pixels padding for focus rectangle + * 2 pixels padding for EditTextFrame */ typedef struct { @@ -476,8 +481,8 @@ static Ttk_ElementSpec EntryElementSpec = { * +++ Combobox: * * NOTES: - * kThemeMetricComboBoxLargeDisclosureWidth -> 17 - * Padding and margins guesstimated by trial-and-error. + * kThemeMetricComboBoxLargeDisclosureWidth -> 17 + * Padding and margins guesstimated by trial-and-error. */ static Ttk_Padding ComboboxPadding = { 2, 3, 17, 1 }; @@ -525,9 +530,9 @@ static Ttk_ElementSpec ComboboxElementSpec = { /*---------------------------------------------------------------------- * +++ Spinbuttons. * - * From Apple HIG, part III, section "Controls", "The Stepper Control": - * there should be 2 pixels of space between the stepper control - * (AKA IncDecButton, AKA "little arrows") and the text field it modifies. + * From Apple HIG, part III, section "Controls", "The Stepper Control": + * there should be 2 pixels of space between the stepper control (AKA + * IncDecButton, AKA "little arrows") and the text field it modifies. */ static Ttk_Padding SpinbuttonMargins = {2,0,2,0}; @@ -575,7 +580,7 @@ static Ttk_ElementSpec SpinButtonElementSpec = { /*---------------------------------------------------------------------- * +++ DrawThemeTrack-based elements -- - * Progress bars and scales. (See also: <>) + * Progress bars and scales. (See also: <>) */ static Ttk_StateTable ThemeTrackEnableTable[] = { @@ -780,9 +785,9 @@ static Ttk_ElementSpec PbarElementSpec = { /*---------------------------------------------------------------------- * +++ Separator element. * - * DrawThemeSeparator() guesses the orientation of the line from - * the width and height of the rectangle, so the same element can - * can be used for horizontal, vertical, and general separators. + * DrawThemeSeparator() guesses the orientation of the line from the width + * and height of the rectangle, so the same element can can be used for + * horizontal, vertical, and general separators. */ static void SeparatorElementSize( @@ -870,28 +875,89 @@ static Ttk_ElementSpec SizegripElementSpec = { /*---------------------------------------------------------------------- * +++ Background and fill elements. * - * This isn't quite right: In Aqua, the correct background for - * a control depends on what kind of container it belongs to, - * and the type of the top-level window. + * Before drawing any ttk widget, its bounding rectangle is filled with a + * background color. This color must match the background color of the + * containing widget to avoid looking ugly. The need for care when doing + * this is exacerbated by the fact that ttk enforces its "native look" by + * not allowing user control of the background or highlight colors of ttk + * widgets. + * + * The first attempt at implementing this attempted to match colors by + * drawing all widgets with the system background color used for dialog + * windows. (In particular, ttk widgets were meant for use in windows like + * those in the Apple preferences application.) The code chose either the + * active background or the inactive background based on the ttk state. + * (Note that current OS releases use the same color #ebebeb in both + * states.) * - * Also: patterned backgrounds should be aligned with the coordinate - * system of the top-level window. If we're drawing into an - * off-screen graphics port this leads to alignment glitches. + * Unfortunately, there is a problem with this approach. The Appkit + * GroupBox (used for ttk LabelFrames) and TabbedPane (used for the Notebook + * widget) both place their content inside a rectangle with rounded corners + * which is darker than 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. In this case the inner widget uses an even + * darker rounded rectangle. In Mojave's preferences panes, these darker + * gray colors appear to be #e3e4e3 and #dbdcdb respectively. The first of + * these is close but not quite equal to the system color + * BackgroundSecondary GroupBox, which appears to be #e3e3e3. The HITheme + * library, which we use to draw these widgets, uses #e2e3e3, which again is + * slightly different. Since none of these quite match, we use a hardwired + * RGB color which matches that used by HITheme. + * + * Patterned backgrounds, which are now obsolete, should be aligned with the + * coordinate system of the top-level window. Apparently failing to do this + * used to cause graphics anomalies when drawing into an off-screen graphics + * port. The code for handling this is currently commented out. */ static void FillElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) { + TkWindow *winPtr = (TkWindow *)tkwin; CGRect bounds = BoxToRect(d, b); - ThemeBrush brush = (state & TTK_STATE_BACKGROUND) + ThemeBrush brush; + static double RB1 = 0.8897365196078432; + static double G1 = 0.8936734068627451; + static double DELTA = 0.031495098039215685; + int depth = 0; + for (TkWindow *topPtr = winPtr->parentPtr; topPtr != NULL; + topPtr = topPtr->parentPtr) { + if (topPtr->privatePtr && + (topPtr->privatePtr->flags & TTK_HAS_DARKER_BG)) { + depth++; + } else { + Tk_Uid className = Tk_Class(topPtr); + if (className) { + if ((strcmp(className, "TLabelFrame") == 0) || + (strcmp(className, "TNotebook") == 0)) { + depth++; + } + } + } + } + BEGIN_DRAWING(d) + switch(depth) { + case 0: + brush = (state & TTK_STATE_BACKGROUND) ? kThemeBrushModelessDialogBackgroundInactive : kThemeBrushModelessDialogBackgroundActive; - - BEGIN_DRAWING(d) - ChkErr(HIThemeSetFill, brush, NULL, dc.context, HIOrientation); - //QDSetPatternOrigin(PatternOrigin(tkwin, d)); + ChkErr(HIThemeSetFill, brush, NULL, dc.context, HIOrientation); + break; + case 1: + CGContextSetRGBFillColor(dc.context, RB1, G1, RB1, 1.0); + break; + default: + /* Really, you should not be nesting this deeply ... */ + CGContextSetRGBFillColor(dc.context, + RB1 - DELTA*(depth - 1), + G1 - DELTA*(depth - 1), + RB1 - DELTA*(depth - 1), 1.0); + break; + } CGContextFillRect(dc.context, bounds); + //QDSetPatternOrigin(PatternOrigin(tkwin, d)); END_DRAWING } @@ -899,9 +965,8 @@ static void BackgroundElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, unsigned int state) { - FillElementDraw( - clientData, elementRecord, tkwin, - d, Ttk_WinBox(tkwin), state); + FillElementDraw(clientData, elementRecord, tkwin, d, Ttk_WinBox(tkwin), + state); } static Ttk_ElementSpec FillElementSpec = { @@ -923,14 +988,14 @@ static Ttk_ElementSpec BackgroundElementSpec = { /*---------------------------------------------------------------------- * +++ ToolbarBackground element -- toolbar style for frames. * - * This is very similar to the normal background element, but uses a - * different ThemeBrush in order to get the lighter pinstripe effect - * used in toolbars. We use SetThemeBackground() rather than - * ApplyThemeBackground() in order to get the right style. + * This is very similar to the normal background element, but uses a + * different ThemeBrush in order to get the lighter pinstripe effect + * used in toolbars. We use SetThemeBackground() rather than + * ApplyThemeBackground() in order to get the right style. * * + * Appearance_Manager/appearance_manager/constant_7.html#/ + * /apple_ref/doc/uid/TP30000243/C005321> * */ static void ToolbarBackgroundElementDraw( @@ -957,7 +1022,7 @@ static Ttk_ElementSpec ToolbarBackgroundElementSpec = { /*---------------------------------------------------------------------- * +++ Treeview header - * Redefine the header to use a kThemeListHeaderButton. + * Redefine the header to use a kThemeListHeaderButton. */ #define TTK_TREEVIEW_STATE_SORTARROW TTK_STATE_USER1 -- cgit v0.12 From 998ef733dd784bdbf4a50349cd74ea26e30cbe5a Mon Sep 17 00:00:00 2001 From: culler Date: Mon, 25 Feb 2019 02:19:14 +0000 Subject: Remove some unneeded code. --- macosx/ttkMacOSXTheme.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index 68ff87c..b9599e5 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -927,14 +927,6 @@ static void FillElementDraw( if (topPtr->privatePtr && (topPtr->privatePtr->flags & TTK_HAS_DARKER_BG)) { depth++; - } else { - Tk_Uid className = Tk_Class(topPtr); - if (className) { - if ((strcmp(className, "TLabelFrame") == 0) || - (strcmp(className, "TNotebook") == 0)) { - depth++; - } - } } } BEGIN_DRAWING(d) -- cgit v0.12 From fd087b19f442d4ea569093b1e9f2a308bb93bade Mon Sep 17 00:00:00 2001 From: culler Date: Wed, 27 Feb 2019 06:31:30 +0000 Subject: Cleaned up the code in tkMacOSXColors.c. Discovered along the way that we can partially support Dark Mode for ttk widgets. --- library/ttk/aquaTheme.tcl | 15 +- macosx/tkMacOSXColor.c | 530 +++++++++++++++++++++++++--------------------- macosx/tkMacOSXInt.h | 1 + macosx/tkMacOSXPort.h | 38 ++-- macosx/ttkMacOSXTheme.c | 58 ++--- 5 files changed, 350 insertions(+), 292 deletions(-) diff --git a/library/ttk/aquaTheme.tcl b/library/ttk/aquaTheme.tcl index a548d65..3d5c4d0 100644 --- a/library/ttk/aquaTheme.tcl +++ b/library/ttk/aquaTheme.tcl @@ -8,18 +8,18 @@ namespace eval ttk::theme::aqua { ttk::style configure . \ -font TkDefaultFont \ -background systemWindowBody \ - -foreground systemModelessDialogActiveText \ + -foreground systemTtkForeground \ -selectbackground systemHighlight \ - -selectforeground systemModelessDialogActiveText \ + -selectforeground systemTtkForeground \ -selectborderwidth 0 \ -insertwidth 1 ttk::style map . \ - -foreground {disabled systemModelessDialogInactiveText - background systemModelessDialogInactiveText} \ + -foreground {disabled systemTtkForeground + background systemTtkForeground} \ -selectbackground {background systemHighlightSecondary !focus systemHighlightSecondary} \ - -selectforeground {background systemModelessDialogInactiveText + -selectforeground {background systemTtkForeground !focus systemDialogActiveText} # Workaround for #1100117: @@ -28,6 +28,7 @@ namespace eval ttk::theme::aqua { ttk::style configure . -stipple {} ttk::style configure TButton -anchor center -width -6 + ttk::style configure Toolbutton -padding 4 ttk::style configure TNotebook -tabmargins {10 0} -tabposition n @@ -44,8 +45,8 @@ namespace eval ttk::theme::aqua { -background [list disabled systemDialogBackgroundInactive \ {selected background} systemHighlightSecondary \ selected systemHighlight] \ - -foreground [list disabled systemModelessDialogInactiveText \ - selected systemModelessDialogActiveText] + -foreground [list disabled black \ + selected black] # Enable animation for ttk::progressbar widget: ttk::style configure TProgressbar -period 100 -maxphase 255 diff --git a/macosx/tkMacOSXColor.c b/macosx/tkMacOSXColor.c index b90fae3..e382892 100644 --- a/macosx/tkMacOSXColor.c +++ b/macosx/tkMacOSXColor.c @@ -17,12 +17,32 @@ #include "tkMacOSXPrivate.h" #include "tkColor.h" +/* + * 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 ttkForeground types are dynamic, meaning + * that they change when dark mode is enabled on OSX 10.13 and later. + */ + +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.*/ + ttkForeground, /* The value can be used as a parameter.*/ +}; + +/* + + */ + struct SystemColorMapEntry { const char *name; - ThemeBrush brush; - ThemeTextColor textColor; - ThemeBackgroundKind background; - int depth; + enum colorType type; + unsigned long value; }; /* unsigned char pixelCode; */ /* @@ -33,165 +53,164 @@ struct SystemColorMapEntry { #define MIN_PIXELCODE 30 static const struct SystemColorMapEntry systemColorMap[] = { - { "Transparent", 0, 0, 0, 0 }, /* 30: TRANSPARENT_PIXEL */ - { "Highlight", kThemeBrushPrimaryHighlightColor, 0, 0, 0 }, /* 31: HIGHLIGHT_PIXEL */ - { "HighlightSecondary", kThemeBrushSecondaryHighlightColor, 0, 0, 0 }, /* 32: HIGHLIGHT_SECONDARY_PIXEL */ - { "HighlightText", kThemeBrushBlack, 0, 0, 0 }, /* 33: HIGHLIGHT_TEXT_PIXEL */ - { "HighlightAlternate", kThemeBrushAlternatePrimaryHighlightColor, 0, 0, 0 }, /* 34: HIGHLIGHT_ALTERNATE_PIXEL */ - { "ButtonText", 0, kThemeTextColorPushButtonActive, 0, 0 }, /* 35: CONTROL_TEXT_PIXEL */ - { "PrimaryHighlightColor", kThemeBrushPrimaryHighlightColor, 0, 0, 0 }, /* 36 */ - { "ButtonFace", kThemeBrushButtonFaceActive, 0, 0, 0 }, /* 37: CONTROL_BODY_PIXEL */ - { "SecondaryHighlightColor", kThemeBrushSecondaryHighlightColor, 0, 0, 0 }, /* 38 */ - { "ButtonFrame", kThemeBrushButtonFrameActive, 0, 0, 0 }, /* 39: CONTROL_FRAME_PIXEL */ - { "AlternatePrimaryHighlightColor", kThemeBrushAlternatePrimaryHighlightColor, 0, 0, 0 }, /* 40 */ - { "WindowBody", kThemeBrushDocumentWindowBackground, 0, 0, 0 }, /* 41: WINDOW_BODY_PIXEL */ - { "SheetBackground", kThemeBrushSheetBackground, 0, 0, 0 }, /* 42 */ - { "MenuActive", kThemeBrushMenuBackgroundSelected, 0, 0, 0 }, /* 43: MENU_ACTIVE_PIXEL */ - { "Black", kThemeBrushBlack, 0, 0, 0 }, /* 44 */ - { "MenuActiveText", 0, kThemeTextColorMenuItemSelected, 0, 0 }, /* 45: MENU_ACTIVE_TEXT_PIXEL */ - { "White", kThemeBrushWhite, 0, 0, 0 }, /* 46 */ - { "Menu", kThemeBrushMenuBackground, 0, 0, 0 }, /* 47: MENU_BACKGROUND_PIXEL */ - { "DialogBackgroundActive", kThemeBrushDialogBackgroundActive, 0, 0, 0 }, /* 48 */ - { "MenuDisabled", 0, kThemeTextColorMenuItemDisabled, 0, 0 }, /* 49: MENU_DISABLED_PIXEL */ - { "DialogBackgroundInactive", kThemeBrushDialogBackgroundInactive, 0, 0, 0 }, /* 50 */ - { "MenuText", 0, kThemeTextColorMenuItemActive, 0, 0 }, /* 51: MENU_TEXT_PIXEL */ - { "AppearanceColor", 0, 0, 0, 0 }, /* 52: APPEARANCE_PIXEL */ - { "AlertBackgroundActive", kThemeBrushAlertBackgroundActive, 0, 0, 0 }, /* 53 */ - { "AlertBackgroundInactive", kThemeBrushAlertBackgroundInactive, 0, 0, 0 }, /* 54 */ - { "ModelessDialogBackgroundActive", kThemeBrushModelessDialogBackgroundActive, 0, 0, 0 }, /* 55 */ - { "ModelessDialogBackgroundInactive", kThemeBrushModelessDialogBackgroundInactive, 0, 0, 0 }, /* 56 */ - { "UtilityWindowBackgroundActive", kThemeBrushUtilityWindowBackgroundActive, 0, 0, 0 }, /* 57 */ - { "UtilityWindowBackgroundInactive", kThemeBrushUtilityWindowBackgroundInactive, 0, 0, 0 }, /* 58 */ - { "ListViewSortColumnBackground", kThemeBrushListViewSortColumnBackground, 0, 0, 0 }, /* 59 */ - { "ListViewBackground", kThemeBrushListViewBackground, 0, 0, 0 }, /* 60 */ - { "IconLabelBackground", kThemeBrushIconLabelBackground, 0, 0, 0 }, /* 61 */ - { "ListViewSeparator", kThemeBrushListViewSeparator, 0, 0, 0 }, /* 62 */ - { "ChasingArrows", kThemeBrushChasingArrows, 0, 0, 0 }, /* 63 */ - { "DragHilite", kThemeBrushDragHilite, 0, 0, 0 }, /* 64 */ - { "DocumentWindowBackground", kThemeBrushDocumentWindowBackground, 0, 0, 0 }, /* 65 */ - { "FinderWindowBackground", kThemeBrushFinderWindowBackground, 0, 0, 0 }, /* 66 */ - { "ScrollBarDelimiterActive", kThemeBrushScrollBarDelimiterActive, 0, 0, 0 }, /* 67 */ - { "ScrollBarDelimiterInactive", kThemeBrushScrollBarDelimiterInactive, 0, 0, 0 }, /* 68 */ - { "FocusHighlight", kThemeBrushFocusHighlight, 0, 0, 0 }, /* 69 */ - { "PopupArrowActive", kThemeBrushPopupArrowActive, 0, 0, 0 }, /* 70 */ - { "PopupArrowPressed", kThemeBrushPopupArrowPressed, 0, 0, 0 }, /* 71 */ - { "PopupArrowInactive", kThemeBrushPopupArrowInactive, 0, 0, 0 }, /* 72 */ - { "AppleGuideCoachmark", kThemeBrushAppleGuideCoachmark, 0, 0, 0 }, /* 73 */ - { "IconLabelBackgroundSelected", kThemeBrushIconLabelBackgroundSelected, 0, 0, 0 }, /* 74 */ - { "StaticAreaFill", kThemeBrushStaticAreaFill, 0, 0, 0 }, /* 75 */ - { "ActiveAreaFill", kThemeBrushActiveAreaFill, 0, 0, 0 }, /* 76 */ - { "ButtonFrameActive", kThemeBrushButtonFrameActive, 0, 0, 0 }, /* 77 */ - { "ButtonFrameInactive", kThemeBrushButtonFrameInactive, 0, 0, 0 }, /* 78 */ - { "ButtonFaceActive", kThemeBrushButtonFaceActive, 0, 0, 0 }, /* 79 */ - { "ButtonFaceInactive", kThemeBrushButtonFaceInactive, 0, 0, 0 }, /* 80 */ - { "ButtonFacePressed", kThemeBrushButtonFacePressed, 0, 0, 0 }, /* 81 */ - { "ButtonActiveDarkShadow", kThemeBrushButtonActiveDarkShadow, 0, 0, 0 }, /* 82 */ - { "ButtonActiveDarkHighlight", kThemeBrushButtonActiveDarkHighlight, 0, 0, 0 }, /* 83 */ - { "ButtonActiveLightShadow", kThemeBrushButtonActiveLightShadow, 0, 0, 0 }, /* 84 */ - { "ButtonActiveLightHighlight", kThemeBrushButtonActiveLightHighlight, 0, 0, 0 }, /* 85 */ - { "ButtonInactiveDarkShadow", kThemeBrushButtonInactiveDarkShadow, 0, 0, 0 }, /* 86 */ - { "ButtonInactiveDarkHighlight", kThemeBrushButtonInactiveDarkHighlight, 0, 0, 0 }, /* 87 */ - { "ButtonInactiveLightShadow", kThemeBrushButtonInactiveLightShadow, 0, 0, 0 }, /* 88 */ - { "ButtonInactiveLightHighlight", kThemeBrushButtonInactiveLightHighlight, 0, 0, 0 }, /* 89 */ - { "ButtonPressedDarkShadow", kThemeBrushButtonPressedDarkShadow, 0, 0, 0 }, /* 90 */ - { "ButtonPressedDarkHighlight", kThemeBrushButtonPressedDarkHighlight, 0, 0, 0 }, /* 91 */ - { "ButtonPressedLightShadow", kThemeBrushButtonPressedLightShadow, 0, 0, 0 }, /* 92 */ - { "ButtonPressedLightHighlight", kThemeBrushButtonPressedLightHighlight, 0, 0, 0 }, /* 93 */ - { "BevelActiveLight", kThemeBrushBevelActiveLight, 0, 0, 0 }, /* 94 */ - { "BevelActiveDark", kThemeBrushBevelActiveDark, 0, 0, 0 }, /* 95 */ - { "BevelInactiveLight", kThemeBrushBevelInactiveLight, 0, 0, 0 }, /* 96 */ - { "BevelInactiveDark", kThemeBrushBevelInactiveDark, 0, 0, 0 }, /* 97 */ - { "NotificationWindowBackground", kThemeBrushNotificationWindowBackground, 0, 0, 0 }, /* 98 */ - { "MovableModalBackground", kThemeBrushMovableModalBackground, 0, 0, 0 }, /* 99 */ - { "SheetBackgroundOpaque", kThemeBrushSheetBackgroundOpaque, 0, 0, 0 }, /* 100 */ - { "DrawerBackground", kThemeBrushDrawerBackground, 0, 0, 0 }, /* 101 */ - { "ToolbarBackground", kThemeBrushToolbarBackground, 0, 0, 0 }, /* 102 */ - { "SheetBackgroundTransparent", kThemeBrushSheetBackgroundTransparent, 0, 0, 0 }, /* 103 */ - { "MenuBackground", kThemeBrushMenuBackground, 0, 0, 0 }, /* 104 */ - { "Pixel", 0, 0, 0, 0 }, /* 105: PIXEL_MAGIC */ - { "MenuBackgroundSelected", kThemeBrushMenuBackgroundSelected, 0, 0, 0 }, /* 106 */ - { "ListViewOddRowBackground", kThemeBrushListViewOddRowBackground, 0, 0, 0 }, /* 107 */ - { "ListViewEvenRowBackground", kThemeBrushListViewEvenRowBackground, 0, 0, 0 }, /* 108 */ - { "ListViewColumnDivider", kThemeBrushListViewColumnDivider, 0, 0, 0 }, /* 109 */ - { "BlackText", 0, kThemeTextColorBlack, 0, 0 }, /* 110 */ - { "DialogActiveText", 0, kThemeTextColorDialogActive, 0, 0 }, /* 111 */ - { "DialogInactiveText", 0, kThemeTextColorDialogInactive, 0, 0 }, /* 112 */ - { "AlertActiveText", 0, kThemeTextColorAlertActive, 0, 0 }, /* 113 */ - { "AlertInactiveText", 0, kThemeTextColorAlertInactive, 0, 0 }, /* 114 */ - { "ModelessDialogActiveText", 0, kThemeTextColorModelessDialogActive, 0, 0 }, /* 115 */ - { "ModelessDialogInactiveText", 0, kThemeTextColorModelessDialogInactive, 0, 0 }, /* 116 */ - { "WindowHeaderActiveText", 0, kThemeTextColorWindowHeaderActive, 0, 0 }, /* 117 */ - { "WindowHeaderInactiveText", 0, kThemeTextColorWindowHeaderInactive, 0, 0 }, /* 118 */ - { "PlacardActiveText", 0, kThemeTextColorPlacardActive, 0, 0 }, /* 119 */ - { "PlacardInactiveText", 0, kThemeTextColorPlacardInactive, 0, 0 }, /* 120 */ - { "PlacardPressedText", 0, kThemeTextColorPlacardPressed, 0, 0 }, /* 121 */ - { "PushButtonActiveText", 0, kThemeTextColorPushButtonActive, 0, 0 }, /* 122 */ - { "PushButtonInactiveText", 0, kThemeTextColorPushButtonInactive, 0, 0 }, /* 123 */ - { "PushButtonPressedText", 0, kThemeTextColorPushButtonPressed, 0, 0 }, /* 124 */ - { "BevelButtonActiveText", 0, kThemeTextColorBevelButtonActive, 0, 0 }, /* 125 */ - { "BevelButtonInactiveText", 0, kThemeTextColorBevelButtonInactive, 0, 0 }, /* 126 */ - { "BevelButtonPressedText", 0, kThemeTextColorBevelButtonPressed, 0, 0 }, /* 127 */ - { "PopupButtonActiveText", 0, kThemeTextColorPopupButtonActive, 0, 0 }, /* 128 */ - { "PopupButtonInactiveText", 0, kThemeTextColorPopupButtonInactive, 0, 0 }, /* 129 */ - { "PopupButtonPressedText", 0, kThemeTextColorPopupButtonPressed, 0, 0 }, /* 130 */ - { "IconLabelText", 0, kThemeTextColorIconLabel, 0, 0 }, /* 131 */ - { "ListViewText", 0, kThemeTextColorListView, 0, 0 }, /* 132 */ - { "DocumentWindowTitleActiveText", 0, kThemeTextColorDocumentWindowTitleActive, 0, 0 }, /* 133 */ - { "DocumentWindowTitleInactiveText", 0, kThemeTextColorDocumentWindowTitleInactive, 0, 0 }, /* 134 */ - { "MovableModalWindowTitleActiveText", 0, kThemeTextColorMovableModalWindowTitleActive, 0, 0 }, /* 135 */ - { "MovableModalWindowTitleInactiveText",0, kThemeTextColorMovableModalWindowTitleInactive, 0, 0 }, /* 136 */ - { "UtilityWindowTitleActiveText", 0, kThemeTextColorUtilityWindowTitleActive, 0, 0 }, /* 137 */ - { "UtilityWindowTitleInactiveText", 0, kThemeTextColorUtilityWindowTitleInactive, 0, 0 }, /* 138 */ - { "PopupWindowTitleActiveText", 0, kThemeTextColorPopupWindowTitleActive, 0, 0 }, /* 139 */ - { "PopupWindowTitleInactiveText", 0, kThemeTextColorPopupWindowTitleInactive, 0, 0 }, /* 140 */ - { "RootMenuActiveText", 0, kThemeTextColorRootMenuActive, 0, 0 }, /* 141 */ - { "RootMenuSelectedText", 0, kThemeTextColorRootMenuSelected, 0, 0 }, /* 142 */ - { "RootMenuDisabledText", 0, kThemeTextColorRootMenuDisabled, 0, 0 }, /* 143 */ - { "MenuItemActiveText", 0, kThemeTextColorMenuItemActive, 0, 0 }, /* 144 */ - { "MenuItemSelectedText", 0, kThemeTextColorMenuItemSelected, 0, 0 }, /* 145 */ - { "MenuItemDisabledText", 0, kThemeTextColorMenuItemDisabled, 0, 0 }, /* 146 */ - { "PopupLabelActiveText", 0, kThemeTextColorPopupLabelActive, 0, 0 }, /* 147 */ - { "PopupLabelInactiveText", 0, kThemeTextColorPopupLabelInactive, 0, 0 }, /* 148 */ - { "TabFrontActiveText", 0, kThemeTextColorTabFrontActive, 0, 0 }, /* 149 */ - { "TabNonFrontActiveText", 0, kThemeTextColorTabNonFrontActive, 0, 0 }, /* 150 */ - { "TabNonFrontPressedText", 0, kThemeTextColorTabNonFrontPressed, 0, 0 }, /* 151 */ - { "TabFrontInactiveText", 0, kThemeTextColorTabFrontInactive, 0, 0 }, /* 152 */ - { "TabNonFrontInactiveText", 0, kThemeTextColorTabNonFrontInactive, 0, 0 }, /* 153 */ - { "IconLabelSelectedText", 0, kThemeTextColorIconLabelSelected, 0, 0 }, /* 154 */ - { "BevelButtonStickyActiveText", 0, kThemeTextColorBevelButtonStickyActive, 0, 0 }, /* 155 */ - { "BevelButtonStickyInactiveText", 0, kThemeTextColorBevelButtonStickyInactive, 0, 0 }, /* 156 */ - { "NotificationText", 0, kThemeTextColorNotification, 0, 0 }, /* 157 */ - { "SystemDetailText", 0, kThemeTextColorSystemDetail, 0, 0 }, /* 158 */ - { "WhiteText", 0, kThemeTextColorWhite, 0, 0 }, /* 159 */ - { "TabPaneBackground", 0, 0, kThemeBackgroundTabPane, 0 }, /* 160 */ - { "PlacardBackground", 0, 0, kThemeBackgroundPlacard, 0 }, /* 161 */ - { "WindowHeaderBackground", 0, 0, kThemeBackgroundWindowHeader, 0 }, /* 162 */ - { "ListViewWindowHeaderBackground", 0, 0, kThemeBackgroundListViewWindowHeader, 0 }, /* 163 */ - { "SecondaryGroupBoxBackground", 0, 0, kThemeBackgroundSecondaryGroupBox, 0 }, /* 164 */ - { "MetalBackground", 0, 0, kThemeBackgroundMetal, 0 }, /* 165 */ - { "TtkBackground", kThemeBrushModelessDialogBackgroundActive, 0, 0, 0 }, /* 166 */ - { "TtkBackground1", 0, 0, 0, 1 }, /* 167 */ - { "TtkBackground2", 0, 0, 0, 2 }, /* 168 */ - { "TtkBackground3", 0, 0, 0, 3 }, /* 169 */ - { "TtkBackground4", 0, 0, 0, 4 }, /* 170 */ - { "TtkBackground5", 0, 0, 0, 5 }, /* 171 */ - { "TtkBackground6", 0, 0, 0, 6 }, /* 172 */ - { "TtkBackground7", 0, 0, 0, 7 }, /* 173 */ - { NULL, 0, 0, 0, 0 } + { "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 */ + { "TtkBackground", HIBrush, kThemeBrushModelessDialogBackgroundActive }, /* 166 */ + { "TtkBackground1", ttkBackground, 1 }, /* 167 */ + { "TtkBackground2", ttkBackground, 2 }, /* 168 */ + { "TtkBackground3", ttkBackground, 3 }, /* 169 */ + { "TtkBackground4", ttkBackground, 4 }, /* 170 */ + { "TtkBackground5", ttkBackground, 5 }, /* 171 */ + { "TtkBackground6", ttkBackground, 6 }, /* 172 */ + { "TtkBackground7", ttkBackground, 7 }, /* 173 */ + { "TtkForeground", ttkForeground, 0 }, /* 174 */ + { NULL, 0, 0 } }; -#define MAX_PIXELCODE 173 +#define MAX_PIXELCODE 174 /* *---------------------------------------------------------------------- * - * GetThemeFromPixelCode -- + * GetEntryFromPixelCode -- * - * When given a pixel code corresponding to a theme system color, - * set one of brush, textColor or background to the corresponding - * Appearance Mgr theme constant. + * Extract a SystemColorMapEntry from the table. * * Results: - * Returns false if not a real pixel, true otherwise. + * Returns false if the code is out of bounds. * * Side effects: * None. @@ -199,34 +218,28 @@ static const struct SystemColorMapEntry systemColorMap[] = { *---------------------------------------------------------------------- */ -static int -GetThemeFromPixelCode( +static bool +GetEntryFromPixelCode( unsigned char code, struct SystemColorMapEntry *entry) { - bool zeroEntry = false; if (code >= MIN_PIXELCODE && code <= MAX_PIXELCODE) { *entry = systemColorMap[code - MIN_PIXELCODE]; + return true; } else { - entry->brush=0; - entry->textColor=0; - entry->background=0; - entry->depth=0; - zeroEntry = true; - } - if (zeroEntry && code != PIXEL_MAGIC && code != TRANSPARENT_PIXEL) { return false; - } else { - return true; } } /* *---------------------------------------------------------------------- * - * GetThemeColor -- + * SetCGColorComponents -- * - * Get RGB color for a given system color or pixel value. + * 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. * * Results: * OSStatus @@ -238,64 +251,101 @@ GetThemeFromPixelCode( */ static OSStatus -GetThemeColor( - unsigned long pixel, +SetCGColorComponents( struct SystemColorMapEntry entry, + unsigned long pixel, CGColorRef *c) { OSStatus err = noErr; - static double RB1 = 0.8897365196078432; - static double G1 = 0.8936734068627451; - static double DELTA = 0.031495098039215685; - - if (entry.brush) { - err = ChkErr(HIThemeBrushCreateCGColor, entry.brush, c); - /*} else if (textColor) { - err = ChkErr(GetThemeTextColor, textColor, 32, true, c);*/ - } else { - CGFloat rgba[4] = {0, 0, 0, 1}; - if (entry.depth) { - rgba[0] = RB1 - DELTA*(entry.depth - 1); - rgba[1] = G1 - DELTA*(entry.depth - 1); - rgba[2] = RB1 - DELTA*(entry.depth - 1); - } else { - switch ((pixel >> 24) & 0xff) { - case PIXEL_MAGIC: { - unsigned short red, green, blue; - red = (pixel >> 16) & 0xff; - green = (pixel >> 8) & 0xff; - blue = (pixel ) & 0xff; - red |= red << 8; - green |= green << 8; - blue |= blue << 8; - rgba[0] = red / 65535.0; - rgba[1] = green / 65535.0; - rgba[2] = blue / 65535.0; - break; - } - case TRANSPARENT_PIXEL: - rgba[3] = 0.0; - break; - } - } - static CGColorSpaceRef deviceRGBSpace = NULL; - if (!deviceRGBSpace) { - deviceRGBSpace = CGColorSpaceCreateDeviceRGB(); + NSColor *bgColor, *fgColor; + CGFloat rgba[4] = {0, 0, 0, 1}; + static CGColorSpaceRef deviceRGBSpace = NULL; + if (!deviceRGBSpace) { + deviceRGBSpace = CGColorSpaceCreateDeviceRGB(); + } + + switch (entry.type) { + case HIBrush: + err = ChkErr(HIThemeBrushCreateCGColor, entry.value, c); + break; + case rgbColor: + rgba[0] = ((pixel >> 16) & 0xff) / 255.0; + rgba[1] = ((pixel >> 8) & 0xff) / 255.0; + rgba[2] = ((pixel ) & 0xff) / 255.0; + break; + case ttkBackground: + bgColor = [[NSColor windowBackgroundColor] colorUsingColorSpace: + [NSColorSpace deviceRGBColorSpace]]; + [bgColor getComponents: rgba]; + for (int i=0; i<4; i++) { + rgba[i] -= entry.value*(8.0/255.0); } - *c = CGColorCreate(deviceRGBSpace, rgba ); + break; + case ttkForeground: + fgColor = [[NSColor labelColor] colorUsingColorSpace: + [NSColorSpace deviceRGBColorSpace]]; + [fgColor getComponents: rgba]; + break; + case clearColor: + rgba[3] = 0.0; + break; + + /* + * 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. + */ + + case HIText: + case HIBackground: + default: + break; } + *c = CGColorCreate(deviceRGBSpace, rgba ); return err; } /* *---------------------------------------------------------------------- * + * TkMacOSXInDarkMode -- + * + * Tests whether the given window's NSView has a DarkAqua Appearance. + * + * Results: + * Returns true if the NSView is in DarkMode, false if not. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +MODULE_SCOPE Bool +TkMacOSXInDarkMode(Tk_Window tkwin) { + TkWindow *winPtr = (TkWindow*)tkwin; + NSView *view = TkMacOSXDrawableView(winPtr->privatePtr); + if (view && [view.effectiveAppearance.name isEqualToString:NSAppearanceNameDarkAqua]) { + return True; + } else { + return false; + } +} + + +/* + *---------------------------------------------------------------------- + * * TkSetMacColor -- * - * Creates a CGColorRef from a X style pixel value. + * 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. * * Results: - * Returns false if not a real pixel, true otherwise. + * Returns false if the high order byte is not a valid index, true + * otherwise. * * Side effects: * The variable macColor is set to a new CGColorRef, the caller is @@ -313,8 +363,8 @@ TkSetMacColor( OSStatus err = -1; struct SystemColorMapEntry entry; - if (GetThemeFromPixelCode((pixel >> 24) & 0xff, &entry)) { - err = ChkErr(GetThemeColor, pixel, entry, color); + if (GetEntryFromPixelCode((pixel >> 24) & 0xff, &entry)) { + err = ChkErr(SetCGColorComponents, entry, pixel, color); } return (err == noErr); } @@ -492,44 +542,52 @@ TkMacOSXSetColorInContext( unsigned long pixel, CGContextRef context) { - OSStatus err = -1; + OSStatus err = noErr; CGColorRef cgColor = CopyCachedColor(gc, pixel); struct SystemColorMapEntry entry; + CGRect rect; + CGFloat rgba[4] = {0.0, 0.0, 0.0, 1.0}; + HIThemeBackgroundDrawInfo info = { 0, kThemeStateActive, entry.value }; + static CGColorSpaceRef deviceRGBSpace = NULL; + if (!deviceRGBSpace) { + deviceRGBSpace = CGColorSpaceCreateDeviceRGB(); + } - if (!cgColor && GetThemeFromPixelCode((pixel >> 24) & 0xff, &entry)) { - if (entry.brush) { - err = ChkErr(HIThemeSetFill, entry.brush, NULL, context, + if (!cgColor && GetEntryFromPixelCode((pixel >> 24) & 0xff, &entry)) { + switch (entry.type) { + case HIBrush: + err = ChkErr(HIThemeSetFill, entry.value, NULL, context, kHIThemeOrientationNormal); if (err == noErr) { - err = ChkErr(HIThemeSetStroke, entry.brush, NULL, context, + err = ChkErr(HIThemeSetStroke, entry.value, NULL, context, kHIThemeOrientationNormal); } - } else if (entry.textColor) { - err = ChkErr(HIThemeSetTextFill, entry.textColor, NULL, context, + break; + case HIText: + err = ChkErr(HIThemeSetTextFill, entry.value, NULL, context, kHIThemeOrientationNormal); - } else if (entry.background) { - CGRect rect = CGContextGetClipBoundingBox(context); - HIThemeBackgroundDrawInfo info = { 0, kThemeStateActive, - entry.background }; - + break; + case HIBackground: + rect = CGContextGetClipBoundingBox(context); err = ChkErr(HIThemeApplyBackground, &rect, &info, context, kHIThemeOrientationNormal); + break; + default: + err = ChkErr(SetCGColorComponents, entry, pixel, &cgColor); + if (err == noErr) { + SetCachedColor(gc, pixel, cgColor); + } + break; } - if (err == noErr) { - return; - } - err = ChkErr(GetThemeColor, pixel, entry, &cgColor); - if (err == noErr) { - SetCachedColor(gc, pixel, cgColor); - } - } else if (!cgColor) { - TkMacOSXDbgMsg("Ignored unknown pixel value 0x%lx", pixel); } if (cgColor) { CGContextSetFillColorWithColor(context, cgColor); CGContextSetStrokeColorWithColor(context, cgColor); CGColorRelease(cgColor); } + if (err != noErr) { + TkMacOSXDbgMsg("Ignored unknown pixel value 0x%lx", pixel); + } } /* @@ -553,7 +611,7 @@ TkMacOSXSetColorInContext( TkColor * TkpGetColor( Tk_Window tkwin, /* Window in which color will be used. */ - Tk_Uid name) /* Name of color to allocated (in form + Tk_Uid name) /* Name of color to be allocated (in form * suitable for passing to XParseColor). */ { Display *display = tkwin != None ? Tk_Display(tkwin) : NULL; @@ -578,7 +636,7 @@ TkpGetColor( unsigned char pixelCode = idx + MIN_PIXELCODE; struct SystemColorMapEntry entry = systemColorMap[idx]; - err = ChkErr(GetThemeColor, 0, entry, &c); + err = ChkErr(SetCGColorComponents, entry, 0, &c); if (err == noErr) { const size_t n = CGColorGetNumberOfComponents(c); const CGFloat *rgba = CGColorGetComponents(c); diff --git a/macosx/tkMacOSXInt.h b/macosx/tkMacOSXInt.h index a137724..ce79498 100644 --- a/macosx/tkMacOSXInt.h +++ b/macosx/tkMacOSXInt.h @@ -202,6 +202,7 @@ MODULE_SCOPE void TkpShiftButton(NSButton *button, NSPoint delta); MODULE_SCOPE Bool TkpAppIsDrawing(void); MODULE_SCOPE void TkpDisplayWindow(Tk_Window tkwin); MODULE_SCOPE Bool TkTestAppIsDrawing(void); +MODULE_SCOPE Bool TkMacOSXInDarkMode(Tk_Window tkwin); /* * Include the stubbed internal platform-specific API. diff --git a/macosx/tkMacOSXPort.h b/macosx/tkMacOSXPort.h index bd48bd5..617abda 100644 --- a/macosx/tkMacOSXPort.h +++ b/macosx/tkMacOSXPort.h @@ -128,17 +128,6 @@ #define TkpSync(display) /* - * The following macro returns the pixel value that corresponds to the - * RGB values in the given XColor structure. - */ - -#define PIXEL_MAGIC ((unsigned char) 0x69) -#define TkpGetPixel(p) ((((((PIXEL_MAGIC << 8) \ - | (((p)->red >> 8) & 0xff)) << 8) \ - | (((p)->green >> 8) & 0xff)) << 8) \ - | (((p)->blue >> 8) & 0xff)) - -/* * This macro stores a representation of the window handle in a string. */ @@ -159,19 +148,20 @@ */ #define TRANSPARENT_PIXEL 30 -#define HIGHLIGHT_PIXEL 31 -#define HIGHLIGHT_SECONDARY_PIXEL 32 -#define HIGHLIGHT_TEXT_PIXEL 33 -#define HIGHLIGHT_ALTERNATE_PIXEL 34 -#define CONTROL_TEXT_PIXEL 35 -#define CONTROL_BODY_PIXEL 37 -#define CONTROL_FRAME_PIXEL 39 -#define WINDOW_BODY_PIXEL 41 -#define MENU_ACTIVE_PIXEL 43 -#define MENU_ACTIVE_TEXT_PIXEL 45 -#define MENU_BACKGROUND_PIXEL 47 -#define MENU_DISABLED_PIXEL 49 -#define MENU_TEXT_PIXEL 51 #define APPEARANCE_PIXEL 52 +#define PIXEL_MAGIC ((unsigned char) 0x69) + +/* + * The following macro returns the pixel value that corresponds to the + * 16-bit RGB values in the given XColor structure. + * The format is: (PIXEL_MAGIC <<< 24) | (R << 16) | (G << 8) | B + * where each of R, G and B is the high order byte of a 16-bit component. + */ + +#define TkpGetPixel(p) ((((((PIXEL_MAGIC << 8) \ + | (((p)->red >> 8) & 0xff)) << 8) \ + | (((p)->green >> 8) & 0xff)) << 8) \ + | (((p)->blue >> 8) & 0xff)) + #endif /* _TKMACPORT */ diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index b9599e5..a5c0e64 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -204,11 +204,25 @@ static void ButtonElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) { + BEGIN_DRAWING(d) ThemeButtonParams *params = clientData; CGRect bounds = BoxToRect(d, Ttk_PadBox(b, ButtonMargins)); - const HIThemeButtonDrawInfo info = computeButtonDrawInfo(params, state); + HIThemeButtonDrawInfo info = computeButtonDrawInfo(params, state); + Tk_Uid className = Tk_Class(tkwin); - BEGIN_DRAWING(d) + /* + * HIToolbox does not support Dark Mode, and Apple says it never will. So + * the best we can do to approximate a Dark Mode button is to draw it in + * the inactive state. The color is not quite as dark as the gray that + * Apple uses for buttons in Dark Mode. But it isn't too far off. We + * don't have to worry about checkButtons and radioButtons. They look OK, + */ + + if (TkMacOSXInDarkMode(tkwin) && className && + strcmp(className, "TCheckbutton") != 0 && + strcmp(className, "TRadiobutton") != 0) { + info.state = kThemeStateInactive; + } ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); END_DRAWING } @@ -900,7 +914,7 @@ static Ttk_ElementSpec SizegripElementSpec = { * darker rounded rectangle. In Mojave's preferences panes, these darker * gray colors appear to be #e3e4e3 and #dbdcdb respectively. The first of * these is close but not quite equal to the system color - * BackgroundSecondary GroupBox, which appears to be #e3e3e3. The HITheme + * BackgroundSecondaryGroupBox, which appears to be #e3e3e3. The HITheme * library, which we use to draw these widgets, uses #e2e3e3, which again is * slightly different. Since none of these quite match, we use a hardwired * RGB color which matches that used by HITheme. @@ -917,37 +931,31 @@ static void FillElementDraw( { TkWindow *winPtr = (TkWindow *)tkwin; CGRect bounds = BoxToRect(d, b); - ThemeBrush brush; - static double RB1 = 0.8897365196078432; - static double G1 = 0.8936734068627451; - static double DELTA = 0.031495098039215685; int depth = 0; + NSColor *bgColor = [[NSColor windowBackgroundColor] colorUsingColorSpace: + [NSColorSpace deviceRGBColorSpace]]; + CGFloat rgba[4]; + BEGIN_DRAWING(d) for (TkWindow *topPtr = winPtr->parentPtr; topPtr != NULL; topPtr = topPtr->parentPtr) { if (topPtr->privatePtr && (topPtr->privatePtr->flags & TTK_HAS_DARKER_BG)) { depth++; } + if (depth > 7) { + break; + } } - BEGIN_DRAWING(d) - switch(depth) { - case 0: - brush = (state & TTK_STATE_BACKGROUND) - ? kThemeBrushModelessDialogBackgroundInactive - : kThemeBrushModelessDialogBackgroundActive; - ChkErr(HIThemeSetFill, brush, NULL, dc.context, HIOrientation); - break; - case 1: - CGContextSetRGBFillColor(dc.context, RB1, G1, RB1, 1.0); - break; - default: - /* Really, you should not be nesting this deeply ... */ - CGContextSetRGBFillColor(dc.context, - RB1 - DELTA*(depth - 1), - G1 - DELTA*(depth - 1), - RB1 - DELTA*(depth - 1), 1.0); - break; + + /* + * Darken the background color one step for each level of nesting. + */ + + [bgColor getComponents: rgba]; + for (int i=0; i<4; i++) { + rgba[i] -= depth*(8.0/255.0); } + CGContextSetRGBFillColor(dc.context, rgba[0], rgba[1], rgba[2], rgba[3]); CGContextFillRect(dc.context, bounds); //QDSetPatternOrigin(PatternOrigin(tkwin, d)); END_DRAWING -- cgit v0.12 From 8f55c5985d13b4b7857066df9cd2ac55f9dc14ef Mon Sep 17 00:00:00 2001 From: culler Date: Wed, 27 Feb 2019 23:22:36 +0000 Subject: Adding 1 character fixes two of the three crashes reported in ticket [1951abf33d] --- macosx/tkMacOSXWm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index 67d6ecb..31f745a 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -3646,7 +3646,7 @@ WmTransientCmd( Transient *transient = ckalloc(sizeof(Transient)); transient->winPtr = winPtr; transient->flags = 0; - transient->nextPtr = wmPtr->transientPtr; + transient->nextPtr = wmPtr2->transientPtr; wmPtr2->transientPtr = transient; /* -- cgit v0.12 From 33c0644d0f0db1639b351981459ed7a9e4d4270d Mon Sep 17 00:00:00 2001 From: culler Date: Thu, 28 Feb 2019 05:02:10 +0000 Subject: Make sure that we don't create cycles in the parent->child digraph even if there are cycles in the master->transient digraph. --- macosx/tkMacOSXWm.c | 62 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 23 deletions(-) diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index 31f745a..c8e0445 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -6793,6 +6793,7 @@ ApplyMasterOverrideChanges( int oldFlags = wmPtr->flags; unsigned long styleMask; NSRect structureRect; + NSWindow *parentWindow; if (!macWindow && winPtr->window != None && TkMacOSXHostToplevelExists(winPtr)) { @@ -6833,7 +6834,6 @@ ApplyMasterOverrideChanges( } } if (macWindow) { - NSWindow *parentWindow = [macWindow parentWindow]; structureRect = [NSWindow frameRectForContentRect:NSZeroRect styleMask:styleMask]; @@ -6873,35 +6873,51 @@ ApplyMasterOverrideChanges( Tk_IdToWindow(dispPtr->display, wmPtr->master); if (masterWinPtr && masterWinPtr->window != None && TkMacOSXHostToplevelExists(masterWinPtr)) { - NSWindow *masterMacWin = - TkMacOSXDrawableWindow(masterWinPtr->window); + NSWindow *masterMacWin = TkMacOSXDrawableWindow(masterWinPtr->window); + + /* + * Try to add the transient window as a child window of the + * master. A child NSWindow retains its relative position with + * respect to the parent when the parent is moved. This is + * pointless if the parent is offscreen, and adding a child to + * an offscreen window causes the parent to be displayed as a + * zombie. So we only do this if the parent is visible. + */ + + if (masterMacWin && + [masterMacWin isVisible] && + (winPtr->flags & TK_MAPPED)) { - if (masterMacWin && masterMacWin != parentWindow && - (winPtr->flags & TK_MAPPED)) { - if (parentWindow) { - [parentWindow removeChildWindow:macWindow]; - } - /* - * A child NSWindow retains its relative position with - * respect to the parent when the parent is moved. This is - * pointless if the parent is offscreen, and adding a child - * to an offscreen window causes the parent to be displayed - * as a zombie. So we should only do this if the parent is - * visible. + * If the transient is already a child of some other window, + * remove it. */ + + parentWindow = [macWindow parentWindow]; + if (parentWindow && parentWindow != masterMacWin) { + [parentWindow removeChildWindow:macWindow]; + } - if ([masterMacWin isVisible]) { - [masterMacWin addChildWindow:macWindow - ordered:NSWindowAbove]; + /* + * To avoid cycles, if the master is a child of some + other window, remove it. + */ + parentWindow = [masterMacWin parentWindow]; + if (parentWindow) { + [parentWindow removeChildWindow:masterMacWin]; } - if (wmPtr->flags & WM_TOPMOST) { - [macWindow setLevel:kCGUtilityWindowLevel]; + [masterMacWin addChildWindow:macWindow + ordered:NSWindowAbove]; } - } } - } else if (parentWindow) { - [parentWindow removeChildWindow:macWindow]; + } else { + parentWindow = [macWindow parentWindow]; + if (parentWindow) { + [parentWindow removeChildWindow:macWindow]; + } + } + if (wmPtr->flags & WM_TOPMOST) { + [macWindow setLevel:kCGUtilityWindowLevel]; } ApplyWindowAttributeFlagChanges(winPtr, macWindow, oldAttributes, oldFlags, 0, 0); -- cgit v0.12 From 25cab35e68932b15367a751414207d51a502e687 Mon Sep 17 00:00:00 2001 From: culler Date: Thu, 28 Feb 2019 06:18:53 +0000 Subject: Remove some bloat from tkMacOSXWm.c. --- generic/tkInt.decls | 2 +- generic/tkIntPlatDecls.h | 4 +- macosx/tkMacOSXWm.c | 98 +++++++++++++++++------------------------------- macosx/tkMacOSXWm.h | 6 +-- 4 files changed, 38 insertions(+), 72 deletions(-) diff --git a/generic/tkInt.decls b/generic/tkInt.decls index d0b7678..a3e1f98 100644 --- a/generic/tkInt.decls +++ b/generic/tkInt.decls @@ -1009,7 +1009,7 @@ declare 47 aqua { Tk_Window TkMacOSXGetCapture(void) } declare 49 aqua { - Window TkGetTransientMaster(TkWindow *winPtr) + Tk_Window TkGetTransientMaster(TkWindow *winPtr) } declare 50 aqua { int TkGenerateButtonEvent(int x, int y, Window window, unsigned int state) diff --git a/generic/tkIntPlatDecls.h b/generic/tkIntPlatDecls.h index ded5ac5..26a5f46 100644 --- a/generic/tkIntPlatDecls.h +++ b/generic/tkIntPlatDecls.h @@ -243,7 +243,7 @@ EXTERN int TkpIsWindowFloating(void *window); EXTERN Tk_Window TkMacOSXGetCapture(void); /* Slot 48 is reserved */ /* 49 */ -EXTERN Window TkGetTransientMaster(TkWindow *winPtr); +EXTERN Tk_Window TkGetTransientMaster(TkWindow *winPtr); /* 50 */ EXTERN int TkGenerateButtonEvent(int x, int y, Window window, unsigned int state); @@ -392,7 +392,7 @@ typedef struct TkIntPlatStubs { int (*tkpIsWindowFloating) (void *window); /* 46 */ Tk_Window (*tkMacOSXGetCapture) (void); /* 47 */ void (*reserved48)(void); - Window (*tkGetTransientMaster) (TkWindow *winPtr); /* 49 */ + Tk_Window (*tkGetTransientMaster) (TkWindow *winPtr); /* 49 */ int (*tkGenerateButtonEvent) (int x, int y, Window window, unsigned int state); /* 50 */ void (*tkGenWMDestroyEvent) (Tk_Window tkwin); /* 51 */ void (*tkMacOSXSetDrawingEnabled) (TkWindow *winPtr, int flag); /* 52 */ diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index c8e0445..ecb4456 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -669,7 +669,7 @@ TkWmNewWindow( wmPtr->reparent = None; wmPtr->titleUid = NULL; wmPtr->iconName = NULL; - wmPtr->master = None; + wmPtr->master = NULL; wmPtr->hints.flags = InputHint | StateHint; wmPtr->hints.input = True; wmPtr->hints.initial_state = NormalState; @@ -679,7 +679,6 @@ TkWmNewWindow( wmPtr->hints.icon_mask = None; wmPtr->hints.window_group = None; wmPtr->leaderName = NULL; - wmPtr->masterWindowName = NULL; wmPtr->icon = NULL; wmPtr->iconFor = NULL; wmPtr->transientPtr = NULL; @@ -884,18 +883,16 @@ TkWmDeadWindow( TkWindow *winPtr) /* Top-level window that's being deleted. */ { WmInfo *wmPtr = winPtr->wmInfoPtr, *wmPtr2; - TkDisplay *dispPtr = TkGetDisplayList(); if (wmPtr == NULL) { return; } - - /* + + /* *If the dead window is a transient, remove it from the master's list. */ RemoveTransient(winPtr); - Tk_ManageGeometry((Tk_Window) winPtr, NULL, NULL); Tk_DeleteEventHandler((Tk_Window) winPtr, StructureNotifyMask, TopLevelEventProc, winPtr); @@ -911,9 +908,6 @@ TkWmDeadWindow( if (wmPtr->leaderName != NULL) { ckfree(wmPtr->leaderName); } - if (wmPtr->masterWindowName != NULL) { - ckfree(wmPtr->masterWindowName); - } if (wmPtr->icon != NULL) { wmPtr2 = ((TkWindow *) wmPtr->icon)->wmInfoPtr; wmPtr2->iconFor = NULL; @@ -942,17 +936,14 @@ TkWmDeadWindow( * If the dead window has a transient, remove references to it from * the transient. */ - + for (Transient *transientPtr = wmPtr->transientPtr; transientPtr != NULL; transientPtr = transientPtr->nextPtr) { TkWindow *winPtr2 = transientPtr->winPtr; - Window master = TkGetTransientMaster(winPtr2); - TkWindow *masterPtr = (TkWindow *)Tk_IdToWindow(dispPtr->display, master); + TkWindow *masterPtr = (TkWindow *)TkGetTransientMaster(winPtr2); if (masterPtr == winPtr) { wmPtr2 = winPtr2->wmInfoPtr; - wmPtr2->master = None; - ckfree(wmPtr2->masterWindowName); - wmPtr2->masterWindowName = NULL; + wmPtr2->master = NULL; } } @@ -1791,7 +1782,6 @@ WmDeiconifyCmd( { register WmInfo *wmPtr = winPtr->wmInfoPtr; NSWindow *win = TkMacOSXDrawableWindow(winPtr->window); - TkDisplay *dispPtr = TkGetDisplayList(); if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "window"); @@ -1830,17 +1820,16 @@ WmDeiconifyCmd( transientPtr != NULL; transientPtr = transientPtr->nextPtr) { TkWindow *winPtr2 = transientPtr->winPtr; WmInfo *wmPtr2 = winPtr2->wmInfoPtr; - Window master = TkGetTransientMaster(winPtr2); - TkWindow *masterPtr = (TkWindow *)Tk_IdToWindow(dispPtr->display, master); + TkWindow *masterPtr = (TkWindow *)TkGetTransientMaster(winPtr2); if (masterPtr == winPtr) { - if (!(wmPtr2->hints.initial_state == WithdrawnState && - (transientPtr->flags & WITHDRAWN_BY_MASTER) == 0)) { + if ((wmPtr2->hints.initial_state == WithdrawnState && + (transientPtr->flags & WITHDRAWN_BY_MASTER) != 0)) { TkpWmSetState(winPtr2, NormalState); transientPtr->flags &= ~WITHDRAWN_BY_MASTER; } } } - + return TCL_OK; } @@ -2327,7 +2316,6 @@ WmIconifyCmd( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - TkDisplay *dispPtr = TkGetDisplayList(); register WmInfo *wmPtr = winPtr->wmInfoPtr; if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "window"); @@ -2341,7 +2329,7 @@ WmIconifyCmd( Tcl_SetErrorCode(interp, "TK", "WM", "ICONIFY", "OVERRIDE_REDIRECT", NULL); return TCL_ERROR; - } else if (wmPtr->master != None) { + } else if (wmPtr->master != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't iconify \"%s\": it is a transient", winPtr->pathName)); Tcl_SetErrorCode(interp, "TK", "WM", "ICONIFY", "TRANSIENT", NULL); @@ -2373,8 +2361,7 @@ WmIconifyCmd( for (Transient *transientPtr = wmPtr->transientPtr; transientPtr != NULL; transientPtr = transientPtr->nextPtr) { TkWindow *winPtr2 = transientPtr->winPtr; - Window master = TkGetTransientMaster(winPtr2); - TkWindow *masterPtr = (TkWindow *)Tk_IdToWindow(dispPtr->display, master); + TkWindow *masterPtr = (TkWindow *)TkGetTransientMaster(winPtr2); if (masterPtr == winPtr && winPtr2->wmInfoPtr->hints.initial_state != WithdrawnState) { TkpWmSetState(winPtr2, WithdrawnState); @@ -3466,7 +3453,7 @@ WmStateCmd( "OVERRIDE_REDIRECT", NULL); return TCL_ERROR; } - if (wmPtr->master != None) { + if (wmPtr->master != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't iconify \"%s\": it is a transient", winPtr->pathName)); @@ -3582,17 +3569,15 @@ WmTransientCmd( register WmInfo *wmPtr = winPtr->wmInfoPtr; Tk_Window master; WmInfo *wmPtr2; - char *masterWindowName; - int length; if ((objc != 3) && (objc != 4)) { Tcl_WrongNumArgs(interp, 2, objv, "window ?master?"); return TCL_ERROR; } if (objc == 3) { - if (wmPtr->master != None) { + if (wmPtr->master != NULL) { Tcl_SetObjResult(interp, - Tcl_NewStringObj(wmPtr->masterWindowName, -1)); + Tcl_NewStringObj(Tk_PathName(wmPtr->master), -1)); } return TCL_OK; } @@ -3648,7 +3633,7 @@ WmTransientCmd( transient->flags = 0; transient->nextPtr = wmPtr2->transientPtr; wmPtr2->transientPtr = transient; - + /* * If the master is withdrawn or iconic then withdraw the transient. */ @@ -3660,14 +3645,7 @@ WmTransientCmd( transient->flags |= WITHDRAWN_BY_MASTER; } - wmPtr->master = Tk_WindowId(masterPtr); - masterWindowName = masterPtr->pathName; - length = strlen(masterWindowName); - if (wmPtr->masterWindowName != NULL) { - ckfree(wmPtr->masterWindowName); - } - wmPtr->masterWindowName = ckalloc(length+1); - strcpy(wmPtr->masterWindowName, masterWindowName); + wmPtr->master = (Tk_Window)masterPtr; } ApplyMasterOverrideChanges(winPtr, NULL); return TCL_OK; @@ -3697,21 +3675,16 @@ RemoveTransient( TkWindow *winPtr) { WmInfo *wmPtr = winPtr->wmInfoPtr, *wmPtr2; - TkDisplay *dispPtr = TkGetDisplayList(); TkWindow *masterPtr; - if (wmPtr == NULL || wmPtr->master == None) { + if (wmPtr == NULL || wmPtr->master == NULL) { return; } - masterPtr = (TkWindow*)Tk_IdToWindow(dispPtr->display, wmPtr->master); + masterPtr = (TkWindow*)wmPtr->master; wmPtr2 = masterPtr->wmInfoPtr; if (wmPtr2 == NULL) { return; } - wmPtr->master = None; - if (wmPtr->masterWindowName != NULL) { - ckfree(wmPtr->masterWindowName); - } - wmPtr->masterWindowName = NULL; + wmPtr->master = NULL; Transient *temp, *cursor = wmPtr2->transientPtr; if (cursor->winPtr == winPtr) { temp = cursor->nextPtr; @@ -3769,9 +3742,8 @@ WmWithdrawCmd( } TkpWmSetState(winPtr, WithdrawnState); - + NSWindow *win = TkMacOSXDrawableWindow(winPtr->window); - TkDisplay *dispPtr = TkGetDisplayList(); [win orderOut:nil]; [win setExcludedFromWindowsMenu:YES]; @@ -3781,8 +3753,7 @@ WmWithdrawCmd( for (Transient *transientPtr = wmPtr->transientPtr; transientPtr != NULL; transientPtr = transientPtr->nextPtr) { TkWindow *winPtr2 = transientPtr->winPtr; - Window master = TkGetTransientMaster(winPtr2); - TkWindow *masterPtr = (TkWindow *)Tk_IdToWindow(dispPtr->display, master); + TkWindow *masterPtr = (TkWindow *)TkGetTransientMaster(winPtr2); if (masterPtr == winPtr && winPtr2->wmInfoPtr->hints.initial_state != WithdrawnState) { TkpWmSetState(winPtr2, WithdrawnState); @@ -5335,14 +5306,14 @@ TkSetWMName( *---------------------------------------------------------------------- */ -Window +Tk_Window TkGetTransientMaster( TkWindow *winPtr) { if (winPtr->wmInfoPtr != NULL) { - return winPtr->wmInfoPtr->master; + return (Tk_Window)winPtr->wmInfoPtr->master; } - return None; + return NULL; } /* @@ -6579,7 +6550,7 @@ TkMacOSXApplyWindowAttributes( { WmInfo *wmPtr = winPtr->wmInfoPtr; ApplyWindowAttributeFlagChanges(winPtr, macWindow, 0, 0, 0, 1); - if (wmPtr->master != None || winPtr->atts.override_redirect) { + if (wmPtr->master != NULL || winPtr->atts.override_redirect) { ApplyMasterOverrideChanges(winPtr, macWindow); } } @@ -6716,7 +6687,7 @@ ApplyWindowAttributeFlagChanges( */ if ((winPtr->atts.override_redirect) || - (wmPtr->master != None) || + (wmPtr->master != NULL) || (winPtr->wmInfoPtr->macClass == kHelpWindowClass)) { b |= (NSWindowCollectionBehaviorCanJoinAllSpaces | NSWindowCollectionBehaviorFullScreenAuxiliary); @@ -6852,7 +6823,7 @@ ApplyMasterOverrideChanges( if (wmPtr->hints.initial_state == NormalState) { [macWindow orderFront:nil]; } - if (wmPtr->master != None) { + if (wmPtr->master != NULL) { wmPtr->flags |= WM_TOPMOST; } else { wmPtr->flags &= ~WM_TOPMOST; @@ -6868,13 +6839,12 @@ ApplyMasterOverrideChanges( wmPtr->flags &= ~WM_TOPMOST; } if (wmPtr->master != None) { - TkDisplay *dispPtr = TkGetDisplayList(); - TkWindow *masterWinPtr = (TkWindow *) - Tk_IdToWindow(dispPtr->display, wmPtr->master); + TkWindow *masterWinPtr = (TkWindow *)wmPtr->master; if (masterWinPtr && masterWinPtr->window != None && TkMacOSXHostToplevelExists(masterWinPtr)) { - NSWindow *masterMacWin = TkMacOSXDrawableWindow(masterWinPtr->window); - + NSWindow *masterMacWin = TkMacOSXDrawableWindow( + masterWinPtr->window); + /* * Try to add the transient window as a child window of the * master. A child NSWindow retains its relative position with @@ -6892,13 +6862,13 @@ ApplyMasterOverrideChanges( * If the transient is already a child of some other window, * remove it. */ - + parentWindow = [macWindow parentWindow]; if (parentWindow && parentWindow != masterMacWin) { [parentWindow removeChildWindow:macWindow]; } - /* + /* * To avoid cycles, if the master is a child of some other window, remove it. */ diff --git a/macosx/tkMacOSXWm.h b/macosx/tkMacOSXWm.h index a7ea92c..5f07fe6 100644 --- a/macosx/tkMacOSXWm.h +++ b/macosx/tkMacOSXWm.h @@ -65,7 +65,7 @@ typedef struct TkWmInfo { Tk_Uid titleUid; /* Title to display in window caption. If NULL, * use name of widget. */ char *iconName; /* Name to display in icon. */ - Window master; /* Master window for TRANSIENT_FOR property, or + Tk_Window master; /* Master window for TRANSIENT_FOR property, or * None. */ XWMHints hints; /* Various pieces of information for window * manager. */ @@ -73,10 +73,6 @@ typedef struct TkWmInfo { * (corresponds to hints.window_group). * Malloc-ed. Note: this field doesn't get * updated if leader is destroyed. */ - char *masterWindowName; /* Path name of window specified as master in - * "wm transient" command, or NULL. Malloc-ed. - * Note: this field doesn't get updated if - * masterWindowName is destroyed. */ Tk_Window icon; /* Window to use as icon for this window, or * NULL. */ Tk_Window iconFor; /* Window for which this window is icon, or -- cgit v0.12 From 827393fdd0d40c400d800dbf3b042b48c8f3a692 Mon Sep 17 00:00:00 2001 From: culler Date: Thu, 28 Feb 2019 15:29:23 +0000 Subject: Fix bugs in the list management code for the record of transient windows. --- macosx/tkMacOSXWm.c | 51 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index ecb4456..599455d 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -3569,6 +3569,7 @@ WmTransientCmd( register WmInfo *wmPtr = winPtr->wmInfoPtr; Tk_Window master; WmInfo *wmPtr2; + Transient *transient; if ((objc != 3) && (objc != 4)) { Tcl_WrongNumArgs(interp, 2, objv, "window ?master?"); @@ -3625,14 +3626,19 @@ WmTransientCmd( } /* - * Add the transient to the master's list. + * Add the transient to the master's list, if it not already there. */ - - Transient *transient = ckalloc(sizeof(Transient)); - transient->winPtr = winPtr; - transient->flags = 0; - transient->nextPtr = wmPtr2->transientPtr; - wmPtr2->transientPtr = transient; + + for (transient = wmPtr2->transientPtr; + transient != NULL && transient->winPtr != winPtr; + transient = transient->nextPtr) {} + if (transient == NULL) { + transient = ckalloc(sizeof(Transient)); + transient->winPtr = winPtr; + transient->flags = 0; + transient->nextPtr = wmPtr2->transientPtr; + wmPtr2->transientPtr = transient; + } /* * If the master is withdrawn or iconic then withdraw the transient. @@ -3676,6 +3682,8 @@ RemoveTransient( { WmInfo *wmPtr = winPtr->wmInfoPtr, *wmPtr2; TkWindow *masterPtr; + Transient *T, *temp; + if (wmPtr == NULL || wmPtr->master == NULL) { return; } @@ -3685,18 +3693,23 @@ RemoveTransient( return; } wmPtr->master = NULL; - Transient *temp, *cursor = wmPtr2->transientPtr; - if (cursor->winPtr == winPtr) { - temp = cursor->nextPtr; - ckfree(cursor); - cursor = temp; - masterPtr->wmInfoPtr->transientPtr = cursor; - } - while (cursor != NULL) { - if (cursor->winPtr == winPtr) { - temp = cursor->nextPtr; - ckfree(cursor); - cursor = temp; + T = wmPtr2->transientPtr; + while (T != NULL) { + if (T->winPtr != winPtr) { + break; + } + temp = T->nextPtr; + ckfree(T); + T = temp; + } + wmPtr2->transientPtr = T; + while (T != NULL) { + if (T->nextPtr && T->nextPtr->winPtr == winPtr) { + temp = T->nextPtr; + T->nextPtr = temp->nextPtr; + ckfree(temp); + } else { + T = T->nextPtr; } } } -- cgit v0.12 From 7883dcdedb3af8454956e7599b139e350dbddfdf Mon Sep 17 00:00:00 2001 From: jaspert Date: Thu, 28 Feb 2019 15:52:15 +0000 Subject: Added a procedure to increase the number of digits in the tick values until the maximum rounding error goes below a certain value, currently 0.2x the tick interval. Also fixed it to work with scales from larger to smaller values. --- generic/tkScale.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/generic/tkScale.c b/generic/tkScale.c index 455c656..95cc399 100644 --- a/generic/tkScale.c +++ b/generic/tkScale.c @@ -759,6 +759,46 @@ ScaleWorldChanged( TkEventuallyRedrawScale(scalePtr, REDRAW_ALL); } + + + /* + *---------------------------------------------------------------------- + * + * MaxTickRoundingError -- + * + * Given the separation between values that can be displayed on ticks, + * this calculates the maximum magnitude of error for the displayed + * value. Tries to be clever by working out the increment in error + * between ticks rather than testing all of them, so may overestimate + * error if it is greater than 0.25 x the value separation. + * + * Results: + * Maximum error magnitude of tick numbers. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static double +MaxTickRoundingError( + TkScale *scalePtr, /* Information about scale widget. */ + double tickResolution) /* Separation between displayable values. */ +{ + double tickPosn, firstTickError, lastTickError, intervalError; + int tickCount; + + tickPosn = scalePtr->fromValue/tickResolution; + firstTickError = tickPosn - round(tickPosn); + tickPosn = scalePtr->tickInterval/tickResolution; + intervalError = tickPosn - round(tickPosn); + tickCount = (int)((scalePtr->toValue-scalePtr->fromValue) / + scalePtr->tickInterval); // not including first + lastTickError = fmin(fabs(firstTickError + tickCount*intervalError), 0.5); + return fmax(fabs(firstTickError),lastTickError)*tickResolution; +} + /* *---------------------------------------------------------------------- @@ -782,7 +822,7 @@ ComputeFormat( TkScale *scalePtr, /* Information about scale widget. */ int forTicks) /* Do for ticks rather than value */ { - double maxValue, x; + double maxValue, x, tickResolution; int mostSigDigit, numDigits, leastSigDigit, afterDecimal; int eDigits, fDigits; @@ -807,8 +847,16 @@ ComputeFormat( * values */ - if (scalePtr->tickInterval > 0) { - numDigits = 1 + mostSigDigit - (int) floor(log10(scalePtr->tickInterval)); + if (scalePtr->tickInterval != 0) { + leastSigDigit = (int) floor(log10(fabs(scalePtr->tickInterval))); + /* + * Now add more digits until max error is less than 0.2 intervals + */ + while (MaxTickRoundingError(scalePtr, pow(10,leastSigDigit)) > + fabs(0.2*scalePtr->tickInterval)) + --leastSigDigit; + + numDigits = 1 + mostSigDigit - leastSigDigit; } else { numDigits = 1; } -- cgit v0.12 From d7c4676109faa97abf627a58d578ba2c0a40c978 Mon Sep 17 00:00:00 2001 From: jaspert Date: Thu, 28 Feb 2019 16:37:23 +0000 Subject: Trimmed an unused variable --- generic/tkScale.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generic/tkScale.c b/generic/tkScale.c index 95cc399..5ed6618 100644 --- a/generic/tkScale.c +++ b/generic/tkScale.c @@ -822,7 +822,7 @@ ComputeFormat( TkScale *scalePtr, /* Information about scale widget. */ int forTicks) /* Do for ticks rather than value */ { - double maxValue, x, tickResolution; + double maxValue, x; int mostSigDigit, numDigits, leastSigDigit, afterDecimal; int eDigits, fDigits; -- cgit v0.12 From 403f01fa032b477c866cb88915f0604d9d9d0dac Mon Sep 17 00:00:00 2001 From: culler Date: Fri, 1 Mar 2019 15:28:48 +0000 Subject: Make it be an error to create a transient/master cycle on Aqua. Other platforms will be handled in separate check-ins. --- doc/wm.n | 29 +++++++++++++++-------------- macosx/tkMacOSXWm.c | 25 +++++++++++-------------- tests/wm.test | 14 ++++++++++++-- 3 files changed, 38 insertions(+), 30 deletions(-) diff --git a/doc/wm.n b/doc/wm.n index e7aedf7..a137d06 100644 --- a/doc/wm.n +++ b/doc/wm.n @@ -710,20 +710,21 @@ specified then the command returns the current title for the .TP \fBwm transient \fIwindow\fR ?\fImaster\fR? . -If \fImaster\fR is specified, then the window manager is informed -that \fIwindow\fR is a transient window (e.g. pull-down menu) working -on behalf of \fImaster\fR (where \fImaster\fR is the -path name for a top-level window). If \fImaster\fR -is specified as an empty string then \fIwindow\fR is marked as not -being a transient window any more. Otherwise the command -returns the path name of \fIwindow\fR's current master, or an -empty string if \fIwindow\fR is not currently a transient window. -A transient window will mirror state changes in the master and -inherit the state of the master when initially mapped. It is an -error to attempt to make a window a transient of itself. -The window manager may also decorate a transient window differently, removing -some features normally present (e.g., minimize and maximize buttons) though -this is entirely at the discretion of the window manager. +If \fImaster\fR is specified, then the window manager is informed that +\fIwindow\fR is a transient window (e.g. pull-down menu) working on +behalf of \fImaster\fR (where \fImaster\fR is the path name for a +top-level window). If \fImaster\fR is specified as an empty string +then \fIwindow\fR is marked as not being a transient window any more. +Otherwise the command returns the path name of \fIwindow\fR's current +master, or an empty string if \fIwindow\fR is not currently a +transient window. A transient window will mirror state changes in the +master and inherit the state of the master when initially mapped. The +directed graph with an edge from each transient to its master must be +acyclic. In particular, it is an error to attempt to make a window a +transient of itself. The window manager may also decorate a transient +window differently, removing some features normally present (e.g., +minimize and maximize buttons) though this is entirely at the +discretion of the window manager. .TP \fBwm withdraw \fIwindow\fR . diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index 599455d..a1fbbde 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -3568,6 +3568,7 @@ WmTransientCmd( { register WmInfo *wmPtr = winPtr->wmInfoPtr; Tk_Window master; + TkWindow *masterPtr, *w; WmInfo *wmPtr2; Transient *transient; @@ -3589,7 +3590,7 @@ WmTransientCmd( if (TkGetWindowFromObj(interp, tkwin, objv[3], &master) != TCL_OK) { return TCL_ERROR; } - TkWindow *masterPtr = (TkWindow*) master; + masterPtr = (TkWindow*) master; while (!Tk_TopWinHierarchy(masterPtr)) { /* @@ -3618,11 +3619,15 @@ WmTransientCmd( return TCL_ERROR; } - if (masterPtr == winPtr) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "can't make \"%s\" its own master", Tk_PathName(winPtr))); - Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "SELF", NULL); - return TCL_ERROR; + for (w = masterPtr; w != NULL && w->wmInfoPtr != NULL; + w = (TkWindow *)w->wmInfoPtr->master) { + if (w == winPtr) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "setting \"%s\" as master creates a transient/master cycle", + Tk_PathName(masterPtr))); + Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "SELF", NULL); + return TCL_ERROR; + } } /* @@ -6881,14 +6886,6 @@ ApplyMasterOverrideChanges( [parentWindow removeChildWindow:macWindow]; } - /* - * To avoid cycles, if the master is a child of some - other window, remove it. - */ - parentWindow = [masterMacWin parentWindow]; - if (parentWindow) { - [parentWindow removeChildWindow:masterMacWin]; - } [masterMacWin addChildWindow:macWindow ordered:NSWindowAbove]; } diff --git a/tests/wm.test b/tests/wm.test index 7b81985..c2bc385 100644 --- a/tests/wm.test +++ b/tests/wm.test @@ -1640,14 +1640,24 @@ test wm-transient-1.7 {usage} -returnCodes error -body { wm transient .master .master } -cleanup { deleteWindows -} -result {can't make ".master" its own master} +} -result {setting ".master" as master creates a transient/master cycle} test wm-transient-1.8 {usage} -returnCodes error -body { + toplevel .t1 + toplevel .t2 + toplevel .t3 + wm transient .t2 .t1 + wm transient .t3 .t2 + wm transient .t1 .t3 +} -cleanup { + deleteWindows +} -result {setting ".t3" as master creates a transient/master cycle} +test wm-transient-1.9 {usage} -returnCodes error -body { toplevel .master frame .master.f wm transient .master .master.f } -cleanup { deleteWindows -} -result {can't make ".master" its own master} +} -result {setting ".master" as master creates a transient/master cycle} test wm-transient-2.1 {basic get/set of master} -setup { set results [list] -- cgit v0.12 From ec1cf983bd80cc43701c88134d9bd94131e6100f Mon Sep 17 00:00:00 2001 From: culler Date: Fri, 1 Mar 2019 15:46:38 +0000 Subject: Make it be an error to create a transient/master cycle on unix. --- unix/tkUnixWm.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/unix/tkUnixWm.c b/unix/tkUnixWm.c index 8944ecc..9ed9082 100644 --- a/unix/tkUnixWm.c +++ b/unix/tkUnixWm.c @@ -3524,7 +3524,7 @@ WmTransientCmd( Tcl_Obj *const objv[]) /* Argument objects. */ { register WmInfo *wmPtr = winPtr->wmInfoPtr; - TkWindow *masterPtr = wmPtr->masterPtr; + TkWindow *masterPtr = wmPtr->masterPtr, *w; WmInfo *wmPtr2; if ((objc != 3) && (objc != 4)) { @@ -3593,12 +3593,18 @@ WmTransientCmd( return TCL_ERROR; } - if (masterPtr == winPtr) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "can't make \"%s\" its own master", Tk_PathName(winPtr))); - Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "SELF", NULL); - return TCL_ERROR; - } else if (masterPtr != wmPtr->masterPtr) { + for (w = masterPtr; w != NULL && w->wmInfoPtr != NULL; + w = (TkWindow *)w->wmInfoPtr->masterPtr) { + if (w == winPtr) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "setting \"%s\" as master creates a transient/master cycle", + Tk_PathName(masterPtr))); + Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "SELF", NULL); + return TCL_ERROR; + } + } + + if (masterPtr != wmPtr->masterPtr) { /* * Remove old master map/unmap binding before setting the new * master. The event handler will ensure that transient states -- cgit v0.12 From 4acf3a1da92f5ef0bc2dbe3ac5fa457ae0ae2836 Mon Sep 17 00:00:00 2001 From: culler Date: Fri, 1 Mar 2019 16:04:19 +0000 Subject: Make it be an error to create a transient/master cycle on Windows. --- win/tkWinWm.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/win/tkWinWm.c b/win/tkWinWm.c index 97cf255..5bb23d1 100644 --- a/win/tkWinWm.c +++ b/win/tkWinWm.c @@ -5526,7 +5526,7 @@ WmTransientCmd( Tcl_Obj *const objv[]) /* Argument objects. */ { register WmInfo *wmPtr = winPtr->wmInfoPtr; - TkWindow *masterPtr = wmPtr->masterPtr, **masterPtrPtr = &masterPtr; + TkWindow *masterPtr = wmPtr->masterPtr, **masterPtrPtr = &masterPtr, *w; WmInfo *wmPtr2; if ((objc != 3) && (objc != 4)) { @@ -5584,13 +5584,17 @@ WmTransientCmd( Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "ICON", NULL); return TCL_ERROR; } - - if (masterPtr == winPtr) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "can't make \"%s\" its own master", Tk_PathName(winPtr))); - Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "SELF", NULL); - return TCL_ERROR; - } else if (masterPtr != wmPtr->masterPtr) { + for (w = masterPtr; w != NULL && w->wmInfoPtr != NULL; + w = (TkWindow *)w->wmInfoPtr->masterPtr) { + if (w == winPtr) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "setting \"%s\" as master creates a transient/master cycle", + Tk_PathName(masterPtr))); + Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "SELF", NULL); + return TCL_ERROR; + } + } + if (masterPtr != wmPtr->masterPtr) { /* * Remove old master map/unmap binding before setting the new * master. The event handler will ensure that transient states -- cgit v0.12 From ffc8760419eff5493bbd2be5f8d8e585c1e8d95c Mon Sep 17 00:00:00 2001 From: culler Date: Sun, 3 Mar 2019 17:04:13 +0000 Subject: Increase the size of the ring buffer for Aqua, and modify bgerror so it doesn't try (and fail) to post a dialog inside [NSView drawRect]. --- generic/tkBind.c | 2 +- library/bgerror.tcl | 17 +++++++++----- macosx/tkMacOSXKeyEvent.c | 56 +++------------------------------------------ macosx/tkMacOSXMouseEvent.c | 51 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 66 insertions(+), 60 deletions(-) diff --git a/generic/tkBind.c b/generic/tkBind.c index 70f10aa..e0971ba 100644 --- a/generic/tkBind.c +++ b/generic/tkBind.c @@ -84,7 +84,7 @@ typedef union { */ #ifndef TK_MAC_OSX - #define EVENT_BUFFER_SIZE 45 + #define EVENT_BUFFER_SIZE 90 #else #define EVENT_BUFFER_SIZE 30 #endif diff --git a/library/bgerror.tcl b/library/bgerror.tcl index b15387e..574ad8b 100644 --- a/library/bgerror.tcl +++ b/library/bgerror.tcl @@ -97,7 +97,7 @@ proc ::tk::dialog::error::ReturnInDetails w { # Arguments: # err - The error message. # -proc ::tk::dialog::error::bgerror err { +proc ::tk::dialog::error::bgerror {err {flag 1}} { global errorInfo variable button @@ -106,15 +106,20 @@ proc ::tk::dialog::error::bgerror err { set ret [catch {::tkerror $err} msg]; if {$ret != 1} {return -code $ret $msg} - # Ok the application's tkerror either failed or was not found - # we use the default dialog then : + # The application's tkerror either failed or was not found + # so we use the default dialog. But on Aqua we cannot display + # the dialog if the background error occurs in an idle task + # being processed inside of [NSView drawRect]. In that case + # we post the dialog as an after task instead. set windowingsystem [tk windowingsystem] if {$windowingsystem eq "aqua"} { - set ok [mc Ok] - } else { - set ok [mc OK] + if $flag { + after 500 [list bgerror "$err" 0] + return + } } + set ok [mc OK] # Truncate the message if it is too wide (>maxLine characters) or # too tall (>4 lines). Truncation occurs at the first point at # which one of those conditions is met. diff --git a/macosx/tkMacOSXKeyEvent.c b/macosx/tkMacOSXKeyEvent.c index 3327f0a..543e7ab 100644 --- a/macosx/tkMacOSXKeyEvent.c +++ b/macosx/tkMacOSXKeyEvent.c @@ -24,9 +24,6 @@ */ #define NS_KEYLOG 0 - -static Tk_Window grabWinPtr = NULL; - /* Current grab window, NULL if no grab. */ static Tk_Window keyboardGrabWinPtr = NULL; /* Current keyboard grab window. */ static NSWindow *keyboardGrabNSWindow = nil; @@ -500,11 +497,12 @@ XGrabKeyboard( Time time) { keyboardGrabWinPtr = Tk_IdToWindow(display, grab_window); - if (keyboardGrabWinPtr && grabWinPtr) { + TkWindow *captureWinPtr = (TkWindow *)TkMacOSXGetCapture(); + if (keyboardGrabWinPtr && captureWinPtr) { NSWindow *w = TkMacOSXDrawableWindow(grab_window); MacDrawable *macWin = (MacDrawable *) grab_window; - if (w && macWin->toplevel->winPtr == (TkWindow*) grabWinPtr) { + if (w && macWin->toplevel->winPtr == (TkWindow*) captureWinPtr) { if (modalSession) { Tcl_Panic("XGrabKeyboard: already grabbed"); } @@ -551,26 +549,6 @@ XUngrabKeyboard( /* *---------------------------------------------------------------------- * - * TkMacOSXGetCapture -- - * - * Results: - * Returns the current grab window - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -Tk_Window -TkMacOSXGetCapture(void) -{ - return grabWinPtr; -} - -/* - *---------------------------------------------------------------------- - * * TkMacOSXGetModalSession -- * * Results: @@ -591,34 +569,6 @@ TkMacOSXGetModalSession(void) /* *---------------------------------------------------------------------- * - * TkpSetCapture -- - * - * This function captures the mouse so that all future events will be - * reported to this window, even if the mouse is outside the window. If - * the specified window is NULL, then the mouse is released. - * - * Results: - * None. - * - * Side effects: - * Sets the capture flag and captures the mouse. - * - *---------------------------------------------------------------------- - */ - -void -TkpSetCapture( - TkWindow *winPtr) /* Capture window, or NULL. */ -{ - while (winPtr && !Tk_IsTopLevel(winPtr)) { - winPtr = winPtr->parentPtr; - } - grabWinPtr = (Tk_Window) winPtr; -} - -/* - *---------------------------------------------------------------------- - * * Tk_SetCaretPos -- * * This enables correct placement of the XIM caret. This is called by diff --git a/macosx/tkMacOSXMouseEvent.c b/macosx/tkMacOSXMouseEvent.c index 7b83679..2d5d152 100644 --- a/macosx/tkMacOSXMouseEvent.c +++ b/macosx/tkMacOSXMouseEvent.c @@ -24,6 +24,7 @@ typedef struct { Point global; Point local; } MouseEventData; +static Tk_Window captureWinPtr = NULL; /* Current capture window; may be NULL. */ static int GenerateButtonEvent(MouseEventData *medPtr); static unsigned int ButtonModifiers2State(UInt32 buttonState, @@ -581,6 +582,56 @@ TkpWarpPointer( } /* + *---------------------------------------------------------------------- + * + * TkpSetCapture -- + * + * This function captures the mouse so that all future events will be + * reported to this window, even if the mouse is outside the window. If + * the specified window is NULL, then the mouse is released. + * + * Results: + * None. + * + * Side effects: + * Sets the capture flag and captures the mouse. + * + *---------------------------------------------------------------------- + */ + +void +TkpSetCapture( + TkWindow *winPtr) /* Capture window, or NULL. */ +{ + while (winPtr && !Tk_IsTopLevel(winPtr)) { + winPtr = winPtr->parentPtr; + } + captureWinPtr = (Tk_Window) winPtr; +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXGetCapture -- + * + * Results: + * Returns the current grab window + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +Tk_Window +TkMacOSXGetCapture(void) +{ + return captureWinPtr; +} + + + +/* * Local Variables: * mode: objc * c-basic-offset: 4 -- cgit v0.12 From bcb56bea15876c7d85bcbf6c9c998ba54454d5bb Mon Sep 17 00:00:00 2001 From: culler Date: Sun, 3 Mar 2019 19:40:15 +0000 Subject: Make notebook tabs readable in dark mode. --- library/ttk/aquaTheme.tcl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/library/ttk/aquaTheme.tcl b/library/ttk/aquaTheme.tcl index 3d5c4d0..cc125b7 100644 --- a/library/ttk/aquaTheme.tcl +++ b/library/ttk/aquaTheme.tcl @@ -34,6 +34,11 @@ namespace eval ttk::theme::aqua { ttk::style configure TNotebook -tabmargins {10 0} -tabposition n ttk::style configure TNotebook -padding {18 8 18 17} ttk::style configure TNotebook.Tab -padding {12 3 12 2} + ttk::style configure TNotebook.Tab -foreground white + ttk::style map TNotebook.Tab -foreground { + {background !disabled} black + disabled darkgray + !selected black} # Combobox: ttk::style configure TCombobox -postoffset {5 -2 -10 0} -- cgit v0.12 From 7f0376c51034471e24aa2b44dd0b1aec38ef03b0 Mon Sep 17 00:00:00 2001 From: fvogel Date: Mon, 4 Mar 2019 20:36:04 +0000 Subject: Make the branch build with MSVC by replacing calls to C99 functions round(), fmin() and fmax() by equivalent macros. --- generic/tkScale.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/generic/tkScale.c b/generic/tkScale.c index 5ed6618..0d9bc10 100644 --- a/generic/tkScale.c +++ b/generic/tkScale.c @@ -185,6 +185,10 @@ static const Tk_ClassProcs scaleClass = { NULL, /* createProc */ NULL /* modalProc */ }; + +#define ROUND(d) ((int) floor((d) + 0.5)) +#define MIN(a, b) ((a) < (b)? (a): (b)) +#define MAX(a, b) ((a) > (b)? (a): (b)) /* *-------------------------------------------------------------- @@ -790,13 +794,13 @@ MaxTickRoundingError( int tickCount; tickPosn = scalePtr->fromValue/tickResolution; - firstTickError = tickPosn - round(tickPosn); + firstTickError = tickPosn - ROUND(tickPosn); tickPosn = scalePtr->tickInterval/tickResolution; - intervalError = tickPosn - round(tickPosn); + intervalError = tickPosn - ROUND(tickPosn); tickCount = (int)((scalePtr->toValue-scalePtr->fromValue) / scalePtr->tickInterval); // not including first - lastTickError = fmin(fabs(firstTickError + tickCount*intervalError), 0.5); - return fmax(fabs(firstTickError),lastTickError)*tickResolution; + lastTickError = MIN(fabs(firstTickError + tickCount*intervalError), 0.5); + return MAX(fabs(firstTickError),lastTickError)*tickResolution; } -- cgit v0.12 From 4e356bee29f77e86babcc504bb647ff078d55c3e Mon Sep 17 00:00:00 2001 From: culler Date: Mon, 4 Mar 2019 23:30:15 +0000 Subject: Fix bug [609e0045f5]: Aqua scrollwheel events have incorrect mouse coordinates. --- macosx/tkMacOSXMouseEvent.c | 115 ++++++++++++++++++++++++++++++++------------ 1 file changed, 85 insertions(+), 30 deletions(-) diff --git a/macosx/tkMacOSXMouseEvent.c b/macosx/tkMacOSXMouseEvent.c index 2d5d152..38adc8c 100644 --- a/macosx/tkMacOSXMouseEvent.c +++ b/macosx/tkMacOSXMouseEvent.c @@ -48,15 +48,17 @@ enum { @implementation TKApplication(TKMouseEvent) - (NSEvent *) tkProcessMouseEvent: (NSEvent *) theEvent { -#ifdef TK_MAC_DEBUG_EVENTS - TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, theEvent); -#endif NSWindow* eventWindow = [theEvent window]; NSEventType eventType = [theEvent type]; + TkWindow *winPtr, *grabWinPtr; + Tk_Window tkwin; #if 0 NSTrackingArea *trackingArea = nil; NSInteger eventNumber, clickCount, buttonNumber; #endif +#ifdef TK_MAC_DEBUG_EVENTS + TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, theEvent); +#endif switch (eventType) { case NSMouseEntered: case NSMouseExited: @@ -88,52 +90,95 @@ enum { [_windowWithMouse retain]; } - /* Create an Xevent to add to the Tk queue. */ + /* + * Compute the mouse position in Tk screen coordinates (global) and in + * the Tk coordinates of its containing Tk Window. + */ + NSPoint global, local = [theEvent locationInWindow]; - if (eventWindow) { /* local will be in window coordinates. */ + + /* + * If the event has no NSWindow, try using the cached NSWindow from the + * last mouse event. + */ + + if (eventWindow == NULL) { + eventWindow == _windowWithMouse; + } + if (eventWindow) { + + /* + * Set the local mouse position to its NSWindow flipped coordinates, + * with the origin at top left, and the global mouse position to the + * flipped screen coordinates. + */ + global = [eventWindow tkConvertPointToScreen: local]; local.y = [eventWindow frame].size.height - local.y; global.y = tkMacOSXZeroScreenHeight - global.y; - } else { /* local will be in screen coordinates. */ - if (_windowWithMouse ) { - eventWindow = _windowWithMouse; - global = local; - local = [eventWindow tkConvertPointFromScreen: local]; - local.y = [eventWindow frame].size.height - local.y; - global.y = tkMacOSXZeroScreenHeight - global.y; - } else { /* We have no window. Use the screen???*/ - local.y = tkMacOSXZeroScreenHeight - local.y; - global = local; - } + + } else { + + /* + * As a last resort, with no NSWindow to work witn, set both local and + * global to the screen coordinates. + */ + + local.y = tkMacOSXZeroScreenHeight - local.y; + global = local; } - TkWindow *winPtr = TkMacOSXGetTkWindow(eventWindow); - Tk_Window tkwin = (Tk_Window) winPtr; + /* + * Find the toplevel which corresponds to the event NSWindow. + */ - if (tkwin) { - TkWindow *grabWinPtr = winPtr->dispPtr->grabWinPtr; - if (grabWinPtr && - grabWinPtr != winPtr && - !winPtr->dispPtr->grabFlags && /* this means the grab is local. */ - grabWinPtr->mainPtr == winPtr->mainPtr) { - return theEvent; - } - } else { + winPtr = TkMacOSXGetTkWindow(eventWindow); + if (winPtr == NULL) { tkwin = TkMacOSXGetCapture(); + winPtr = (TkWindow *)tkwin; + } else { + tkwin = (Tk_Window) winPtr; } if (!tkwin) { TkMacOSXDbgMsg("tkwin == NULL"); return theEvent; /* Give up. No window for this event. */ - } else { - winPtr = (TkWindow *)tkwin; } + /* + * If another toplevel has a grab, we ignore the event. + */ + + grabWinPtr = winPtr->dispPtr->grabWinPtr; + if (grabWinPtr && + grabWinPtr != winPtr && + !winPtr->dispPtr->grabFlags && /* this means the grab is local. */ + grabWinPtr->mainPtr == winPtr->mainPtr) { + return theEvent; + } + + /* + * Convert local from NSWindow flipped coordinates to the toplevel's + * coordinates. + */ + local.x -= winPtr->wmInfoPtr->xInParent; local.y -= winPtr->wmInfoPtr->yInParent; + /* + * Find the containing Tk window, and convert local into the coordinates + * of the Tk window. (The converted local coordinates are only needed + * for scrollwheel events.) + */ + int win_x, win_y; tkwin = Tk_TopCoordsToWindow(tkwin, local.x, local.y, &win_x, &win_y); + local.x = win_x; + local.y = win_y; + /* + * Generate an XEvent for this mouse event. + */ + unsigned int state = 0; NSInteger button = [theEvent buttonNumber]; EventRef eventRef = (EventRef)[theEvent eventRef]; @@ -182,11 +227,21 @@ enum { } if (eventType != NSScrollWheel) { + + /* + * For normal mouse events, Tk_UpdatePointer will send the XEvent. + */ + #ifdef TK_MAC_DEBUG_EVENTS TKLog(@"UpdatePointer %p x %f.0 y %f.0 %d", tkwin, global.x, global.y, state); #endif Tk_UpdatePointer(tkwin, global.x, global.y, state); - } else { /* handle scroll wheel event */ + } else { + + /* + * For scroll wheel events we need to send the XEvent here. + */ + CGFloat delta; int coarseDelta; XEvent xEvent; -- cgit v0.12 From 63f73c5f9542e461a6daa5e95cb7fd16e161f3b6 Mon Sep 17 00:00:00 2001 From: apnadkarni Date: Wed, 6 Mar 2019 04:54:35 +0000 Subject: Copy PDBs to installation if option PDBS is given during install --- win/makefile.vc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/win/makefile.vc b/win/makefile.vc index 947e167..1e44bff 100644 --- a/win/makefile.vc +++ b/win/makefile.vc @@ -336,6 +336,9 @@ all: release $(CAT32) core: setup $(TKSTUBLIB) $(TKLIB) cwish: $(WISHC) install: install-binaries install-libraries install-docs +!if $(SYMBOLS) +install: install-pdbs +!endif tktest: setup $(TKTEST) $(CAT32) setup: default-setup @@ -516,6 +519,11 @@ install-docs: !endif # "emacs font-lock highlighting fix +install-pdbs: + @echo Installing debug symbols + @$(CPY) "$(OUT_DIR)\*.pdb" "$(BIN_INSTALL_DIR)\" +# "emacs font-lock highlighting fix + #--------------------------------------------------------------------- # Special case object file targets #--------------------------------------------------------------------- -- cgit v0.12 From f0e41e0b182797c82d84310e554e2c208753b703 Mon Sep 17 00:00:00 2001 From: culler Date: Thu, 7 Mar 2019 16:20:11 +0000 Subject: Add a drawing procedure to draw PushButtons and PopupButtons in Dark Mode. --- library/ttk/aquaTheme.tcl | 2 +- macosx/tkMacOSXButton.c | 2 +- macosx/ttkMacOSXTheme.c | 123 ++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 110 insertions(+), 17 deletions(-) diff --git a/library/ttk/aquaTheme.tcl b/library/ttk/aquaTheme.tcl index cc125b7..3556c6b 100644 --- a/library/ttk/aquaTheme.tcl +++ b/library/ttk/aquaTheme.tcl @@ -29,7 +29,7 @@ namespace eval ttk::theme::aqua { ttk::style configure TButton -anchor center -width -6 - ttk::style configure Toolbutton -padding 4 + ttk::style configure Toolbutton -padding 4 -foreground black ttk::style configure TNotebook -tabmargins {10 0} -tabposition n ttk::style configure TNotebook -padding {18 8 18 17} diff --git a/macosx/tkMacOSXButton.c b/macosx/tkMacOSXButton.c index c0b83f2..a335703 100644 --- a/macosx/tkMacOSXButton.c +++ b/macosx/tkMacOSXButton.c @@ -388,7 +388,7 @@ TkpComputeButtonGeometry( * expanded by the standard padding. */ - tmpRect = CGRectMake(0, 0, width + 2*HI_PADX, height + 2*HI_PADY); + tmpRect = CGRectMake(0, 0, width + 2*HI_PADX, height + 2*HI_PADY); HIThemeGetButtonContentBounds(&tmpRect, &mbPtr->drawinfo, &contBounds); if (height < contBounds.size.height) { height = contBounds.size.height; diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index a5c0e64..ef9080c 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -200,6 +200,108 @@ static void ButtonElementSize( *heightPtr += Ttk_PaddingHeight(ButtonMargins); } +/* + * MacOSXDrawDarkButton -- + * + * The HIToolbox does not support Dark Mode, and apparently never will. + * This is a standalone drawing procedure which draws PushButtons and + * PopupButtons in the Dark Mode style. + */ + +static CGFloat darkButtonFill[4] = {107.0/255, 108.0/255, 110.0/255.0, 1.0}; +static CGFloat darkButtonStroke[4] = {1.0, 1.0, 1.0, 0.5}; +static CGFloat darkButtonGradient[8] = {1.0, 1.0, 1.0, 0.45, 1.0, 1.0, 1.0, 0.0}; +static CGFloat darkPopupGradient[8] = {23.0/255, 111.0/255, 232.0/255, 1.0, + 20.0/255, 94.0/255, 206.0/255, 1.0}; + +static void MacOSXDrawDarkButton( + CGRect bounds, + HIThemeButtonDrawInfo *info, + CGContextRef c) +{ + CGPathRef path; + CGColorSpaceRef RGB = CGColorSpaceCreateDeviceRGB(); + CGGradientRef topGradient = CGGradientCreateWithColorComponents( + RGB, darkButtonGradient, NULL, 2); + CGFloat *fill, *stroke; + + /* + * Compensate for the missing bottom border on dark buttons. + */ + + bounds.size.height -= 1; + bounds.origin.y += 1; + CGPoint start = {bounds.origin.x + 5, bounds.origin.y}; + CGPoint end = {bounds.origin.x + 5, bounds.origin.y + 5}; + + fill = darkButtonFill; + CGContextSetRGBFillColor(c, fill[0], fill[1], fill[2], fill[3]); + stroke = darkButtonStroke; + CGContextSetRGBStrokeColor(c, stroke[0], stroke[1], stroke[2], stroke[3]); + CGContextSetLineWidth(c, 0.5); + CGContextClipToRect(c, bounds); + + /* + * Fill a rounded rectangle with the dark background color. + */ + + path = CGPathCreateWithRoundedRect(bounds, 4, 4, NULL); + CGContextBeginPath(c); + CGContextAddPath(c, path); + CGContextDrawPath(c, kCGPathFill); + + /* + * Draw the arrow button if this is a popup. + */ + + if (info->kind == kThemePopupButton) { + CGFloat x, y; + CGRect arrowBounds = bounds; + arrowBounds.size.width = 16; + arrowBounds.origin.x += bounds.size.width - 16; + CGContextSaveGState(c); + if (info->state == kThemeStateActive) { + CGGradientRef popupGradient = CGGradientCreateWithColorComponents( + RGB, darkPopupGradient, NULL, 2); + CGPoint popupStart = {arrowBounds.origin.x + 8, arrowBounds.origin.y}; + CGPoint popupEnd = {arrowBounds.origin.x + 8, + arrowBounds.origin.y + arrowBounds.size.height}; + CGContextBeginPath(c); + CGContextAddPath(c, path); + CGContextClip(c); + CGContextClipToRect(c, arrowBounds); + CGContextDrawLinearGradient(c, popupGradient, popupStart, popupEnd, 0); + CFRelease(popupGradient); + } + CGContextSetRGBStrokeColor(c, 1.0, 1.0, 1.0, 1.0); + CGContextSetLineWidth(c, 1.5); + x = arrowBounds.origin.x + 5; + y = arrowBounds.origin.y + trunc(arrowBounds.size.height/2); + CGContextBeginPath(c); + CGPoint bottomArrow[3] = {{x, y + 2}, {x + 3.5, y + 5.5}, {x + 7, y + 2}}; + CGContextAddLines(c, bottomArrow, 3); + CGPoint topArrow[3] = {{x, y - 2}, {x + 3.5, y - 5.5}, {x + 7, y - 2}}; + CGContextAddLines(c, topArrow, 3); + CGContextStrokePath(c); + CGContextRestoreGState(c); + } + + /* + * Draw the top border with a transparent white gradient. + */ + + CGContextBeginPath(c); + CGContextAddArc(c, bounds.origin.x + 4, bounds.origin.y + 4, 4, PI, 3*PI/2, 0); + CGContextAddArc(c, bounds.origin.x + bounds.size.width - 4, + bounds.origin.y + 4, 4, 3*PI/2, 0.0, 0); + CGContextReplacePathWithStrokedPath(c); + CGContextClip(c); + CGContextDrawLinearGradient(c, topGradient, start, end, 0); + CFRelease(path); + CFRelease(topGradient); + CGColorSpaceRelease(RGB); +} + static void ButtonElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) @@ -208,22 +310,13 @@ static void ButtonElementDraw( ThemeButtonParams *params = clientData; CGRect bounds = BoxToRect(d, Ttk_PadBox(b, ButtonMargins)); HIThemeButtonDrawInfo info = computeButtonDrawInfo(params, state); - Tk_Uid className = Tk_Class(tkwin); - /* - * HIToolbox does not support Dark Mode, and Apple says it never will. So - * the best we can do to approximate a Dark Mode button is to draw it in - * the inactive state. The color is not quite as dark as the gray that - * Apple uses for buttons in Dark Mode. But it isn't too far off. We - * don't have to worry about checkButtons and radioButtons. They look OK, - */ - - if (TkMacOSXInDarkMode(tkwin) && className && - strcmp(className, "TCheckbutton") != 0 && - strcmp(className, "TRadiobutton") != 0) { - info.state = kThemeStateInactive; + if (TkMacOSXInDarkMode(tkwin) && + (info.kind == kThemePushButton || info.kind == kThemePopupButton)) { + MacOSXDrawDarkButton(bounds, &info, dc.context); + } else { + ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); } - ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); END_DRAWING } @@ -1210,7 +1303,7 @@ static int AquaTheme_Init(Tcl_Interp *interp) Ttk_RegisterElementSpec(themePtr, "Radiobutton.button", &ButtonElementSpec, &RadioButtonParams); Ttk_RegisterElementSpec(themePtr, "Toolbutton.border", - &ButtonElementSpec, &BevelButtonParams); + &ButtonElementSpec, &BevelButtonParams); Ttk_RegisterElementSpec(themePtr, "Menubutton.button", &ButtonElementSpec, &PopupButtonParams); Ttk_RegisterElementSpec(themePtr, "Spinbox.spinbutton", -- cgit v0.12 From 4f7024c77a1a45eff1194e3148e9cbc26146be16 Mon Sep 17 00:00:00 2001 From: jaspert Date: Fri, 8 Mar 2019 14:58:54 +0000 Subject: Changed scale man page to reflect how tick values are now displayed --- doc/scale.n | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/scale.n b/doc/scale.n index 6b960ce..b1f1981 100644 --- a/doc/scale.n +++ b/doc/scale.n @@ -55,7 +55,7 @@ it is the scale's width. .OP \-resolution resolution Resolution A real value specifying the resolution for the scale. If this value is greater than zero then the scale's value will always be -rounded to an even multiple of this value, as will tick marks and +rounded to an even multiple of this value, as will the endpoints of the scale. If the value is less than zero then no rounding occurs. Defaults to 1 (i.e., the value will be integral). .OP \-showvalue showValue ShowValue @@ -78,7 +78,7 @@ specified by the \fB\-activebackground\fR option. .OP \-tickinterval tickInterval TickInterval Must be a real value. Determines the spacing between numerical -tick marks displayed below or to the left of the slider. +tick marks displayed below or to the left of the slider. The values will all be displayed with the same number of decimal places, which will be enough to ensure they are all accurate to within 20% of a tick interval. If 0, no tick marks will be displayed. .OP \-to to To Specifies a real value corresponding -- cgit v0.12 From 4dc6002eb8151fd593fca4ec98db71109fcda126 Mon Sep 17 00:00:00 2001 From: culler Date: Fri, 8 Mar 2019 18:54:30 +0000 Subject: Fix bug [9286526144]: incorrect menu locations for ttk menubuttons. --- library/menu.tcl | 9 --- library/ttk/menubutton.tcl | 134 ++++++++++++++++++++++++++++++++++----------- 2 files changed, 101 insertions(+), 42 deletions(-) diff --git a/library/menu.tcl b/library/menu.tcl index 8d06868..9d6370a 100644 --- a/library/menu.tcl +++ b/library/menu.tcl @@ -1178,15 +1178,6 @@ if {[tk windowingsystem] eq "aqua"} { set entry 0 } } - if {$entry ne ""} { - if {$entry == [$menu index last]} { - set entryHeight [expr {[winfo reqheight $menu] \ - - [$menu yposition $entry]}] - } else { - set entryHeight [expr {[$menu yposition [expr {$entry+1}]] \ - - [$menu yposition $entry]}] - } - } set x [winfo rootx $button] set y [winfo rooty $button] switch [$button cget -direction] { diff --git a/library/ttk/menubutton.tcl b/library/ttk/menubutton.tcl index 2be064c..9d12b05 100644 --- a/library/ttk/menubutton.tcl +++ b/library/ttk/menubutton.tcl @@ -61,43 +61,106 @@ if {[tk windowingsystem] eq "x11"} { } # PostPosition -- -# Returns the x and y coordinates where the menu -# should be posted, based on the menubutton and menu size -# and -direction option. +# Returns x and y coordinates and a menu item index. +# If the index is not an empty string the menu should +# be posted so that the upper left corner of the indexed +# menu item is located at the point (x, y). Otherwise +# the top left corner of the menu itself should be located +# at that point. # # TODO: adjust menu width to be at least as wide as the button # for -direction above, below. # -proc ttk::menubutton::PostPosition {mb menu} { - set x [winfo rootx $mb] - set y [winfo rooty $mb] - set dir [$mb cget -direction] - set bw [winfo width $mb] - set bh [winfo height $mb] - set mw [winfo reqwidth $menu] - set mh [winfo reqheight $menu] - set sw [expr {[winfo screenwidth $menu] - $bw - $mw}] - set sh [expr {[winfo screenheight $menu] - $bh - $mh}] - - switch -- $dir { - above { if {$y >= $mh} { incr y -$mh } { incr y $bh } } - below { if {$y <= $sh} { incr y $bh } { incr y -$mh } } - left { if {$x >= $mw} { incr x -$mw } { incr x $bw } } - right { if {$x <= $sw} { incr x $bw } { incr x -$mw } } - flush { - # post menu atop menubutton. - # If there's a menu entry whose label matches the - # menubutton -text, assume this is an optionmenu - # and place that entry over the menubutton. - set index [FindMenuEntry $menu [$mb cget -text]] - if {$index ne ""} { - incr y -[$menu yposition $index] +if {[tk windowingsystem] eq "aqua"} { + proc ::ttk::menubutton::PostPosition {mb menu} { + set mh [expr {[winfo reqheight $menu] - 6}] + set bh [expr {[winfo height $mb] + 1}] + set mw [expr {[winfo reqwidth $menu] - 2}] + set bw [expr {[winfo width $mb] -1}] + set dF [expr {[winfo width $mb] - [winfo reqwidth $menu] -9}] + set entry "" + set entry [::tk::MenuFindName $menu [$mb cget -text]] + if {$entry eq ""} { + set entry 0 + } + set x [winfo rootx $mb] + set y [expr {2 + [winfo rooty $mb]}] + switch [$mb cget -direction] { + above { + set entry "" + incr y -$mh + } + below { + set entry "" + incr y $bh + } + left { + incr x -$mw + } + right { + incr x $bw + } + default { + incr x $dF } } + return [list $x $y $entry] + } +} else { + proc ::ttk::menubutton::PostPosition {mb menu} { + set mh [expr {[winfo reqheight $menu]}] + set bh [expr {[winfo height $mb]}] + set mw [expr {[winfo reqwidth $menu]}] + set bw [expr {[winfo width $mb]}] + set dF [expr {[winfo width $mb] - [winfo reqwidth $menu]}] + if {[tk windowingsystem] eq "win32"} { + incr mh 6 + incr mw 16 + } + set entry {} + set entry [::tk::MenuFindName $menu [$mb cget -text]] + if {$entry eq {}} { + set entry 0 + } + set x [winfo rootx $mb] + set y [winfo rooty $mb] + switch [$mb cget -direction] { + above { + set entry {} + incr y -$mh + # if we go offscreen to the top, show as 'below' + if {$y < [winfo vrooty $mb]} { + set y [expr {[winfo vrooty $mb] + [winfo rooty $mb]\ + + [winfo reqheight $mb]}] + } + } + below { + set entry {} + incr y $bh + # if we go offscreen to the bottom, show as 'above' + if {($y + $mh) > ([winfo vrooty $mb] + [winfo vrootheight $mb])} { + set y [expr {[winfo vrooty $mb] + [winfo vrootheight $mb] \ + + [winfo rooty $mb] - $mh}] + } + } + left { + incr x -$mw + } + right { + incr x $bw + } + default { + if {[$mb cget -style] eq ""} { + incr x [expr {([winfo width $mb] - \ + [winfo reqwidth $menu])/ 2}] + } else { + incr y $bh + } + } + } + return [list $x $y $entry] } - - return [list $x $y] } # Popdown -- @@ -107,8 +170,8 @@ proc ttk::menubutton::Popdown {mb} { if {[$mb instate disabled] || [set menu [$mb cget -menu]] eq ""} { return } - foreach {x y} [PostPosition $mb $menu] { break } - tk_popup $menu $x $y + foreach {x y entry} [PostPosition $mb $menu] { break } + tk_popup $menu $x $y $entry } # Pulldown (X11 only) -- @@ -121,13 +184,17 @@ proc ttk::menubutton::Pulldown {mb} { if {[$mb instate disabled] || [set menu [$mb cget -menu]] eq ""} { return } - foreach {x y} [PostPosition $mb $menu] { break } set State(pulldown) 1 set State(oldcursor) [$mb cget -cursor] $mb state pressed $mb configure -cursor [$menu cget -cursor] - $menu post $x $y + foreach {x y entry} [PostPosition $mb $menu] { break } + if {$entry ne {}} { + $menu post $x $y $entry + } else { + $menu post $x $y + } tk_menuSetFocus $menu } @@ -143,6 +210,7 @@ proc ttk::menubutton::TransferGrab {mb} { set State(pulldown) 0 set menu [$mb cget -menu] + foreach {x y entry} [PostPosition $mb $menu] { break } tk_popup $menu [winfo rootx $menu] [winfo rooty $menu] } } -- cgit v0.12 From 0d7ad4aa9a15ecef728ce891f752dbb786cf469d Mon Sep 17 00:00:00 2001 From: culler Date: Sun, 10 Mar 2019 03:46:45 +0000 Subject: Added a drawing procedure to make LabelFrame and Notebook panes render correctly in Dark Mode. Fixed a bug in the computation of background colors, where alpha was accidentally being modified. --- library/ttk/aquaTheme.tcl | 9 +- macosx/tkMacOSXColor.c | 3 +- macosx/ttkMacOSXTheme.c | 347 ++++++++++++++++++++++++++++------------------ 3 files changed, 219 insertions(+), 140 deletions(-) diff --git a/library/ttk/aquaTheme.tcl b/library/ttk/aquaTheme.tcl index 3556c6b..92cc0d1 100644 --- a/library/ttk/aquaTheme.tcl +++ b/library/ttk/aquaTheme.tcl @@ -17,20 +17,21 @@ namespace eval ttk::theme::aqua { ttk::style map . \ -foreground {disabled systemTtkForeground background systemTtkForeground} \ - -selectbackground {background systemHighlightSecondary + -selectbackground {background systemHighlight !focus systemHighlightSecondary} \ -selectforeground {background systemTtkForeground !focus systemDialogActiveText} + # Buttons + ttk::style configure TButton -anchor center -width -6 + ttk::style configure Toolbutton -padding 4 -foreground black # Workaround for #1100117: # Actually, on Aqua we probably shouldn't stipple images in # disabled buttons even if it did work... ttk::style configure . -stipple {} - ttk::style configure TButton -anchor center -width -6 - - ttk::style configure Toolbutton -padding 4 -foreground black + # Notebook ttk::style configure TNotebook -tabmargins {10 0} -tabposition n ttk::style configure TNotebook -padding {18 8 18 17} ttk::style configure TNotebook.Tab -padding {12 3 12 2} diff --git a/macosx/tkMacOSXColor.c b/macosx/tkMacOSXColor.c index e382892..fd2326c 100644 --- a/macosx/tkMacOSXColor.c +++ b/macosx/tkMacOSXColor.c @@ -277,7 +277,7 @@ SetCGColorComponents( bgColor = [[NSColor windowBackgroundColor] colorUsingColorSpace: [NSColorSpace deviceRGBColorSpace]]; [bgColor getComponents: rgba]; - for (int i=0; i<4; i++) { + for (int i=0; i<3; i++) { rgba[i] -= entry.value*(8.0/255.0); } break; @@ -546,7 +546,6 @@ TkMacOSXSetColorInContext( CGColorRef cgColor = CopyCachedColor(gc, pixel); struct SystemColorMapEntry entry; CGRect rect; - CGFloat rgba[4] = {0.0, 0.0, 0.0, 1.0}; HIThemeBackgroundDrawInfo info = { 0, kThemeStateActive, entry.value }; static CGColorSpaceRef deviceRGBSpace = NULL; if (!deviceRGBSpace) { diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index ef9080c..ed22c0c 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -34,7 +34,7 @@ #include "ttk/ttkTheme.h" #include /* - * Use this version in the core: + * Macros for handling drawing contexts. */ #define BEGIN_DRAWING(d) { \ TkMacOSXDrawingContext dc; \ @@ -94,6 +94,205 @@ static Ttk_StateTable ThemeStateTable[] = { }; /*---------------------------------------------------------------------- + * +++ Support for contrasting background colors when nesting GroupBoxes + * or Tabbed panes. + */ + +static int MacOSXSetBoxColor( + CGContextRef context, + Tk_Window tkwin, + int depth) +{ + TkWindow *winPtr = (TkWindow *)tkwin; + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + NSColor *windowColor = [[NSColor windowBackgroundColor] + colorUsingColorSpace: deviceRGB]; + NSColor *bgColor; + CGFloat intensity, fill[4]; + [windowColor getComponents: fill]; + intensity = fill[0] + fill[1] + fill[2]; + int isDark = (intensity < 1.5); + + /* + * Compute the nesting depth of the widget. + */ + + for (TkWindow *topPtr = winPtr->parentPtr; topPtr != NULL; + topPtr = topPtr->parentPtr) { + if (topPtr->privatePtr && + (topPtr->privatePtr->flags & TTK_HAS_DARKER_BG)) { + depth++; + } + if (depth > 7) { + break; + } + } + + /* + * Increase the contrast by one step for each level of nesting. + */ + + if (isDark) { + for (int i=0; i<3; i++) { + fill[i] += (1.0 + depth*7.0)/255.0; + } + } else { + for (int i=0; i<3; i++) { + fill[i] -= (depth*8.0)/255.0; + } + } + bgColor = [NSColor colorWithColorSpace: deviceRGB components: fill + count: 4]; + CGContextSetFillColorSpace(context, deviceRGB.CGColorSpace); + CGContextSetFillColorWithColor(context, bgColor.CGColor); + return depth; +} + +/*---------------------------------------------------------------------- + * +++ Drawing procedures for widgets in Apple's "Dark Mode" (10.14 and up). + * + * The HIToolbox does not support Dark Mode, and apparently never will, + * so to make widgets look "native" we have to provide analogues of the + * HITheme drawing functions to be used in DarkAqua. We continue to use + * HITheme in Aqua, since it understands earlier versions of the OS. + */ + +/* + * MacOSXDrawDarkButton -- + * + * This is a standalone drawing procedure which draws PushButtons and + * PopupButtons in the Dark Mode style. + */ + +static CGFloat darkButtonFill[4] = {107.0/255, 108.0/255, 110.0/255.0, 1.0}; +static CGFloat darkButtonStroke[4] = {1.0, 1.0, 1.0, 0.5}; +static CGFloat darkButtonGradient[8] = {1.0, 1.0, 1.0, 0.45, 1.0, 1.0, 1.0, 0.0}; +static CGFloat darkPopupGradient[8] = {23.0/255, 111.0/255, 232.0/255, 1.0, + 20.0/255, 94.0/255, 206.0/255, 1.0}; + +static void MacOSXDrawDarkButton( + CGRect bounds, + HIThemeButtonDrawInfo *info, + CGContextRef c) +{ + CGPathRef path; + CGColorSpaceRef RGB = CGColorSpaceCreateDeviceRGB(); + CGGradientRef topGradient = CGGradientCreateWithColorComponents( + RGB, darkButtonGradient, NULL, 2); + CGFloat *fill, *stroke; + + /* + * Compensate for the missing bottom border on dark buttons. + */ + + bounds.size.height -= 1; + bounds.origin.y += 1; + CGPoint start = {bounds.origin.x + 5, bounds.origin.y}; + CGPoint end = {bounds.origin.x + 5, bounds.origin.y + 5}; + + fill = darkButtonFill; + CGContextSetRGBFillColor(c, fill[0], fill[1], fill[2], fill[3]); + stroke = darkButtonStroke; + CGContextSetRGBStrokeColor(c, stroke[0], stroke[1], stroke[2], stroke[3]); + CGContextSetLineWidth(c, 0.5); + CGContextClipToRect(c, bounds); + + /* + * Fill a rounded rectangle with the dark background color. + */ + + path = CGPathCreateWithRoundedRect(bounds, 4, 4, NULL); + CGContextBeginPath(c); + CGContextAddPath(c, path); + CGContextFillPath(c); + + /* + * Draw the arrow button if this is a popup. + */ + + if (info->kind == kThemePopupButton) { + CGFloat x, y; + CGRect arrowBounds = bounds; + arrowBounds.size.width = 16; + arrowBounds.origin.x += bounds.size.width - 16; + CGContextSaveGState(c); + if (info->state == kThemeStateActive) { + CGGradientRef popupGradient = CGGradientCreateWithColorComponents( + RGB, darkPopupGradient, NULL, 2); + CGPoint popupStart = {arrowBounds.origin.x + 8, arrowBounds.origin.y}; + CGPoint popupEnd = {arrowBounds.origin.x + 8, + arrowBounds.origin.y + arrowBounds.size.height}; + CGContextBeginPath(c); + CGContextAddPath(c, path); + CGContextClip(c); + CGContextClipToRect(c, arrowBounds); + CGContextDrawLinearGradient(c, popupGradient, popupStart, popupEnd, 0); + CFRelease(popupGradient); + } + CGContextSetRGBStrokeColor(c, 1.0, 1.0, 1.0, 1.0); + CGContextSetLineWidth(c, 1.5); + x = arrowBounds.origin.x + 5; + y = arrowBounds.origin.y + trunc(arrowBounds.size.height/2); + CGContextBeginPath(c); + CGPoint bottomArrow[3] = {{x, y + 2}, {x + 3.5, y + 5.5}, {x + 7, y + 2}}; + CGContextAddLines(c, bottomArrow, 3); + CGPoint topArrow[3] = {{x, y - 2}, {x + 3.5, y - 5.5}, {x + 7, y - 2}}; + CGContextAddLines(c, topArrow, 3); + CGContextStrokePath(c); + CGContextRestoreGState(c); + } + + /* + * Draw the top border with a transparent white gradient. + */ + + CGContextBeginPath(c); + CGContextAddArc(c, bounds.origin.x + 4, bounds.origin.y + 4, 4, PI, 3*PI/2, 0); + CGContextAddArc(c, bounds.origin.x + bounds.size.width - 4, + bounds.origin.y + 4, 4, 3*PI/2, 0.0, 0); + CGContextReplacePathWithStrokedPath(c); + CGContextClip(c); + CGContextDrawLinearGradient(c, topGradient, start, end, 0); + CFRelease(path); + CFRelease(topGradient); + CGColorSpaceRelease(RGB); +} + +/* + * MacOSXDrawDarkGroupBox -- + * + * This is a standalone drawing procedure which draws the contrasting + * rounded rectangular contrasting box for Labelframes and Notebook panes + */ + +static void MacOSXDrawDarkGroupBox( + CGRect bounds, + const HIThemeGroupBoxDrawInfo *info, + CGContextRef context, + Tk_Window tkwin) +{ + CGPathRef path; + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + NSColor *borderColor; + static CGFloat stroke[4] = {1.0, 1.0, 1.0, 0.25}; + MacOSXSetBoxColor(context, tkwin, 1); + borderColor = [NSColor colorWithColorSpace: deviceRGB components: stroke + count: 4]; + path = CGPathCreateWithRoundedRect(bounds, 4, 4, NULL); + CGContextClipToRect(context, bounds); + CGContextBeginPath(context); + CGContextAddPath(context, path); + CGContextFillPath(context); + CGContextSetFillColorWithColor(context, borderColor.CGColor); + CGContextBeginPath(context); + CGContextAddPath(context, path); + CGContextReplacePathWithStrokedPath(context); + CGContextFillPath(context); + CFRelease(path); +} + + +/*---------------------------------------------------------------------- * +++ Button element: Used for elements drawn with DrawThemeButton. */ @@ -200,107 +399,6 @@ static void ButtonElementSize( *heightPtr += Ttk_PaddingHeight(ButtonMargins); } -/* - * MacOSXDrawDarkButton -- - * - * The HIToolbox does not support Dark Mode, and apparently never will. - * This is a standalone drawing procedure which draws PushButtons and - * PopupButtons in the Dark Mode style. - */ - -static CGFloat darkButtonFill[4] = {107.0/255, 108.0/255, 110.0/255.0, 1.0}; -static CGFloat darkButtonStroke[4] = {1.0, 1.0, 1.0, 0.5}; -static CGFloat darkButtonGradient[8] = {1.0, 1.0, 1.0, 0.45, 1.0, 1.0, 1.0, 0.0}; -static CGFloat darkPopupGradient[8] = {23.0/255, 111.0/255, 232.0/255, 1.0, - 20.0/255, 94.0/255, 206.0/255, 1.0}; - -static void MacOSXDrawDarkButton( - CGRect bounds, - HIThemeButtonDrawInfo *info, - CGContextRef c) -{ - CGPathRef path; - CGColorSpaceRef RGB = CGColorSpaceCreateDeviceRGB(); - CGGradientRef topGradient = CGGradientCreateWithColorComponents( - RGB, darkButtonGradient, NULL, 2); - CGFloat *fill, *stroke; - - /* - * Compensate for the missing bottom border on dark buttons. - */ - - bounds.size.height -= 1; - bounds.origin.y += 1; - CGPoint start = {bounds.origin.x + 5, bounds.origin.y}; - CGPoint end = {bounds.origin.x + 5, bounds.origin.y + 5}; - - fill = darkButtonFill; - CGContextSetRGBFillColor(c, fill[0], fill[1], fill[2], fill[3]); - stroke = darkButtonStroke; - CGContextSetRGBStrokeColor(c, stroke[0], stroke[1], stroke[2], stroke[3]); - CGContextSetLineWidth(c, 0.5); - CGContextClipToRect(c, bounds); - - /* - * Fill a rounded rectangle with the dark background color. - */ - - path = CGPathCreateWithRoundedRect(bounds, 4, 4, NULL); - CGContextBeginPath(c); - CGContextAddPath(c, path); - CGContextDrawPath(c, kCGPathFill); - - /* - * Draw the arrow button if this is a popup. - */ - - if (info->kind == kThemePopupButton) { - CGFloat x, y; - CGRect arrowBounds = bounds; - arrowBounds.size.width = 16; - arrowBounds.origin.x += bounds.size.width - 16; - CGContextSaveGState(c); - if (info->state == kThemeStateActive) { - CGGradientRef popupGradient = CGGradientCreateWithColorComponents( - RGB, darkPopupGradient, NULL, 2); - CGPoint popupStart = {arrowBounds.origin.x + 8, arrowBounds.origin.y}; - CGPoint popupEnd = {arrowBounds.origin.x + 8, - arrowBounds.origin.y + arrowBounds.size.height}; - CGContextBeginPath(c); - CGContextAddPath(c, path); - CGContextClip(c); - CGContextClipToRect(c, arrowBounds); - CGContextDrawLinearGradient(c, popupGradient, popupStart, popupEnd, 0); - CFRelease(popupGradient); - } - CGContextSetRGBStrokeColor(c, 1.0, 1.0, 1.0, 1.0); - CGContextSetLineWidth(c, 1.5); - x = arrowBounds.origin.x + 5; - y = arrowBounds.origin.y + trunc(arrowBounds.size.height/2); - CGContextBeginPath(c); - CGPoint bottomArrow[3] = {{x, y + 2}, {x + 3.5, y + 5.5}, {x + 7, y + 2}}; - CGContextAddLines(c, bottomArrow, 3); - CGPoint topArrow[3] = {{x, y - 2}, {x + 3.5, y - 5.5}, {x + 7, y - 2}}; - CGContextAddLines(c, topArrow, 3); - CGContextStrokePath(c); - CGContextRestoreGState(c); - } - - /* - * Draw the top border with a transparent white gradient. - */ - - CGContextBeginPath(c); - CGContextAddArc(c, bounds.origin.x + 4, bounds.origin.y + 4, 4, PI, 3*PI/2, 0); - CGContextAddArc(c, bounds.origin.x + bounds.size.width - 4, - bounds.origin.y + 4, 4, 3*PI/2, 0.0, 0); - CGContextReplacePathWithStrokedPath(c); - CGContextClip(c); - CGContextDrawLinearGradient(c, topGradient, start, end, 0); - CFRelease(path); - CFRelease(topGradient); - CGColorSpaceRelease(RGB); -} static void ButtonElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, @@ -464,7 +562,11 @@ static void PaneElementDraw( bounds.origin.y -= kThemeMetricTabFrameOverlap; bounds.size.height += kThemeMetricTabFrameOverlap; BEGIN_DRAWING(d) - ChkErr(HIThemeDrawTabPane, &bounds, &info, dc.context, HIOrientation); + if (TkMacOSXInDarkMode(tkwin)) { + MacOSXDrawDarkGroupBox(bounds, &info, dc.context, tkwin); + } else { + ChkErr(HIThemeDrawTabPane, &bounds, &info, dc.context, HIOrientation); + } END_DRAWING if (winPtr->privatePtr != NULL) { winPtr->privatePtr->flags |= TTK_HAS_DARKER_BG; @@ -502,13 +604,18 @@ static void GroupElementDraw( { TkWindow *winPtr = (TkWindow *)tkwin; CGRect bounds = BoxToRect(d, b); + const HIThemeGroupBoxDrawInfo info = { .version = 0, .state = Ttk_StateTableLookup(ThemeStateTable, state), .kind = kHIThemeGroupBoxKindPrimary, }; BEGIN_DRAWING(d) - ChkErr(HIThemeDrawGroupBox, &bounds, &info, dc.context, HIOrientation); + if (TkMacOSXInDarkMode(tkwin)) { + MacOSXDrawDarkGroupBox(bounds, &info, dc.context, tkwin); + } else { + ChkErr(HIThemeDrawGroupBox, &bounds, &info, dc.context, HIOrientation); + } END_DRAWING if (winPtr->privatePtr != NULL) { winPtr->privatePtr->flags |= TTK_HAS_DARKER_BG; @@ -630,10 +737,6 @@ static Ttk_ElementSpec ComboboxElementSpec = { ComboboxElementDraw }; - - - - /*---------------------------------------------------------------------- * +++ Spinbuttons. * @@ -1018,37 +1121,14 @@ static Ttk_ElementSpec SizegripElementSpec = { * port. The code for handling this is currently commented out. */ + static void FillElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) { - TkWindow *winPtr = (TkWindow *)tkwin; CGRect bounds = BoxToRect(d, b); - int depth = 0; - NSColor *bgColor = [[NSColor windowBackgroundColor] colorUsingColorSpace: - [NSColorSpace deviceRGBColorSpace]]; - CGFloat rgba[4]; BEGIN_DRAWING(d) - for (TkWindow *topPtr = winPtr->parentPtr; topPtr != NULL; - topPtr = topPtr->parentPtr) { - if (topPtr->privatePtr && - (topPtr->privatePtr->flags & TTK_HAS_DARKER_BG)) { - depth++; - } - if (depth > 7) { - break; - } - } - - /* - * Darken the background color one step for each level of nesting. - */ - - [bgColor getComponents: rgba]; - for (int i=0; i<4; i++) { - rgba[i] -= depth*(8.0/255.0); - } - CGContextSetRGBFillColor(dc.context, rgba[0], rgba[1], rgba[2], rgba[3]); + MacOSXSetBoxColor(dc.context, tkwin, 0); CGContextFillRect(dc.context, bounds); //QDSetPatternOrigin(PatternOrigin(tkwin, d)); END_DRAWING @@ -1362,4 +1442,3 @@ int Ttk_MacOSXPlatformInit(Tcl_Interp *interp) * coding: utf-8 * End: */ - -- cgit v0.12 From 576148dc6a8447e707fbf78f83980a626b02d96b Mon Sep 17 00:00:00 2001 From: culler Date: Sun, 10 Mar 2019 16:04:20 +0000 Subject: Add a drawing procedure for a ttk Separator in Dark Mode. Fixed the foreground color for the TreeView in Dark Mode. --- library/ttk/aquaTheme.tcl | 36 +++++++++++-------- macosx/ttkMacOSXTheme.c | 90 ++++++++++++++++++++++++++++------------------- 2 files changed, 75 insertions(+), 51 deletions(-) diff --git a/library/ttk/aquaTheme.tcl b/library/ttk/aquaTheme.tcl index 92cc0d1..6117b94 100644 --- a/library/ttk/aquaTheme.tcl +++ b/library/ttk/aquaTheme.tcl @@ -15,12 +15,15 @@ namespace eval ttk::theme::aqua { -insertwidth 1 ttk::style map . \ - -foreground {disabled systemTtkForeground - background systemTtkForeground} \ - -selectbackground {background systemHighlight - !focus systemHighlightSecondary} \ - -selectforeground {background systemTtkForeground - !focus systemDialogActiveText} + -foreground { + disabled systemTtkForeground + background systemTtkForeground} \ + -selectbackground { + background systemHighlight + !focus systemHighlightSecondary} \ + -selectforeground { + background systemTtkForeground + !focus systemDialogActiveText} # Buttons ttk::style configure TButton -anchor center -width -6 @@ -36,10 +39,11 @@ namespace eval ttk::theme::aqua { ttk::style configure TNotebook -padding {18 8 18 17} ttk::style configure TNotebook.Tab -padding {12 3 12 2} ttk::style configure TNotebook.Tab -foreground white - ttk::style map TNotebook.Tab -foreground { - {background !disabled} black - disabled darkgray - !selected black} + ttk::style map TNotebook.Tab \ + -foreground { + {background !disabled} black + disabled darkgray + !selected black} # Combobox: ttk::style configure TCombobox -postoffset {5 -2 -10 0} @@ -48,11 +52,13 @@ namespace eval ttk::theme::aqua { ttk::style configure Heading -font TkHeadingFont ttk::style configure Treeview -rowheight 18 -background White ttk::style map Treeview \ - -background [list disabled systemDialogBackgroundInactive \ - {selected background} systemHighlightSecondary \ - selected systemHighlight] \ - -foreground [list disabled black \ - selected black] + -background { + disabled systemDialogBackgroundInactive + {selected background} systemHighlightSecondary + selected systemHighlight} \ + -foreground { + disabled black + !disabled black} # Enable animation for ttk::progressbar widget: ttk::style configure TProgressbar -period 100 -maxphase 255 diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index ed22c0c..dea581d 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -173,7 +173,7 @@ static CGFloat darkPopupGradient[8] = {23.0/255, 111.0/255, 232.0/255, 1.0, static void MacOSXDrawDarkButton( CGRect bounds, HIThemeButtonDrawInfo *info, - CGContextRef c) + CGContextRef context) { CGPathRef path; CGColorSpaceRef RGB = CGColorSpaceCreateDeviceRGB(); @@ -191,20 +191,20 @@ static void MacOSXDrawDarkButton( CGPoint end = {bounds.origin.x + 5, bounds.origin.y + 5}; fill = darkButtonFill; - CGContextSetRGBFillColor(c, fill[0], fill[1], fill[2], fill[3]); + CGContextSetRGBFillColor(context, fill[0], fill[1], fill[2], fill[3]); stroke = darkButtonStroke; - CGContextSetRGBStrokeColor(c, stroke[0], stroke[1], stroke[2], stroke[3]); - CGContextSetLineWidth(c, 0.5); - CGContextClipToRect(c, bounds); + CGContextSetRGBStrokeColor(context, stroke[0], stroke[1], stroke[2], stroke[3]); + CGContextSetLineWidth(context, 0.5); + CGContextClipToRect(context, bounds); /* * Fill a rounded rectangle with the dark background color. */ path = CGPathCreateWithRoundedRect(bounds, 4, 4, NULL); - CGContextBeginPath(c); - CGContextAddPath(c, path); - CGContextFillPath(c); + CGContextBeginPath(context); + CGContextAddPath(context, path); + CGContextFillPath(context); /* * Draw the arrow button if this is a popup. @@ -215,44 +215,46 @@ static void MacOSXDrawDarkButton( CGRect arrowBounds = bounds; arrowBounds.size.width = 16; arrowBounds.origin.x += bounds.size.width - 16; - CGContextSaveGState(c); + CGContextSaveGState(context); if (info->state == kThemeStateActive) { CGGradientRef popupGradient = CGGradientCreateWithColorComponents( RGB, darkPopupGradient, NULL, 2); - CGPoint popupStart = {arrowBounds.origin.x + 8, arrowBounds.origin.y}; + CGPoint popupStart = {arrowBounds.origin.x + 8, + arrowBounds.origin.y}; CGPoint popupEnd = {arrowBounds.origin.x + 8, arrowBounds.origin.y + arrowBounds.size.height}; - CGContextBeginPath(c); - CGContextAddPath(c, path); - CGContextClip(c); - CGContextClipToRect(c, arrowBounds); - CGContextDrawLinearGradient(c, popupGradient, popupStart, popupEnd, 0); + CGContextBeginPath(context); + CGContextAddPath(context, path); + CGContextClip(context); + CGContextClipToRect(context, arrowBounds); + CGContextDrawLinearGradient(context, popupGradient, + popupStart, popupEnd, 0); CFRelease(popupGradient); } - CGContextSetRGBStrokeColor(c, 1.0, 1.0, 1.0, 1.0); - CGContextSetLineWidth(c, 1.5); + CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0); + CGContextSetLineWidth(context, 1.5); x = arrowBounds.origin.x + 5; y = arrowBounds.origin.y + trunc(arrowBounds.size.height/2); - CGContextBeginPath(c); - CGPoint bottomArrow[3] = {{x, y + 2}, {x + 3.5, y + 5.5}, {x + 7, y + 2}}; - CGContextAddLines(c, bottomArrow, 3); - CGPoint topArrow[3] = {{x, y - 2}, {x + 3.5, y - 5.5}, {x + 7, y - 2}}; - CGContextAddLines(c, topArrow, 3); - CGContextStrokePath(c); - CGContextRestoreGState(c); + CGContextBeginPath(context); + CGPoint bottomArrow[3] = {{x, y+2}, {x+3.5, y+5.5}, {x+7, y+2}}; + CGContextAddLines(context, bottomArrow, 3); + CGPoint topArrow[3] = {{x, y-2}, {x+3.5, y-5.5}, {x+7, y-2}}; + CGContextAddLines(context, topArrow, 3); + CGContextStrokePath(context); + CGContextRestoreGState(context); } /* * Draw the top border with a transparent white gradient. */ - CGContextBeginPath(c); - CGContextAddArc(c, bounds.origin.x + 4, bounds.origin.y + 4, 4, PI, 3*PI/2, 0); - CGContextAddArc(c, bounds.origin.x + bounds.size.width - 4, + CGContextBeginPath(context); + CGContextAddArc(context, bounds.origin.x + 4, bounds.origin.y + 4, 4, PI, 3*PI/2, 0); + CGContextAddArc(context, bounds.origin.x + bounds.size.width - 4, bounds.origin.y + 4, 4, 3*PI/2, 0.0, 0); - CGContextReplacePathWithStrokedPath(c); - CGContextClip(c); - CGContextDrawLinearGradient(c, topGradient, start, end, 0); + CGContextReplacePathWithStrokedPath(context); + CGContextClip(context); + CGContextDrawLinearGradient(context, topGradient, start, end, 0); CFRelease(path); CFRelease(topGradient); CGColorSpaceRelease(RGB); @@ -267,16 +269,15 @@ static void MacOSXDrawDarkButton( static void MacOSXDrawDarkGroupBox( CGRect bounds, - const HIThemeGroupBoxDrawInfo *info, CGContextRef context, Tk_Window tkwin) { CGPathRef path; NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; NSColor *borderColor; - static CGFloat stroke[4] = {1.0, 1.0, 1.0, 0.25}; + static CGFloat border[4] = {1.0, 1.0, 1.0, 0.25}; MacOSXSetBoxColor(context, tkwin, 1); - borderColor = [NSColor colorWithColorSpace: deviceRGB components: stroke + borderColor = [NSColor colorWithColorSpace: deviceRGB components: border count: 4]; path = CGPathCreateWithRoundedRect(bounds, 4, 4, NULL); CGContextClipToRect(context, bounds); @@ -291,6 +292,19 @@ static void MacOSXDrawDarkGroupBox( CFRelease(path); } +static void MacOSXDrawDarkSeparator( + CGRect bounds, + CGContextRef context, + Tk_Window tkwin) +{ + static CGFloat fill[4] = {1.0, 1.0, 1.0, 0.3}; + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + NSColor *fillColor = [NSColor colorWithColorSpace: deviceRGB + components: fill + count:4]; + CGContextSetFillColorWithColor(context, fillColor.CGColor); + CGContextFillRect(context, bounds); +} /*---------------------------------------------------------------------- * +++ Button element: Used for elements drawn with DrawThemeButton. @@ -563,7 +577,7 @@ static void PaneElementDraw( bounds.size.height += kThemeMetricTabFrameOverlap; BEGIN_DRAWING(d) if (TkMacOSXInDarkMode(tkwin)) { - MacOSXDrawDarkGroupBox(bounds, &info, dc.context, tkwin); + MacOSXDrawDarkGroupBox(bounds, dc.context, tkwin); } else { ChkErr(HIThemeDrawTabPane, &bounds, &info, dc.context, HIOrientation); } @@ -612,7 +626,7 @@ static void GroupElementDraw( }; BEGIN_DRAWING(d) if (TkMacOSXInDarkMode(tkwin)) { - MacOSXDrawDarkGroupBox(bounds, &info, dc.context, tkwin); + MacOSXDrawDarkGroupBox(bounds, dc.context, tkwin); } else { ChkErr(HIThemeDrawGroupBox, &bounds, &info, dc.context, HIOrientation); } @@ -1019,7 +1033,11 @@ static void SeparatorElementDraw( }; BEGIN_DRAWING(d) - ChkErr(HIThemeDrawSeparator, &bounds, &info, dc.context, HIOrientation); + if (TkMacOSXInDarkMode(tkwin)) { + MacOSXDrawDarkSeparator(bounds, dc.context, tkwin); + } else { + ChkErr(HIThemeDrawSeparator, &bounds, &info, dc.context, HIOrientation); + } END_DRAWING } -- cgit v0.12 From 62af69aa8797a1c99370681d5e7d31784c119151 Mon Sep 17 00:00:00 2001 From: culler Date: Sun, 10 Mar 2019 16:11:29 +0000 Subject: Additional Treeview fix. --- library/ttk/aquaTheme.tcl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/library/ttk/aquaTheme.tcl b/library/ttk/aquaTheme.tcl index 6117b94..11574dc 100644 --- a/library/ttk/aquaTheme.tcl +++ b/library/ttk/aquaTheme.tcl @@ -50,15 +50,16 @@ namespace eval ttk::theme::aqua { # Treeview: ttk::style configure Heading -font TkHeadingFont - ttk::style configure Treeview -rowheight 18 -background White + ttk::style configure Treeview -rowheight 18 -background White \ + -foreground black ttk::style map Treeview \ -background { disabled systemDialogBackgroundInactive {selected background} systemHighlightSecondary selected systemHighlight} \ -foreground { - disabled black - !disabled black} + !active black + } # Enable animation for ttk::progressbar widget: ttk::style configure TProgressbar -period 100 -maxphase 255 -- cgit v0.12 From ecdf944613bc935541cc765dbfb03b93ab8d389d Mon Sep 17 00:00:00 2001 From: culler Date: Mon, 11 Mar 2019 14:34:58 +0000 Subject: Fine tune the button appearance. --- library/ttk/aquaTheme.tcl | 1 + macosx/ttkMacOSXTheme.c | 144 +++++++++++++++++++++++++++------------------- 2 files changed, 87 insertions(+), 58 deletions(-) diff --git a/library/ttk/aquaTheme.tcl b/library/ttk/aquaTheme.tcl index 11574dc..df8eb24 100644 --- a/library/ttk/aquaTheme.tcl +++ b/library/ttk/aquaTheme.tcl @@ -27,6 +27,7 @@ namespace eval ttk::theme::aqua { # Buttons ttk::style configure TButton -anchor center -width -6 + #-padding {0 2 0 3} ttk::style configure Toolbutton -padding 4 -foreground black # Workaround for #1100117: # Actually, on Aqua we probably shouldn't stipple images in diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index dea581d..584051d 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -50,6 +50,9 @@ #define RangeToFactor(maximum) (((double) (LONG_MAX >> 1)) / (maximum)) #endif /* __LP64__ */ +#define TTK_STATE_FIRST_TAB TTK_STATE_USER1 +#define TTK_STATE_LAST_TAB TTK_STATE_USER2 + /*---------------------------------------------------------------------- * +++ Utilities. */ @@ -157,6 +160,15 @@ static int MacOSXSetBoxColor( * HITheme in Aqua, since it understands earlier versions of the OS. */ + +static CGFloat darkButtonFill[4] = {112.0/255, 113.0/255, 115.0/255, 1.0}; +static CGFloat darkTopGradient[8] = {1.0, 1.0, 1.0, 0.3, + 1.0, 1.0, 1.0, 0.0}; +static CGFloat darkBackgroundGradient[8] = {0.0, 0.0, 0.0, 0.1, + 0.0, 0.0, 0.0, 0.25}; +static CGFloat darkSelectedGradient[8] = {23.0/255, 111.0/255, 232.0/255, 1.0, + 20.0/255, 94.0/255, 206.0/255, 1.0}; + /* * MacOSXDrawDarkButton -- * @@ -164,73 +176,84 @@ static int MacOSXSetBoxColor( * PopupButtons in the Dark Mode style. */ -static CGFloat darkButtonFill[4] = {107.0/255, 108.0/255, 110.0/255.0, 1.0}; -static CGFloat darkButtonStroke[4] = {1.0, 1.0, 1.0, 0.5}; -static CGFloat darkButtonGradient[8] = {1.0, 1.0, 1.0, 0.45, 1.0, 1.0, 1.0, 0.0}; -static CGFloat darkPopupGradient[8] = {23.0/255, 111.0/255, 232.0/255, 1.0, - 20.0/255, 94.0/255, 206.0/255, 1.0}; - static void MacOSXDrawDarkButton( CGRect bounds, - HIThemeButtonDrawInfo *info, + ThemeButtonKind kind, + Ttk_State state, CGContextRef context) { CGPathRef path; - CGColorSpaceRef RGB = CGColorSpaceCreateDeviceRGB(); - CGGradientRef topGradient = CGGradientCreateWithColorComponents( - RGB, darkButtonGradient, NULL, 2); - CGFloat *fill, *stroke; + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + CGGradientRef topGradient, backgroundGradient, selectedGradient; + NSColor *fill; /* - * Compensate for the missing bottom border on dark buttons. + * Fill the rounded bounded rectangle with a transparent black gradient. */ - bounds.size.height -= 1; - bounds.origin.y += 1; - CGPoint start = {bounds.origin.x + 5, bounds.origin.y}; - CGPoint end = {bounds.origin.x + 5, bounds.origin.y + 5}; - - fill = darkButtonFill; - CGContextSetRGBFillColor(context, fill[0], fill[1], fill[2], fill[3]); - stroke = darkButtonStroke; - CGContextSetRGBStrokeColor(context, stroke[0], stroke[1], stroke[2], stroke[3]); - CGContextSetLineWidth(context, 0.5); + CGContextSetLineWidth(context, 1.0); CGContextClipToRect(context, bounds); + backgroundGradient = CGGradientCreateWithColorComponents( + deviceRGB.CGColorSpace, darkBackgroundGradient, NULL, 2); + CGPoint backgroundEnd = {bounds.origin.x, + bounds.origin.y + bounds.size.height}; + CGContextBeginPath(context); + path = CGPathCreateWithRoundedRect(bounds, 5, 5, NULL); + CGContextAddPath(context, path); + CGContextClip(context); + CGContextDrawLinearGradient(context, backgroundGradient, + bounds.origin, backgroundEnd, 0); + CFRelease(backgroundGradient); + + /* - * Fill a rounded rectangle with the dark background color. + * Fill the button face with the button fill color. */ - + bounds = CGRectInset(bounds, 1, 1); + fill = [NSColor colorWithColorSpace: deviceRGB + components: darkButtonFill + count: 4]; + CGContextSetFillColorWithColor(context, fill.CGColor); path = CGPathCreateWithRoundedRect(bounds, 4, 4, NULL); CGContextBeginPath(context); CGContextAddPath(context, path); CGContextFillPath(context); + CFRelease(path); /* - * Draw the arrow button if this is a popup. + * If this is a popup, draw the arrow button. */ - if (info->kind == kThemePopupButton) { + if (kind == kThemePopupButton) { CGFloat x, y; CGRect arrowBounds = bounds; arrowBounds.size.width = 16; arrowBounds.origin.x += bounds.size.width - 16; CGContextSaveGState(context); - if (info->state == kThemeStateActive) { - CGGradientRef popupGradient = CGGradientCreateWithColorComponents( - RGB, darkPopupGradient, NULL, 2); - CGPoint popupStart = {arrowBounds.origin.x + 8, - arrowBounds.origin.y}; - CGPoint popupEnd = {arrowBounds.origin.x + 8, - arrowBounds.origin.y + arrowBounds.size.height}; + + /* + * If the toplevel is front, paint the button blue. + */ + + if (!(state & TTK_STATE_BACKGROUND)) { + selectedGradient = CGGradientCreateWithColorComponents( + deviceRGB.CGColorSpace, darkSelectedGradient, NULL, 2); + CGPoint arrowEnd = {arrowBounds.origin.x + 8, + arrowBounds.origin.y + arrowBounds.size.height}; CGContextBeginPath(context); CGContextAddPath(context, path); CGContextClip(context); CGContextClipToRect(context, arrowBounds); - CGContextDrawLinearGradient(context, popupGradient, - popupStart, popupEnd, 0); - CFRelease(popupGradient); + CGContextDrawLinearGradient(context, selectedGradient, + arrowBounds.origin, arrowEnd, 0); + CFRelease(selectedGradient); } + + /* + * Stroke the arrows. + */ + CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0); CGContextSetLineWidth(context, 1.5); x = arrowBounds.origin.x + 5; @@ -245,19 +268,23 @@ static void MacOSXDrawDarkButton( } /* - * Draw the top border with a transparent white gradient. + * Accent the top border with a transparent white gradient. */ + CGPoint topEnd = {bounds.origin.x, bounds.origin.y + 3}; + topGradient = CGGradientCreateWithColorComponents( + deviceRGB.CGColorSpace, darkTopGradient, NULL, 2); + CGContextSaveGState(context); CGContextBeginPath(context); - CGContextAddArc(context, bounds.origin.x + 4, bounds.origin.y + 4, 4, PI, 3*PI/2, 0); + CGContextAddArc(context, bounds.origin.x + 4, bounds.origin.y + 4, + 4, PI, 3*PI/2, 0); CGContextAddArc(context, bounds.origin.x + bounds.size.width - 4, - bounds.origin.y + 4, 4, 3*PI/2, 0.0, 0); + bounds.origin.y + 4, 4, 3*PI/2, 0, 0); CGContextReplacePathWithStrokedPath(context); CGContextClip(context); - CGContextDrawLinearGradient(context, topGradient, start, end, 0); - CFRelease(path); + CGContextDrawLinearGradient(context, topGradient, bounds.origin, topEnd, 0.0); + CGContextRestoreGState(context); CFRelease(topGradient); - CGColorSpaceRelease(RGB); } /* @@ -399,9 +426,14 @@ static void ButtonElementSize( &scratchBounds, &info, &contentBounds); paddingPtr->left = CGRectGetMinX(contentBounds); - paddingPtr->top = CGRectGetMinY(contentBounds); paddingPtr->right = CGRectGetMaxX(scratchBounds) - CGRectGetMaxX(contentBounds) + 1; - paddingPtr->bottom = CGRectGetMaxY(scratchBounds) - CGRectGetMaxY(contentBounds); + if (TkMacOSXInDarkMode(tkwin)) { + paddingPtr->top = CGRectGetMinY(contentBounds) + 2; + paddingPtr->bottom = CGRectGetMaxY(scratchBounds) - CGRectGetMaxY(contentBounds) + 3; + } else { + paddingPtr->top = CGRectGetMinY(contentBounds) + 3; + paddingPtr->bottom = CGRectGetMaxY(scratchBounds) - CGRectGetMaxY(contentBounds) + 2; + } /* * Now add a little extra padding to account for drop shadows. @@ -425,7 +457,7 @@ static void ButtonElementDraw( if (TkMacOSXInDarkMode(tkwin) && (info.kind == kThemePushButton || info.kind == kThemePopupButton)) { - MacOSXDrawDarkButton(bounds, &info, dc.context); + MacOSXDrawDarkButton(bounds, info.kind, state, dc.context); } else { ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); } @@ -447,12 +479,10 @@ static Ttk_ElementSpec ButtonElementSpec = { /* Tab position logic, c.f. ttkNotebook.c TabState() */ -#define TTK_STATE_NOTEBOOK_FIRST TTK_STATE_USER1 -#define TTK_STATE_NOTEBOOK_LAST TTK_STATE_USER2 static Ttk_StateTable TabStyleTable[] = { - { kThemeTabFrontInactive, TTK_STATE_SELECTED|TTK_STATE_BACKGROUND}, + { kThemeTabFrontInactive, TTK_STATE_SELECTED | TTK_STATE_BACKGROUND}, { kThemeTabNonFrontInactive, TTK_STATE_BACKGROUND}, - { kThemeTabFrontUnavailable, TTK_STATE_DISABLED|TTK_STATE_SELECTED}, + { kThemeTabFrontUnavailable, TTK_STATE_DISABLED | TTK_STATE_SELECTED}, { kThemeTabNonFrontUnavailable, TTK_STATE_DISABLED}, { kThemeTabFront, TTK_STATE_SELECTED}, { kThemeTabNonFrontPressed, TTK_STATE_PRESSED}, @@ -460,18 +490,16 @@ static Ttk_StateTable TabStyleTable[] = { }; static Ttk_StateTable TabAdornmentTable[] = { - { kHIThemeTabAdornmentNone, - TTK_STATE_NOTEBOOK_FIRST|TTK_STATE_NOTEBOOK_LAST}, - {kHIThemeTabAdornmentTrailingSeparator, TTK_STATE_NOTEBOOK_FIRST}, - {kHIThemeTabAdornmentNone, TTK_STATE_NOTEBOOK_LAST}, - {kHIThemeTabAdornmentTrailingSeparator, 0 }, + { kHIThemeTabAdornmentNone, TTK_STATE_FIRST_TAB | TTK_STATE_LAST_TAB}, + { kHIThemeTabAdornmentTrailingSeparator, TTK_STATE_FIRST_TAB}, + { kHIThemeTabAdornmentNone, TTK_STATE_LAST_TAB}, + { kHIThemeTabAdornmentTrailingSeparator, 0 }, }; static Ttk_StateTable TabPositionTable[] = { - { kHIThemeTabPositionOnly, - TTK_STATE_NOTEBOOK_FIRST|TTK_STATE_NOTEBOOK_LAST}, - { kHIThemeTabPositionFirst, TTK_STATE_NOTEBOOK_FIRST}, - { kHIThemeTabPositionLast, TTK_STATE_NOTEBOOK_LAST}, + { kHIThemeTabPositionOnly, TTK_STATE_FIRST_TAB | TTK_STATE_LAST_TAB}, + { kHIThemeTabPositionFirst, TTK_STATE_FIRST_TAB}, + { kHIThemeTabPositionLast, TTK_STATE_LAST_TAB}, { kHIThemeTabPositionMiddle, 0 }, }; -- cgit v0.12 From cc0838e96eb2896404e634bea95769c4fd7ebd76 Mon Sep 17 00:00:00 2001 From: culler Date: Mon, 11 Mar 2019 16:18:42 +0000 Subject: Add colors systemControlTextColor and systemDisabledControlTextColor and use them for ttk buttons. These colors adapt to Dark Mode. --- library/ttk/aquaTheme.tcl | 19 +++++++++++-------- macosx/tkMacOSXColor.c | 22 ++++++++++++++++++---- macosx/ttkMacOSXTheme.c | 11 +++++++++-- 3 files changed, 38 insertions(+), 14 deletions(-) diff --git a/library/ttk/aquaTheme.tcl b/library/ttk/aquaTheme.tcl index df8eb24..01ce869 100644 --- a/library/ttk/aquaTheme.tcl +++ b/library/ttk/aquaTheme.tcl @@ -8,26 +8,29 @@ namespace eval ttk::theme::aqua { ttk::style configure . \ -font TkDefaultFont \ -background systemWindowBody \ - -foreground systemTtkForeground \ + -foreground systemLabelColor \ -selectbackground systemHighlight \ - -selectforeground systemTtkForeground \ + -selectforeground systemLabelColor \ -selectborderwidth 0 \ -insertwidth 1 ttk::style map . \ -foreground { - disabled systemTtkForeground - background systemTtkForeground} \ + disabled systemLabelColor + background systemLabelColor} \ -selectbackground { background systemHighlight !focus systemHighlightSecondary} \ -selectforeground { - background systemTtkForeground + background systemLabelColor !focus systemDialogActiveText} # Buttons - ttk::style configure TButton -anchor center -width -6 - #-padding {0 2 0 3} + ttk::style configure TButton -anchor center -width -6 \ + -foreground systemControlTextColor + ttk::style map TButton \ + -foreground { + disabled systemDisabledControlTextColor} ttk::style configure Toolbutton -padding 4 -foreground black # Workaround for #1100117: # Actually, on Aqua we probably shouldn't stipple images in @@ -43,7 +46,7 @@ namespace eval ttk::theme::aqua { ttk::style map TNotebook.Tab \ -foreground { {background !disabled} black - disabled darkgray + disabled darkGray !selected black} # Combobox: diff --git a/macosx/tkMacOSXColor.c b/macosx/tkMacOSXColor.c index fd2326c..985b09b 100644 --- a/macosx/tkMacOSXColor.c +++ b/macosx/tkMacOSXColor.c @@ -197,10 +197,12 @@ static const struct SystemColorMapEntry systemColorMap[] = { { "TtkBackground5", ttkBackground, 5 }, /* 171 */ { "TtkBackground6", ttkBackground, 6 }, /* 172 */ { "TtkBackground7", ttkBackground, 7 }, /* 173 */ - { "TtkForeground", ttkForeground, 0 }, /* 174 */ + { "LabelColor", ttkForeground, 0 }, /* 174 */ + { "ControlTextColor", ttkForeground, 1 }, /* 175 */ + { "DisabledControlTextColor", ttkForeground, 2 }, /* 176 */ { NULL, 0, 0 } }; -#define MAX_PIXELCODE 174 +#define MAX_PIXELCODE 176 /* *---------------------------------------------------------------------- @@ -282,8 +284,20 @@ SetCGColorComponents( } break; case ttkForeground: - fgColor = [[NSColor labelColor] colorUsingColorSpace: - [NSColorSpace deviceRGBColorSpace]]; + switch (entry.value) { + case 1: + fgColor = [[NSColor controlTextColor] colorUsingColorSpace: + [NSColorSpace deviceRGBColorSpace]]; + break; + case 2: + fgColor = [[NSColor disabledControlTextColor] colorUsingColorSpace: + [NSColorSpace deviceRGBColorSpace]]; + break; + default: + fgColor = [[NSColor labelColor] colorUsingColorSpace: + [NSColorSpace deviceRGBColorSpace]]; + break; + } [fgColor getComponents: rgba]; break; case clearColor: diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index 584051d..bb85773 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -162,6 +162,7 @@ static int MacOSXSetBoxColor( static CGFloat darkButtonFill[4] = {112.0/255, 113.0/255, 115.0/255, 1.0}; +static CGFloat darkDisabledButtonFill[4] = {86.0/255, 87.0/255, 89.0/255, 1.0}; static CGFloat darkTopGradient[8] = {1.0, 1.0, 1.0, 0.3, 1.0, 1.0, 1.0, 0.0}; static CGFloat darkBackgroundGradient[8] = {0.0, 0.0, 0.0, 0.1, @@ -211,9 +212,15 @@ static void MacOSXDrawDarkButton( * Fill the button face with the button fill color. */ bounds = CGRectInset(bounds, 1, 1); + if (state & TTK_STATE_DISABLED) { fill = [NSColor colorWithColorSpace: deviceRGB - components: darkButtonFill + components: darkDisabledButtonFill count: 4]; + } else { + fill = [NSColor colorWithColorSpace: deviceRGB + components: darkButtonFill + count: 4]; + } CGContextSetFillColorWithColor(context, fill.CGColor); path = CGPathCreateWithRoundedRect(bounds, 4, 4, NULL); CGContextBeginPath(context); @@ -1185,7 +1192,7 @@ static void BackgroundElementDraw( Drawable d, Ttk_Box b, unsigned int state) { FillElementDraw(clientData, elementRecord, tkwin, d, Ttk_WinBox(tkwin), - state); + state); } static Ttk_ElementSpec FillElementSpec = { -- cgit v0.12 From ce316903413a6a66f75fc4efa83b0263757fe6d5 Mon Sep 17 00:00:00 2001 From: culler Date: Tue, 12 Mar 2019 16:08:54 +0000 Subject: Added a drawing procedure for notebook tabs in Dark Mode. --- library/ttk/aquaTheme.tcl | 7 +- macosx/tkMacOSXColor.c | 17 +++-- macosx/ttkMacOSXTheme.c | 166 ++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 178 insertions(+), 12 deletions(-) diff --git a/library/ttk/aquaTheme.tcl b/library/ttk/aquaTheme.tcl index 01ce869..9dfa1be 100644 --- a/library/ttk/aquaTheme.tcl +++ b/library/ttk/aquaTheme.tcl @@ -45,9 +45,10 @@ namespace eval ttk::theme::aqua { ttk::style configure TNotebook.Tab -foreground white ttk::style map TNotebook.Tab \ -foreground { - {background !disabled} black - disabled darkGray - !selected black} + {background !disabled !selected} systemControlTextColor + {background selected} black + disabled systemDisabledControlTextColor + !selected systemControlTextColor} # Combobox: ttk::style configure TCombobox -postoffset {5 -2 -10 0} diff --git a/macosx/tkMacOSXColor.c b/macosx/tkMacOSXColor.c index 985b09b..1aef9bc 100644 --- a/macosx/tkMacOSXColor.c +++ b/macosx/tkMacOSXColor.c @@ -269,7 +269,7 @@ SetCGColorComponents( switch (entry.type) { case HIBrush: err = ChkErr(HIThemeBrushCreateCGColor, entry.value, c); - break; + return err; case rgbColor: rgba[0] = ((pixel >> 16) & 0xff) / 255.0; rgba[1] = ((pixel >> 8) & 0xff) / 255.0; @@ -294,9 +294,15 @@ SetCGColorComponents( [NSColorSpace deviceRGBColorSpace]]; break; default: - fgColor = [[NSColor labelColor] colorUsingColorSpace: - [NSColorSpace deviceRGBColorSpace]]; - break; + if ([NSApp macMinorVersion] < 10) { + err = ChkErr(HIThemeBrushCreateCGColor, + kThemeBrushDialogBackgroundActive, c); + return err; + } else { + fgColor = [[NSColor labelColor] colorUsingColorSpace: + [NSColorSpace deviceRGBColorSpace]]; + break; + } } [fgColor getComponents: rgba]; break; @@ -337,9 +343,10 @@ SetCGColorComponents( MODULE_SCOPE Bool TkMacOSXInDarkMode(Tk_Window tkwin) { + static NSAppearanceName darkAqua = @"NSAppearanceNameDarkAqua"; TkWindow *winPtr = (TkWindow*)tkwin; NSView *view = TkMacOSXDrawableView(winPtr->privatePtr); - if (view && [view.effectiveAppearance.name isEqualToString:NSAppearanceNameDarkAqua]) { + if (view && [view.effectiveAppearance.name isEqualToString:darkAqua]) { return True; } else { return false; diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index bb85773..896fec3 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -163,6 +163,8 @@ static int MacOSXSetBoxColor( static CGFloat darkButtonFill[4] = {112.0/255, 113.0/255, 115.0/255, 1.0}; static CGFloat darkDisabledButtonFill[4] = {86.0/255, 87.0/255, 89.0/255, 1.0}; +static CGFloat darkInactiveSelectedTab[4] = {159.0/255, 160.0/255, 161.0/255, 1.0}; +static CGFloat darkTabSeparator[4] = {0.0, 0.0, 0.0, 0.25}; static CGFloat darkTopGradient[8] = {1.0, 1.0, 1.0, 0.3, 1.0, 1.0, 1.0, 0.0}; static CGFloat darkBackgroundGradient[8] = {0.0, 0.0, 0.0, 0.1, @@ -189,7 +191,7 @@ static void MacOSXDrawDarkButton( NSColor *fill; /* - * Fill the rounded bounded rectangle with a transparent black gradient. + * Fill the rounded bounding rectangle with a transparent black gradient. */ CGContextSetLineWidth(context, 1.0); @@ -213,7 +215,7 @@ static void MacOSXDrawDarkButton( */ bounds = CGRectInset(bounds, 1, 1); if (state & TTK_STATE_DISABLED) { - fill = [NSColor colorWithColorSpace: deviceRGB + fill = [NSColor colorWithColorSpace: deviceRGB components: darkDisabledButtonFill count: 4]; } else { @@ -246,7 +248,7 @@ static void MacOSXDrawDarkButton( if (!(state & TTK_STATE_BACKGROUND)) { selectedGradient = CGGradientCreateWithColorComponents( deviceRGB.CGColorSpace, darkSelectedGradient, NULL, 2); - CGPoint arrowEnd = {arrowBounds.origin.x + 8, + CGPoint arrowEnd = {arrowBounds.origin.x, arrowBounds.origin.y + arrowBounds.size.height}; CGContextBeginPath(context); CGContextAddPath(context, path); @@ -295,6 +297,158 @@ static void MacOSXDrawDarkButton( } /* + * MacOSXDrawDarkTab -- + * + * This is a standalone drawing procedure which draws Tabbed Pane + * Tabs in the Dark Mode style. + */ + +static void MacOSXDrawDarkTab( + CGRect bounds, + Ttk_State state, + CGContextRef context) +{ + CGPathRef path; + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + CGGradientRef topGradient, backgroundGradient, selectedGradient; + NSColor *fill, *stroke; + CGRect originalBounds= bounds; + + CGContextSetLineWidth(context, 1.0); + CGContextClipToRect(context, bounds); + + /* + * Extend the bounds to one or both sides so the rounded part will be + * clipped off. + */ + + if (!(state & TTK_STATE_FIRST_TAB)) { + bounds.origin.x -= 10; + bounds.size.width += 10; + } + + if (!(state & TTK_STATE_LAST_TAB)) { + bounds.size.width += 10; + } + + + /* + * Fill the rounded bounding rectangle with a transparent black gradient. + */ + + backgroundGradient = CGGradientCreateWithColorComponents( + deviceRGB.CGColorSpace, darkBackgroundGradient, NULL, 2); + CGPoint backgroundEnd = {bounds.origin.x, + bounds.origin.y + bounds.size.height}; + CGContextBeginPath(context); + path = CGPathCreateWithRoundedRect(bounds, 5, 5, NULL); + CGContextAddPath(context, path); + CGContextClip(context); + CGContextDrawLinearGradient(context, backgroundGradient, + bounds.origin, backgroundEnd, 0); + CFRelease(backgroundGradient); + bounds = CGRectInset(bounds, 1, 1); + + /* + * Fill the button face with the button fill color. Use the + * background color if the tab is not selected, otherwise the + * blue or gray gradient. + */ + + if (!(state & TTK_STATE_SELECTED)) { + if (state & TTK_STATE_DISABLED) { + fill = [NSColor colorWithColorSpace: deviceRGB + components: darkDisabledButtonFill + count: 4]; + } else { + fill = [NSColor colorWithColorSpace: deviceRGB + components: darkButtonFill + count: 4]; + } + CGContextSetFillColorWithColor(context, fill.CGColor); + path = CGPathCreateWithRoundedRect(bounds, 4, 4, NULL); + CGContextBeginPath(context); + CGContextAddPath(context, path); + CGContextFillPath(context); + CFRelease(path); + + /* + * Draw a separator line on the left side of the tab if it + * not first. + */ + + if (!(state & TTK_STATE_FIRST_TAB)) { + CGContextSaveGState(context); + CGContextSetShouldAntialias(context, false); + stroke = [NSColor colorWithColorSpace: deviceRGB + components: darkTabSeparator + count: 4]; + CGContextSetStrokeColorWithColor(context, stroke.CGColor); + CGContextBeginPath(context); + CGContextMoveToPoint(context, originalBounds.origin.x, + originalBounds.origin.y + 1); + CGContextAddLineToPoint(context, originalBounds.origin.x, + originalBounds.origin.y + originalBounds.size.height - 1); + CGContextStrokePath(context); + CGContextRestoreGState(context); + } + } else { + + /* + * This is the selected tab; paint it. If it is first, cover up + * the separator line drawn by the second one. + */ + if ((state && TTK_STATE_FIRST_TAB) && !(state && TTK_STATE_LAST_TAB)) { + bounds.size.width += 1; + } + + if (!(state & TTK_STATE_BACKGROUND)) { + selectedGradient = CGGradientCreateWithColorComponents( + deviceRGB.CGColorSpace, darkSelectedGradient, NULL, 2); + CGPoint end = {bounds.origin.x, bounds.origin.y + bounds.size.height}; + path = CGPathCreateWithRoundedRect(bounds, 4, 4, NULL); + CGContextBeginPath(context); + CGContextAddPath(context, path); + CGContextClip(context); + CGContextDrawLinearGradient(context, selectedGradient, + bounds.origin, end, 0); + CFRelease(path); + CFRelease(selectedGradient); + } else { + fill = [NSColor colorWithColorSpace: deviceRGB + components: darkInactiveSelectedTab + count: 4]; + CGContextSetFillColorWithColor(context, fill.CGColor); + path = CGPathCreateWithRoundedRect(bounds, 4, 4, NULL); + CGContextBeginPath(context); + CGContextAddPath(context, path); + CGContextFillPath(context); + CFRelease(path); + } + + /* + * Accent the top border with a transparent white gradient. + */ + + CGPoint topEnd = {bounds.origin.x, bounds.origin.y + 3}; + topGradient = CGGradientCreateWithColorComponents( + deviceRGB.CGColorSpace, darkTopGradient, NULL, 2); + CGContextSaveGState(context); + CGContextBeginPath(context); + CGContextAddArc(context, bounds.origin.x + 4, bounds.origin.y + 4, + 4, PI, 3*PI/2, 0); + CGContextAddArc(context, bounds.origin.x + bounds.size.width - 4, + bounds.origin.y + 4, 4, 3*PI/2, 0, 0); + CGContextReplacePathWithStrokedPath(context); + CGContextClip(context); + CGContextDrawLinearGradient(context, topGradient, bounds.origin, + topEnd, 0.0); + CFRelease(topGradient); + CGContextRestoreGState(context); + } +} + +/* * MacOSXDrawDarkGroupBox -- * * This is a standalone drawing procedure which draws the contrasting @@ -572,7 +726,11 @@ static void TabElementDraw( .position = Ttk_StateTableLookup(TabPositionTable, state), }; BEGIN_DRAWING(d) - ChkErr(HIThemeDrawTab, &bounds, &info, dc.context, HIOrientation, NULL); + if (TkMacOSXInDarkMode(tkwin)) { + MacOSXDrawDarkTab(bounds, state, dc.context); + } else { + ChkErr(HIThemeDrawTab, &bounds, &info, dc.context, HIOrientation, NULL); + } END_DRAWING } -- cgit v0.12 From e7744246f0f00326c78f6c3dcf6d3cdc4637ba22 Mon Sep 17 00:00:00 2001 From: culler Date: Tue, 12 Mar 2019 16:24:32 +0000 Subject: Fixed a typo. --- macosx/ttkMacOSXTheme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index 896fec3..d6b9d38 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -398,7 +398,7 @@ static void MacOSXDrawDarkTab( * This is the selected tab; paint it. If it is first, cover up * the separator line drawn by the second one. */ - if ((state && TTK_STATE_FIRST_TAB) && !(state && TTK_STATE_LAST_TAB)) { + if ((state & TTK_STATE_FIRST_TAB) && !(state & TTK_STATE_LAST_TAB)) { bounds.size.width += 1; } -- cgit v0.12 From 200838bcb00126575a4fa1037adfd6337357a83b Mon Sep 17 00:00:00 2001 From: culler Date: Wed, 13 Mar 2019 13:30:52 +0000 Subject: Make the GroupBox render correctly on High Sierra. --- macosx/ttkMacOSXTheme.c | 205 ++++++++++++++++++++++++++---------------------- 1 file changed, 112 insertions(+), 93 deletions(-) diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index d6b9d38..1cad90c 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -97,24 +97,38 @@ static Ttk_StateTable ThemeStateTable[] = { }; /*---------------------------------------------------------------------- - * +++ Support for contrasting background colors when nesting GroupBoxes - * or Tabbed panes. + * +++ Support for contrasting background colors when GroupBoxes + * or Tabbed panes are nested inside each other. */ -static int MacOSXSetBoxColor( +/* + * For systems older than 10.14, [NSColor windowBackGroundColor] generates + * garbage when called from this function. In 10.14 it works correctly, + * and must be used in order to have a background color which responds + * to Dark Mode. So we use this hard-wired RGBA color on the older systems + * which don't support Dark Mode anyway. + */ + +static CGFloat windowBackground[4] = {235.0/255, 235.0/255, 235.0/255, 1.0}; + +static int MacOSXGetBoxColor( CGContextRef context, Tk_Window tkwin, - int depth) + int depth, + CGFloat *fill) { TkWindow *winPtr = (TkWindow *)tkwin; NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; - NSColor *windowColor = [[NSColor windowBackgroundColor] - colorUsingColorSpace: deviceRGB]; - NSColor *bgColor; - CGFloat intensity, fill[4]; - [windowColor getComponents: fill]; - intensity = fill[0] + fill[1] + fill[2]; - int isDark = (intensity < 1.5); + if ([NSApp macMinorVersion] > 13) { + NSColor *windowColor = [[NSColor windowBackgroundColor] + colorUsingColorSpace: deviceRGB]; + [windowColor getComponents: fill]; + } else { + for (int i = 0; i < 4; i++) { + fill[i] = windowBackground[i]; + } + } + int isDark = (fill[0] + fill[1] + fill[2] < 1.5); /* * Compute the nesting depth of the widget. @@ -144,11 +158,44 @@ static int MacOSXSetBoxColor( fill[i] -= (depth*8.0)/255.0; } } + return depth; +} + +/* + * MacOSXDrawDarkGroupBox -- + * + * This is a standalone drawing procedure which draws the contrasting + * rounded rectangular box for LabelFrames and Notebook panes. + */ + +static void MacOSXDrawGroupBox( + CGRect bounds, + CGContextRef context, + Tk_Window tkwin) +{ + CGPathRef path; + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + NSColor *borderColor, *bgColor; + static CGFloat border[4] = {1.0, 1.0, 1.0, 0.25}; + CGFloat fill[4]; + MacOSXGetBoxColor(context, tkwin, 1, fill); bgColor = [NSColor colorWithColorSpace: deviceRGB components: fill count: 4]; CGContextSetFillColorSpace(context, deviceRGB.CGColorSpace); CGContextSetFillColorWithColor(context, bgColor.CGColor); - return depth; + path = CGPathCreateWithRoundedRect(bounds, 4, 4, NULL); + CGContextClipToRect(context, bounds); + CGContextBeginPath(context); + CGContextAddPath(context, path); + CGContextFillPath(context); + borderColor = [NSColor colorWithColorSpace: deviceRGB components: border + count: 4]; + CGContextSetFillColorWithColor(context, borderColor.CGColor); + CGContextBeginPath(context); + CGContextAddPath(context, path); + CGContextReplacePathWithStrokedPath(context); + CGContextFillPath(context); + CFRelease(path); } /*---------------------------------------------------------------------- @@ -313,7 +360,7 @@ static void MacOSXDrawDarkTab( CGGradientRef topGradient, backgroundGradient, selectedGradient; NSColor *fill, *stroke; CGRect originalBounds= bounds; - + CGContextSetLineWidth(context, 1.0); CGContextClipToRect(context, bounds); @@ -331,7 +378,6 @@ static void MacOSXDrawDarkTab( bounds.size.width += 10; } - /* * Fill the rounded bounding rectangle with a transparent black gradient. */ @@ -348,10 +394,10 @@ static void MacOSXDrawDarkTab( bounds.origin, backgroundEnd, 0); CFRelease(backgroundGradient); bounds = CGRectInset(bounds, 1, 1); - + /* * Fill the button face with the button fill color. Use the - * background color if the tab is not selected, otherwise the + * background color if the tab is not selected, otherwise use a * blue or gray gradient. */ @@ -393,11 +439,12 @@ static void MacOSXDrawDarkTab( CGContextRestoreGState(context); } } else { - + /* * This is the selected tab; paint it. If it is first, cover up * the separator line drawn by the second one. */ + if ((state & TTK_STATE_FIRST_TAB) && !(state & TTK_STATE_LAST_TAB)) { bounds.size.width += 1; } @@ -449,37 +496,12 @@ static void MacOSXDrawDarkTab( } /* - * MacOSXDrawDarkGroupBox -- + * MacOSXDrawDarkSeparator -- * - * This is a standalone drawing procedure which draws the contrasting - * rounded rectangular contrasting box for Labelframes and Notebook panes + * This is a standalone drawing procedure which draws a separator widget + * in Dark Mode. */ -static void MacOSXDrawDarkGroupBox( - CGRect bounds, - CGContextRef context, - Tk_Window tkwin) -{ - CGPathRef path; - NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; - NSColor *borderColor; - static CGFloat border[4] = {1.0, 1.0, 1.0, 0.25}; - MacOSXSetBoxColor(context, tkwin, 1); - borderColor = [NSColor colorWithColorSpace: deviceRGB components: border - count: 4]; - path = CGPathCreateWithRoundedRect(bounds, 4, 4, NULL); - CGContextClipToRect(context, bounds); - CGContextBeginPath(context); - CGContextAddPath(context, path); - CGContextFillPath(context); - CGContextSetFillColorWithColor(context, borderColor.CGColor); - CGContextBeginPath(context); - CGContextAddPath(context, path); - CGContextReplacePathWithStrokedPath(context); - CGContextFillPath(context); - CFRelease(path); -} - static void MacOSXDrawDarkSeparator( CGRect bounds, CGContextRef context, @@ -501,7 +523,7 @@ static void MacOSXDrawDarkSeparator( /* * Extra margins to account for drop shadow. */ -static Ttk_Padding ButtonMargins = {2,2,2,2}; +static Ttk_Padding ButtonMargins = {2, 2, 2, 2}; #define NoThemeMetric 0xFFFFFFFF @@ -538,6 +560,7 @@ static Ttk_StateTable ButtonAdornmentTable[] = { * computeButtonDrawInfo -- * Fill in an appearance manager HIThemeButtonDrawInfo record. */ + static inline HIThemeButtonDrawInfo computeButtonDrawInfo( ThemeButtonParams *params, Ttk_State state) { @@ -583,6 +606,7 @@ static void ButtonElementSize( * for the content bounds of a dummy rectangle, then use * the difference as the padding. */ + ChkErr(HIThemeGetButtonContentBounds, &scratchBounds, &info, &contentBounds); @@ -745,6 +769,7 @@ static Ttk_ElementSpec TabElementSpec = { /* * Notebook panes: */ + static void PaneElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) @@ -757,26 +782,16 @@ static void PaneElementDraw( Drawable d, Ttk_Box b, Ttk_State state) { TkWindow *winPtr = (TkWindow *)tkwin; + MacDrawable *macWin = winPtr->privatePtr; CGRect bounds = BoxToRect(d, b); - HIThemeTabPaneDrawInfo info = { - .version = 1, - .state = Ttk_StateTableLookup(ThemeStateTable, state), - .direction = kThemeTabNorth, - .size = kHIThemeTabSizeNormal, - .kind = kHIThemeTabKindNormal, - .adornment = kHIThemeTabPaneAdornmentNormal, - }; bounds.origin.y -= kThemeMetricTabFrameOverlap; bounds.size.height += kThemeMetricTabFrameOverlap; BEGIN_DRAWING(d) - if (TkMacOSXInDarkMode(tkwin)) { - MacOSXDrawDarkGroupBox(bounds, dc.context, tkwin); - } else { - ChkErr(HIThemeDrawTabPane, &bounds, &info, dc.context, HIOrientation); - } + MacOSXDrawGroupBox(bounds, dc.context, tkwin); END_DRAWING - if (winPtr->privatePtr != NULL) { - winPtr->privatePtr->flags |= TTK_HAS_DARKER_BG; + [TkMacOSXDrawableView(macWin) setNeedsDisplay:YES]; + if (macWin != NULL) { + macWin->flags |= TTK_HAS_DARKER_BG; } } @@ -798,6 +813,7 @@ static Ttk_ElementSpec PaneElementSpec = { * "Maximum of 2 pixels thick" is apparently a lie; * looks more like 4 to me with shading. */ + static void GroupElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) @@ -812,17 +828,8 @@ static void GroupElementDraw( TkWindow *winPtr = (TkWindow *)tkwin; CGRect bounds = BoxToRect(d, b); - const HIThemeGroupBoxDrawInfo info = { - .version = 0, - .state = Ttk_StateTableLookup(ThemeStateTable, state), - .kind = kHIThemeGroupBoxKindPrimary, - }; BEGIN_DRAWING(d) - if (TkMacOSXInDarkMode(tkwin)) { - MacOSXDrawDarkGroupBox(bounds, dc.context, tkwin); - } else { - ChkErr(HIThemeDrawGroupBox, &bounds, &info, dc.context, HIOrientation); - } + MacOSXDrawGroupBox(bounds, dc.context, tkwin); END_DRAWING if (winPtr->privatePtr != NULL) { winPtr->privatePtr->flags |= TTK_HAS_DARKER_BG; @@ -878,6 +885,7 @@ static void EntryElementDraw( /* * Erase w/background color: */ + XFillRectangle(Tk_Display(tkwin), d, Tk_3DBorderGC(tkwin, backgroundPtr, TK_3D_FLAT_GC), inner.x,inner.y, inner.width, inner.height); @@ -1245,6 +1253,7 @@ static Ttk_ElementSpec SeparatorElementSpec = { /*---------------------------------------------------------------------- * +++ Size grip element. */ + static const ThemeGrowDirection sizegripGrowDirection = kThemeGrowRight|kThemeGrowDown; @@ -1303,28 +1312,29 @@ static Ttk_ElementSpec SizegripElementSpec = { * not allowing user control of the background or highlight colors of ttk * widgets. * - * The first attempt at implementing this attempted to match colors by - * drawing all widgets with the system background color used for dialog - * windows. (In particular, ttk widgets were meant for use in windows like - * those in the Apple preferences application.) The code chose either the - * active background or the inactive background based on the ttk state. - * (Note that current OS releases use the same color #ebebeb in both - * states.) + * This job is made more complicated 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. * - * Unfortunately, there is a problem with this approach. The Appkit - * GroupBox (used for ttk LabelFrames) and TabbedPane (used for the Notebook - * widget) both place their content inside a rectangle with rounded corners - * which is darker than 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. In this case the inner widget uses an even - * darker rounded rectangle. In Mojave's preferences panes, these darker - * gray colors appear to be #e3e4e3 and #dbdcdb respectively. The first of - * these is close but not quite equal to the system color - * BackgroundSecondaryGroupBox, which appears to be #e3e3e3. The HITheme - * library, which we use to draw these widgets, uses #e2e3e3, which again is - * slightly different. Since none of these quite match, we use a hardwired - * RGB color which matches that used by HITheme. + * Previous Tk releases used the HIThemeDrawGroupBox routine 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 + * system background color. If widgets inside the box were drawn with the + * system background color the backgrounds would match. But this produces a + * GroupBox with no contrast, so the only visual clue is a faint + * highlighting around the top of the GroupBox. Moreover, the TabbedPane + * does not have an Opaque version, so while it is drawn inside a + * contrasting rounded rectangle, the widgets inside the pane needed to be + * enclosed in a frame with the system background color. This added a visual + * artifact since the frame's background color does not match the Pane's + * background color. That code has been replaced with the standalone + * drawing procedure macOSXDrawGroupBox, which draws a rounded rectangle + * with an appropriate contrasting background color. * * Patterned backgrounds, which are now obsolete, should be aligned with the * coordinate system of the top-level window. Apparently failing to do this @@ -1339,7 +1349,14 @@ static void FillElementDraw( { CGRect bounds = BoxToRect(d, b); BEGIN_DRAWING(d) - MacOSXSetBoxColor(dc.context, tkwin, 0); + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + NSColor *bgColor; + CGFloat fill[4]; + MacOSXGetBoxColor(dc.context, tkwin, 0, fill); + bgColor = [NSColor colorWithColorSpace: deviceRGB components: fill + count: 4]; + CGContextSetFillColorSpace(dc.context, deviceRGB.CGColorSpace); + CGContextSetFillColorWithColor(dc.context, bgColor.CGColor); CGContextFillRect(dc.context, bounds); //QDSetPatternOrigin(PatternOrigin(tkwin, d)); END_DRAWING @@ -1382,6 +1399,7 @@ static Ttk_ElementSpec BackgroundElementSpec = { * /apple_ref/doc/uid/TP30000243/C005321> * */ + static void ToolbarBackgroundElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) @@ -1456,6 +1474,7 @@ static Ttk_ElementSpec TreeHeaderElementSpec = { /* * Disclosure triangle: */ + #define TTK_TREEVIEW_STATE_OPEN TTK_STATE_USER1 #define TTK_TREEVIEW_STATE_LEAF TTK_STATE_USER2 static Ttk_StateTable DisclosureValueTable[] = { -- cgit v0.12 From 5dfba62ce57f046cbc029d1d598dd4ceefba668d Mon Sep 17 00:00:00 2001 From: culler Date: Wed, 13 Mar 2019 16:08:11 +0000 Subject: Fix the build for 10.6 (Snow Leopard). --- macosx/tkMacOSXColor.c | 21 +++++++++++-------- macosx/ttkMacOSXTheme.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 9 deletions(-) diff --git a/macosx/tkMacOSXColor.c b/macosx/tkMacOSXColor.c index 1aef9bc..6199bf4 100644 --- a/macosx/tkMacOSXColor.c +++ b/macosx/tkMacOSXColor.c @@ -31,8 +31,8 @@ enum colorType { 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.*/ - ttkForeground, /* The value can be used as a parameter.*/ + ttkBackground, /* The value can be used as a parameter.*/ + ttkForeground, /* The value can be used as a parameter.*/ }; /* @@ -295,12 +295,13 @@ SetCGColorComponents( break; default: if ([NSApp macMinorVersion] < 10) { - err = ChkErr(HIThemeBrushCreateCGColor, - kThemeBrushDialogBackgroundActive, c); - return err; + fgColor = [[NSColor textColor] colorUsingColorSpace: + [NSColorSpace deviceRGBColorSpace]]; } else { +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101000 fgColor = [[NSColor labelColor] colorUsingColorSpace: [NSColorSpace deviceRGBColorSpace]]; +#endif break; } } @@ -317,7 +318,7 @@ SetCGColorComponents( */ case HIText: - case HIBackground: + case HIBackground: default: break; } @@ -343,6 +344,9 @@ SetCGColorComponents( MODULE_SCOPE Bool TkMacOSXInDarkMode(Tk_Window tkwin) { +#if MAC_OS_X_VERSION_MIN_REQUIRED < 101300 + return false; +#else static NSAppearanceName darkAqua = @"NSAppearanceNameDarkAqua"; TkWindow *winPtr = (TkWindow*)tkwin; NSView *view = TkMacOSXDrawableView(winPtr->privatePtr); @@ -351,6 +355,7 @@ TkMacOSXInDarkMode(Tk_Window tkwin) { } else { return false; } +#endif } @@ -576,7 +581,7 @@ TkMacOSXSetColorInContext( if (!cgColor && GetEntryFromPixelCode((pixel >> 24) & 0xff, &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, @@ -607,7 +612,7 @@ TkMacOSXSetColorInContext( } if (err != noErr) { TkMacOSXDbgMsg("Ignored unknown pixel value 0x%lx", pixel); - } + } } /* diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index 1cad90c..7170fe2 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -96,6 +96,7 @@ static Ttk_StateTable ThemeStateTable[] = { */ }; +#if MAC_OS_X_VERSION_MIN_REQUIRED > 1080 /*---------------------------------------------------------------------- * +++ Support for contrasting background colors when GroupBoxes * or Tabbed panes are nested inside each other. @@ -162,7 +163,7 @@ static int MacOSXGetBoxColor( } /* - * MacOSXDrawDarkGroupBox -- + * MacOSXDrawGroupBox -- * * This is a standalone drawing procedure which draws the contrasting * rounded rectangular box for LabelFrames and Notebook panes. @@ -191,6 +192,9 @@ static void MacOSXDrawGroupBox( borderColor = [NSColor colorWithColorSpace: deviceRGB components: border count: 4]; CGContextSetFillColorWithColor(context, borderColor.CGColor); + [borderColor getComponents: fill]; + CGContextSetRGBFillColor(context, fill[0], fill[1], fill[2], fill[3]); + CGContextBeginPath(context); CGContextAddPath(context, path); CGContextReplacePathWithStrokedPath(context); @@ -198,6 +202,9 @@ static void MacOSXDrawGroupBox( CFRelease(path); } +#endif /* MAC_OS_X_VERSION_MIN_REQUIRED > 1080 */ + +#if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 /*---------------------------------------------------------------------- * +++ Drawing procedures for widgets in Apple's "Dark Mode" (10.14 and up). * @@ -516,6 +523,8 @@ static void MacOSXDrawDarkSeparator( CGContextFillRect(context, bounds); } +#endif /* MAC_OS_X_VERSION_MIN_REQUIRED < 101300 */ + /*---------------------------------------------------------------------- * +++ Button element: Used for elements drawn with DrawThemeButton. */ @@ -640,12 +649,16 @@ static void ButtonElementDraw( CGRect bounds = BoxToRect(d, Ttk_PadBox(b, ButtonMargins)); HIThemeButtonDrawInfo info = computeButtonDrawInfo(params, state); +#if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 if (TkMacOSXInDarkMode(tkwin) && (info.kind == kThemePushButton || info.kind == kThemePopupButton)) { MacOSXDrawDarkButton(bounds, info.kind, state, dc.context); } else { ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); } +#else + ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); +#endif END_DRAWING } @@ -750,11 +763,15 @@ static void TabElementDraw( .position = Ttk_StateTableLookup(TabPositionTable, state), }; BEGIN_DRAWING(d) +#if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 if (TkMacOSXInDarkMode(tkwin)) { MacOSXDrawDarkTab(bounds, state, dc.context); } else { ChkErr(HIThemeDrawTab, &bounds, &info, dc.context, HIOrientation, NULL); } +#else + ChkErr(HIThemeDrawTab, &bounds, &info, dc.context, HIOrientation, NULL); +#endif END_DRAWING } @@ -787,7 +804,21 @@ static void PaneElementDraw( bounds.origin.y -= kThemeMetricTabFrameOverlap; bounds.size.height += kThemeMetricTabFrameOverlap; BEGIN_DRAWING(d) +#if MAC_OS_X_VERSION_MIN_REQUIRED > 10800 MacOSXDrawGroupBox(bounds, dc.context, tkwin); +#else + HIThemeTabPaneDrawInfo info = { + .version = 1, + .state = Ttk_StateTableLookup(ThemeStateTable, state), + .direction = kThemeTabNorth, + .size = kHIThemeTabSizeNormal, + .kind = kHIThemeTabKindNormal, + .adornment = kHIThemeTabPaneAdornmentNormal, + }; + bounds.origin.y -= kThemeMetricTabFrameOverlap; + bounds.size.height += kThemeMetricTabFrameOverlap; + ChkErr(HIThemeDrawTabPane, &bounds, &info, dc.context, HIOrientation); +#endif END_DRAWING [TkMacOSXDrawableView(macWin) setNeedsDisplay:YES]; if (macWin != NULL) { @@ -829,7 +860,16 @@ static void GroupElementDraw( CGRect bounds = BoxToRect(d, b); BEGIN_DRAWING(d) +#if MAC_OS_X_VERSION_MIN_REQUIRED > 10800 MacOSXDrawGroupBox(bounds, dc.context, tkwin); +#else + const HIThemeGroupBoxDrawInfo info = { + .version = 0, + .state = Ttk_StateTableLookup(ThemeStateTable, state), + .kind = kHIThemeGroupBoxKindPrimaryOpaque, + }; + ChkErr(HIThemeDrawGroupBox, &bounds, &info, dc.context, HIOrientation); +#endif END_DRAWING if (winPtr->privatePtr != NULL) { winPtr->privatePtr->flags |= TTK_HAS_DARKER_BG; @@ -1234,11 +1274,15 @@ static void SeparatorElementDraw( }; BEGIN_DRAWING(d) +#if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 if (TkMacOSXInDarkMode(tkwin)) { MacOSXDrawDarkSeparator(bounds, dc.context, tkwin); } else { ChkErr(HIThemeDrawSeparator, &bounds, &info, dc.context, HIOrientation); } +#else + ChkErr(HIThemeDrawSeparator, &bounds, &info, dc.context, HIOrientation); +#endif END_DRAWING } @@ -1349,6 +1393,7 @@ static void FillElementDraw( { CGRect bounds = BoxToRect(d, b); BEGIN_DRAWING(d) +#if MAC_OS_X_VERSION_MIN_REQUIRED > 10800 NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; NSColor *bgColor; CGFloat fill[4]; @@ -1358,7 +1403,14 @@ static void FillElementDraw( CGContextSetFillColorSpace(dc.context, deviceRGB.CGColorSpace); CGContextSetFillColorWithColor(dc.context, bgColor.CGColor); CGContextFillRect(dc.context, bounds); +#else + ThemeBrush brush = (state & TTK_STATE_BACKGROUND) + ? kThemeBrushModelessDialogBackgroundInactive + : kThemeBrushModelessDialogBackgroundActive; + ChkErr(HIThemeSetFill, brush, NULL, dc.context, HIOrientation); //QDSetPatternOrigin(PatternOrigin(tkwin, d)); + CGContextFillRect(dc.context, bounds); +#endif END_DRAWING } -- cgit v0.12 From 94e3312823c2643efc49c1631b0c8ab84e2995bc Mon Sep 17 00:00:00 2001 From: culler Date: Wed, 13 Mar 2019 21:46:57 +0000 Subject: Added a drawing procedure for dark CheckBoxes. Added drawing primitives to make the code DRYer. --- macosx/ttkMacOSXTheme.c | 335 ++++++++++++++++++++++++++++-------------------- 1 file changed, 197 insertions(+), 138 deletions(-) diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index 7170fe2..52c9896 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -215,17 +215,119 @@ static void MacOSXDrawGroupBox( */ -static CGFloat darkButtonFill[4] = {112.0/255, 113.0/255, 115.0/255, 1.0}; -static CGFloat darkDisabledButtonFill[4] = {86.0/255, 87.0/255, 89.0/255, 1.0}; +static CGFloat darkButtonFace[4] = {112.0/255, 113.0/255, 115.0/255, 1.0}; +static CGFloat darkDisabledButtonFace[4] = {86.0/255, 87.0/255, 89.0/255, 1.0}; static CGFloat darkInactiveSelectedTab[4] = {159.0/255, 160.0/255, 161.0/255, 1.0}; static CGFloat darkTabSeparator[4] = {0.0, 0.0, 0.0, 0.25}; static CGFloat darkTopGradient[8] = {1.0, 1.0, 1.0, 0.3, 1.0, 1.0, 1.0, 0.0}; static CGFloat darkBackgroundGradient[8] = {0.0, 0.0, 0.0, 0.1, 0.0, 0.0, 0.0, 0.25}; +static CGFloat darkCheckGradient[8] = {89.0/255, 90.0/255, 93.0/255, 1.0, + 119.0/255, 120.0/255, 122.0/255, 1.0}; static CGFloat darkSelectedGradient[8] = {23.0/255, 111.0/255, 232.0/255, 1.0, 20.0/255, 94.0/255, 206.0/255, 1.0}; +/* FillButtonBackground -- + * + * Fills a rounded rectangle with a transparent black gradient. + */ + +static void FillButtonBackground( + CGContextRef context, + CGRect bounds, + CGFloat radius) +{ + CGPathRef path; + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + CGGradientRef backgroundGradient = CGGradientCreateWithColorComponents( + deviceRGB.CGColorSpace, darkBackgroundGradient, NULL, 2); + CGPoint backgroundEnd = {bounds.origin.x, + bounds.origin.y + bounds.size.height}; + CGContextBeginPath(context); + path = CGPathCreateWithRoundedRect(bounds, radius, radius, NULL); + CGContextAddPath(context, path); + CGContextClip(context); + CGContextDrawLinearGradient(context, backgroundGradient, + bounds.origin, backgroundEnd, 0); + CFRelease(path); + CFRelease(backgroundGradient); +} + +/* HighlightButtonBorder -- + * + * Accent the top border of a rounded rectangle with a transparent + * white gradient. + */ + +static void HighlightButtonBorder( + CGContextRef context, + CGRect bounds) +{ + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + CGPoint topEnd = {bounds.origin.x, bounds.origin.y + 3}; + CGGradientRef topGradient = CGGradientCreateWithColorComponents( + deviceRGB.CGColorSpace, darkTopGradient, NULL, 2); + CGContextSaveGState(context); + CGContextBeginPath(context); + CGContextAddArc(context, bounds.origin.x + 4, bounds.origin.y + 4, + 4, PI, 3*PI/2, 0); + CGContextAddArc(context, bounds.origin.x + bounds.size.width - 4, + bounds.origin.y + 4, 4, 3*PI/2, 0, 0); + CGContextReplacePathWithStrokedPath(context); + CGContextClip(context); + CGContextDrawLinearGradient(context, topGradient, bounds.origin, topEnd, 0.0); + CGContextRestoreGState(context); + CFRelease(topGradient); +} + +/* SolidFillButtonFace -- + * + * Fill a rounded rectangle with a specified solid color. + */ + +static void SolidFillButtonFace( + CGContextRef context, + CGRect bounds, + CGFloat radius, + NSColor *color) +{ + CGPathRef path; + CGContextSetFillColorWithColor(context, color.CGColor); + path = CGPathCreateWithRoundedRect(bounds, radius, radius, NULL); + CGContextBeginPath(context); + CGContextAddPath(context, path); + CGContextFillPath(context); + CFRelease(path); +} + +/* GradientFillButtonFace -- + * + * Fill a rounded rectangle with a specified gradient. + */ + +static void GradientFillButtonFace( + CGContextRef context, + CGRect bounds, + CGFloat radius, + CGFloat* colors, + int numColors) +{ + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + CGPathRef path; + CGPoint end = {bounds.origin.x, + bounds.origin.y + bounds.size.height}; + CGGradientRef gradient = CGGradientCreateWithColorComponents( + deviceRGB.CGColorSpace, colors, NULL, numColors); + path = CGPathCreateWithRoundedRect(bounds, radius, radius, NULL); + CGContextBeginPath(context); + CGContextAddPath(context, path); + CGContextClip(context); + CGContextDrawLinearGradient(context, gradient, bounds.origin, end, 0); + CFRelease(path); + CFRelease(gradient); +} + /* * MacOSXDrawDarkButton -- * @@ -239,50 +341,28 @@ static void MacOSXDrawDarkButton( Ttk_State state, CGContextRef context) { - CGPathRef path; NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; - CGGradientRef topGradient, backgroundGradient, selectedGradient; - NSColor *fill; - - /* - * Fill the rounded bounding rectangle with a transparent black gradient. - */ + NSColor *faceColor; CGContextSetLineWidth(context, 1.0); CGContextClipToRect(context, bounds); - - backgroundGradient = CGGradientCreateWithColorComponents( - deviceRGB.CGColorSpace, darkBackgroundGradient, NULL, 2); - CGPoint backgroundEnd = {bounds.origin.x, - bounds.origin.y + bounds.size.height}; - CGContextBeginPath(context); - path = CGPathCreateWithRoundedRect(bounds, 5, 5, NULL); - CGContextAddPath(context, path); - CGContextClip(context); - CGContextDrawLinearGradient(context, backgroundGradient, - bounds.origin, backgroundEnd, 0); - CFRelease(backgroundGradient); - + FillButtonBackground(context, bounds, 5); /* - * Fill the button face with the button fill color. + * Fill the button face with the appropriate color. */ + bounds = CGRectInset(bounds, 1, 1); if (state & TTK_STATE_DISABLED) { - fill = [NSColor colorWithColorSpace: deviceRGB - components: darkDisabledButtonFill + faceColor = [NSColor colorWithColorSpace: deviceRGB + components: darkDisabledButtonFace count: 4]; } else { - fill = [NSColor colorWithColorSpace: deviceRGB - components: darkButtonFill + faceColor = [NSColor colorWithColorSpace: deviceRGB + components: darkButtonFace count: 4]; } - CGContextSetFillColorWithColor(context, fill.CGColor); - path = CGPathCreateWithRoundedRect(bounds, 4, 4, NULL); - CGContextBeginPath(context); - CGContextAddPath(context, path); - CGContextFillPath(context); - CFRelease(path); + SolidFillButtonFace(context, bounds, 4, faceColor); /* * If this is a popup, draw the arrow button. @@ -300,17 +380,8 @@ static void MacOSXDrawDarkButton( */ if (!(state & TTK_STATE_BACKGROUND)) { - selectedGradient = CGGradientCreateWithColorComponents( - deviceRGB.CGColorSpace, darkSelectedGradient, NULL, 2); - CGPoint arrowEnd = {arrowBounds.origin.x, - arrowBounds.origin.y + arrowBounds.size.height}; - CGContextBeginPath(context); - CGContextAddPath(context, path); - CGContextClip(context); - CGContextClipToRect(context, arrowBounds); - CGContextDrawLinearGradient(context, selectedGradient, - arrowBounds.origin, arrowEnd, 0); - CFRelease(selectedGradient); + GradientFillButtonFace(context, arrowBounds, 4, + darkSelectedGradient, 2); } /* @@ -330,24 +401,56 @@ static void MacOSXDrawDarkButton( CGContextRestoreGState(context); } - /* - * Accent the top border with a transparent white gradient. - */ + HighlightButtonBorder(context, bounds); +} - CGPoint topEnd = {bounds.origin.x, bounds.origin.y + 3}; - topGradient = CGGradientCreateWithColorComponents( - deviceRGB.CGColorSpace, darkTopGradient, NULL, 2); - CGContextSaveGState(context); - CGContextBeginPath(context); - CGContextAddArc(context, bounds.origin.x + 4, bounds.origin.y + 4, - 4, PI, 3*PI/2, 0); - CGContextAddArc(context, bounds.origin.x + bounds.size.width - 4, - bounds.origin.y + 4, 4, 3*PI/2, 0, 0); - CGContextReplacePathWithStrokedPath(context); - CGContextClip(context); - CGContextDrawLinearGradient(context, topGradient, bounds.origin, topEnd, 0.0); - CGContextRestoreGState(context); - CFRelease(topGradient); +/* + * MacOSXDrawDarkCheckBox -- + * + * This is a standalone drawing procedure which draws Checkboxes + * in the Dark Mode style. + */ + +static void MacOSXDrawDarkCheckBox( + CGRect bounds, + Ttk_State state, + CGContextRef context) +{ + CGRect checkbounds = {{2, 3},{16, 16}}; + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + NSColor *stroke; + CGFloat x, y; + bounds = CGRectOffset(checkbounds, bounds.origin.x, bounds.origin.y); + x = bounds.origin.x; + y = bounds.origin.y; + + CGContextClipToRect(context, bounds); + FillButtonBackground(context, bounds, 4); + bounds = CGRectInset(bounds, 1, 1); + GradientFillButtonFace(context, bounds, 3, darkCheckGradient, 2); + HighlightButtonBorder(context, bounds); + if ((state & TTK_STATE_SELECTED) || (state & TTK_STATE_ALTERNATE)) { + CGContextSetStrokeColorSpace(context, deviceRGB.CGColorSpace); + if (state & TTK_STATE_DISABLED) { + stroke = [NSColor disabledControlTextColor]; + } else { + stroke = [NSColor controlTextColor]; + } + CGContextSetStrokeColorWithColor(context, stroke.CGColor); + } + if (state & TTK_STATE_SELECTED) { + CGContextSetLineWidth(context, 1.5); + CGContextBeginPath(context); + CGPoint check[3] = {{x+3, y+7}, {x+6.5, y+9.5}, {x+10, y+4}}; + CGContextAddLines(context, check, 3); + CGContextStrokePath(context); + } else if (state & TTK_STATE_ALTERNATE) { + CGContextSetLineWidth(context, 2.0); + CGContextBeginPath(context); + CGPoint check[2] = {{x+4, y+7}, {x+12, y+7}}; + CGContextAddLines(context, check, 2); + CGContextStrokePath(context); + } } /* @@ -362,10 +465,8 @@ static void MacOSXDrawDarkTab( Ttk_State state, CGContextRef context) { - CGPathRef path; NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; - CGGradientRef topGradient, backgroundGradient, selectedGradient; - NSColor *fill, *stroke; + NSColor *faceColor, *stroke; CGRect originalBounds= bounds; CGContextSetLineWidth(context, 1.0); @@ -386,44 +487,23 @@ static void MacOSXDrawDarkTab( } /* - * Fill the rounded bounding rectangle with a transparent black gradient. + * Fill the tab face with the appropriate color or gradient. Use a + * solid color if the tab is not selected, otherwise use a blue or + * gray gradient. */ - backgroundGradient = CGGradientCreateWithColorComponents( - deviceRGB.CGColorSpace, darkBackgroundGradient, NULL, 2); - CGPoint backgroundEnd = {bounds.origin.x, - bounds.origin.y + bounds.size.height}; - CGContextBeginPath(context); - path = CGPathCreateWithRoundedRect(bounds, 5, 5, NULL); - CGContextAddPath(context, path); - CGContextClip(context); - CGContextDrawLinearGradient(context, backgroundGradient, - bounds.origin, backgroundEnd, 0); - CFRelease(backgroundGradient); bounds = CGRectInset(bounds, 1, 1); - - /* - * Fill the button face with the button fill color. Use the - * background color if the tab is not selected, otherwise use a - * blue or gray gradient. - */ - if (!(state & TTK_STATE_SELECTED)) { if (state & TTK_STATE_DISABLED) { - fill = [NSColor colorWithColorSpace: deviceRGB - components: darkDisabledButtonFill + faceColor = [NSColor colorWithColorSpace: deviceRGB + components: darkDisabledButtonFace count: 4]; } else { - fill = [NSColor colorWithColorSpace: deviceRGB - components: darkButtonFill + faceColor = [NSColor colorWithColorSpace: deviceRGB + components: darkButtonFace count: 4]; } - CGContextSetFillColorWithColor(context, fill.CGColor); - path = CGPathCreateWithRoundedRect(bounds, 4, 4, NULL); - CGContextBeginPath(context); - CGContextAddPath(context, path); - CGContextFillPath(context); - CFRelease(path); + SolidFillButtonFace(context, bounds, 4, faceColor); /* * Draw a separator line on the left side of the tab if it @@ -448,57 +528,23 @@ static void MacOSXDrawDarkTab( } else { /* - * This is the selected tab; paint it. If it is first, cover up - * the separator line drawn by the second one. + * This is the selected tab; paint it blue. If it is first, cover up + * the separator line drawn by the second one. (The selected tab is + * always drawn last.) */ if ((state & TTK_STATE_FIRST_TAB) && !(state & TTK_STATE_LAST_TAB)) { bounds.size.width += 1; } - if (!(state & TTK_STATE_BACKGROUND)) { - selectedGradient = CGGradientCreateWithColorComponents( - deviceRGB.CGColorSpace, darkSelectedGradient, NULL, 2); - CGPoint end = {bounds.origin.x, bounds.origin.y + bounds.size.height}; - path = CGPathCreateWithRoundedRect(bounds, 4, 4, NULL); - CGContextBeginPath(context); - CGContextAddPath(context, path); - CGContextClip(context); - CGContextDrawLinearGradient(context, selectedGradient, - bounds.origin, end, 0); - CFRelease(path); - CFRelease(selectedGradient); + GradientFillButtonFace(context, bounds, 4, darkSelectedGradient, 2); } else { - fill = [NSColor colorWithColorSpace: deviceRGB + faceColor = [NSColor colorWithColorSpace: deviceRGB components: darkInactiveSelectedTab count: 4]; - CGContextSetFillColorWithColor(context, fill.CGColor); - path = CGPathCreateWithRoundedRect(bounds, 4, 4, NULL); - CGContextBeginPath(context); - CGContextAddPath(context, path); - CGContextFillPath(context); - CFRelease(path); + SolidFillButtonFace(context, bounds, 4, faceColor); } - - /* - * Accent the top border with a transparent white gradient. - */ - - CGPoint topEnd = {bounds.origin.x, bounds.origin.y + 3}; - topGradient = CGGradientCreateWithColorComponents( - deviceRGB.CGColorSpace, darkTopGradient, NULL, 2); - CGContextSaveGState(context); - CGContextBeginPath(context); - CGContextAddArc(context, bounds.origin.x + 4, bounds.origin.y + 4, - 4, PI, 3*PI/2, 0); - CGContextAddArc(context, bounds.origin.x + bounds.size.width - 4, - bounds.origin.y + 4, 4, 3*PI/2, 0, 0); - CGContextReplacePathWithStrokedPath(context); - CGContextClip(context); - CGContextDrawLinearGradient(context, topGradient, bounds.origin, - topEnd, 0.0); - CFRelease(topGradient); - CGContextRestoreGState(context); + HighlightButtonBorder(context, bounds); } } @@ -523,7 +569,7 @@ static void MacOSXDrawDarkSeparator( CGContextFillRect(context, bounds); } -#endif /* MAC_OS_X_VERSION_MIN_REQUIRED < 101300 */ +#endif /* MAC_OS_X_VERSION_MIN_REQUIRED >101300 */ /*---------------------------------------------------------------------- * +++ Button element: Used for elements drawn with DrawThemeButton. @@ -650,9 +696,22 @@ static void ButtonElementDraw( HIThemeButtonDrawInfo info = computeButtonDrawInfo(params, state); #if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 - if (TkMacOSXInDarkMode(tkwin) && - (info.kind == kThemePushButton || info.kind == kThemePopupButton)) { - MacOSXDrawDarkButton(bounds, info.kind, state, dc.context); + if (TkMacOSXInDarkMode(tkwin)) { + switch (info.kind) { + case kThemePushButton: + case kThemePopupButton: + MacOSXDrawDarkButton(bounds, info.kind, state, dc.context); + break; + case kThemeCheckBox: + if (!(state & (TTK_STATE_SELECTED | TTK_STATE_ALTERNATE)) || + (state & TTK_STATE_BACKGROUND) || + (state & TTK_STATE_DISABLED)) { + MacOSXDrawDarkCheckBox(bounds, state, dc.context); + break; + } + default: + ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); + } } else { ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); } -- cgit v0.12 From 804f3a603296dff36b4c678e180edb2ca69f6eb3 Mon Sep 17 00:00:00 2001 From: fvogel Date: Thu, 14 Mar 2019 20:59:55 +0000 Subject: Fix typo --- macosx/tkMacOSXMouseEvent.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/macosx/tkMacOSXMouseEvent.c b/macosx/tkMacOSXMouseEvent.c index 38adc8c..9a1988d 100644 --- a/macosx/tkMacOSXMouseEvent.c +++ b/macosx/tkMacOSXMouseEvent.c @@ -94,7 +94,7 @@ enum { * Compute the mouse position in Tk screen coordinates (global) and in * the Tk coordinates of its containing Tk Window. */ - + NSPoint global, local = [theEvent locationInWindow]; /* @@ -106,7 +106,7 @@ enum { eventWindow == _windowWithMouse; } if (eventWindow) { - + /* * Set the local mouse position to its NSWindow flipped coordinates, * with the origin at top left, and the global mouse position to the @@ -120,7 +120,7 @@ enum { } else { /* - * As a last resort, with no NSWindow to work witn, set both local and + * As a last resort, with no NSWindow to work with, set both local and * global to the screen coordinates. */ @@ -160,7 +160,7 @@ enum { * Convert local from NSWindow flipped coordinates to the toplevel's * coordinates. */ - + local.x -= winPtr->wmInfoPtr->xInParent; local.y -= winPtr->wmInfoPtr->yInParent; @@ -178,7 +178,7 @@ enum { /* * Generate an XEvent for this mouse event. */ - + unsigned int state = 0; NSInteger button = [theEvent buttonNumber]; EventRef eventRef = (EventRef)[theEvent eventRef]; -- cgit v0.12 From 254899e1f793884db337509c56edbd723b937cde Mon Sep 17 00:00:00 2001 From: culler Date: Fri, 15 Mar 2019 02:42:39 +0000 Subject: Added a drawing procedure for dark RadioButtons and dealt with many slightly wrong ttk details. --- library/ttk/aquaTheme.tcl | 13 ++- macosx/ttkMacOSXTheme.c | 256 ++++++++++++++++++++++++++++++---------------- 2 files changed, 182 insertions(+), 87 deletions(-) diff --git a/library/ttk/aquaTheme.tcl b/library/ttk/aquaTheme.tcl index 9dfa1be..81d7ffe 100644 --- a/library/ttk/aquaTheme.tcl +++ b/library/ttk/aquaTheme.tcl @@ -31,7 +31,18 @@ namespace eval ttk::theme::aqua { ttk::style map TButton \ -foreground { disabled systemDisabledControlTextColor} - ttk::style configure Toolbutton -padding 4 -foreground black + ttk::style map TCheckbutton \ + -foreground { + disabled systemDisabledControlTextColor} + ttk::style map TRadiobutton \ + -foreground { + disabled systemDisabledControlTextColor} + ttk::style configure Toolbutton -padding 4 +# ttk::style configure Toolbutton -padding 4 -foreground black +# ttk::style map Toolbutton \ +# -background { +# background systemWindowBody} + # Workaround for #1100117: # Actually, on Aqua we probably shouldn't stipple images in # disabled buttons even if it did work... diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index 52c9896..57a5e41 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -112,7 +112,7 @@ static Ttk_StateTable ThemeStateTable[] = { static CGFloat windowBackground[4] = {235.0/255, 235.0/255, 235.0/255, 1.0}; -static int MacOSXGetBoxColor( +static int GetBoxColor( CGContextRef context, Tk_Window tkwin, int depth, @@ -163,13 +163,13 @@ static int MacOSXGetBoxColor( } /* - * MacOSXDrawGroupBox -- + * DrawGroupBox -- * * This is a standalone drawing procedure which draws the contrasting * rounded rectangular box for LabelFrames and Notebook panes. */ -static void MacOSXDrawGroupBox( +static void DrawGroupBox( CGRect bounds, CGContextRef context, Tk_Window tkwin) @@ -179,7 +179,7 @@ static void MacOSXDrawGroupBox( NSColor *borderColor, *bgColor; static CGFloat border[4] = {1.0, 1.0, 1.0, 0.25}; CGFloat fill[4]; - MacOSXGetBoxColor(context, tkwin, 1, fill); + GetBoxColor(context, tkwin, 1, fill); bgColor = [NSColor colorWithColorSpace: deviceRGB components: fill count: 4]; CGContextSetFillColorSpace(context, deviceRGB.CGColorSpace); @@ -214,6 +214,9 @@ static void MacOSXDrawGroupBox( * HITheme in Aqua, since it understands earlier versions of the OS. */ +/* + * Colors and gradients used in Dark Mode. + */ static CGFloat darkButtonFace[4] = {112.0/255, 113.0/255, 115.0/255, 1.0}; static CGFloat darkDisabledButtonFace[4] = {86.0/255, 87.0/255, 89.0/255, 1.0}; @@ -223,11 +226,33 @@ static CGFloat darkTopGradient[8] = {1.0, 1.0, 1.0, 0.3, 1.0, 1.0, 1.0, 0.0}; static CGFloat darkBackgroundGradient[8] = {0.0, 0.0, 0.0, 0.1, 0.0, 0.0, 0.0, 0.25}; -static CGFloat darkCheckGradient[8] = {89.0/255, 90.0/255, 93.0/255, 1.0, +static CGFloat darkInactiveGradient[8] = {89.0/255, 90.0/255, 93.0/255, 1.0, 119.0/255, 120.0/255, 122.0/255, 1.0}; static CGFloat darkSelectedGradient[8] = {23.0/255, 111.0/255, 232.0/255, 1.0, 20.0/255, 94.0/255, 206.0/255, 1.0}; +/* + * NormalizeButtonBounds -- + * + * Apple's Human Interface Guidelines only allow three specific heights for buttons: + * Regular, small and mini. We always use the regular size. However, Ttk may + * provide an arbitrary bounding rectangle. We always draw the button centered + * vertically on the rectangle, and having the same width as the rectangle. + * This function returns the actual bounding rectangle that will be used in + * drawing the button. + */ + +static CGRect NormalizeButtonBounds( + SInt32 heightMetric, + CGRect bounds) +{ + SInt32 height; + ChkErr(GetThemeMetric, heightMetric, &height); + bounds.origin.y += (bounds.size.height - height)/2; + bounds.size.height = height; + return bounds; +} + /* FillButtonBackground -- * * Fills a rounded rectangle with a transparent black gradient. @@ -329,13 +354,13 @@ static void GradientFillButtonFace( } /* - * MacOSXDrawDarkButton -- + * DrawDarkButton -- * * This is a standalone drawing procedure which draws PushButtons and * PopupButtons in the Dark Mode style. */ -static void MacOSXDrawDarkButton( +static void DrawDarkButton( CGRect bounds, ThemeButtonKind kind, Ttk_State state, @@ -344,7 +369,13 @@ static void MacOSXDrawDarkButton( NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; NSColor *faceColor; - CGContextSetLineWidth(context, 1.0); + /* + * To match the appearance of Apple's buttons we need to increase the + * height by 1 pixel. + */ + + bounds.size.height += 1; + CGContextClipToRect(context, bounds); FillButtonBackground(context, bounds, 5); @@ -405,18 +436,18 @@ static void MacOSXDrawDarkButton( } /* - * MacOSXDrawDarkCheckBox -- + * DrawDarkCheckBox -- * * This is a standalone drawing procedure which draws Checkboxes * in the Dark Mode style. */ -static void MacOSXDrawDarkCheckBox( +static void DrawDarkCheckBox( CGRect bounds, Ttk_State state, CGContextRef context) { - CGRect checkbounds = {{2, 3},{16, 16}}; + CGRect checkbounds = {{0, bounds.size.height/2 - 8},{16, 16}}; NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; NSColor *stroke; CGFloat x, y; @@ -427,7 +458,12 @@ static void MacOSXDrawDarkCheckBox( CGContextClipToRect(context, bounds); FillButtonBackground(context, bounds, 4); bounds = CGRectInset(bounds, 1, 1); - GradientFillButtonFace(context, bounds, 3, darkCheckGradient, 2); + if (!(state & TTK_STATE_BACKGROUND) && + ((state & TTK_STATE_SELECTED) || (state & TTK_STATE_ALTERNATE))) { + GradientFillButtonFace(context, bounds, 3, darkSelectedGradient, 2); + } else { + GradientFillButtonFace(context, bounds, 3, darkInactiveGradient, 2); + } HighlightButtonBorder(context, bounds); if ((state & TTK_STATE_SELECTED) || (state & TTK_STATE_ALTERNATE)) { CGContextSetStrokeColorSpace(context, deviceRGB.CGColorSpace); @@ -441,26 +477,76 @@ static void MacOSXDrawDarkCheckBox( if (state & TTK_STATE_SELECTED) { CGContextSetLineWidth(context, 1.5); CGContextBeginPath(context); - CGPoint check[3] = {{x+3, y+7}, {x+6.5, y+9.5}, {x+10, y+4}}; + CGPoint check[3] = {{x+4, y+8}, {x+7, y+11}, {x+11, y+4}}; CGContextAddLines(context, check, 3); CGContextStrokePath(context); } else if (state & TTK_STATE_ALTERNATE) { CGContextSetLineWidth(context, 2.0); CGContextBeginPath(context); - CGPoint check[2] = {{x+4, y+7}, {x+12, y+7}}; - CGContextAddLines(context, check, 2); + CGPoint bar[2] = {{x+4, y+8}, {x+12, y+8}}; + CGContextAddLines(context, bar, 2); CGContextStrokePath(context); } } /* - * MacOSXDrawDarkTab -- + * DrawDarkRadioButton -- + * + * This is a standalone drawing procedure which draws RadioButtons + * in the Dark Mode style. + */ + +static void DrawDarkRadioButton( + CGRect bounds, + Ttk_State state, + CGContextRef context) +{ + CGRect checkbounds = {{0, bounds.size.height/2 - 9},{18, 18}}; + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + NSColor *fill; + CGFloat x, y; + bounds = CGRectOffset(checkbounds, bounds.origin.x, bounds.origin.y); + x = bounds.origin.x; + y = bounds.origin.y; + + CGContextClipToRect(context, bounds); + FillButtonBackground(context, bounds, 9); + bounds = CGRectInset(bounds, 1, 1); + if (!(state & TTK_STATE_BACKGROUND) && + ((state & TTK_STATE_SELECTED) || (state & TTK_STATE_ALTERNATE))) { + GradientFillButtonFace(context, bounds, 8, darkSelectedGradient, 2); + } else { + GradientFillButtonFace(context, bounds, 8, darkInactiveGradient, 2); + } + HighlightButtonBorder(context, bounds); + if ((state & TTK_STATE_SELECTED) || (state & TTK_STATE_ALTERNATE)) { + CGContextSetStrokeColorSpace(context, deviceRGB.CGColorSpace); + if (state & TTK_STATE_DISABLED) { + fill = [NSColor disabledControlTextColor]; + } else { + fill = [NSColor controlTextColor]; + } + CGContextSetFillColorWithColor(context, fill.CGColor); + } + if (state & TTK_STATE_SELECTED) { + CGContextBeginPath(context); + CGRect dot = {{x + 6, y + 6}, {6, 6}}; + CGContextAddEllipseInRect(context, dot); + CGContextFillPath(context); + } else if (state & TTK_STATE_ALTERNATE) { + CGRect bar = {{x + 5, y + 8}, {8, 2}}; + CGContextFillRect(context, bar); + } +} + +/* + * DrawDarkTab -- * * This is a standalone drawing procedure which draws Tabbed Pane * Tabs in the Dark Mode style. */ -static void MacOSXDrawDarkTab( +static void DrawDarkTab( CGRect bounds, Ttk_State state, CGContextRef context) @@ -549,13 +635,13 @@ static void MacOSXDrawDarkTab( } /* - * MacOSXDrawDarkSeparator -- + * DrawDarkSeparator -- * * This is a standalone drawing procedure which draws a separator widget * in Dark Mode. */ -static void MacOSXDrawDarkSeparator( +static void DrawDarkSeparator( CGRect bounds, CGContextRef context, Tk_Window tkwin) @@ -575,11 +661,6 @@ static void MacOSXDrawDarkSeparator( * +++ Button element: Used for elements drawn with DrawThemeButton. */ -/* - * Extra margins to account for drop shadow. - */ -static Ttk_Padding ButtonMargins = {2, 2, 2, 2}; - #define NoThemeMetric 0xFFFFFFFF typedef struct { @@ -619,9 +700,15 @@ static Ttk_StateTable ButtonAdornmentTable[] = { static inline HIThemeButtonDrawInfo computeButtonDrawInfo( ThemeButtonParams *params, Ttk_State state) { + /* + * See ButtonElementDraw for the explanation of why we always draw + * PushButtons in the active state. + */ + const HIThemeButtonDrawInfo info = { .version = 0, - .state = Ttk_StateTableLookup(ThemeStateTable, state), + .state = params && params->kind == kThemePushButton ? + kThemeStateActive : Ttk_StateTableLookup(ThemeStateTable, state), .kind = params ? params->kind : 0, .value = Ttk_StateTableLookup(ButtonValueTable, state), .adornment = Ttk_StateTableLookup(ButtonAdornmentTable, state), @@ -652,9 +739,8 @@ static void ButtonElementSize( static const CGRect scratchBounds = {{0, 0}, {100, 100}}; CGRect contentBounds; - ButtonElementSizeNoPadding( - clientData, elementRecord, tkwin, - widthPtr, heightPtr, paddingPtr); + ButtonElementSizeNoPadding( clientData, elementRecord, tkwin, + widthPtr, heightPtr, paddingPtr); /* * To compute internal padding, query the appearance manager @@ -666,58 +752,54 @@ static void ButtonElementSize( &scratchBounds, &info, &contentBounds); paddingPtr->left = CGRectGetMinX(contentBounds); - paddingPtr->right = CGRectGetMaxX(scratchBounds) - CGRectGetMaxX(contentBounds) + 1; - if (TkMacOSXInDarkMode(tkwin)) { - paddingPtr->top = CGRectGetMinY(contentBounds) + 2; - paddingPtr->bottom = CGRectGetMaxY(scratchBounds) - CGRectGetMaxY(contentBounds) + 3; - } else { - paddingPtr->top = CGRectGetMinY(contentBounds) + 3; - paddingPtr->bottom = CGRectGetMaxY(scratchBounds) - CGRectGetMaxY(contentBounds) + 2; - } - - /* - * Now add a little extra padding to account for drop shadows. - * @@@ SHOULD: call GetThemeButtonBackgroundBounds() instead. - */ - - *paddingPtr = Ttk_AddPadding(*paddingPtr, ButtonMargins); - *widthPtr += Ttk_PaddingWidth(ButtonMargins); - *heightPtr += Ttk_PaddingHeight(ButtonMargins); + paddingPtr->right = CGRectGetMaxX(scratchBounds) - CGRectGetMaxX(contentBounds); } - static void ButtonElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) { BEGIN_DRAWING(d) ThemeButtonParams *params = clientData; - CGRect bounds = BoxToRect(d, Ttk_PadBox(b, ButtonMargins)); + CGRect bounds = BoxToRect(d, b); HIThemeButtonDrawInfo info = computeButtonDrawInfo(params, state); + bounds = NormalizeButtonBounds(params->heightMetric, bounds); -#if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 if (TkMacOSXInDarkMode(tkwin)) { +#if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 switch (info.kind) { case kThemePushButton: case kThemePopupButton: - MacOSXDrawDarkButton(bounds, info.kind, state, dc.context); + DrawDarkButton(bounds, info.kind, state, dc.context); break; case kThemeCheckBox: - if (!(state & (TTK_STATE_SELECTED | TTK_STATE_ALTERNATE)) || - (state & TTK_STATE_BACKGROUND) || - (state & TTK_STATE_DISABLED)) { - MacOSXDrawDarkCheckBox(bounds, state, dc.context); - break; - } + DrawDarkCheckBox(bounds, state, dc.context); + break; + case kThemeRadioButton: + DrawDarkRadioButton(bounds, state, dc.context); + break; default: ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); +#endif } } else { + /* + * Apple's PushButton and PopupButton do not change their (white) fill + * color when the window is inactive although, except in 10.7 (Lion), + * the color of the arrow button on a PopupButton does change. For + * some reason HITheme fills inactive buttons with a transparent color + * that allows the window background to show through, leading to + * inconsistent behavior. We work around this by filling behind an + * inactive PopupButton with a white color before asking HIToolbox to + * draw it. PopupButton. For PushButtons, we simply draw them in the + * active state. + */ + if (info.kind == kThemePopupButton && (state & TTK_STATE_BACKGROUND)) { + CGRect innerBounds = CGRectInset(bounds, 1, 1); + SolidFillButtonFace(dc.context, innerBounds, 4, [NSColor whiteColor]); + } ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); } -#else - ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); -#endif END_DRAWING } @@ -824,7 +906,7 @@ static void TabElementDraw( BEGIN_DRAWING(d) #if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 if (TkMacOSXInDarkMode(tkwin)) { - MacOSXDrawDarkTab(bounds, state, dc.context); + DrawDarkTab(bounds, state, dc.context); } else { ChkErr(HIThemeDrawTab, &bounds, &info, dc.context, HIOrientation, NULL); } @@ -864,7 +946,7 @@ static void PaneElementDraw( bounds.size.height += kThemeMetricTabFrameOverlap; BEGIN_DRAWING(d) #if MAC_OS_X_VERSION_MIN_REQUIRED > 10800 - MacOSXDrawGroupBox(bounds, dc.context, tkwin); + DrawGroupBox(bounds, dc.context, tkwin); #else HIThemeTabPaneDrawInfo info = { .version = 1, @@ -920,7 +1002,7 @@ static void GroupElementDraw( BEGIN_DRAWING(d) #if MAC_OS_X_VERSION_MIN_REQUIRED > 10800 - MacOSXDrawGroupBox(bounds, dc.context, tkwin); + DrawGroupBox(bounds, dc.context, tkwin); #else const HIThemeGroupBoxDrawInfo info = { .version = 0, @@ -1014,7 +1096,7 @@ static Ttk_ElementSpec EntryElementSpec = { */ static Ttk_Padding ComboboxPadding = { 2, 3, 17, 1 }; -static Ttk_Padding ComboboxMargins = { 3, 3, 4, 4 }; +static Ttk_Padding ComboboxMargins = { 3, 4, 4, 3 }; static void ComboboxElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, @@ -1335,7 +1417,7 @@ static void SeparatorElementDraw( BEGIN_DRAWING(d) #if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 if (TkMacOSXInDarkMode(tkwin)) { - MacOSXDrawDarkSeparator(bounds, dc.context, tkwin); + DrawDarkSeparator(bounds, dc.context, tkwin); } else { ChkErr(HIThemeDrawSeparator, &bounds, &info, dc.context, HIOrientation); } @@ -1415,29 +1497,31 @@ static Ttk_ElementSpec SizegripElementSpec = { * not allowing user control of the background or highlight colors of ttk * widgets. * - * This job is made more complicated 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. + * 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 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 - * system background color. If widgets inside the box were drawn with the - * system background color the backgrounds would match. But this produces a - * GroupBox with no contrast, so the only visual clue is a faint - * highlighting around the top of the GroupBox. Moreover, the TabbedPane - * does not have an Opaque version, so while it is drawn inside a - * contrasting rounded rectangle, the widgets inside the pane needed to be - * enclosed in a frame with the system background color. This added a visual - * artifact since the frame's background color does not match the Pane's - * background color. That code has been replaced with the standalone - * drawing procedure macOSXDrawGroupBox, which draws a rounded rectangle - * with an appropriate contrasting background 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 system background color. If widgets + * inside the box were drawn with the system background color the + * backgrounds would match. But this produces a GroupBox with no contrast, + * the only visual clue being a faint highlighting around the top of the + * GroupBox. Moreover, the TabbedPane does not have an Opaque version, so + * while it is drawn inside a contrasting rounded rectangle, the widgets + * inside the pane needed to be enclosed in a frame with the system + * background color. This added a visual artifact since the frame's + * background color does not match the Pane's background color. That code + * has now been replaced with the standalone drawing procedure + * macOSXDrawGroupBox, which draws a rounded rectangle with an appropriate + * contrasting background color. * * Patterned backgrounds, which are now obsolete, should be aligned with the * coordinate system of the top-level window. Apparently failing to do this @@ -1456,7 +1540,7 @@ static void FillElementDraw( NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; NSColor *bgColor; CGFloat fill[4]; - MacOSXGetBoxColor(dc.context, tkwin, 0, fill); + GetBoxColor(dc.context, tkwin, 0, fill); bgColor = [NSColor colorWithColorSpace: deviceRGB components: fill count: 4]; CGContextSetFillColorSpace(dc.context, deviceRGB.CGColorSpace); -- cgit v0.12 From 5d3696a737a0d6cbfc1c3eda16547cff2f9078d7 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 15 Mar 2019 20:24:47 +0000 Subject: Make Tk run on win32/win64 using -DTCL_UTF_MAX=6. Adapted from androwish. --- generic/tkFocus.c | 6 +++--- generic/tkImgGIF.c | 2 +- generic/tkMain.c | 39 ++++++++++++++++++++++++++------------- unix/tkUnixMenu.c | 6 +----- win/tkWinDialog.c | 7 ++----- win/tkWinMenu.c | 16 +++++++++++----- win/ttkWinXPTheme.c | 53 +++++++++++++++++++++++++++++++++++++---------------- 7 files changed, 81 insertions(+), 48 deletions(-) diff --git a/generic/tkFocus.c b/generic/tkFocus.c index c621bf9..eae981e 100644 --- a/generic/tkFocus.c +++ b/generic/tkFocus.c @@ -630,7 +630,7 @@ TkSetFocusWin( tlFocusPtr->focusWinPtr = winPtr; if (topLevelPtr->flags & TK_EMBEDDED) { - + /* * We are assigning focus to an embedded toplevel. The platform * specific function TkpClaimFocus needs to handle the job of @@ -646,7 +646,7 @@ TkSetFocusWin( * toplevel from a different application, clear the focus in that * application. */ - + if (force) { TkWindow *focusPtr = winPtr->dispPtr->focusPtr; if (focusPtr && focusPtr->mainPtr != winPtr->mainPtr) { @@ -660,7 +660,7 @@ TkSetFocusWin( * Call the platform specific function TkpChangeFocus to move the * window manager's focus to a new toplevel. */ - + serial = TkpChangeFocus(TkpGetWrapperWindow(topLevelPtr), force); if (serial != 0) { displayFocusPtr->focusSerial = serial; diff --git a/generic/tkImgGIF.c b/generic/tkImgGIF.c index fa4b728..0c32047 100644 --- a/generic/tkImgGIF.c +++ b/generic/tkImgGIF.c @@ -1260,7 +1260,7 @@ ReadImage( * * The field "stack" is abused for temporary buffer. it has 4096 bytes * and we need 256. - * + * * Loop until we hit a 0 length block which is the end sign. */ while ( 0 < (count = GetDataBlock(gifConfPtr, chan, stack))) diff --git a/generic/tkMain.c b/generic/tkMain.c index a7d4ca1..3600142 100644 --- a/generic/tkMain.c +++ b/generic/tkMain.c @@ -79,22 +79,35 @@ extern const TclIntPlatStubs *tclIntPlatStubsPtr; #endif /* - * Further on, in UNICODE mode, we need to use Tcl_NewUnicodeObj, - * while otherwise NewNativeObj is needed (which provides proper - * conversion from native encoding to UTF-8). + * Further on, in UNICODE mode we just use Tcl_NewUnicodeObj, otherwise + * NewNativeObj is needed (which provides proper conversion from native + * encoding to UTF-8). */ -#ifdef UNICODE + +#if defined(UNICODE) && (TCL_UTF_MAX <= 4) # define NewNativeObj Tcl_NewUnicodeObj -#else /* !UNICODE */ - static Tcl_Obj *NewNativeObj(char *string, int length) { - Tcl_Obj *obj; - Tcl_DString ds; - Tcl_ExternalToUtfDString(NULL, string, length, &ds); - obj = Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds)); - Tcl_DStringFree(&ds); - return obj; +#else /* !UNICODE || (TCL_UTF_MAX > 4) */ +static inline Tcl_Obj * +NewNativeObj( + TCHAR *string, + int length) +{ + Tcl_Obj *obj; + Tcl_DString ds; + +#ifdef UNICODE + if (length > 0) { + length *= sizeof(WCHAR); + } + Tcl_WinTCharToUtf(string, length, &ds); +#else + Tcl_ExternalToUtfDString(NULL, (char *) string, length, &ds); +#endif + obj = Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds)); + Tcl_DStringFree(&ds); + return obj; } -#endif /* !UNICODE */ +#endif /* !UNICODE || (TCL_UTF_MAX > 4) */ /* * Declarations for various library functions and variables (don't want to diff --git a/unix/tkUnixMenu.c b/unix/tkUnixMenu.c index d7ed873..909276a 100644 --- a/unix/tkUnixMenu.c +++ b/unix/tkUnixMenu.c @@ -857,11 +857,7 @@ DrawMenuUnderline( if ((mePtr->underline >= 0) && (mePtr->labelPtr != NULL)) { int len; - /* - * Do the unicode call just to prevent overruns. - */ - - Tcl_GetUnicodeFromObj(mePtr->labelPtr, &len); + len = Tcl_GetCharLength(mePtr->labelPtr); if (mePtr->underline < len) { int activeBorderWidth, leftEdge; const char *label, *start, *end; diff --git a/win/tkWinDialog.c b/win/tkWinDialog.c index 366485b..4ad3b9e 100644 --- a/win/tkWinDialog.c +++ b/win/tkWinDialog.c @@ -2911,13 +2911,10 @@ Tk_MessageBoxObjCmd( flags |= icon | type | MB_TASKMODAL | MB_SETFOREGROUND; - tmpObj = messageObj ? Tcl_DuplicateObj(messageObj) - : Tcl_NewUnicodeObj(NULL, 0); + tmpObj = messageObj ? Tcl_DuplicateObj(messageObj) : Tcl_NewObj(); Tcl_IncrRefCount(tmpObj); if (detailObj) { - const Tcl_UniChar twoNL[] = { '\n', '\n' }; - - Tcl_AppendUnicodeToObj(tmpObj, twoNL, 2); + Tcl_AppendStringsToObj(tmpObj, "\n\n", NULL); Tcl_AppendObjToObj(tmpObj, detailObj); } diff --git a/win/tkWinMenu.c b/win/tkWinMenu.c index 8dc0e24..7a2924d 100644 --- a/win/tkWinMenu.c +++ b/win/tkWinMenu.c @@ -1249,7 +1249,9 @@ TkWinHandleMenuEvent( if (hashEntryPtr != NULL) { int i, len, underline; Tcl_Obj *labelPtr; - Tcl_UniChar *wlabel, menuChar; + WCHAR *wlabel; + Tcl_UniChar menuChar; + Tcl_DString ds; *plResult = 0; menuPtr = Tcl_GetHashValue(hashEntryPtr); @@ -1259,6 +1261,7 @@ TkWinHandleMenuEvent( */ menuChar = Tcl_UniCharToUpper((Tcl_UniChar) LOWORD(*pwParam)); + Tcl_DStringInit(&ds); for (i = 0; i < menuPtr->numEntries; i++) { underline = menuPtr->entries[i]->underline; labelPtr = menuPtr->entries[i]->labelPtr; @@ -1266,7 +1269,10 @@ TkWinHandleMenuEvent( /* * Ensure we don't exceed the label length, then check */ - wlabel = Tcl_GetUnicodeFromObj(labelPtr, &len); + const char *src = Tcl_GetStringFromObj(labelPtr, &len); + + Tcl_DStringFree(&ds); + wlabel = (WCHAR *) Tcl_WinUtfToTChar(src, len, &ds); if ((underline < len) && (menuChar == Tcl_UniCharToUpper(wlabel[underline]))) { *plResult = (2 << 16) | i; @@ -1275,6 +1281,7 @@ TkWinHandleMenuEvent( } } } + Tcl_DStringFree(&ds); } break; } @@ -2070,8 +2077,7 @@ DrawMenuUnderline( if ((mePtr->underline >= 0) && (mePtr->labelPtr != NULL)) { int len; - /* do the unicode call just to prevent overruns */ - Tcl_GetUnicodeFromObj(mePtr->labelPtr, &len); + len = Tcl_GetCharLength(mePtr->labelPtr); if (mePtr->underline < len) { const char *label, *start, *end; @@ -2467,7 +2473,7 @@ DrawMenuEntryLabel( XFillRectangle(menuPtr->display, d, menuPtr->disabledGC, x, y, (unsigned) width, (unsigned) height); } else if ((mePtr->image != NULL) - && (menuPtr->disabledImageGC != NULL)) { + && menuPtr->disabledImageGC) { XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC, leftEdge + imageXOffset, (int) (y + (mePtr->height - imageHeight)/2 + imageYOffset), diff --git a/win/ttkWinXPTheme.c b/win/ttkWinXPTheme.c index 3de1504..b828221 100644 --- a/win/ttkWinXPTheme.c +++ b/win/ttkWinXPTheme.c @@ -455,7 +455,7 @@ InitElementData(ElementData *elementData, Tk_Window tkwin, Drawable d) { Window win = Tk_WindowId(tkwin); - if (win != None) { + if (win) { elementData->hwnd = Tk_GetHWND(win); } else { elementData->hwnd = elementData->procs->stubWindow; @@ -829,16 +829,21 @@ static void TextElementSize( ElementData *elementData = clientData; RECT rc = {0, 0}; HRESULT hr = S_OK; + const char *src; + int len; + Tcl_DString ds; if (!InitElementData(elementData, tkwin, 0)) return; + src = Tcl_GetStringFromObj(element->textObj, &len); + Tcl_WinUtfToTChar(src, len, &ds); hr = elementData->procs->GetThemeTextExtent( elementData->hTheme, elementData->hDC, elementData->info->partId, Ttk_StateTableLookup(elementData->info->statemap, 0), - Tcl_GetUnicode(element->textObj), + (WCHAR *) Tcl_DStringValue(&ds), -1, DT_LEFT,// | DT_BOTTOM | DT_NOPREFIX, NULL, @@ -851,6 +856,7 @@ static void TextElementSize( if (*widthPtr < 80) *widthPtr = 80; if (*heightPtr < 20) *heightPtr = 20; + Tcl_DStringFree(&ds); FreeElementData(elementData); } @@ -862,20 +868,27 @@ static void TextElementDraw( ElementData *elementData = clientData; RECT rc = BoxToRect(b); HRESULT hr = S_OK; + const char *src; + int len; + Tcl_DString ds; if (!InitElementData(elementData, tkwin, d)) return; + src = Tcl_GetStringFromObj(element->textObj, &len); + Tcl_WinUtfToTChar(src, len, &ds); hr = elementData->procs->DrawThemeText( elementData->hTheme, elementData->hDC, elementData->info->partId, Ttk_StateTableLookup(elementData->info->statemap, state), - Tcl_GetUnicode(element->textObj), + (WCHAR *) Tcl_DStringValue(&ds), -1, DT_LEFT,// | DT_BOTTOM | DT_NOPREFIX, (state & TTK_STATE_DISABLED) ? DTT_GRAYED : 0, &rc); + + Tcl_DStringFree(&ds); FreeElementData(elementData); } @@ -1102,7 +1115,7 @@ Ttk_CreateVsapiElement( XPThemeData *themeData = clientData; ElementInfo *elementPtr = NULL; ClientData elementData; - Tcl_UniChar *className; + WCHAR *className; int partId = 0; Ttk_StateTable *stateTable; Ttk_Padding pad = {0, 0, 0, 0}; @@ -1111,6 +1124,7 @@ Ttk_CreateVsapiElement( char *name; LPWSTR wname; Ttk_ElementSpec *elementSpec = &GenericElementSpec; + Tcl_DString classBuf; static const char *optionStrings[] = { "-padding","-width","-height","-margins", "-syssize", @@ -1128,7 +1142,8 @@ Ttk_CreateVsapiElement( if (Tcl_GetIntFromObj(interp, objv[1], &partId) != TCL_OK) { return TCL_ERROR; } - className = Tcl_GetUnicodeFromObj(objv[0], &length); + name = Tcl_GetStringFromObj(objv[0], &length); + className = (WCHAR *) Tcl_WinUtfToTChar(name, length, &classBuf); /* flags or padding */ if (objc > 3) { @@ -1140,54 +1155,54 @@ Ttk_CreateVsapiElement( "Missing value for \"%s\".", Tcl_GetString(objv[i]))); Tcl_SetErrorCode(interp, "TTK", "VSAPI", "MISSING", NULL); - return TCL_ERROR; + goto retErr; } if (Tcl_GetIndexFromObjStruct(interp, objv[i], optionStrings, sizeof(char *), "option", 0, &option) != TCL_OK) - return TCL_ERROR; + goto retErr; switch (option) { case O_PADDING: if (Ttk_GetBorderFromObj(interp, objv[i+1], &pad) != TCL_OK) { - return TCL_ERROR; + goto retErr; } break; case O_MARGINS: if (Ttk_GetBorderFromObj(interp, objv[i+1], &pad) != TCL_OK) { - return TCL_ERROR; + goto retErr; } flags |= PAD_MARGINS; break; case O_WIDTH: if (Tcl_GetIntFromObj(interp, objv[i+1], &tmp) != TCL_OK) { - return TCL_ERROR; + goto retErr; } pad.left = pad.right = tmp; flags |= IGNORE_THEMESIZE; break; case O_HEIGHT: if (Tcl_GetIntFromObj(interp, objv[i+1], &tmp) != TCL_OK) { - return TCL_ERROR; + goto retErr; } pad.top = pad.bottom = tmp; flags |= IGNORE_THEMESIZE; break; case O_SYSSIZE: if (GetSysFlagFromObj(interp, objv[i+1], &tmp) != TCL_OK) { - return TCL_ERROR; + goto retErr; } elementSpec = &GenericSizedElementSpec; flags |= (tmp & 0xFFFF); break; case O_HALFHEIGHT: if (Tcl_GetBooleanFromObj(interp, objv[i+1], &tmp) != TCL_OK) { - return TCL_ERROR; + goto retErr; } if (tmp) flags |= HALF_HEIGHT; break; case O_HALFWIDTH: if (Tcl_GetBooleanFromObj(interp, objv[i+1], &tmp) != TCL_OK) { - return TCL_ERROR; + goto retErr; } if (tmp) flags |= HALF_WIDTH; @@ -1201,7 +1216,7 @@ Ttk_CreateVsapiElement( Tcl_Obj **specs; int n,j,count, status = TCL_OK; if (Tcl_ListObjGetElements(interp, objv[2], &count, &specs) != TCL_OK) - return TCL_ERROR; + goto retErr; /* we over-allocate to ensure there is a terminating entry */ stateTable = ckalloc(sizeof(Ttk_StateTable) * (count + 1)); memset(stateTable, 0, sizeof(Ttk_StateTable) * (count + 1)); @@ -1217,6 +1232,7 @@ Ttk_CreateVsapiElement( } if (status != TCL_OK) { ckfree(stateTable); + Tcl_DStringFree(&classBuf); return status; } } else { @@ -1237,7 +1253,7 @@ Ttk_CreateVsapiElement( elementPtr->elementName = name; /* set the class name to an allocated copy */ - wname = ckalloc(sizeof(WCHAR) * (length + 1)); + wname = ckalloc(Tcl_DStringLength(&classBuf) + sizeof(WCHAR)); wcscpy(wname, className); elementPtr->className = wname; @@ -1247,7 +1263,12 @@ Ttk_CreateVsapiElement( Ttk_RegisterCleanup(interp, elementData, DestroyElementData); Tcl_SetObjResult(interp, Tcl_NewStringObj(elementName, -1)); + Tcl_DStringFree(&classBuf); return TCL_OK; + +retErr: + Tcl_DStringFree(&classBuf); + return TCL_ERROR; } /*---------------------------------------------------------------------- -- cgit v0.12 From 1e85c07bbeffce3e6195088bb488c1a784f81190 Mon Sep 17 00:00:00 2001 From: culler Date: Fri, 15 Mar 2019 21:14:49 +0000 Subject: Fix some conditional compilation misconfiguration. --- macosx/ttkMacOSXTheme.c | 85 ++++++++++++++++++++++++------------------------- 1 file changed, 42 insertions(+), 43 deletions(-) diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index 57a5e41..7c91752 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -202,6 +202,48 @@ static void DrawGroupBox( CFRelease(path); } +/* + * NormalizeButtonBounds -- + * + * Apple's Human Interface Guidelines only allow three specific heights for buttons: + * Regular, small and mini. We always use the regular size. However, Ttk may + * provide an arbitrary bounding rectangle. We always draw the button centered + * vertically on the rectangle, and having the same width as the rectangle. + * This function returns the actual bounding rectangle that will be used in + * drawing the button. + */ + +static CGRect NormalizeButtonBounds( + SInt32 heightMetric, + CGRect bounds) +{ + SInt32 height; + ChkErr(GetThemeMetric, heightMetric, &height); + bounds.origin.y += (bounds.size.height - height)/2; + bounds.size.height = height; + return bounds; +} + +/* SolidFillButtonFace -- + * + * Fill a rounded rectangle with a specified solid color. + */ + +static void SolidFillButtonFace( + CGContextRef context, + CGRect bounds, + CGFloat radius, + NSColor *color) +{ + CGPathRef path; + CGContextSetFillColorWithColor(context, color.CGColor); + path = CGPathCreateWithRoundedRect(bounds, radius, radius, NULL); + CGContextBeginPath(context); + CGContextAddPath(context, path); + CGContextFillPath(context); + CFRelease(path); +} + #endif /* MAC_OS_X_VERSION_MIN_REQUIRED > 1080 */ #if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 @@ -231,28 +273,6 @@ static CGFloat darkInactiveGradient[8] = {89.0/255, 90.0/255, 93.0/255, 1.0, static CGFloat darkSelectedGradient[8] = {23.0/255, 111.0/255, 232.0/255, 1.0, 20.0/255, 94.0/255, 206.0/255, 1.0}; -/* - * NormalizeButtonBounds -- - * - * Apple's Human Interface Guidelines only allow three specific heights for buttons: - * Regular, small and mini. We always use the regular size. However, Ttk may - * provide an arbitrary bounding rectangle. We always draw the button centered - * vertically on the rectangle, and having the same width as the rectangle. - * This function returns the actual bounding rectangle that will be used in - * drawing the button. - */ - -static CGRect NormalizeButtonBounds( - SInt32 heightMetric, - CGRect bounds) -{ - SInt32 height; - ChkErr(GetThemeMetric, heightMetric, &height); - bounds.origin.y += (bounds.size.height - height)/2; - bounds.size.height = height; - return bounds; -} - /* FillButtonBackground -- * * Fills a rounded rectangle with a transparent black gradient. @@ -306,26 +326,6 @@ static void HighlightButtonBorder( CFRelease(topGradient); } -/* SolidFillButtonFace -- - * - * Fill a rounded rectangle with a specified solid color. - */ - -static void SolidFillButtonFace( - CGContextRef context, - CGRect bounds, - CGFloat radius, - NSColor *color) -{ - CGPathRef path; - CGContextSetFillColorWithColor(context, color.CGColor); - path = CGPathCreateWithRoundedRect(bounds, radius, radius, NULL); - CGContextBeginPath(context); - CGContextAddPath(context, path); - CGContextFillPath(context); - CFRelease(path); -} - /* GradientFillButtonFace -- * * Fill a rounded rectangle with a specified gradient. @@ -781,7 +781,6 @@ static void ButtonElementDraw( default: ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); #endif - } } else { /* * Apple's PushButton and PopupButton do not change their (white) fill -- cgit v0.12 From 1a51c9879564046631bbbada7f28a9d4033efbd8 Mon Sep 17 00:00:00 2001 From: culler Date: Fri, 15 Mar 2019 21:31:44 +0000 Subject: Dealt with dark BevelButtons and progress bars. --- library/ttk/aquaTheme.tcl | 5 --- macosx/ttkMacOSXTheme.c | 99 ++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 80 insertions(+), 24 deletions(-) diff --git a/library/ttk/aquaTheme.tcl b/library/ttk/aquaTheme.tcl index 81d7ffe..d04a1d5 100644 --- a/library/ttk/aquaTheme.tcl +++ b/library/ttk/aquaTheme.tcl @@ -38,17 +38,12 @@ namespace eval ttk::theme::aqua { -foreground { disabled systemDisabledControlTextColor} ttk::style configure Toolbutton -padding 4 -# ttk::style configure Toolbutton -padding 4 -foreground black -# ttk::style map Toolbutton \ -# -background { -# background systemWindowBody} # Workaround for #1100117: # Actually, on Aqua we probably shouldn't stipple images in # disabled buttons even if it did work... ttk::style configure . -stipple {} - # Notebook ttk::style configure TNotebook -tabmargins {10 0} -tabposition n ttk::style configure TNotebook -padding {18 8 18 17} diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index 7c91752..2f3a321 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -8,6 +8,7 @@ * Copyright (c) 2006-2009 Daniel A. Steffen * Copyright 2008-2009, Apple Inc. * Copyright 2009 Kevin Walzer/WordTech Communications LLC. + * Copyright 2019 Marc Culler * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. @@ -43,6 +44,7 @@ TkMacOSXRestoreDrawingContext(&dc); } #define HIOrientation kHIThemeOrientationNormal +#define NoThemeMetric 0xFFFFFFFF #ifdef __LP64__ #define RangeToFactor(maximum) (((double) (INT_MAX >> 1)) / (maximum)) @@ -264,6 +266,7 @@ static CGFloat darkButtonFace[4] = {112.0/255, 113.0/255, 115.0/255, 1.0}; static CGFloat darkDisabledButtonFace[4] = {86.0/255, 87.0/255, 89.0/255, 1.0}; static CGFloat darkInactiveSelectedTab[4] = {159.0/255, 160.0/255, 161.0/255, 1.0}; static CGFloat darkTabSeparator[4] = {0.0, 0.0, 0.0, 0.25}; +static CGFloat darkTrack[4] = {1.0, 1.0, 1.0, 0.25}; static CGFloat darkTopGradient[8] = {1.0, 1.0, 1.0, 0.3, 1.0, 1.0, 1.0, 0.0}; static CGFloat darkBackgroundGradient[8] = {0.0, 0.0, 0.0, 0.1, @@ -661,7 +664,6 @@ static void DrawDarkSeparator( * +++ Button element: Used for elements drawn with DrawThemeButton. */ -#define NoThemeMetric 0xFFFFFFFF typedef struct { ThemeButtonKind kind; @@ -698,17 +700,35 @@ static Ttk_StateTable ButtonAdornmentTable[] = { */ static inline HIThemeButtonDrawInfo computeButtonDrawInfo( - ThemeButtonParams *params, Ttk_State state) + ThemeButtonParams *params, + Ttk_State state, + Tk_Window tkwin) { /* * See ButtonElementDraw for the explanation of why we always draw - * PushButtons in the active state. + * PushButtons in the active state. The deprecated BezelButton can be + * faked to at least be usable in Dark Mode if it is always drawn as + * inactive. */ - + + SInt32 HIThemeState; + switch (params->kind) { + case kThemePushButton: + HIThemeState = kThemeStateActive; + break; + case kThemeBevelButton: + if (TkMacOSXInDarkMode(tkwin)) { + HIThemeState = kThemeStateInactive; + break; + } + default: + HIThemeState = Ttk_StateTableLookup(ThemeStateTable, state); + break; + } + const HIThemeButtonDrawInfo info = { .version = 0, - .state = params && params->kind == kThemePushButton ? - kThemeStateActive : Ttk_StateTableLookup(ThemeStateTable, state), + .state = HIThemeState, .kind = params ? params->kind : 0, .value = Ttk_StateTableLookup(ButtonValueTable, state), .adornment = Ttk_StateTableLookup(ButtonAdornmentTable, state), @@ -735,7 +755,7 @@ static void ButtonElementSize( int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) { ThemeButtonParams *params = clientData; - const HIThemeButtonDrawInfo info = computeButtonDrawInfo(params, 0); + const HIThemeButtonDrawInfo info = computeButtonDrawInfo(params, 0, tkwin); static const CGRect scratchBounds = {{0, 0}, {100, 100}}; CGRect contentBounds; @@ -762,7 +782,7 @@ static void ButtonElementDraw( BEGIN_DRAWING(d) ThemeButtonParams *params = clientData; CGRect bounds = BoxToRect(d, b); - HIThemeButtonDrawInfo info = computeButtonDrawInfo(params, state); + HIThemeButtonDrawInfo info = computeButtonDrawInfo(params, state, tkwin); bounds = NormalizeButtonBounds(params->heightMetric, bounds); if (TkMacOSXInDarkMode(tkwin)) { @@ -780,6 +800,7 @@ static void ButtonElementDraw( break; default: ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); + } #endif } else { /* @@ -1188,9 +1209,14 @@ static Ttk_ElementSpec SpinButtonElementSpec = { * Progress bars and scales. (See also: <>) */ +/* + * Apple does not change the appearance of a slider when the window + * becomes inactive. So we shouldn't either. + */ + static Ttk_StateTable ThemeTrackEnableTable[] = { { kThemeTrackDisabled, TTK_STATE_DISABLED, 0 }, - { kThemeTrackInactive, TTK_STATE_BACKGROUND, 0 }, + { kThemeTrackActive, TTK_STATE_BACKGROUND, 0 }, { kThemeTrackActive, 0, 0 } /* { kThemeTrackNothingToScroll, ?, ? }, */ }; @@ -1263,11 +1289,30 @@ static void TrackElementDraw( if (info.kind == kThemeSlider) { info.trackInfo.slider.pressState = state & TTK_STATE_PRESSED ? kThemeThumbPressed : 0; - info.trackInfo.slider.thumbDir = kThemeThumbPlain; + if (state & TTK_STATE_ALTERNATE) { + info.trackInfo.slider.thumbDir = kThemeThumbDownward; + } else { + info.trackInfo.slider.thumbDir = kThemeThumbPlain; + } } BEGIN_DRAWING(d) +#if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 + if (TkMacOSXInDarkMode(tkwin)) { + CGRect bounds = BoxToRect(d, b); + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + NSColor *trackColor = [NSColor colorWithColorSpace: deviceRGB + components: darkTrack + count: 4]; + if (orientation == TTK_ORIENT_HORIZONTAL) { + bounds = CGRectInset(bounds, 1, bounds.size.height/2 - 3); + } else { + bounds = CGRectInset(bounds, bounds.size.width/2 - 3, 1); + } + SolidFillButtonFace(dc.context, bounds, 3, trackColor); + } +#endif ChkErr(HIThemeDrawTrack, &info, NULL, dc.context, HIOrientation); END_DRAWING } @@ -1342,7 +1387,8 @@ static void PbarElementSize( SInt32 size = 24; /* @@@ Check HIG for correct default */ ChkErr(GetThemeMetric, kThemeMetricLargeProgressBarThickness, &size); - *widthPtr = *heightPtr = size; + // *widthPtr = *heightPtr = size; + *heightPtr = size; } static void PbarElementDraw( @@ -1375,6 +1421,21 @@ static void PbarElementDraw( }; BEGIN_DRAWING(d) +#if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 + if (TkMacOSXInDarkMode(tkwin)) { + CGRect bounds = BoxToRect(d, b); + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + NSColor *trackColor = [NSColor colorWithColorSpace: deviceRGB + components: darkTrack + count: 4]; + if (orientation == TTK_ORIENT_HORIZONTAL) { + bounds = CGRectInset(bounds, 1, bounds.size.height/2 - 3); + } else { + bounds = CGRectInset(bounds, bounds.size.width/2 - 3, 1); + } + SolidFillButtonFace(dc.context, bounds, 3, trackColor); + } +#endif ChkErr(HIThemeDrawTrack, &info, NULL, dc.context, HIOrientation); END_DRAWING } @@ -1822,15 +1883,15 @@ static int AquaTheme_Init(Tcl_Interp *interp) Ttk_RegisterElementSpec(themePtr, "Notebook.tab", &TabElementSpec, 0); Ttk_RegisterElementSpec(themePtr, "Notebook.client", &PaneElementSpec, 0); - Ttk_RegisterElementSpec(themePtr, "Labelframe.border",&GroupElementSpec,0); - Ttk_RegisterElementSpec(themePtr, "Entry.field",&EntryElementSpec,0); - Ttk_RegisterElementSpec(themePtr, "Spinbox.field",&EntryElementSpec,0); + Ttk_RegisterElementSpec(themePtr, "Labelframe.border", &GroupElementSpec,0); + Ttk_RegisterElementSpec(themePtr, "Entry.field", &EntryElementSpec,0); + Ttk_RegisterElementSpec(themePtr, "Spinbox.field", &EntryElementSpec,0); - Ttk_RegisterElementSpec(themePtr, "separator",&SeparatorElementSpec,0); - Ttk_RegisterElementSpec(themePtr, "hseparator",&SeparatorElementSpec,0); - Ttk_RegisterElementSpec(themePtr, "vseparator",&SeparatorElementSpec,0); + Ttk_RegisterElementSpec(themePtr, "separator", &SeparatorElementSpec,0); + Ttk_RegisterElementSpec(themePtr, "hseparator", &SeparatorElementSpec,0); + Ttk_RegisterElementSpec(themePtr, "vseparator", &SeparatorElementSpec,0); - Ttk_RegisterElementSpec(themePtr, "sizegrip",&SizegripElementSpec,0); + Ttk_RegisterElementSpec(themePtr, "sizegrip", &SizegripElementSpec,0); /* * <> @@ -1840,7 +1901,7 @@ static int AquaTheme_Init(Tcl_Interp *interp) */ Ttk_RegisterElementSpec(themePtr,"Scale.trough", &TrackElementSpec, &ScaleData); - Ttk_RegisterElementSpec(themePtr,"Scale.slider",&SliderElementSpec,0); + Ttk_RegisterElementSpec(themePtr,"Scale.slider", &SliderElementSpec,0); Ttk_RegisterElementSpec(themePtr,"Progressbar.track", &PbarElementSpec, 0); /* -- cgit v0.12 From 08d659386041de223506290e10310e9a5fb0ab27 Mon Sep 17 00:00:00 2001 From: culler Date: Fri, 15 Mar 2019 23:22:34 +0000 Subject: Small corrections. --- macosx/ttkMacOSXTheme.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index 2f3a321..6a78c2a 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -1295,8 +1295,6 @@ static void TrackElementDraw( info.trackInfo.slider.thumbDir = kThemeThumbPlain; } } - - BEGIN_DRAWING(d) #if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 if (TkMacOSXInDarkMode(tkwin)) { @@ -1306,11 +1304,11 @@ static void TrackElementDraw( components: darkTrack count: 4]; if (orientation == TTK_ORIENT_HORIZONTAL) { - bounds = CGRectInset(bounds, 1, bounds.size.height/2 - 3); + bounds = CGRectInset(bounds, 1, bounds.size.height/2 - 2); } else { - bounds = CGRectInset(bounds, bounds.size.width/2 - 3, 1); + bounds = CGRectInset(bounds, bounds.size.width/2 - 3, 2); } - SolidFillButtonFace(dc.context, bounds, 3, trackColor); + SolidFillButtonFace(dc.context, bounds, 2, trackColor); } #endif ChkErr(HIThemeDrawTrack, &info, NULL, dc.context, HIOrientation); @@ -1387,8 +1385,7 @@ static void PbarElementSize( SInt32 size = 24; /* @@@ Check HIG for correct default */ ChkErr(GetThemeMetric, kThemeMetricLargeProgressBarThickness, &size); - // *widthPtr = *heightPtr = size; - *heightPtr = size; + *widthPtr = *heightPtr = size; } static void PbarElementDraw( -- cgit v0.12 From 9fc8201b82240aab48b8f5189bdb67f0e2280142 Mon Sep 17 00:00:00 2001 From: culler Date: Sat, 16 Mar 2019 03:55:14 +0000 Subject: Fixed a logic error with selected disabled CheckBoxes and RadioButtons. --- macosx/ttkMacOSXTheme.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index 6a78c2a..979d723 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -462,6 +462,7 @@ static void DrawDarkCheckBox( FillButtonBackground(context, bounds, 4); bounds = CGRectInset(bounds, 1, 1); if (!(state & TTK_STATE_BACKGROUND) && + !(state & TTK_STATE_DISABLED) && ((state & TTK_STATE_SELECTED) || (state & TTK_STATE_ALTERNATE))) { GradientFillButtonFace(context, bounds, 3, darkSelectedGradient, 2); } else { @@ -516,6 +517,7 @@ static void DrawDarkRadioButton( FillButtonBackground(context, bounds, 9); bounds = CGRectInset(bounds, 1, 1); if (!(state & TTK_STATE_BACKGROUND) && + !(state & TTK_STATE_DISABLED) && ((state & TTK_STATE_SELECTED) || (state & TTK_STATE_ALTERNATE))) { GradientFillButtonFace(context, bounds, 8, darkSelectedGradient, 2); } else { -- cgit v0.12 From cc4e3278ea1ebd0e15a67d99597bd76587d54e9d Mon Sep 17 00:00:00 2001 From: culler Date: Sun, 17 Mar 2019 03:20:41 +0000 Subject: Made PushButtons display correctly in pressed state. --- macosx/ttkMacOSXTheme.c | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index 979d723..60d475b 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -387,17 +387,22 @@ static void DrawDarkButton( */ bounds = CGRectInset(bounds, 1, 1); - if (state & TTK_STATE_DISABLED) { - faceColor = [NSColor colorWithColorSpace: deviceRGB - components: darkDisabledButtonFace - count: 4]; + if (kind == kThemePushButton && (state & TTK_STATE_PRESSED)) { + GradientFillButtonFace(context, bounds, 4, + darkSelectedGradient, 2); } else { - faceColor = [NSColor colorWithColorSpace: deviceRGB - components: darkButtonFace - count: 4]; + if (state & TTK_STATE_DISABLED) { + faceColor = [NSColor colorWithColorSpace: deviceRGB + components: darkDisabledButtonFace + count: 4]; + } else { + faceColor = [NSColor colorWithColorSpace: deviceRGB + components: darkButtonFace + count: 4]; + } + SolidFillButtonFace(context, bounds, 4, faceColor); } - SolidFillButtonFace(context, bounds, 4, faceColor); - + /* * If this is a popup, draw the arrow button. */ @@ -689,12 +694,11 @@ static Ttk_StateTable ButtonValueTable[] = { }; static Ttk_StateTable ButtonAdornmentTable[] = { - { kThemeAdornmentDefault| kThemeAdornmentFocus, - TTK_STATE_ALTERNATE| TTK_STATE_FOCUS, 0 }, + { kThemeAdornmentDefault | kThemeAdornmentFocus, + TTK_STATE_ALTERNATE | TTK_STATE_FOCUS, 0 }, { kThemeAdornmentDefault, TTK_STATE_ALTERNATE, 0 }, { kThemeAdornmentFocus, TTK_STATE_FOCUS, 0 }, - { kThemeAdornmentNone, 0, 0 } -}; + { kThemeAdornmentNone, 0, 0 }}; /* * computeButtonDrawInfo -- @@ -708,9 +712,7 @@ static inline HIThemeButtonDrawInfo computeButtonDrawInfo( { /* * See ButtonElementDraw for the explanation of why we always draw - * PushButtons in the active state. The deprecated BezelButton can be - * faked to at least be usable in Dark Mode if it is always drawn as - * inactive. + * PushButtons in the active state. */ SInt32 HIThemeState; @@ -718,11 +720,6 @@ static inline HIThemeButtonDrawInfo computeButtonDrawInfo( case kThemePushButton: HIThemeState = kThemeStateActive; break; - case kThemeBevelButton: - if (TkMacOSXInDarkMode(tkwin)) { - HIThemeState = kThemeStateInactive; - break; - } default: HIThemeState = Ttk_StateTableLookup(ThemeStateTable, state); break; -- cgit v0.12 From 2dd62f3b2f103f5c345fa3d92a9112cdf20c60db Mon Sep 17 00:00:00 2001 From: culler Date: Sun, 17 Mar 2019 14:13:07 +0000 Subject: Fixed error in height computation for BevelButtons. --- macosx/ttkMacOSXTheme.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index 60d475b..2e55e62 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -220,9 +220,11 @@ static CGRect NormalizeButtonBounds( CGRect bounds) { SInt32 height; - ChkErr(GetThemeMetric, heightMetric, &height); - bounds.origin.y += (bounds.size.height - height)/2; - bounds.size.height = height; + if (heightMetric != NoThemeMetric) { + ChkErr(GetThemeMetric, heightMetric, &height); + bounds.origin.y += (bounds.size.height - height)/2; + bounds.size.height = height; + } return bounds; } -- cgit v0.12 From b29e48c2415674197423a527cef1c8fd5028b8a4 Mon Sep 17 00:00:00 2001 From: culler Date: Sun, 17 Mar 2019 19:41:04 +0000 Subject: Improve the behavior and appearance of BevelButtons. --- library/demos/toolbar.tcl | 4 +- library/ttk/aquaTheme.tcl | 8 ++- macosx/ttkMacOSXTheme.c | 139 +++++++++++++++++++++++++++++----------------- 3 files changed, 96 insertions(+), 55 deletions(-) diff --git a/library/demos/toolbar.tcl b/library/demos/toolbar.tcl index 0ae4669..cb2a495 100644 --- a/library/demos/toolbar.tcl +++ b/library/demos/toolbar.tcl @@ -31,7 +31,7 @@ ttk::separator $w.sep ttk::frame $t.tearoff -cursor fleur ttk::separator $t.tearoff.to -orient vertical ttk::separator $t.tearoff.to2 -orient vertical -pack $t.tearoff.to -fill y -expand 1 -padx 2 -side left +pack $t.tearoff.to -fill y -expand 1 -padx 4 -side left pack $t.tearoff.to2 -fill y -expand 1 -side left ttk::frame $t.contents grid $t.tearoff $t.contents -sticky nsew @@ -79,7 +79,7 @@ text $w.txt -width 40 -height 10 interp alias {} doInsert {} $w.txt insert end ;# Make bindings easy to write ## Arrange contents -grid $t.button $t.check $t.menu $t.combo -in $t.contents -padx 2 -sticky ns +grid $t.button $t.check $t.menu $t.combo -in $t.contents -padx 2 -pady 4 -sticky ns grid $t -sticky ew grid $w.sep -sticky ew grid $w.msg -sticky ew diff --git a/library/ttk/aquaTheme.tcl b/library/ttk/aquaTheme.tcl index d04a1d5..5343671 100644 --- a/library/ttk/aquaTheme.tcl +++ b/library/ttk/aquaTheme.tcl @@ -26,7 +26,8 @@ namespace eval ttk::theme::aqua { !focus systemDialogActiveText} # Buttons - ttk::style configure TButton -anchor center -width -6 \ +# ttk::style configure TButton -anchor center -width -6 \ + ttk::style configure TButton -anchor center \ -foreground systemControlTextColor ttk::style map TButton \ -foreground { @@ -37,7 +38,10 @@ namespace eval ttk::theme::aqua { ttk::style map TRadiobutton \ -foreground { disabled systemDisabledControlTextColor} - ttk::style configure Toolbutton -padding 4 + ttk::style map Toolbutton \ + -foreground { + disabled systemDisabledControlTextColor + } # Workaround for #1100117: # Actually, on Aqua we probably shouldn't stipple images in diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index 2e55e62..7201df5 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -45,6 +45,10 @@ #define HIOrientation kHIThemeOrientationNormal #define NoThemeMetric 0xFFFFFFFF +#define BEVEL_XPAD 6 +#define BEVEL_YPAD 6 +static Ttk_Padding BevelButtonMargins = {BEVEL_XPAD, BEVEL_YPAD, + BEVEL_XPAD, BEVEL_YPAD}; #ifdef __LP64__ #define RangeToFactor(maximum) (((double) (INT_MAX >> 1)) / (maximum)) @@ -207,14 +211,18 @@ static void DrawGroupBox( /* * NormalizeButtonBounds -- * - * Apple's Human Interface Guidelines only allow three specific heights for buttons: - * Regular, small and mini. We always use the regular size. However, Ttk may - * provide an arbitrary bounding rectangle. We always draw the button centered - * vertically on the rectangle, and having the same width as the rectangle. - * This function returns the actual bounding rectangle that will be used in - * drawing the button. + * Apple's Human Interface Guidelines only allow three specific heights for + * most buttons: Regular, small and mini. We always use the regular size. + * However, Ttk may provide an arbitrary bounding rectangle. We always draw + * the button centered vertically on the rectangle, and having the same width + * as the rectangle. This function returns the actual bounding rectangle that + * will be used in drawing the button. + * + * The BevelButton is allowed to have arbitrary size, and also has external + * padding. This is handled separately here. */ + static CGRect NormalizeButtonBounds( SInt32 heightMetric, CGRect bounds) @@ -228,12 +236,12 @@ static CGRect NormalizeButtonBounds( return bounds; } -/* SolidFillButtonFace -- +/* SolidFillRoundedRectangle -- * * Fill a rounded rectangle with a specified solid color. */ -static void SolidFillButtonFace( +static void SolidFillRoundedRectangle( CGContextRef context, CGRect bounds, CGFloat radius, @@ -248,6 +256,34 @@ static void SolidFillButtonFace( CFRelease(path); } + +/* GradientFillRoundedRectangle -- + * + * Fill a rounded rectangle with a specified gradient. + */ + +static void GradientFillRoundedRectangle( + CGContextRef context, + CGRect bounds, + CGFloat radius, + CGFloat* colors, + int numColors) +{ + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + CGPathRef path; + CGPoint end = {bounds.origin.x, + bounds.origin.y + bounds.size.height}; + CGGradientRef gradient = CGGradientCreateWithColorComponents( + deviceRGB.CGColorSpace, colors, NULL, numColors); + path = CGPathCreateWithRoundedRect(bounds, radius, radius, NULL); + CGContextBeginPath(context); + CGContextAddPath(context, path); + CGContextClip(context); + CGContextDrawLinearGradient(context, gradient, bounds.origin, end, 0); + CFRelease(path); + CFRelease(gradient); +} + #endif /* MAC_OS_X_VERSION_MIN_REQUIRED > 1080 */ #if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 @@ -331,33 +367,6 @@ static void HighlightButtonBorder( CFRelease(topGradient); } -/* GradientFillButtonFace -- - * - * Fill a rounded rectangle with a specified gradient. - */ - -static void GradientFillButtonFace( - CGContextRef context, - CGRect bounds, - CGFloat radius, - CGFloat* colors, - int numColors) -{ - NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; - CGPathRef path; - CGPoint end = {bounds.origin.x, - bounds.origin.y + bounds.size.height}; - CGGradientRef gradient = CGGradientCreateWithColorComponents( - deviceRGB.CGColorSpace, colors, NULL, numColors); - path = CGPathCreateWithRoundedRect(bounds, radius, radius, NULL); - CGContextBeginPath(context); - CGContextAddPath(context, path); - CGContextClip(context); - CGContextDrawLinearGradient(context, gradient, bounds.origin, end, 0); - CFRelease(path); - CFRelease(gradient); -} - /* * DrawDarkButton -- * @@ -390,7 +399,7 @@ static void DrawDarkButton( bounds = CGRectInset(bounds, 1, 1); if (kind == kThemePushButton && (state & TTK_STATE_PRESSED)) { - GradientFillButtonFace(context, bounds, 4, + GradientFillRoundedRectangle(context, bounds, 4, darkSelectedGradient, 2); } else { if (state & TTK_STATE_DISABLED) { @@ -402,7 +411,7 @@ static void DrawDarkButton( components: darkButtonFace count: 4]; } - SolidFillButtonFace(context, bounds, 4, faceColor); + SolidFillRoundedRectangle(context, bounds, 4, faceColor); } /* @@ -421,7 +430,7 @@ static void DrawDarkButton( */ if (!(state & TTK_STATE_BACKGROUND)) { - GradientFillButtonFace(context, arrowBounds, 4, + GradientFillRoundedRectangle(context, arrowBounds, 4, darkSelectedGradient, 2); } @@ -471,9 +480,11 @@ static void DrawDarkCheckBox( if (!(state & TTK_STATE_BACKGROUND) && !(state & TTK_STATE_DISABLED) && ((state & TTK_STATE_SELECTED) || (state & TTK_STATE_ALTERNATE))) { - GradientFillButtonFace(context, bounds, 3, darkSelectedGradient, 2); + GradientFillRoundedRectangle(context, bounds, 3, + darkSelectedGradient, 2); } else { - GradientFillButtonFace(context, bounds, 3, darkInactiveGradient, 2); + GradientFillRoundedRectangle(context, bounds, 3, + darkInactiveGradient, 2); } HighlightButtonBorder(context, bounds); if ((state & TTK_STATE_SELECTED) || (state & TTK_STATE_ALTERNATE)) { @@ -526,9 +537,11 @@ static void DrawDarkRadioButton( if (!(state & TTK_STATE_BACKGROUND) && !(state & TTK_STATE_DISABLED) && ((state & TTK_STATE_SELECTED) || (state & TTK_STATE_ALTERNATE))) { - GradientFillButtonFace(context, bounds, 8, darkSelectedGradient, 2); + GradientFillRoundedRectangle(context, bounds, 8, + darkSelectedGradient, 2); } else { - GradientFillButtonFace(context, bounds, 8, darkInactiveGradient, 2); + GradientFillRoundedRectangle(context, bounds, 8, + darkInactiveGradient, 2); } HighlightButtonBorder(context, bounds); if ((state & TTK_STATE_SELECTED) || (state & TTK_STATE_ALTERNATE)) { @@ -601,7 +614,7 @@ static void DrawDarkTab( components: darkButtonFace count: 4]; } - SolidFillButtonFace(context, bounds, 4, faceColor); + SolidFillRoundedRectangle(context, bounds, 4, faceColor); /* * Draw a separator line on the left side of the tab if it @@ -635,12 +648,13 @@ static void DrawDarkTab( bounds.size.width += 1; } if (!(state & TTK_STATE_BACKGROUND)) { - GradientFillButtonFace(context, bounds, 4, darkSelectedGradient, 2); + GradientFillRoundedRectangle(context, bounds, 4, + darkSelectedGradient, 2); } else { faceColor = [NSColor colorWithColorSpace: deviceRGB components: darkInactiveSelectedTab count: 4]; - SolidFillButtonFace(context, bounds, 4, faceColor); + SolidFillRoundedRectangle(context, bounds, 4, faceColor); } HighlightButtonBorder(context, bounds); } @@ -683,7 +697,7 @@ static ThemeButtonParams PushButtonParams = { kThemePushButton, kThemeMetricPushButtonHeight }, CheckBoxParams = { kThemeCheckBox, kThemeMetricCheckBoxHeight }, RadioButtonParams = { kThemeRadioButton, kThemeMetricRadioButtonHeight }, - BevelButtonParams = { kThemeBevelButton, NoThemeMetric }, + BevelButtonParams = { kThemeRoundedBevelButton, NoThemeMetric }, PopupButtonParams = { kThemePopupButton, kThemeMetricPopupButtonHeight }, DisclosureParams = { kThemeDisclosureButton, kThemeMetricDisclosureTriangleHeight }, ListHeaderParams = { kThemeListHeaderButton, kThemeMetricListHeaderHeight }; @@ -699,6 +713,7 @@ static Ttk_StateTable ButtonAdornmentTable[] = { { kThemeAdornmentDefault | kThemeAdornmentFocus, TTK_STATE_ALTERNATE | TTK_STATE_FOCUS, 0 }, { kThemeAdornmentDefault, TTK_STATE_ALTERNATE, 0 }, + { kThemeAdornmentNone, TTK_STATE_ALTERNATE, 0 }, { kThemeAdornmentFocus, TTK_STATE_FOCUS, 0 }, { kThemeAdornmentNone, 0, 0 }}; @@ -759,6 +774,7 @@ static void ButtonElementSize( const HIThemeButtonDrawInfo info = computeButtonDrawInfo(params, 0, tkwin); static const CGRect scratchBounds = {{0, 0}, {100, 100}}; CGRect contentBounds; + int verticalPad; ButtonElementSizeNoPadding( clientData, elementRecord, tkwin, widthPtr, heightPtr, paddingPtr); @@ -772,8 +788,17 @@ static void ButtonElementSize( ChkErr(HIThemeGetButtonContentBounds, &scratchBounds, &info, &contentBounds); - paddingPtr->left = CGRectGetMinX(contentBounds); - paddingPtr->right = CGRectGetMaxX(scratchBounds) - CGRectGetMaxX(contentBounds); + CGRect backgroundBounds; + ChkErr(HIThemeGetButtonBackgroundBounds, + &scratchBounds, &info, &backgroundBounds); + + paddingPtr->left = contentBounds.origin.x - backgroundBounds.origin.x; + paddingPtr->right = CGRectGetMaxX(backgroundBounds) - CGRectGetMaxX(contentBounds); + verticalPad = contentBounds.origin.y - backgroundBounds.origin.y; + verticalPad += CGRectGetMaxY(backgroundBounds) - CGRectGetMaxY(contentBounds); + paddingPtr->top = verticalPad /2; + paddingPtr->bottom = verticalPad - paddingPtr->top; + } static void ButtonElementDraw( @@ -817,7 +842,19 @@ static void ButtonElementDraw( */ if (info.kind == kThemePopupButton && (state & TTK_STATE_BACKGROUND)) { CGRect innerBounds = CGRectInset(bounds, 1, 1); - SolidFillButtonFace(dc.context, innerBounds, 4, [NSColor whiteColor]); + NSColor *white = [NSColor whiteColor]; + SolidFillRoundedRectangle(dc.context, innerBounds, 4, white); + } + + /* + * A BevelButton with mixed value is drawn borderless, which does make + * much sense for us. + */ + + if (info.kind == kThemeRoundedBevelButton && + info.value == kThemeButtonMixed) { + info.value = kThemeButtonOff; + info.state = kThemeStateInactive; } ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); } @@ -1309,7 +1346,7 @@ static void TrackElementDraw( } else { bounds = CGRectInset(bounds, bounds.size.width/2 - 3, 2); } - SolidFillButtonFace(dc.context, bounds, 2, trackColor); + SolidFillRoundedRectangle(dc.context, bounds, 2, trackColor); } #endif ChkErr(HIThemeDrawTrack, &info, NULL, dc.context, HIOrientation); @@ -1431,7 +1468,7 @@ static void PbarElementDraw( } else { bounds = CGRectInset(bounds, bounds.size.width/2 - 3, 1); } - SolidFillButtonFace(dc.context, bounds, 3, trackColor); + SolidFillRoundedRectangle(dc.context, bounds, 3, trackColor); } #endif ChkErr(HIThemeDrawTrack, &info, NULL, dc.context, HIOrientation); -- cgit v0.12 From f357757e215618b09711c710048d925db11c2125 Mon Sep 17 00:00:00 2001 From: culler Date: Sun, 17 Mar 2019 20:40:28 +0000 Subject: Added a drawing procedure for dark BevelButtons. --- macosx/ttkMacOSXTheme.c | 69 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 63 insertions(+), 6 deletions(-) diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index 7201df5..750bdd6 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -45,10 +45,6 @@ #define HIOrientation kHIThemeOrientationNormal #define NoThemeMetric 0xFFFFFFFF -#define BEVEL_XPAD 6 -#define BEVEL_YPAD 6 -static Ttk_Padding BevelButtonMargins = {BEVEL_XPAD, BEVEL_YPAD, - BEVEL_XPAD, BEVEL_YPAD}; #ifdef __LP64__ #define RangeToFactor(maximum) (((double) (INT_MAX >> 1)) / (maximum)) @@ -105,7 +101,8 @@ static Ttk_StateTable ThemeStateTable[] = { #if MAC_OS_X_VERSION_MIN_REQUIRED > 1080 /*---------------------------------------------------------------------- * +++ Support for contrasting background colors when GroupBoxes - * or Tabbed panes are nested inside each other. + * or Tabbed panes are nested inside each other. Early versions + * of macOS used ridged borders, so do not need contrasting backgrounds. */ /* @@ -118,6 +115,13 @@ static Ttk_StateTable ThemeStateTable[] = { static CGFloat windowBackground[4] = {235.0/255, 235.0/255, 235.0/255, 1.0}; +/* + * GetBoxColor -- + * + * Compute a contrasting box color, based on nesting depth, and save the + * RGBA components in an array. + */ + static int GetBoxColor( CGContextRef context, Tk_Window tkwin, @@ -301,6 +305,8 @@ static void GradientFillRoundedRectangle( */ static CGFloat darkButtonFace[4] = {112.0/255, 113.0/255, 115.0/255, 1.0}; +static CGFloat darkPressedBevelFace[4] = {135.0/255, 136.0/255, 138.0/255, 1.0}; +static CGFloat darkSelectedBevelFace[4] = {162.0/255, 163.0/255, 165.0/255, 1.0}; static CGFloat darkDisabledButtonFace[4] = {86.0/255, 87.0/255, 89.0/255, 1.0}; static CGFloat darkInactiveSelectedTab[4] = {159.0/255, 160.0/255, 161.0/255, 1.0}; static CGFloat darkTabSeparator[4] = {0.0, 0.0, 0.0, 0.25}; @@ -455,6 +461,50 @@ static void DrawDarkButton( } /* + * DrawDarkButton -- + * + * This is a standalone drawing procedure which draws + * RoundedBevelButtons in the Dark Mode style. + */ + +static void DrawDarkBevelButton( + CGRect bounds, + Ttk_State state, + CGContextRef context) +{ + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + NSColor *faceColor; + CGContextClipToRect(context, bounds); + FillButtonBackground(context, bounds, 5); + + /* + * Fill the button face with the appropriate color. + */ + + bounds = CGRectInset(bounds, 1, 1); + if (state & TTK_STATE_PRESSED) { + faceColor = [NSColor colorWithColorSpace: deviceRGB + components: darkPressedBevelFace + count: 4]; + } else if ((state & TTK_STATE_DISABLED) || + (state & TTK_STATE_ALTERNATE)){ + faceColor = [NSColor colorWithColorSpace: deviceRGB + components: darkDisabledButtonFace + count: 4]; + } else if (state & TTK_STATE_SELECTED) { + faceColor = [NSColor colorWithColorSpace: deviceRGB + components: darkSelectedBevelFace + count: 4]; + } else { + faceColor = [NSColor colorWithColorSpace: deviceRGB + components: darkButtonFace + count: 4]; + } + SolidFillRoundedRectangle(context, bounds, 4, faceColor); + HighlightButtonBorder(context, bounds); +} + +/* * DrawDarkCheckBox -- * * This is a standalone drawing procedure which draws Checkboxes @@ -798,7 +848,11 @@ static void ButtonElementSize( verticalPad += CGRectGetMaxY(backgroundBounds) - CGRectGetMaxY(contentBounds); paddingPtr->top = verticalPad /2; paddingPtr->bottom = verticalPad - paddingPtr->top; - + if (info.kind == kThemePopupButton) { + static Ttk_Padding popupTweak = {0, 1, 0, 1}; + *paddingPtr = Ttk_AddPadding(*paddingPtr, popupTweak); + *heightPtr += Ttk_PaddingHeight(popupTweak); + } } static void ButtonElementDraw( @@ -824,6 +878,9 @@ static void ButtonElementDraw( case kThemeRadioButton: DrawDarkRadioButton(bounds, state, dc.context); break; + case kThemeRoundedBevelButton: + DrawDarkBevelButton(bounds, state, dc.context); + break; default: ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); } -- cgit v0.12 From 446875a3bad587fe6e6388f6576d12246df14154 Mon Sep 17 00:00:00 2001 From: culler Date: Mon, 18 Mar 2019 15:36:31 +0000 Subject: Added ::tk::unsupported::MacWindowStyle appearance to control which appearances are allowed on a per-window basis. --- macosx/README | 10 +++++ macosx/tkMacOSXWm.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 121 insertions(+), 6 deletions(-) diff --git a/macosx/README b/macosx/README index adc709c..c79c372 100644 --- a/macosx/README +++ b/macosx/README @@ -189,6 +189,16 @@ tk::unsupported::MacWindowStyle tabbingid window ?newId? which can be used to get or set the tabbingIdentifier for the NSWindow associated with a Tk Window. See section 3 for details. +- A command tk::unsupported::MacWindowStyle appearance window ?newAappearance? +is available when Tk is built and run on macOS 10.14 (Mojave) or later. In +that case the Ttk widgets all support the "Dark Mode" appearance which was +introduced in 10.14. The command accepts the following values for the optional +newAppearance option: "aqua", "darkaqua", or "auto". If the appearance is set +to aqua or darkaqua then the window will be displayed with the corresponding +appearance independent of any preferences settings. If it is set to "auto" +the appearance will be determined by the preferences. This command can be +used to opt out of Dark Mode on a per-window basis. + - If you want to use Remote Debugging with Xcode, you need to set the environment variable XCNOSTDIN to 1 in the Executable editor for Wish. That will cause us to force closing stdin & stdout. Otherwise, given how Xcode launches diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index 67d6ecb..1d31fe1 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -311,6 +311,8 @@ static int WmWinStyle(Tcl_Interp *interp, TkWindow *winPtr, int objc, Tcl_Obj *const objv[]); static int WmWinTabbingId(Tcl_Interp *interp, TkWindow *winPtr, int objc, Tcl_Obj *const objv[]); +static int WmWinAppearance(Tcl_Interp *interp, TkWindow *winPtr, + int objc, Tcl_Obj *const objv[]); static void ApplyWindowAttributeFlagChanges(TkWindow *winPtr, NSWindow *macWindow, UInt64 oldAttributes, int oldFlags, int create, int initial); @@ -5509,10 +5511,10 @@ TkUnsupported1ObjCmd( Tcl_Obj *const objv[]) /* Argument objects. */ { static const char *const subcmds[] = { - "style", "tabbingid", NULL + "style", "tabbingid", "appearance", NULL }; enum SubCmds { - TKMWS_STYLE, TKMWS_TABID + TKMWS_STYLE, TKMWS_TABID, TKMWS_APPEARANCE }; Tk_Window tkwin = clientData; TkWindow *winPtr; @@ -5540,13 +5542,14 @@ TkUnsupported1ObjCmd( sizeof(char *), "option", 0, &index) != TCL_OK) { return TCL_ERROR; } - if (((enum SubCmds) index) == TKMWS_STYLE) { + switch((enum SubCmds) index) { + case TKMWS_STYLE: if ((objc < 3) || (objc > 5)) { Tcl_WrongNumArgs(interp, 2, objv, "window ?class attributes?"); return TCL_ERROR; } return WmWinStyle(interp, winPtr, objc, objv); - } else if (((enum SubCmds) index) == TKMWS_TABID) { + case TKMWS_TABID: if ([NSApp macMinorVersion] < 12) { Tcl_AddErrorInfo(interp, "\n (TabbingIdentifiers only exist on OSX 10.12 or later)"); @@ -5557,9 +5560,20 @@ TkUnsupported1ObjCmd( return TCL_ERROR; } return WmWinTabbingId(interp, winPtr, objc, objv); + case TKMWS_APPEARANCE: + if ([NSApp macMinorVersion] < 12) { + Tcl_AddErrorInfo(interp, + "\n (The appearance command requires OSX 10.14 or later)"); + return TCL_ERROR; + } + if ((objc < 3) || (objc > 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "appearance window ?appearancename?"); + return TCL_ERROR; + } + return WmWinAppearance(interp, winPtr, objc, objv); + default: + return TCL_ERROR; } - /* won't be reached */ - return TCL_ERROR; } /* @@ -5817,6 +5831,97 @@ WmWinTabbingId( /* *---------------------------------------------------------------------- * + * WmWinAppearance -- + * + * This procedure is invoked to process the + * "::tk::unsupported::MacWindowStyle appearance" subcommand. The command + * allows you to get or set the appearance for the NSWindow + * associated with a Tk Window. The syntax is: + * tk::unsupported::MacWindowStyle tabbingid window ?newAppearance? + * Allowed appearance names are "aqua", "darkaqua", and "auto". + * + * Results: + * Returns the appearance setting of the window prior to calling this + * function. + * + * Side effects: + * The underlying NSWindow's appearance property is set to the specified + * value if the optional newAppearance argument is supplied. Otherwise + * the window's appearance property is not changed. If the appearance is + * set to aqua or darkaqua then the window will use the associated + * NSAppearance even if the user has selected a different appearance with + * the system preferences. If it is set to auto then the appearance + * property is set to nil, meaning that the preferences will determine the + * appearance. + * + * + *---------------------------------------------------------------------- + */ + + static int +WmWinAppearance( + Tcl_Interp *interp, /* Current interpreter. */ + TkWindow *winPtr, /* Window to be manipulated. */ + int objc, /* Number of arguments. */ + Tcl_Obj * const objv[]) /* Argument objects. */ +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 + static const char *const appearanceStrings[] = { + "aqua", "darkaqua", "auto", NULL + }; + enum appearances { + APPEARANCE_AQUA, APPEARANCE_DARKAQUA, APPEARANCE_AUTO + }; + Tcl_Obj *result = NULL; + NSAppearanceName appearance; + const char *resultString; + NSWindow *win = TkMacOSXDrawableWindow(winPtr->window); + if (win) { + appearance = win.appearance.name; + if (appearance == nil) { + resultString = appearanceStrings[APPEARANCE_AUTO]; + } else if (appearance == NSAppearanceNameAqua) { + resultString = appearanceStrings[APPEARANCE_AQUA]; + } else if (appearance == NSAppearanceNameDarkAqua) { + resultString = appearanceStrings[APPEARANCE_DARKAQUA]; + } else { + resultString = "unrecognized"; + } + result = Tcl_NewStringObj(resultString, strlen(resultString)); + } + if (result == NULL) { + Tcl_Panic("Failed to read appearance name."); + } + Tcl_SetObjResult(interp, result); + if (objc == 3) { + return TCL_OK; + } else if (objc == 4) { + int index; + if (Tcl_GetIndexFromObjStruct(interp, objv[3], appearanceStrings, + sizeof(char *), "appearancename", 0, &index) != TCL_OK) { + return TCL_ERROR; + } + switch ((enum appearances) index) { + case APPEARANCE_AQUA: + win.appearance = [NSAppearance appearanceNamed: + NSAppearanceNameAqua]; + break; + case APPEARANCE_DARKAQUA: + win.appearance = [NSAppearance appearanceNamed: + NSAppearanceNameDarkAqua]; + break; + default: + win.appearance = nil; + } + return TCL_OK; + } +#endif + return TCL_ERROR; +} + +/* + *---------------------------------------------------------------------- + * * TkpMakeMenuWindow -- * * Configure the window to be either a undecorated pull-down (or pop-up) -- cgit v0.12 From 166f5c30a43eedc50130c564fe27d80c8ca12bbe Mon Sep 17 00:00:00 2001 From: culler Date: Mon, 18 Mar 2019 17:39:52 +0000 Subject: Patched up the combobox behavior, without a special drawing procedure for Dark Mode. --- library/ttk/aquaTheme.tcl | 16 +++++++++++++++- macosx/ttkMacOSXTheme.c | 12 ++++++++++-- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/library/ttk/aquaTheme.tcl b/library/ttk/aquaTheme.tcl index 5343671..182af76 100644 --- a/library/ttk/aquaTheme.tcl +++ b/library/ttk/aquaTheme.tcl @@ -61,7 +61,21 @@ namespace eval ttk::theme::aqua { !selected systemControlTextColor} # Combobox: - ttk::style configure TCombobox -postoffset {5 -2 -10 0} + # We do not have a drawing procedure for Dark Comboboxes. + # This fakes the color in Dark Mode by using the system + # background color for (light) inactive widgets, and uses a + # white background for active Comboboxes, even in Dark Mode. + ttk::style configure TCombobox -selectforeground black + ttk::style map TCombobox \ + -foreground { + disabled systemDisabledControlTextColor + focus black + {} black + !active systemControlTextColor + } \ + -selectbackground { + !focus white + } # Treeview: ttk::style configure Heading -font TkHeadingFont diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index 750bdd6..10afbdf 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -1210,8 +1210,8 @@ static Ttk_ElementSpec EntryElementSpec = { * Padding and margins guesstimated by trial-and-error. */ -static Ttk_Padding ComboboxPadding = { 2, 3, 17, 1 }; -static Ttk_Padding ComboboxMargins = { 3, 4, 4, 3 }; +static Ttk_Padding ComboboxPadding = { 3, 0, 17, 4 }; +static Ttk_Padding ComboboxMargins = { 3, 5, 4, 2 }; static void ComboboxElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, @@ -1236,6 +1236,14 @@ static void ComboboxElementDraw( }; BEGIN_DRAWING(d) + if (TkMacOSXInDarkMode(tkwin)) { + bounds.size.height += 1; + } else if ((state & TTK_STATE_BACKGROUND) && + !(state & TTK_STATE_DISABLED)) { + CGRect innerBounds = CGRectInset(bounds, 1, 1); + NSColor *white = [NSColor whiteColor]; + SolidFillRoundedRectangle(dc.context, innerBounds, 4, white); + } ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); END_DRAWING } -- cgit v0.12 From a17b244b6280ceb300cf13876c9b32e7dc461206 Mon Sep 17 00:00:00 2001 From: culler Date: Tue, 19 Mar 2019 02:04:41 +0000 Subject: Fix error handling for MacWindowStyle appearance and tabbingid. --- macosx/tkMacOSXWm.c | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index 1d31fe1..6ccdb47 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -10,7 +10,7 @@ * Copyright 2001-2009, Apple Inc. * Copyright (c) 2006-2009 Daniel A. Steffen * Copyright (c) 2010 Kevin Walzer/WordTech Communications LLC. - * Copyright (c) 2017-2018 Marc Culler. + * Copyright (c) 2017-2019 Marc Culler. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. @@ -5551,8 +5551,9 @@ TkUnsupported1ObjCmd( return WmWinStyle(interp, winPtr, objc, objv); case TKMWS_TABID: if ([NSApp macMinorVersion] < 12) { - Tcl_AddErrorInfo(interp, - "\n (TabbingIdentifiers only exist on OSX 10.12 or later)"); + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "Tabbing identifiers did not exist until OSX 10.12.", -1)); + Tcl_SetErrorCode(interp, "TK", "WINDOWSTYLE", "TABBINGID", NULL); return TCL_ERROR; } if ((objc < 3) || (objc > 4)) { @@ -5561,15 +5562,22 @@ TkUnsupported1ObjCmd( } return WmWinTabbingId(interp, winPtr, objc, objv); case TKMWS_APPEARANCE: - if ([NSApp macMinorVersion] < 12) { - Tcl_AddErrorInfo(interp, - "\n (The appearance command requires OSX 10.14 or later)"); + if ([NSApp macMinorVersion] < 9) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "Window appearances did not exist until OSX 10.9.", -1)); + Tcl_SetErrorCode(interp, "TK", "WINDOWSTYLE", "APPEARANCE", NULL); return TCL_ERROR; } if ((objc < 3) || (objc > 4)) { Tcl_WrongNumArgs(interp, 2, objv, "appearance window ?appearancename?"); return TCL_ERROR; } + if (objc == 4 && [NSApp macMinorVersion] < 14) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "Window appearances cannot be changed before OSX 10.14.", -1)); + Tcl_SetErrorCode(interp, "TK", "WINDOWSTYLE", "APPEARANCE", NULL); + return TCL_ERROR; + } return WmWinAppearance(interp, winPtr, objc, objv); default: return TCL_ERROR; @@ -5858,14 +5866,14 @@ WmWinTabbingId( *---------------------------------------------------------------------- */ - static int +static int WmWinAppearance( Tcl_Interp *interp, /* Current interpreter. */ TkWindow *winPtr, /* Window to be manipulated. */ int objc, /* Number of arguments. */ Tcl_Obj * const objv[]) /* Argument objects. */ { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1090 static const char *const appearanceStrings[] = { "aqua", "darkaqua", "auto", NULL }; @@ -5882,8 +5890,10 @@ WmWinAppearance( resultString = appearanceStrings[APPEARANCE_AUTO]; } else if (appearance == NSAppearanceNameAqua) { resultString = appearanceStrings[APPEARANCE_AQUA]; +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 } else if (appearance == NSAppearanceNameDarkAqua) { resultString = appearanceStrings[APPEARANCE_DARKAQUA]; +#endif } else { resultString = "unrecognized"; } @@ -5892,15 +5902,13 @@ WmWinAppearance( if (result == NULL) { Tcl_Panic("Failed to read appearance name."); } - Tcl_SetObjResult(interp, result); - if (objc == 3) { - return TCL_OK; - } else if (objc == 4) { + if (objc == 4) { int index; if (Tcl_GetIndexFromObjStruct(interp, objv[3], appearanceStrings, sizeof(char *), "appearancename", 0, &index) != TCL_OK) { return TCL_ERROR; } +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 switch ((enum appearances) index) { case APPEARANCE_AQUA: win.appearance = [NSAppearance appearanceNamed: @@ -5913,8 +5921,10 @@ WmWinAppearance( default: win.appearance = nil; } - return TCL_OK; +#endif } + Tcl_SetObjResult(interp, result); + return TCL_OK; #endif return TCL_ERROR; } -- cgit v0.12 From 7ee3cf1eefe8f83ea1e5a48fd3b8c0d01803f3b9 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 19 Mar 2019 16:31:21 +0000 Subject: More use of Tcl_WinTCharToUtf() in stead of Tcl_UniCharToUtfDString(), making Tk less sensitive to the value of TCL_UTF_MAX (either 3, 4, or 6) --- generic/tkMain.c | 4 ---- generic/tkSelect.c | 2 +- win/tkWinClipboard.c | 8 ++------ win/tkWinKey.c | 2 +- win/tkWinMenu.c | 4 ++-- 5 files changed, 6 insertions(+), 14 deletions(-) diff --git a/generic/tkMain.c b/generic/tkMain.c index 3600142..b80ce4d 100644 --- a/generic/tkMain.c +++ b/generic/tkMain.c @@ -84,9 +84,6 @@ extern const TclIntPlatStubs *tclIntPlatStubsPtr; * encoding to UTF-8). */ -#if defined(UNICODE) && (TCL_UTF_MAX <= 4) -# define NewNativeObj Tcl_NewUnicodeObj -#else /* !UNICODE || (TCL_UTF_MAX > 4) */ static inline Tcl_Obj * NewNativeObj( TCHAR *string, @@ -107,7 +104,6 @@ NewNativeObj( Tcl_DStringFree(&ds); return obj; } -#endif /* !UNICODE || (TCL_UTF_MAX > 4) */ /* * Declarations for various library functions and variables (don't want to diff --git a/generic/tkSelect.c b/generic/tkSelect.c index fcfd323..8ba0c5f 100644 --- a/generic/tkSelect.c +++ b/generic/tkSelect.c @@ -26,7 +26,7 @@ typedef struct { int charOffset; /* The offset of the next char to retrieve. */ int byteOffset; /* The expected byte offset of the next * chunk. */ - char buffer[TCL_UTF_MAX]; /* A buffer to hold part of a UTF character + char buffer[4]; /* A buffer to hold part of a UTF character * that is split across chunks. */ char command[1]; /* Command to invoke. Actual space is * allocated as large as necessary. This must diff --git a/win/tkWinClipboard.c b/win/tkWinClipboard.c index 877eed4..93c5d42 100644 --- a/win/tkWinClipboard.c +++ b/win/tkWinClipboard.c @@ -79,9 +79,7 @@ TkSelGetSelection( goto error; } data = GlobalLock(handle); - Tcl_DStringInit(&ds); - Tcl_UniCharToUtfDString((Tcl_UniChar *)data, - Tcl_UniCharLen((Tcl_UniChar *)data), &ds); + Tcl_WinTCharToUtf((TCHAR *)data, -1, &ds); GlobalUnlock(handle); } else if (IsClipboardFormatAvailable(CF_TEXT)) { /* @@ -157,9 +155,7 @@ TkSelGetSelection( if (count) { Tcl_DStringAppend(&ds, "\n", 1); } - len = Tcl_UniCharLen((Tcl_UniChar *) fname); - Tcl_DStringInit(&dsTmp); - Tcl_UniCharToUtfDString((Tcl_UniChar *) fname, len, &dsTmp); + Tcl_WinTCharToUtf(fname, -1, &dsTmp); Tcl_DStringAppend(&ds, Tcl_DStringValue(&dsTmp), Tcl_DStringLength(&dsTmp)); Tcl_DStringFree(&dsTmp); diff --git a/win/tkWinKey.c b/win/tkWinKey.c index 357a804..8db34af 100644 --- a/win/tkWinKey.c +++ b/win/tkWinKey.c @@ -122,7 +122,7 @@ TkpGetString( if (((keysym != NoSymbol) && (keysym > 0) && (keysym < 256)) || (keysym == XK_Return) || (keysym == XK_Tab)) { - len = Tcl_UniCharToUtf((Tcl_UniChar) (keysym & 255), buf); + len = Tcl_UniCharToUtf(keysym & 255, buf); Tcl_DStringAppend(dsPtr, buf, len); } } diff --git a/win/tkWinMenu.c b/win/tkWinMenu.c index 7a2924d..3223759 100644 --- a/win/tkWinMenu.c +++ b/win/tkWinMenu.c @@ -1250,7 +1250,7 @@ TkWinHandleMenuEvent( int i, len, underline; Tcl_Obj *labelPtr; WCHAR *wlabel; - Tcl_UniChar menuChar; + int menuChar; Tcl_DString ds; *plResult = 0; @@ -1259,7 +1259,7 @@ TkWinHandleMenuEvent( * Assume we have something directly convertable to Tcl_UniChar. * True at least for wide systems. */ - menuChar = Tcl_UniCharToUpper((Tcl_UniChar) LOWORD(*pwParam)); + menuChar = Tcl_UniCharToUpper(LOWORD(*pwParam)); Tcl_DStringInit(&ds); for (i = 0; i < menuPtr->numEntries; i++) { -- cgit v0.12 From 42587637ebeafa53539f1a01c6bf3837bc570415 Mon Sep 17 00:00:00 2001 From: culler Date: Tue, 19 Mar 2019 18:33:56 +0000 Subject: Rename variables and reorganize to clarify how Ttk and HITheme interact. --- macosx/ttkMacOSXTheme.c | 155 ++++++++++++++++++++++++++++-------------------- 1 file changed, 92 insertions(+), 63 deletions(-) diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index 10afbdf..f1281c2 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -744,13 +744,13 @@ typedef struct { } ThemeButtonParams; static ThemeButtonParams - PushButtonParams = { kThemePushButton, kThemeMetricPushButtonHeight }, - CheckBoxParams = { kThemeCheckBox, kThemeMetricCheckBoxHeight }, + PushButtonParams = { kThemePushButton, kThemeMetricPushButtonHeight }, + CheckBoxParams = { kThemeCheckBox, kThemeMetricCheckBoxHeight }, RadioButtonParams = { kThemeRadioButton, kThemeMetricRadioButtonHeight }, BevelButtonParams = { kThemeRoundedBevelButton, NoThemeMetric }, PopupButtonParams = { kThemePopupButton, kThemeMetricPopupButtonHeight }, - DisclosureParams = { kThemeDisclosureButton, kThemeMetricDisclosureTriangleHeight }, - ListHeaderParams = { kThemeListHeaderButton, kThemeMetricListHeaderHeight }; + DisclosureParams = { kThemeDisclosureButton, kThemeMetricDisclosureTriangleHeight }, + ListHeaderParams = { kThemeListHeaderButton, kThemeMetricListHeaderHeight }; static Ttk_StateTable ButtonValueTable[] = { { kThemeButtonMixed, TTK_STATE_ALTERNATE, 0 }, @@ -802,57 +802,73 @@ static inline HIThemeButtonDrawInfo computeButtonDrawInfo( return info; } -static void ButtonElementSizeNoPadding( +static void ButtonElementMinSize( void *clientData, void *elementRecord, Tk_Window tkwin, - int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) + int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) { ThemeButtonParams *params = clientData; if (params->heightMetric != NoThemeMetric) { - SInt32 height; + ChkErr(GetThemeMetric, params->heightMetric, minHeight); - ChkErr(GetThemeMetric, params->heightMetric, &height); - *heightPtr = height; + /* + * The theme height does not include the 1-pixel border around + * the button, although it does include the 1-pixel shadow at + * the bottom. The corner radius is 4, so 8 is a reasonable + * minimum width. + */ + + *minHeight += 2; + *minWidth = 8; } } static void ButtonElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, - int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) + int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) { ThemeButtonParams *params = clientData; const HIThemeButtonDrawInfo info = computeButtonDrawInfo(params, 0, tkwin); - static const CGRect scratchBounds = {{0, 0}, {100, 100}}; - CGRect contentBounds; + static const CGRect scratchBounds = {{0, 0}, {100, 20}}; + CGRect contentBounds, backgroundBounds; int verticalPad; - ButtonElementSizeNoPadding( clientData, elementRecord, tkwin, - widthPtr, heightPtr, paddingPtr); + ButtonElementMinSize(clientData, elementRecord, tkwin, + minWidth, minHeight, paddingPtr); /* - * To compute internal padding, query the appearance manager - * for the content bounds of a dummy rectangle, then use - * the difference as the padding. + * Given a hypothetical bounding rectangle for a button, HIToolbox will + * compute a bounding rectangle for the button contents and a bounding + * rectangle for the button background. The background bounds are large + * enough to contain the image of the button in any state, which might + * include highlight borders, shadows, etc. The content rectangle is not + * centered vertically within the background rectangle, presumably because + * shadows only appear on the bottom. Nonetheless, when HITools is asked + * to draw a button with a certain bounding rectangle it draws the button + * centered within the rectangle. + * + * To compute the effective padding around a button we request the + * content and bounding rectangles for a 100x100 button and use the + * padding between those. However, we symmetrize the padding on the + * top and bottom, because that is how the button will be drawn. */ ChkErr(HIThemeGetButtonContentBounds, &scratchBounds, &info, &contentBounds); - - CGRect backgroundBounds; ChkErr(HIThemeGetButtonBackgroundBounds, &scratchBounds, &info, &backgroundBounds); - + if (info.kind == kThemeComboBox) { + printf("ButtonElementSize: combobox %s contentBounds = %s\n", + Tk_PathName(tkwin), NSStringFromRect(contentBounds).UTF8String); + printf("ButtonElementSize: combobox %s backgroundBounds = %s\n\n", + Tk_PathName(tkwin), NSStringFromRect(backgroundBounds).UTF8String); + } paddingPtr->left = contentBounds.origin.x - backgroundBounds.origin.x; - paddingPtr->right = CGRectGetMaxX(backgroundBounds) - CGRectGetMaxX(contentBounds); - verticalPad = contentBounds.origin.y - backgroundBounds.origin.y; - verticalPad += CGRectGetMaxY(backgroundBounds) - CGRectGetMaxY(contentBounds); + paddingPtr->right = (CGRectGetMaxX(backgroundBounds) - + CGRectGetMaxX(contentBounds)); + verticalPad = backgroundBounds.size.height - contentBounds.size.height; paddingPtr->top = verticalPad /2; paddingPtr->bottom = verticalPad - paddingPtr->top; - if (info.kind == kThemePopupButton) { - static Ttk_Padding popupTweak = {0, 1, 0, 1}; - *paddingPtr = Ttk_AddPadding(*paddingPtr, popupTweak); - *heightPtr += Ttk_PaddingHeight(popupTweak); - } } static void ButtonElementDraw( @@ -909,7 +925,7 @@ static void ButtonElementDraw( */ if (info.kind == kThemeRoundedBevelButton && - info.value == kThemeButtonMixed) { + info.value == kThemeButtonMixed) { info.value = kThemeButtonOff; info.state = kThemeStateInactive; } @@ -997,9 +1013,9 @@ static Ttk_StateTable TabPositionTable[] = { static void TabElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, - int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) + int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) { - GetThemeMetric(kThemeMetricLargeTabHeight, (SInt32 *)heightPtr); + GetThemeMetric(kThemeMetricLargeTabHeight, (SInt32 *)minHeight); *paddingPtr = Ttk_MakePadding(0, 0, 0, 2); } @@ -1045,7 +1061,7 @@ static Ttk_ElementSpec TabElementSpec = { static void PaneElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, - int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) + int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) { *paddingPtr = Ttk_MakePadding(9, 5, 9, 9); } @@ -1103,7 +1119,7 @@ static Ttk_ElementSpec PaneElementSpec = { static void GroupElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, - int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) + int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) { *paddingPtr = Ttk_UniformPadding(4); } @@ -1158,7 +1174,7 @@ static Ttk_ElementOptionSpec EntryElementOptions[] = { static void EntryElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, - int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) + int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) { *paddingPtr = Ttk_UniformPadding(5); } @@ -1206,27 +1222,39 @@ static Ttk_ElementSpec EntryElementSpec = { * +++ Combobox: * * NOTES: - * kThemeMetricComboBoxLargeDisclosureWidth -> 17 - * Padding and margins guesstimated by trial-and-error. + * The HIToolbox has incomplete and inconsistent support for ComboBoxes. + * There is no constant available to get the height of a ComboBox with + * GetThemeMetric. In fact, ComboBoxes are the same (fixed) height as + * PopupButtons and PushButtons, but they have no shadow at the bottom. + * As a result, they are drawn 1 pixel above the center of the bounds + * rectangle rather than being centered like the other buttons. One + * can request background bounds for a ComboBox, and it is reported with + * height 23, while the actual button face, including its 1-pixel border + * has height 21. Attempting to request the content bounds returns a + * 0 x 0 rectangle. Measurement indicates that the arrow button has + * width 18. + * + * With no help available from HIToolbox, we have to use hard-wired + * constants for the padding. We shift the bounding rectangle downward + * by 1 pixel to account for the fact that the button is not centered. */ -static Ttk_Padding ComboboxPadding = { 3, 0, 17, 4 }; -static Ttk_Padding ComboboxMargins = { 3, 5, 4, 2 }; +static Ttk_Padding ComboboxPadding = {4, 2, 20, 2 }; static void ComboboxElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, - int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) + int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) { - *widthPtr = 0; - *heightPtr = 0; - *paddingPtr = Ttk_AddPadding(ComboboxMargins, ComboboxPadding); + *minWidth = 24; + *minHeight = 23; + *paddingPtr = ComboboxPadding; } static void ComboboxElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) { - CGRect bounds = BoxToRect(d, Ttk_PadBox(b, ComboboxMargins)); + CGRect bounds = BoxToRect(d, b); const HIThemeButtonDrawInfo info = { .version = 0, .state = Ttk_StateTableLookup(ThemeStateTable, state), @@ -1240,10 +1268,11 @@ static void ComboboxElementDraw( bounds.size.height += 1; } else if ((state & TTK_STATE_BACKGROUND) && !(state & TTK_STATE_DISABLED)) { - CGRect innerBounds = CGRectInset(bounds, 1, 1); + CGRect innerBounds = CGRectInset(bounds, 1, 2); NSColor *white = [NSColor whiteColor]; SolidFillRoundedRectangle(dc.context, innerBounds, 4, white); } + bounds.origin.y += 1; ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); END_DRAWING } @@ -1267,14 +1296,14 @@ static Ttk_ElementSpec ComboboxElementSpec = { static Ttk_Padding SpinbuttonMargins = {2,0,2,0}; static void SpinButtonElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, - int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) + int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) { SInt32 s; ChkErr(GetThemeMetric, kThemeMetricLittleArrowsWidth, &s); - *widthPtr = s + Ttk_PaddingWidth(SpinbuttonMargins); + *minWidth = s + Ttk_PaddingWidth(SpinbuttonMargins); ChkErr(GetThemeMetric, kThemeMetricLittleArrowsHeight, &s); - *heightPtr = s + Ttk_PaddingHeight(SpinbuttonMargins); + *minHeight = s + Ttk_PaddingHeight(SpinbuttonMargins); } static void SpinButtonElementDraw( @@ -1351,13 +1380,13 @@ static Ttk_ElementOptionSpec TrackElementOptions[] = { static void TrackElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, - int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) + int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) { TrackElementData *data = clientData; SInt32 size = 24; /* reasonable default ... */ ChkErr(GetThemeMetric, data->thicknessMetric, &size); - *widthPtr = *heightPtr = size; + *minWidth = *minHeight = size; } static void TrackElementDraw( @@ -1438,9 +1467,9 @@ static Ttk_ElementSpec TrackElementSpec = { */ static void SliderElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, - int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) + int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) { - *widthPtr = *heightPtr = 24; + *minWidth = *minHeight = 24; } static Ttk_ElementSpec SliderElementSpec = { @@ -1483,12 +1512,12 @@ static Ttk_ElementOptionSpec PbarElementOptions[] = { static void PbarElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, - int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) + int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) { SInt32 size = 24; /* @@@ Check HIG for correct default */ ChkErr(GetThemeMetric, kThemeMetricLargeProgressBarThickness, &size); - *widthPtr = *heightPtr = size; + *minWidth = *minHeight = size; } static void PbarElementDraw( @@ -1558,9 +1587,9 @@ static Ttk_ElementSpec PbarElementSpec = { static void SeparatorElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, - int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) + int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) { - *widthPtr = *heightPtr = 1; + *minWidth = *minHeight = 1; } static void SeparatorElementDraw( @@ -1604,7 +1633,7 @@ static const ThemeGrowDirection sizegripGrowDirection static void SizegripElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, - int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) + int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) { HIThemeGrowBoxDrawInfo info = { .version = 0, @@ -1616,8 +1645,8 @@ static void SizegripElementSize( CGRect bounds = CGRectZero; ChkErr(HIThemeGetGrowBoxBounds, &bounds.origin, &info, &bounds); - *widthPtr = bounds.size.width; - *heightPtr = bounds.size.height; + *minWidth = bounds.size.width; + *minHeight = bounds.size.height; } static void SizegripElementDraw( @@ -1822,7 +1851,7 @@ static Ttk_ElementSpec TreeHeaderElementSpec = { TK_STYLE_VERSION_2, sizeof(NullElement), TtkNullElementOptions, - ButtonElementSizeNoPadding, + ButtonElementMinSize, TreeHeaderElementDraw }; @@ -1839,14 +1868,14 @@ static Ttk_StateTable DisclosureValueTable[] = { static void DisclosureElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, - int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) + int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) { SInt32 s; ChkErr(GetThemeMetric, kThemeMetricDisclosureTriangleWidth, &s); - *widthPtr = s; + *minWidth = s; ChkErr(GetThemeMetric, kThemeMetricDisclosureTriangleHeight, &s); - *heightPtr = s; + *minHeight = s; } static void DisclosureElementDraw( @@ -1907,7 +1936,7 @@ TTK_LAYOUT("TMenubutton", TTK_NODE("Menubutton.label", TTK_PACK_LEFT)))) TTK_LAYOUT("TCombobox", - TTK_GROUP("Combobox.button", TTK_PACK_TOP|TTK_FILL_X, + TTK_GROUP("Combobox.button", TTK_FILL_BOTH, TTK_GROUP("Combobox.padding", TTK_FILL_BOTH, TTK_NODE("Combobox.textarea", TTK_FILL_X)))) -- cgit v0.12 From 63f067286fc348190bd0e780deec6c9566b2409b Mon Sep 17 00:00:00 2001 From: culler Date: Tue, 19 Mar 2019 22:25:22 +0000 Subject: Fixed a typo that was causing extraneous "tkwin == NULL" debug messages in the mac regression tests. --- macosx/tkMacOSXMouseEvent.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/macosx/tkMacOSXMouseEvent.c b/macosx/tkMacOSXMouseEvent.c index 9a1988d..ec713d4 100644 --- a/macosx/tkMacOSXMouseEvent.c +++ b/macosx/tkMacOSXMouseEvent.c @@ -103,7 +103,7 @@ enum { */ if (eventWindow == NULL) { - eventWindow == _windowWithMouse; + eventWindow = _windowWithMouse; } if (eventWindow) { -- cgit v0.12 From c2d76ae4a48ea319f88ee98cf01dfa111dbd3e78 Mon Sep 17 00:00:00 2001 From: culler Date: Wed, 20 Mar 2019 15:15:59 +0000 Subject: Fix text layout issue for ttk::button by setting minWidth to 0. Button text was not being centered as requested by -anchor center. --- library/ttk/aquaTheme.tcl | 3 +-- macosx/ttkMacOSXTheme.c | 13 ++++++++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/library/ttk/aquaTheme.tcl b/library/ttk/aquaTheme.tcl index 182af76..f83a710 100644 --- a/library/ttk/aquaTheme.tcl +++ b/library/ttk/aquaTheme.tcl @@ -26,8 +26,7 @@ namespace eval ttk::theme::aqua { !focus systemDialogActiveText} # Buttons -# ttk::style configure TButton -anchor center -width -6 \ - ttk::style configure TButton -anchor center \ + ttk::style configure TButton -anchor center -width -6 \ -foreground systemControlTextColor ttk::style map TButton \ -foreground { diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index f1281c2..4fd506b 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -814,12 +814,19 @@ static void ButtonElementMinSize( /* * The theme height does not include the 1-pixel border around * the button, although it does include the 1-pixel shadow at - * the bottom. The corner radius is 4, so 8 is a reasonable - * minimum width. + * the bottom. */ *minHeight += 2; - *minWidth = 8; + + /* + * 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; } } -- cgit v0.12 From 99c3a9e7d167549e8bf097bc09404f02e1400846 Mon Sep 17 00:00:00 2001 From: culler Date: Wed, 20 Mar 2019 18:46:39 +0000 Subject: The systemTtkBackground color should be an NSColor too. --- library/ttk/aquaTheme.tcl | 3 ++- macosx/tkMacOSXColor.c | 8 +++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/library/ttk/aquaTheme.tcl b/library/ttk/aquaTheme.tcl index f83a710..e32d984 100644 --- a/library/ttk/aquaTheme.tcl +++ b/library/ttk/aquaTheme.tcl @@ -26,7 +26,7 @@ namespace eval ttk::theme::aqua { !focus systemDialogActiveText} # Buttons - ttk::style configure TButton -anchor center -width -6 \ + ttk::style configure TButton -anchor center -width -6\ -foreground systemControlTextColor ttk::style map TButton \ -foreground { @@ -37,6 +37,7 @@ namespace eval ttk::theme::aqua { ttk::style map TRadiobutton \ -foreground { disabled systemDisabledControlTextColor} + ttk::style configure Toolbutton -anchor center ttk::style map Toolbutton \ -foreground { disabled systemDisabledControlTextColor diff --git a/macosx/tkMacOSXColor.c b/macosx/tkMacOSXColor.c index 6199bf4..4a9b300 100644 --- a/macosx/tkMacOSXColor.c +++ b/macosx/tkMacOSXColor.c @@ -42,7 +42,7 @@ enum colorType { struct SystemColorMapEntry { const char *name; enum colorType type; - unsigned long value; + long value; }; /* unsigned char pixelCode; */ /* @@ -189,7 +189,7 @@ static const struct SystemColorMapEntry systemColorMap[] = { { "ListViewWindowHeaderBackground", HIBackground, kThemeBackgroundListViewWindowHeader }, /* 163 */ { "SecondaryGroupBoxBackground", HIBackground, kThemeBackgroundSecondaryGroupBox }, /* 164 */ { "MetalBackground", HIBackground, kThemeBackgroundMetal }, /* 165 */ - { "TtkBackground", HIBrush, kThemeBrushModelessDialogBackgroundActive }, /* 166 */ + { "TtkBackground", ttkBackground, 0 }, /* 166 */ { "TtkBackground1", ttkBackground, 1 }, /* 167 */ { "TtkBackground2", ttkBackground, 2 }, /* 168 */ { "TtkBackground3", ttkBackground, 3 }, /* 169 */ @@ -388,7 +388,6 @@ TkSetMacColor( CGColorRef *color = (CGColorRef*)macColor; OSStatus err = -1; struct SystemColorMapEntry entry; - if (GetEntryFromPixelCode((pixel >> 24) & 0xff, &entry)) { err = ChkErr(SetCGColorComponents, entry, pixel, color); } @@ -648,6 +647,7 @@ TkpGetColor( * Check to see if this is a system color. Otherwise, XParseColor * will do all the work. */ + if (strncasecmp(name, "system", 6) == 0) { Tcl_Obj *strPtr = Tcl_NewStringObj(name+6, -1); int idx, result; @@ -660,8 +660,6 @@ TkpGetColor( CGColorRef c; unsigned char pixelCode = idx + MIN_PIXELCODE; struct SystemColorMapEntry entry = systemColorMap[idx]; - - err = ChkErr(SetCGColorComponents, entry, 0, &c); if (err == noErr) { const size_t n = CGColorGetNumberOfComponents(c); const CGFloat *rgba = CGColorGetComponents(c); -- cgit v0.12 From 91c351387c0e9dbfa5f5ae1c32a1c05bb88959cc Mon Sep 17 00:00:00 2001 From: culler Date: Wed, 20 Mar 2019 19:11:52 +0000 Subject: Restore line that was accidentally deleted. --- macosx/tkMacOSXColor.c | 1 + 1 file changed, 1 insertion(+) diff --git a/macosx/tkMacOSXColor.c b/macosx/tkMacOSXColor.c index 4a9b300..5f3264b 100644 --- a/macosx/tkMacOSXColor.c +++ b/macosx/tkMacOSXColor.c @@ -660,6 +660,7 @@ TkpGetColor( CGColorRef c; unsigned char pixelCode = idx + MIN_PIXELCODE; struct SystemColorMapEntry entry = systemColorMap[idx]; + err = ChkErr(SetCGColorComponents, entry, 0, &c); if (err == noErr) { const size_t n = CGColorGetNumberOfComponents(c); const CGFloat *rgba = CGColorGetComponents(c); -- cgit v0.12 From 9aba30314f2d23fe5a6ac36d7c12d056fa286ab9 Mon Sep 17 00:00:00 2001 From: culler Date: Wed, 20 Mar 2019 20:05:29 +0000 Subject: Avoid caching semantic colors so they will respond to appearance changes when used, e.g, in a canvas. --- macosx/tkMacOSXColor.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/macosx/tkMacOSXColor.c b/macosx/tkMacOSXColor.c index 5f3264b..3ca813c 100644 --- a/macosx/tkMacOSXColor.c +++ b/macosx/tkMacOSXColor.c @@ -202,6 +202,7 @@ static const struct SystemColorMapEntry systemColorMap[] = { { "DisabledControlTextColor", ttkForeground, 2 }, /* 176 */ { NULL, 0, 0 } }; +#define FIRST_SEMANTIC_COLOR 166 #define MAX_PIXELCODE 176 /* @@ -404,7 +405,7 @@ TkSetMacColor( * Results: * None resp. retained CGColorRef for CopyCachedColor() * - * Side effects: + * Side effects:M * None. * *---------------------------------------------------------------------- @@ -568,16 +569,19 @@ TkMacOSXSetColorInContext( CGContextRef context) { OSStatus err = noErr; - CGColorRef cgColor = CopyCachedColor(gc, pixel); + CGColorRef cgColor = nil; struct SystemColorMapEntry entry; CGRect rect; + int code = (pixel >> 24) & 0xff; HIThemeBackgroundDrawInfo info = { 0, kThemeStateActive, entry.value }; static CGColorSpaceRef deviceRGBSpace = NULL; if (!deviceRGBSpace) { deviceRGBSpace = CGColorSpaceCreateDeviceRGB(); } - - if (!cgColor && GetEntryFromPixelCode((pixel >> 24) & 0xff, &entry)) { + if (code < FIRST_SEMANTIC_COLOR) { + cgColor = CopyCachedColor(gc, pixel); + } + if (!cgColor && GetEntryFromPixelCode(code, &entry)) { switch (entry.type) { case HIBrush: err = ChkErr(HIThemeSetFill, entry.value, NULL, context, -- cgit v0.12 From 524655affdae491aad1119f37f59df0109de17e8 Mon Sep 17 00:00:00 2001 From: culler Date: Thu, 21 Mar 2019 14:49:26 +0000 Subject: Make top and bottom button padding equal, even when the suggested total vertical padding is odd. --- macosx/ttkMacOSXTheme.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index 4fd506b..d136b99 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -836,7 +836,7 @@ static void ButtonElementSize( { ThemeButtonParams *params = clientData; const HIThemeButtonDrawInfo info = computeButtonDrawInfo(params, 0, tkwin); - static const CGRect scratchBounds = {{0, 0}, {100, 20}}; + static const CGRect scratchBounds = {{0, 0}, {100, 100}}; CGRect contentBounds, backgroundBounds; int verticalPad; @@ -864,18 +864,11 @@ static void ButtonElementSize( &scratchBounds, &info, &contentBounds); ChkErr(HIThemeGetButtonBackgroundBounds, &scratchBounds, &info, &backgroundBounds); - if (info.kind == kThemeComboBox) { - printf("ButtonElementSize: combobox %s contentBounds = %s\n", - Tk_PathName(tkwin), NSStringFromRect(contentBounds).UTF8String); - printf("ButtonElementSize: combobox %s backgroundBounds = %s\n\n", - Tk_PathName(tkwin), NSStringFromRect(backgroundBounds).UTF8String); - } paddingPtr->left = contentBounds.origin.x - backgroundBounds.origin.x; paddingPtr->right = (CGRectGetMaxX(backgroundBounds) - CGRectGetMaxX(contentBounds)); verticalPad = backgroundBounds.size.height - contentBounds.size.height; - paddingPtr->top = verticalPad /2; - paddingPtr->bottom = verticalPad - paddingPtr->top; + paddingPtr->top = paddingPtr->bottom = verticalPad / 2; } static void ButtonElementDraw( -- cgit v0.12 From 4494f123bac86f61b2f1c3c8b56949c9e0aa2e92 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 22 Mar 2019 14:13:15 +0000 Subject: Bugfix in tkWinClipboard: Failed to determine fname length in loop. --- win/tkWinClipboard.c | 3 ++- win/tkWinInit.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/win/tkWinClipboard.c b/win/tkWinClipboard.c index 93c5d42..a00909c 100644 --- a/win/tkWinClipboard.c +++ b/win/tkWinClipboard.c @@ -155,7 +155,8 @@ TkSelGetSelection( if (count) { Tcl_DStringAppend(&ds, "\n", 1); } - Tcl_WinTCharToUtf(fname, -1, &dsTmp); + len = Tcl_UniCharLen((Tcl_UniChar *) fname); + Tcl_WinTCharToUtf(fname, len * sizeof(WCHAR), &dsTmp); Tcl_DStringAppend(&ds, Tcl_DStringValue(&dsTmp), Tcl_DStringLength(&dsTmp)); Tcl_DStringFree(&dsTmp); diff --git a/win/tkWinInit.c b/win/tkWinInit.c index 4c18399..780888a 100644 --- a/win/tkWinInit.c +++ b/win/tkWinInit.c @@ -199,7 +199,7 @@ TkWin32ErrorObj( } #ifdef _UNICODE - Tcl_WinTCharToUtf(lpBuffer, (int)wcslen(lpBuffer) * sizeof (WCHAR), &ds); + Tcl_WinTCharToUtf(lpBuffer, wcslen(lpBuffer) * sizeof (WCHAR), &ds); errPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds)); Tcl_DStringFree(&ds); #else -- cgit v0.12 From 53623d974a56e46a09078d5c6d72a792f9018829 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 22 Mar 2019 14:15:37 +0000 Subject: Slightly better: Don't use Tcl_UniCharLen() but wcslen(). --- win/tkWinClipboard.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/win/tkWinClipboard.c b/win/tkWinClipboard.c index a00909c..8c6a4a4 100644 --- a/win/tkWinClipboard.c +++ b/win/tkWinClipboard.c @@ -149,13 +149,14 @@ TkSelGetSelection( if (drop->fWide) { WCHAR *fname = (WCHAR *) ((char *) drop + drop->pFiles); Tcl_DString dsTmp; - int count = 0, len; + int count = 0; + size_t len; while (*fname != 0) { if (count) { Tcl_DStringAppend(&ds, "\n", 1); } - len = Tcl_UniCharLen((Tcl_UniChar *) fname); + len = wcslen(fname); Tcl_WinTCharToUtf(fname, len * sizeof(WCHAR), &dsTmp); Tcl_DStringAppend(&ds, Tcl_DStringValue(&dsTmp), Tcl_DStringLength(&dsTmp)); -- cgit v0.12 From 5d23499fac449980d06f4ca3535f02a27a4052a1 Mon Sep 17 00:00:00 2001 From: dkf Date: Sun, 24 Mar 2019 12:31:12 +0000 Subject: Minor tinkering (style, efficiency, etc.) --- generic/tkScale.c | 116 ++++++++++++++++++++++++++++++++++++++--------------- unix/tkUnixScale.c | 67 ++++++++++++++++--------------- 2 files changed, 118 insertions(+), 65 deletions(-) diff --git a/generic/tkScale.c b/generic/tkScale.c index 0d9bc10..8118436 100644 --- a/generic/tkScale.c +++ b/generic/tkScale.c @@ -162,6 +162,8 @@ static void ComputeScaleGeometry(TkScale *scalePtr); static int ConfigureScale(Tcl_Interp *interp, TkScale *scalePtr, int objc, Tcl_Obj *const objv[]); static void DestroyScale(char *memPtr); +static double MaxTickRoundingError(TkScale *scalePtr, + double tickResolution); static void ScaleCmdDeletedProc(ClientData clientData); static void ScaleEventProc(ClientData clientData, XEvent *eventPtr); @@ -182,13 +184,50 @@ static void ScaleSetVariable(TkScale *scalePtr); static const Tk_ClassProcs scaleClass = { sizeof(Tk_ClassProcs), /* size */ ScaleWorldChanged, /* worldChangedProc */ - NULL, /* createProc */ - NULL /* modalProc */ + NULL, /* createProc */ + NULL /* modalProc */ }; + +/* + *-------------------------------------------------------------- + * + * ScaleDigit, ScaleMax, ScaleMin, ScaleRound -- + * + * Simple math helper functions, designed to be automatically inlined by + * the compiler most of the time. + * + *-------------------------------------------------------------- + */ -#define ROUND(d) ((int) floor((d) + 0.5)) -#define MIN(a, b) ((a) < (b)? (a): (b)) -#define MAX(a, b) ((a) > (b)? (a): (b)) +static inline int +ScaleDigit( + double value) +{ + return (int) floor(log10(fabs(value))); +} + +static inline double +ScaleMax( + double a, + double b) +{ + return (a > b) ? a : b; +} + +static inline double +ScaleMin( + double a, + double b) +{ + return (a < b) ? a : b; +} + +static inline int +ScaleRound( + double value) +{ + return (int) floor(value + 0.5); +} /* *-------------------------------------------------------------- @@ -763,7 +802,6 @@ ScaleWorldChanged( TkEventuallyRedrawScale(scalePtr, REDRAW_ALL); } - /* *---------------------------------------------------------------------- @@ -784,8 +822,8 @@ ScaleWorldChanged( * *---------------------------------------------------------------------- */ - -static double + +static double MaxTickRoundingError( TkScale *scalePtr, /* Information about scale widget. */ double tickResolution) /* Separation between displayable values. */ @@ -793,16 +831,27 @@ MaxTickRoundingError( double tickPosn, firstTickError, lastTickError, intervalError; int tickCount; - tickPosn = scalePtr->fromValue/tickResolution; - firstTickError = tickPosn - ROUND(tickPosn); - tickPosn = scalePtr->tickInterval/tickResolution; - intervalError = tickPosn - ROUND(tickPosn); - tickCount = (int)((scalePtr->toValue-scalePtr->fromValue) / - scalePtr->tickInterval); // not including first - lastTickError = MIN(fabs(firstTickError + tickCount*intervalError), 0.5); - return MAX(fabs(firstTickError),lastTickError)*tickResolution; -} + /* + * Compute the error for each tick-related measure. + */ + tickPosn = scalePtr->fromValue / tickResolution; + firstTickError = tickPosn - ScaleRound(tickPosn); + + tickPosn = scalePtr->tickInterval / tickResolution; + intervalError = tickPosn - ScaleRound(tickPosn); + + tickCount = (int) ((scalePtr->toValue - scalePtr->fromValue) / + scalePtr->tickInterval); /* not including first */ + lastTickError = ScaleMin(0.5, + fabs(firstTickError + tickCount * intervalError)); + + /* + * Compute the maximum cumulative rounding error. + */ + + return ScaleMax(fabs(firstTickError), lastTickError) * tickResolution; +} /* *---------------------------------------------------------------------- @@ -843,23 +892,25 @@ ComputeFormat( if (maxValue == 0) { maxValue = 1; } - mostSigDigit = (int) floor(log10(maxValue)); + mostSigDigit = ScaleDigit(maxValue); if (forTicks) { /* * Display only enough digits to ensure adjacent ticks have different - * values + * values. */ if (scalePtr->tickInterval != 0) { - leastSigDigit = (int) floor(log10(fabs(scalePtr->tickInterval))); + leastSigDigit = ScaleDigit(scalePtr->tickInterval); + /* * Now add more digits until max error is less than 0.2 intervals */ - while (MaxTickRoundingError(scalePtr, pow(10,leastSigDigit)) > - fabs(0.2*scalePtr->tickInterval)) - --leastSigDigit; + while (MaxTickRoundingError(scalePtr, pow(10, leastSigDigit)) + > fabs(0.2 * scalePtr->tickInterval)) { + --leastSigDigit; + } numDigits = 1 + mostSigDigit - leastSigDigit; } else { numDigits = 1; @@ -884,21 +935,21 @@ ComputeFormat( /* * A resolution was specified for the scale, so just use it. */ - - leastSigDigit = (int) floor(log10(scalePtr->resolution)); + + leastSigDigit = ScaleDigit(scalePtr->resolution); } else { /* * No resolution was specified, so compute the difference in * value between adjacent pixels and use it for the least * significant digit. */ - + x = fabs(scalePtr->fromValue - scalePtr->toValue); if (scalePtr->length > 0) { x /= scalePtr->length; } - if (x > 0){ - leastSigDigit = (int) floor(log10(x)); + if (x > 0) { + leastSigDigit = ScaleDigit(x); } else { leastSigDigit = 0; } @@ -930,17 +981,18 @@ ComputeFormat( if (mostSigDigit < 0) { fDigits++; /* Zero to left of decimal point. */ } + if (forTicks) { if (fDigits <= eDigits) { sprintf(scalePtr->tickFormat, "%%.%df", afterDecimal); } else { - sprintf(scalePtr->tickFormat, "%%.%de", numDigits-1); + sprintf(scalePtr->tickFormat, "%%.%de", numDigits - 1); } } else { if (fDigits <= eDigits) { sprintf(scalePtr->valueFormat, "%%.%df", afterDecimal); } else { - sprintf(scalePtr->valueFormat, "%%.%de", numDigits-1); + sprintf(scalePtr->valueFormat, "%%.%de", numDigits - 1); } } } @@ -1546,8 +1598,8 @@ TkScaleValueToPixel( if (valueRange == 0) { y = 0; } else { - y = (int) ((value - scalePtr->fromValue) * pixelRange - / valueRange + 0.5); + y = ScaleRound((value - scalePtr->fromValue) * pixelRange + / valueRange); if (y < 0) { y = 0; } else if (y > pixelRange) { diff --git a/unix/tkUnixScale.c b/unix/tkUnixScale.c index f5e3fc2..778c010 100644 --- a/unix/tkUnixScale.c +++ b/unix/tkUnixScale.c @@ -24,13 +24,13 @@ static void DisplayHorizontalScale(TkScale *scalePtr, Drawable drawable, XRectangle *drawnAreaPtr); static void DisplayHorizontalValue(TkScale *scalePtr, - Drawable drawable, double value, - int top, char* format); + Drawable drawable, double value, int top, + const char *format); static void DisplayVerticalScale(TkScale *scalePtr, Drawable drawable, XRectangle *drawnAreaPtr); static void DisplayVerticalValue(TkScale *scalePtr, - Drawable drawable, double value, - int rightEdge, char* format); + Drawable drawable, double value, int rightEdge, + const char *format); /* *---------------------------------------------------------------------- @@ -178,7 +178,7 @@ DisplayVerticalScale( if (scalePtr->showValue) { DisplayVerticalValue(scalePtr, drawable, scalePtr->value, - scalePtr->vertValueRightX, scalePtr->valueFormat); + scalePtr->vertValueRightX, scalePtr->valueFormat); } /* @@ -230,8 +230,8 @@ DisplayVerticalScale( Tk_GetFontMetrics(scalePtr->tkfont, &fm); Tk_DrawChars(scalePtr->display, drawable, scalePtr->textGC, scalePtr->tkfont, scalePtr->label, - scalePtr->labelLength, scalePtr->vertLabelX, - scalePtr->inset + (3*fm.ascent)/2); + scalePtr->labelLength, scalePtr->vertLabelX, + scalePtr->inset + (3 * fm.ascent) / 2); } } @@ -265,7 +265,7 @@ DisplayVerticalValue( * pixels (we'll compute pixels). */ int rightEdge, /* X-coordinate of right edge of text, * specified in pixels. */ - char* format) /* Format string to use for the value */ + const char *format) /* Format string to use for the value */ { register Tk_Window tkwin = scalePtr->tkwin; int y, width, length; @@ -275,7 +275,7 @@ DisplayVerticalValue( Tk_GetFontMetrics(scalePtr->tkfont, &fm); y = TkScaleValueToPixel(scalePtr, value) + fm.ascent/2; if (snprintf(valueString, TCL_DOUBLE_SPACE, format, value) < 0) { - valueString[TCL_DOUBLE_SPACE - 1] = '\0'; + valueString[TCL_DOUBLE_SPACE - 1] = '\0'; } length = (int) strlen(valueString); width = Tk_TextWidth(scalePtr->tkfont, valueString, length); @@ -285,10 +285,10 @@ DisplayVerticalValue( * the window. */ - if ((y - fm.ascent) < (scalePtr->inset + SPACING)) { + if (y - fm.ascent < scalePtr->inset + SPACING) { y = scalePtr->inset + SPACING + fm.ascent; } - if ((y + fm.descent) > (Tk_Height(tkwin) - scalePtr->inset - SPACING)) { + if (y + fm.descent > Tk_Height(tkwin) - scalePtr->inset - SPACING) { y = Tk_Height(tkwin) - scalePtr->inset - SPACING - fm.descent; } Tk_DrawChars(scalePtr->display, drawable, scalePtr->textGC, @@ -327,7 +327,7 @@ DisplayHorizontalScale( { register Tk_Window tkwin = scalePtr->tkwin; int x, y, width, height, shadowWidth; - double tickValue, tickInterval = scalePtr->tickInterval; + double tickInterval = scalePtr->tickInterval; Tk_3DBorder sliderBorder; /* @@ -351,7 +351,7 @@ DisplayHorizontalScale( if (tickInterval != 0) { char valueString[TCL_DOUBLE_SPACE]; - double ticks, maxTicks; + double ticks, maxTicks, tickValue; /* * Ensure that we will only draw enough of the tick values such @@ -361,17 +361,17 @@ DisplayHorizontalScale( ticks = fabs((scalePtr->toValue - scalePtr->fromValue) / tickInterval); - if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->tickFormat, - scalePtr->fromValue) < 0) { - valueString[TCL_DOUBLE_SPACE - 1] = '\0'; - } + if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->tickFormat, + scalePtr->fromValue) < 0) { + valueString[TCL_DOUBLE_SPACE - 1] = '\0'; + } maxTicks = (double) Tk_Width(tkwin) / (double) Tk_TextWidth(scalePtr->tkfont, valueString, -1); if (ticks > maxTicks) { - tickInterval *= (ticks / maxTicks); + tickInterval *= ticks / maxTicks; } - for (tickValue = scalePtr->fromValue; ; - tickValue += tickInterval) { + tickValue = scalePtr->fromValue; + while (1) { /* * The TkRoundValueToResolution call gets rid of accumulated * round-off errors, if any. @@ -389,6 +389,7 @@ DisplayHorizontalScale( } DisplayHorizontalValue(scalePtr, drawable, tickValue, scalePtr->horizTickY, scalePtr->tickFormat); + tickValue += tickInterval; } } } @@ -452,8 +453,8 @@ DisplayHorizontalScale( Tk_GetFontMetrics(scalePtr->tkfont, &fm); Tk_DrawChars(scalePtr->display, drawable, scalePtr->textGC, scalePtr->tkfont, scalePtr->label, - scalePtr->labelLength, scalePtr->inset + fm.ascent/2, - scalePtr->horizLabelY + fm.ascent); + scalePtr->labelLength, scalePtr->inset + fm.ascent/2, + scalePtr->horizLabelY + fm.ascent); } } @@ -487,7 +488,7 @@ DisplayHorizontalValue( * pixels (we'll compute pixels). */ int top, /* Y-coordinate of top edge of text, specified * in pixels. */ - char* format) /* Format string to use for the value */ + const char *format) /* Format string to use for the value */ { register Tk_Window tkwin = scalePtr->tkwin; int x, y, length, width; @@ -498,7 +499,7 @@ DisplayHorizontalValue( Tk_GetFontMetrics(scalePtr->tkfont, &fm); y = top + fm.ascent; if (snprintf(valueString, TCL_DOUBLE_SPACE, format, value) < 0) { - valueString[TCL_DOUBLE_SPACE - 1] = '\0'; + valueString[TCL_DOUBLE_SPACE - 1] = '\0'; } length = (int) strlen(valueString); width = Tk_TextWidth(scalePtr->tkfont, valueString, length); @@ -508,8 +509,8 @@ DisplayHorizontalValue( * the window. */ - x -= (width)/2; - if (x < (scalePtr->inset + SPACING)) { + x -= width / 2; + if (x < scalePtr->inset + SPACING) { x = scalePtr->inset + SPACING; } @@ -566,10 +567,10 @@ TkpDisplayScale( Tcl_Preserve(scalePtr); if ((scalePtr->flags & INVOKE_COMMAND) && (scalePtr->command != NULL)) { Tcl_Preserve(interp); - if (snprintf(string, TCL_DOUBLE_SPACE, scalePtr->valueFormat, - scalePtr->value) < 0) { - string[TCL_DOUBLE_SPACE - 1] = '\0'; - } + if (snprintf(string, TCL_DOUBLE_SPACE, scalePtr->valueFormat, + scalePtr->value) < 0) { + string[TCL_DOUBLE_SPACE - 1] = '\0'; + } Tcl_DStringInit(&buf); Tcl_DStringAppend(&buf, scalePtr->command, -1); Tcl_DStringAppend(&buf, " ", -1); @@ -638,7 +639,7 @@ TkpDisplayScale( gc = Tk_GCForColor(scalePtr->highlightColorPtr, pixmap); } else { gc = Tk_GCForColor( - Tk_3DBorderColor(scalePtr->highlightBorder), pixmap); + Tk_3DBorderColor(scalePtr->highlightBorder), pixmap); } Tk_DrawFocusHighlight(tkwin, gc, scalePtr->highlightWidth, pixmap); } @@ -700,7 +701,7 @@ TkpScaleElement( if (y < sliderFirst) { return TROUGH1; } - if (y < (sliderFirst+scalePtr->sliderLength)) { + if (y < sliderFirst + scalePtr->sliderLength) { return SLIDER; } return TROUGH2; @@ -720,7 +721,7 @@ TkpScaleElement( if (x < sliderFirst) { return TROUGH1; } - if (x < (sliderFirst+scalePtr->sliderLength)) { + if (x < sliderFirst + scalePtr->sliderLength) { return SLIDER; } return TROUGH2; -- cgit v0.12 From bd919c12a0d87ab9bf1bd86a114ed66898bbfcd1 Mon Sep 17 00:00:00 2001 From: fvogel Date: Sun, 24 Mar 2019 20:20:39 +0000 Subject: Name the TICK_VALUES_DISPLAY_ACCURACY constant --- generic/tkScale.c | 5 +++-- generic/tkScale.h | 8 ++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/generic/tkScale.c b/generic/tkScale.c index 8118436..c5cdaff 100644 --- a/generic/tkScale.c +++ b/generic/tkScale.c @@ -904,11 +904,12 @@ ComputeFormat( leastSigDigit = ScaleDigit(scalePtr->tickInterval); /* - * Now add more digits until max error is less than 0.2 intervals + * Now add more digits until max error is less than + * TICK_VALUES_DISPLAY_ACCURACY intervals */ while (MaxTickRoundingError(scalePtr, pow(10, leastSigDigit)) - > fabs(0.2 * scalePtr->tickInterval)) { + > fabs(TICK_VALUES_DISPLAY_ACCURACY * scalePtr->tickInterval)) { --leastSigDigit; } numDigits = 1 + mostSigDigit - leastSigDigit; diff --git a/generic/tkScale.h b/generic/tkScale.h index 4250b06..e68b786 100644 --- a/generic/tkScale.h +++ b/generic/tkScale.h @@ -217,6 +217,14 @@ typedef struct TkScale { #define SPACING 2 /* + * The tick values are all displayed with the same number of decimal places. + * This number of decimal places is such that the displayed values are all + * accurate to within the following proportion of a tick interval. + */ + +#define TICK_VALUES_DISPLAY_ACCURACY 0.2 + +/* * Declaration of procedures used in the implementation of the scale widget. */ -- cgit v0.12 From 2cf5a82a75201dd866c90d3add0462c19854d88f Mon Sep 17 00:00:00 2001 From: culler Date: Mon, 25 Mar 2019 15:50:47 +0000 Subject: Fix bug [48c39440af]: On macOS, Buttons and Labels do not recompute their textLayout when the text option is set to an empty string. --- macosx/tkMacOSXButton.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/macosx/tkMacOSXButton.c b/macosx/tkMacOSXButton.c index c0b83f2..484dcf2 100644 --- a/macosx/tkMacOSXButton.c +++ b/macosx/tkMacOSXButton.c @@ -295,11 +295,11 @@ TkpComputeButtonGeometry( haveImage = 1; } - if (strlen(text) > 0) { + if (haveImage == 0 || butPtr->compound != COMPOUND_NONE) { Tk_FreeTextLayout(butPtr->textLayout); butPtr->textLayout = Tk_ComputeTextLayout(butPtr->tkfont, - Tcl_GetString(butPtr->textPtr), -1, butPtr->wrapLength, - butPtr->justify, 0, &butPtr->textWidth, &butPtr->textHeight); + text, -1, butPtr->wrapLength, butPtr->justify, 0, + &butPtr->textWidth, &butPtr->textHeight); txtWidth = butPtr->textWidth + 2*butPtr->padX; txtHeight = butPtr->textHeight + 2*butPtr->padY; -- cgit v0.12 From 155b295553449458a4eb8bd2a3ab1f12df26cf3b Mon Sep 17 00:00:00 2001 From: fvogel Date: Tue, 26 Mar 2019 07:14:28 +0000 Subject: Change TICK_VALUES_DISPLAY_ACCURACY for the more correct word TICK_VALUES_DISPLAY_PRECISION --- doc/scale.n | 4 +++- generic/tkScale.c | 4 ++-- generic/tkScale.h | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/doc/scale.n b/doc/scale.n index b1f1981..c5f22b4 100644 --- a/doc/scale.n +++ b/doc/scale.n @@ -78,7 +78,9 @@ specified by the \fB\-activebackground\fR option. .OP \-tickinterval tickInterval TickInterval Must be a real value. Determines the spacing between numerical -tick marks displayed below or to the left of the slider. The values will all be displayed with the same number of decimal places, which will be enough to ensure they are all accurate to within 20% of a tick interval. +tick marks displayed below or to the left of the slider. The values will all +be displayed with the same number of decimal places, which will be enough to +ensure they are all precise to within 20% of a tick interval. If 0, no tick marks will be displayed. .OP \-to to To Specifies a real value corresponding diff --git a/generic/tkScale.c b/generic/tkScale.c index c5cdaff..b28b08d 100644 --- a/generic/tkScale.c +++ b/generic/tkScale.c @@ -905,11 +905,11 @@ ComputeFormat( /* * Now add more digits until max error is less than - * TICK_VALUES_DISPLAY_ACCURACY intervals + * TICK_VALUES_DISPLAY_PRECISION intervals */ while (MaxTickRoundingError(scalePtr, pow(10, leastSigDigit)) - > fabs(TICK_VALUES_DISPLAY_ACCURACY * scalePtr->tickInterval)) { + > fabs(TICK_VALUES_DISPLAY_PRECISION * scalePtr->tickInterval)) { --leastSigDigit; } numDigits = 1 + mostSigDigit - leastSigDigit; diff --git a/generic/tkScale.h b/generic/tkScale.h index e68b786..b307aa2 100644 --- a/generic/tkScale.h +++ b/generic/tkScale.h @@ -222,7 +222,7 @@ typedef struct TkScale { * accurate to within the following proportion of a tick interval. */ -#define TICK_VALUES_DISPLAY_ACCURACY 0.2 +#define TICK_VALUES_DISPLAY_PRECISION 0.2 /* * Declaration of procedures used in the implementation of the scale widget. -- cgit v0.12 From 7ffe9f76440019f4fea87c29f2b42a543066ea3b Mon Sep 17 00:00:00 2001 From: culler Date: Tue, 26 Mar 2019 16:06:55 +0000 Subject: Add a few more semantic colors to make ttk::Entry and ttk::Treeview work in dark mode. --- generic/ttk/ttkTheme.h | 6 ++++- library/ttk/aquaTheme.tcl | 48 ++++++++++++++++++++++++---------------- macosx/tkMacOSXColor.c | 45 ++++++++++++++++++++++++++----------- macosx/ttkMacOSXTheme.c | 56 +++++++++++++++++++++++++++++++++++++++++------ 4 files changed, 115 insertions(+), 40 deletions(-) diff --git a/generic/ttk/ttkTheme.h b/generic/ttk/ttkTheme.h index 9251dea..cf0a07c 100644 --- a/generic/ttk/ttkTheme.h +++ b/generic/ttk/ttkTheme.h @@ -29,9 +29,13 @@ extern "C" { * +++ Defaults for element option specifications. */ #define DEFAULT_FONT "TkDefaultFont" +#ifdef MAC_OSX_TK +#define DEFAULT_BACKGROUND "systemTextBackgroundColor" +#define DEFAULT_FOREGROUND "systemTextColor" +#else #define DEFAULT_BACKGROUND "#d9d9d9" #define DEFAULT_FOREGROUND "black" - +#endif /*------------------------------------------------------------------------ * +++ Widget states. * Keep in sync with stateNames[] in tkstate.c. diff --git a/library/ttk/aquaTheme.tcl b/library/ttk/aquaTheme.tcl index e32d984..50fcd7a 100644 --- a/library/ttk/aquaTheme.tcl +++ b/library/ttk/aquaTheme.tcl @@ -25,7 +25,7 @@ namespace eval ttk::theme::aqua { background systemLabelColor !focus systemDialogActiveText} - # Buttons + # Button ttk::style configure TButton -anchor center -width -6\ -foreground systemControlTextColor ttk::style map TButton \ @@ -37,12 +37,22 @@ namespace eval ttk::theme::aqua { ttk::style map TRadiobutton \ -foreground { disabled systemDisabledControlTextColor} + ttk::style configure TMenubutton -anchor center -padding {2 0 0 2} ttk::style configure Toolbutton -anchor center ttk::style map Toolbutton \ -foreground { disabled systemDisabledControlTextColor } + # Entry + ttk::style configure TEntry \ + -foreground systemTextColor \ + -background systemTextBackgroundColor \ + -selectforeground systemSelectedTextColor + ttk::style map TEntry \ + -foreground { + disabled systemDisabledControlTextColor} + # Workaround for #1100117: # Actually, on Aqua we probably shouldn't stipple images in # disabled buttons even if it did work... @@ -56,39 +66,39 @@ namespace eval ttk::theme::aqua { ttk::style map TNotebook.Tab \ -foreground { {background !disabled !selected} systemControlTextColor - {background selected} black + {background selected} systemTextBackgroundColor disabled systemDisabledControlTextColor !selected systemControlTextColor} # Combobox: - # We do not have a drawing procedure for Dark Comboboxes. - # This fakes the color in Dark Mode by using the system - # background color for (light) inactive widgets, and uses a - # white background for active Comboboxes, even in Dark Mode. - ttk::style configure TCombobox -selectforeground black + ttk::style configure TCombobox -selectforeground black \ + -background systemTextBackgroundColor ttk::style map TCombobox \ -foreground { disabled systemDisabledControlTextColor focus black {} black - !active systemControlTextColor + !active systemTextColor } \ -selectbackground { !focus white + } # Treeview: - ttk::style configure Heading -font TkHeadingFont - ttk::style configure Treeview -rowheight 18 -background White \ - -foreground black - ttk::style map Treeview \ - -background { - disabled systemDialogBackgroundInactive - {selected background} systemHighlightSecondary - selected systemHighlight} \ - -foreground { - !active black - } + ttk::style configure Heading -font TkHeadingFont -foreground black + ttk::style configure Treeview -rowheight 18 \ + -fieldbackground systemTextBackgroundColor \ + -background systemTextBackgroundColor \ + -foreground systemTextColor + # ttk::style map Treeview \ + # -background { + # disabled systemDialogBackgroundInactive + # {selected background} systemHighlightSecondary + # selected systemHighlight} \ + # -foreground { + # !active black + # } # Enable animation for ttk::progressbar widget: ttk::style configure TProgressbar -period 100 -maxphase 255 diff --git a/macosx/tkMacOSXColor.c b/macosx/tkMacOSXColor.c index 3ca813c..f0bcb7c 100644 --- a/macosx/tkMacOSXColor.c +++ b/macosx/tkMacOSXColor.c @@ -20,7 +20,7 @@ /* * 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 ttkForeground types are dynamic, meaning + * an XColor. The ttkBackground and semantic types are dynamic, meaning * that they change when dark mode is enabled on OSX 10.13 and later. */ @@ -32,7 +32,7 @@ enum colorType { 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.*/ - ttkForeground, /* The value can be used as a parameter.*/ + semantic, /* The value can be used as a parameter.*/ }; /* @@ -197,13 +197,16 @@ static const struct SystemColorMapEntry systemColorMap[] = { { "TtkBackground5", ttkBackground, 5 }, /* 171 */ { "TtkBackground6", ttkBackground, 6 }, /* 172 */ { "TtkBackground7", ttkBackground, 7 }, /* 173 */ - { "LabelColor", ttkForeground, 0 }, /* 174 */ - { "ControlTextColor", ttkForeground, 1 }, /* 175 */ - { "DisabledControlTextColor", ttkForeground, 2 }, /* 176 */ + { "TextColor", semantic, 0 }, /* 174 */ + { "SelectedTextColor", semantic, 1 }, /* 175 */ + { "LabelColor", semantic, 2 }, /* 176 */ + { "ControlTextColor", semantic, 3 }, /* 177 */ + { "DisabledControlTextColor", semantic, 4 }, /* 178 */ + { "TextBackgroundColor", semantic, 5 }, /* 179 */ { NULL, 0, 0 } }; #define FIRST_SEMANTIC_COLOR 166 -#define MAX_PIXELCODE 176 +#define MAX_PIXELCODE 179 /* *---------------------------------------------------------------------- @@ -260,7 +263,7 @@ SetCGColorComponents( CGColorRef *c) { OSStatus err = noErr; - NSColor *bgColor, *fgColor; + NSColor *bgColor, *color; CGFloat rgba[4] = {0, 0, 0, 1}; static CGColorSpaceRef deviceRGBSpace = NULL; if (!deviceRGBSpace) { @@ -284,29 +287,45 @@ SetCGColorComponents( rgba[i] -= entry.value*(8.0/255.0); } break; - case ttkForeground: + case semantic: switch (entry.value) { + case 0: + color = [[NSColor textColor] colorUsingColorSpace: + [NSColorSpace deviceRGBColorSpace]]; + break; case 1: - fgColor = [[NSColor controlTextColor] colorUsingColorSpace: + color = [[NSColor selectedTextColor] colorUsingColorSpace: [NSColorSpace deviceRGBColorSpace]]; break; case 2: - fgColor = [[NSColor disabledControlTextColor] colorUsingColorSpace: + color = [[NSColor labelColor] colorUsingColorSpace: + [NSColorSpace deviceRGBColorSpace]]; + break; + case 3: + color = [[NSColor controlTextColor] colorUsingColorSpace: + [NSColorSpace deviceRGBColorSpace]]; + break; + case 4: + color = [[NSColor disabledControlTextColor] colorUsingColorSpace: + [NSColorSpace deviceRGBColorSpace]]; + break; + case 5: + color = [[NSColor textBackgroundColor] colorUsingColorSpace: [NSColorSpace deviceRGBColorSpace]]; break; default: if ([NSApp macMinorVersion] < 10) { - fgColor = [[NSColor textColor] colorUsingColorSpace: + color = [[NSColor textColor] colorUsingColorSpace: [NSColorSpace deviceRGBColorSpace]]; } else { #if MAC_OS_X_VERSION_MIN_REQUIRED >= 101000 - fgColor = [[NSColor labelColor] colorUsingColorSpace: + color = [[NSColor labelColor] colorUsingColorSpace: [NSColorSpace deviceRGBColorSpace]]; #endif break; } } - [fgColor getComponents: rgba]; + [color getComponents: rgba]; break; case clearColor: rgba[3] = 0.0; diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index d136b99..6d6e90c 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -1200,7 +1200,7 @@ static void EntryElementDraw( XFillRectangle(Tk_Display(tkwin), d, Tk_3DBorderGC(tkwin, backgroundPtr, TK_3D_FLAT_GC), - inner.x,inner.y, inner.width, inner.height); + inner.x, inner.y, inner.width, inner.height); BEGIN_DRAWING(d) ChkErr(HIThemeDrawFrame, &bounds, &info, dc.context, HIOrientation); @@ -1268,9 +1268,9 @@ static void ComboboxElementDraw( bounds.size.height += 1; } else if ((state & TTK_STATE_BACKGROUND) && !(state & TTK_STATE_DISABLED)) { + NSColor *background = [NSColor textBackgroundColor]; CGRect innerBounds = CGRectInset(bounds, 1, 2); - NSColor *white = [NSColor whiteColor]; - SolidFillRoundedRectangle(dc.context, innerBounds, 4, white); + SolidFillRoundedRectangle(dc.context, innerBounds, 4, background); } bounds.origin.y += 1; ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); @@ -1807,6 +1807,41 @@ static Ttk_ElementSpec ToolbarBackgroundElementSpec = { }; /*---------------------------------------------------------------------- + * +++ Field element: + * Used for the Treeview widget. This is like the BackgroundElement + * except that the fieldbackground color is configureable. + */ + +typedef struct { + Tcl_Obj *backgroundObj; +} 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) +{ + FieldElement *e = elementRecord; + Tk_3DBorder backgroundPtr = Tk_Get3DBorderFromObj(tkwin,e->backgroundObj); + XFillRectangle(Tk_Display(tkwin), d, + Tk_3DBorderGC(tkwin, backgroundPtr, TK_3D_FLAT_GC), + b.x, b.y, b.width, b.height); +} + +static Ttk_ElementSpec FieldElementSpec = { + TK_STYLE_VERSION_2, + sizeof(FieldElement), + FieldElementOptions, + TtkNullElementSize, + FieldElementDraw +}; + +/*---------------------------------------------------------------------- * +++ Treeview header * Redefine the header to use a kThemeListHeaderButton. */ @@ -1851,7 +1886,7 @@ static Ttk_ElementSpec TreeHeaderElementSpec = { TK_STYLE_VERSION_2, sizeof(NullElement), TtkNullElementOptions, - ButtonElementMinSize, + ButtonElementSize, TreeHeaderElementDraw }; @@ -1938,7 +1973,7 @@ TTK_LAYOUT("TMenubutton", TTK_LAYOUT("TCombobox", TTK_GROUP("Combobox.button", TTK_FILL_BOTH, TTK_GROUP("Combobox.padding", TTK_FILL_BOTH, - TTK_NODE("Combobox.textarea", TTK_FILL_X)))) + TTK_NODE("Combobox.textarea", TTK_FILL_BOTH)))) /* Notebook tabs -- no focus ring */ TTK_LAYOUT("Tab", @@ -1955,11 +1990,17 @@ TTK_LAYOUT("TSpinbox", TTK_LAYOUT("TProgressbar", TTK_NODE("Progressbar.track", TTK_EXPAND|TTK_FILL_BOTH)) +/* Treeview -- no border. */ +TTK_LAYOUT("Treeview", + TTK_GROUP("Treeview.field", TTK_FILL_BOTH, + TTK_GROUP("Treeview.padding", TTK_FILL_BOTH, + TTK_NODE("Treeview.treearea", TTK_FILL_BOTH)))) + /* Tree heading -- no border, fixed height */ TTK_LAYOUT("Heading", - TTK_NODE("Treeheading.cell", TTK_FILL_X) + TTK_NODE("Treeheading.cell", TTK_FILL_BOTH) TTK_NODE("Treeheading.image", TTK_PACK_RIGHT) - TTK_NODE("Treeheading.text", 0)) + TTK_NODE("Treeheading.text", TTK_PACK_TOP)) /* Tree items -- omit focus ring */ TTK_LAYOUT("Item", @@ -1987,6 +2028,7 @@ static int AquaTheme_Init(Tcl_Interp *interp) */ Ttk_RegisterElementSpec(themePtr, "background", &BackgroundElementSpec, 0); Ttk_RegisterElementSpec(themePtr, "fill", &FillElementSpec, 0); + Ttk_RegisterElementSpec(themePtr, "field", &FieldElementSpec, 0); Ttk_RegisterElementSpec(themePtr, "Toolbar.background", &ToolbarBackgroundElementSpec, 0); -- cgit v0.12 From 549747a2a8c86ef81e37f32f1d96cb94b6b99a95 Mon Sep 17 00:00:00 2001 From: culler Date: Tue, 26 Mar 2019 18:11:17 +0000 Subject: Added a drawing procedure for dark mode comboboxes. --- library/demos/tree.tcl | 2 +- library/ttk/aquaTheme.tcl | 24 ++++++-------- macosx/tkMacOSXColor.c | 7 +++- macosx/ttkMacOSXTheme.c | 82 +++++++++++++++++++++++++++++++---------------- 4 files changed, 72 insertions(+), 43 deletions(-) diff --git a/library/demos/tree.tcl b/library/demos/tree.tcl index 71c32c1..8decdf2 100644 --- a/library/demos/tree.tcl +++ b/library/demos/tree.tcl @@ -75,7 +75,7 @@ ttk::scrollbar $w.vsb -orient vertical -command "$w.tree yview" ttk::scrollbar $w.hsb -orient horizontal -command "$w.tree xview" $w.tree heading \#0 -text "Directory Structure" $w.tree heading size -text "File Size" -$w.tree column size -stretch 0 -width 70 +$w.tree column size -width 70 populateRoots $w.tree bind $w.tree <> {populateTree %W [%W focus]} diff --git a/library/ttk/aquaTheme.tcl b/library/ttk/aquaTheme.tcl index 50fcd7a..5e04fc6 100644 --- a/library/ttk/aquaTheme.tcl +++ b/library/ttk/aquaTheme.tcl @@ -71,18 +71,22 @@ namespace eval ttk::theme::aqua { !selected systemControlTextColor} # Combobox: - ttk::style configure TCombobox -selectforeground black \ - -background systemTextBackgroundColor + ttk::style configure TCombobox \ + -foreground systemTextColor \ + -background systemTransparent \ + -selectforeground systemSelectedTextColor \ + -selectbackground systemSelectedTextBackgroundColor ttk::style map TCombobox \ -foreground { disabled systemDisabledControlTextColor - focus black - {} black + } \ + -selectforeground { !active systemTextColor } \ -selectbackground { - !focus white - + !active systemTextBackgroundColor + !focus systemTextBackgroundColor + focus systemSelectedTextBackgroundColor } # Treeview: @@ -91,14 +95,6 @@ namespace eval ttk::theme::aqua { -fieldbackground systemTextBackgroundColor \ -background systemTextBackgroundColor \ -foreground systemTextColor - # ttk::style map Treeview \ - # -background { - # disabled systemDialogBackgroundInactive - # {selected background} systemHighlightSecondary - # selected systemHighlight} \ - # -foreground { - # !active black - # } # Enable animation for ttk::progressbar widget: ttk::style configure TProgressbar -period 100 -maxphase 255 diff --git a/macosx/tkMacOSXColor.c b/macosx/tkMacOSXColor.c index f0bcb7c..91f0578 100644 --- a/macosx/tkMacOSXColor.c +++ b/macosx/tkMacOSXColor.c @@ -203,10 +203,11 @@ static const struct SystemColorMapEntry systemColorMap[] = { { "ControlTextColor", semantic, 3 }, /* 177 */ { "DisabledControlTextColor", semantic, 4 }, /* 178 */ { "TextBackgroundColor", semantic, 5 }, /* 179 */ + { "SelectedTextBackgroundColor", semantic, 6 }, /* 180 */ { NULL, 0, 0 } }; #define FIRST_SEMANTIC_COLOR 166 -#define MAX_PIXELCODE 179 +#define MAX_PIXELCODE 180 /* *---------------------------------------------------------------------- @@ -313,6 +314,10 @@ SetCGColorComponents( color = [[NSColor textBackgroundColor] colorUsingColorSpace: [NSColorSpace deviceRGBColorSpace]]; break; + case 6: + color = [[NSColor selectedTextBackgroundColor] colorUsingColorSpace: + [NSColorSpace deviceRGBColorSpace]]; + break; default: if ([NSApp macMinorVersion] < 10) { color = [[NSColor textColor] colorUsingColorSpace: diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index 6d6e90c..47bea73 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -373,6 +373,41 @@ static void HighlightButtonBorder( CFRelease(topGradient); } + +static void DrawUpDownArrows( + CGRect bounds, + CGContextRef context) +{ + CGFloat x, y; + CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0); + CGContextSetLineWidth(context, 1.5); + x = bounds.origin.x + 5; + y = bounds.origin.y + trunc(bounds.size.height/2); + CGContextBeginPath(context); + CGPoint bottomArrow[3] = {{x, y+2}, {x+3.5, y+5.5}, {x+7, y+2}}; + CGContextAddLines(context, bottomArrow, 3); + CGPoint topArrow[3] = {{x, y-2}, {x+3.5, y-5.5}, {x+7, y-2}}; + CGContextAddLines(context, topArrow, 3); + CGContextStrokePath(context); + CGContextRestoreGState(context); +} + +static void DrawDownArrow( + CGRect bounds, + CGContextRef context) +{ + CGFloat x, y; + CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0); + CGContextSetLineWidth(context, 1.5); + x = bounds.origin.x + 5; + y = bounds.origin.y + trunc(bounds.size.height/2); + CGContextBeginPath(context); + CGPoint bottomArrow[3] = {{x, y-3}, {x+3.5, y+3}, {x+7, y-3}}; + CGContextAddLines(context, bottomArrow, 3); + CGContextStrokePath(context); + CGContextRestoreGState(context); +} + /* * DrawDarkButton -- * @@ -424,8 +459,7 @@ static void DrawDarkButton( * If this is a popup, draw the arrow button. */ - if (kind == kThemePopupButton) { - CGFloat x, y; + if (kind == kThemePopupButton | kind == kThemeComboBox) { CGRect arrowBounds = bounds; arrowBounds.size.width = 16; arrowBounds.origin.x += bounds.size.width - 16; @@ -439,29 +473,18 @@ static void DrawDarkButton( GradientFillRoundedRectangle(context, arrowBounds, 4, darkSelectedGradient, 2); } - - /* - * Stroke the arrows. - */ - - CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0); - CGContextSetLineWidth(context, 1.5); - x = arrowBounds.origin.x + 5; - y = arrowBounds.origin.y + trunc(arrowBounds.size.height/2); - CGContextBeginPath(context); - CGPoint bottomArrow[3] = {{x, y+2}, {x+3.5, y+5.5}, {x+7, y+2}}; - CGContextAddLines(context, bottomArrow, 3); - CGPoint topArrow[3] = {{x, y-2}, {x+3.5, y-5.5}, {x+7, y-2}}; - CGContextAddLines(context, topArrow, 3); - CGContextStrokePath(context); - CGContextRestoreGState(context); + if (kind == kThemePopupButton) { + DrawUpDownArrows(arrowBounds, context); + } else { + DrawDownArrow(arrowBounds, context); + } } HighlightButtonBorder(context, bounds); } /* - * DrawDarkButton -- + * DrawDarkBevelButton -- * * This is a standalone drawing procedure which draws * RoundedBevelButtons in the Dark Mode style. @@ -1264,16 +1287,19 @@ static void ComboboxElementDraw( }; BEGIN_DRAWING(d) + bounds.origin.y += 1; if (TkMacOSXInDarkMode(tkwin)) { bounds.size.height += 1; - } else if ((state & TTK_STATE_BACKGROUND) && - !(state & TTK_STATE_DISABLED)) { - NSColor *background = [NSColor textBackgroundColor]; - CGRect innerBounds = CGRectInset(bounds, 1, 2); - SolidFillRoundedRectangle(dc.context, innerBounds, 4, background); + DrawDarkButton(bounds, info.kind, state, dc.context); + } else { + if ((state & TTK_STATE_BACKGROUND) && + !(state & TTK_STATE_DISABLED)) { + NSColor *background = [NSColor textBackgroundColor]; + CGRect innerBounds = CGRectInset(bounds, 1, 2); + SolidFillRoundedRectangle(dc.context, innerBounds, 4, background); + } + ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); } - bounds.origin.y += 1; - ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); END_DRAWING } @@ -1918,10 +1944,12 @@ static void DisclosureElementDraw( Drawable d, Ttk_Box b, Ttk_State state) { if (!(state & TTK_TREEVIEW_STATE_LEAF)) { + int triangleState = TkMacOSXInDarkMode(tkwin) ? + kThemeStateInactive : kThemeStateActive; CGRect bounds = BoxToRect(d, b); const HIThemeButtonDrawInfo info = { .version = 0, - .state = Ttk_StateTableLookup(ThemeStateTable, state), + .state = triangleState, .kind = kThemeDisclosureTriangle, .value = Ttk_StateTableLookup(DisclosureValueTable, state), .adornment = kThemeAdornmentDrawIndicatorOnly, -- cgit v0.12 From ac76edf06fe2e72f49ee79f2705eb3371964f67a Mon Sep 17 00:00:00 2001 From: culler Date: Wed, 27 Mar 2019 19:11:02 +0000 Subject: Implemented a real ttk::scrollbar for Aqua. --- library/ttk/scrollbar.tcl | 18 ---- macosx/ttkMacOSXTheme.c | 220 ++++++++++++++++++++++++++++++++++++++-------- tests/ttk/scrollbar.test | 30 +++++-- 3 files changed, 207 insertions(+), 61 deletions(-) diff --git a/library/ttk/scrollbar.tcl b/library/ttk/scrollbar.tcl index 4bd5107..d08e1e2 100644 --- a/library/ttk/scrollbar.tcl +++ b/library/ttk/scrollbar.tcl @@ -2,24 +2,6 @@ # Bindings for TScrollbar widget # -# Still don't have a working ttk::scrollbar under OSX - -# Swap in a [tk::scrollbar] on that platform, -# unless user specifies -class or -style. -# -if {[tk windowingsystem] eq "aqua"} { - rename ::ttk::scrollbar ::ttk::_scrollbar - proc ttk::scrollbar {w args} { - set constructor ::tk::scrollbar - foreach {option _} $args { - if {$option eq "-class" || $option eq "-style"} { - set constructor ::ttk::_scrollbar - break - } - } - return [$constructor $w {*}$args] - } -} - namespace eval ttk::scrollbar { variable State # State(xPress) -- diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index 47bea73..abed36e 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -119,7 +119,7 @@ static CGFloat windowBackground[4] = {235.0/255, 235.0/255, 235.0/255, 1.0}; * GetBoxColor -- * * Compute a contrasting box color, based on nesting depth, and save the - * RGBA components in an array. + * RGBA components in an array. Used by the Fill and Background elements. */ static int GetBoxColor( @@ -221,9 +221,9 @@ static void DrawGroupBox( * the button centered vertically on the rectangle, and having the same width * as the rectangle. This function returns the actual bounding rectangle that * will be used in drawing the button. - * + * * The BevelButton is allowed to have arbitrary size, and also has external - * padding. This is handled separately here. + * padding. This is handled separately here. */ @@ -454,7 +454,7 @@ static void DrawDarkButton( } SolidFillRoundedRectangle(context, bounds, 4, faceColor); } - + /* * If this is a popup, draw the arrow button. */ @@ -814,7 +814,7 @@ static inline HIThemeButtonDrawInfo computeButtonDrawInfo( HIThemeState = Ttk_StateTableLookup(ThemeStateTable, state); break; } - + const HIThemeButtonDrawInfo info = { .version = 0, .state = HIThemeState, @@ -842,7 +842,7 @@ static void ButtonElementMinSize( *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 @@ -880,7 +880,7 @@ static void ButtonElementSize( * To compute the effective padding around a button we request the * content and bounding rectangles for a 100x100 button and use the * padding between those. However, we symmetrize the padding on the - * top and bottom, because that is how the button will be drawn. + * top and bottom, because that is how the button will be drawn. */ ChkErr(HIThemeGetButtonContentBounds, @@ -926,14 +926,14 @@ static void ButtonElementDraw( #endif } else { /* - * Apple's PushButton and PopupButton do not change their (white) fill - * color when the window is inactive although, except in 10.7 (Lion), - * the color of the arrow button on a PopupButton does change. For - * some reason HITheme fills inactive buttons with a transparent color - * that allows the window background to show through, leading to + * Apple's PushButton and PopupButton do not change their fill color + * when the window is inactive. However, except in 10.7 (Lion), the + * color of the arrow button on a PopupButton does change. For some + * reason HITheme fills inactive buttons with a transparent color that + * allows the window background to show through, leading to * inconsistent behavior. We work around this by filling behind an - * inactive PopupButton with a white color before asking HIToolbox to - * draw it. PopupButton. For PushButtons, we simply draw them in the + * inactive PopupButton with a text background color before asking + * HIToolbox to draw it. For PushButtons, we simply draw them in the * active state. */ if (info.kind == kThemePopupButton && (state & TTK_STATE_BACKGROUND)) { @@ -946,7 +946,7 @@ static void ButtonElementDraw( * A BevelButton with mixed value is drawn borderless, which does make * much sense for us. */ - + if (info.kind == kThemeRoundedBevelButton && info.value == kThemeButtonMixed) { info.value = kThemeButtonOff; @@ -969,7 +969,6 @@ static Ttk_ElementSpec ButtonElementSpec = { * +++ Notebook elements. */ - /* Tab position logic, c.f. ttkNotebook.c TabState() */ static Ttk_StateTable TabStyleTable[] = { @@ -1462,9 +1461,9 @@ static void TrackElementDraw( components: darkTrack count: 4]; if (orientation == TTK_ORIENT_HORIZONTAL) { - bounds = CGRectInset(bounds, 1, bounds.size.height/2 - 2); + bounds = CGRectInset(bounds, 1, bounds.size.height/2 - 2); } else { - bounds = CGRectInset(bounds, bounds.size.width/2 - 3, 2); + bounds = CGRectInset(bounds, bounds.size.width/2 - 3, 2); } SolidFillRoundedRectangle(dc.context, bounds, 2, trackColor); } @@ -1507,7 +1506,7 @@ static Ttk_ElementSpec SliderElementSpec = { }; /*---------------------------------------------------------------------- - * +++ Progress bar element (new): + * +++ Progress bar element: * * @@@ NOTE: According to an older revision of the Aqua reference docs, * @@@ the 'phase' field is between 0 and 4. Newer revisions say @@ -1584,9 +1583,9 @@ static void PbarElementDraw( components: darkTrack count: 4]; if (orientation == TTK_ORIENT_HORIZONTAL) { - bounds = CGRectInset(bounds, 1, bounds.size.height/2 - 3); + bounds = CGRectInset(bounds, 1, bounds.size.height/2 - 3); } else { - bounds = CGRectInset(bounds, bounds.size.width/2 - 3, 1); + bounds = CGRectInset(bounds, bounds.size.width/2 - 3, 1); } SolidFillRoundedRectangle(dc.context, bounds, 3, trackColor); } @@ -1604,6 +1603,138 @@ static Ttk_ElementSpec PbarElementSpec = { }; /*---------------------------------------------------------------------- + * +++ Scrollbar element + */ + +typedef struct +{ + Tcl_Obj *orientObj; +} ScrollbarElement; + +static Ttk_ElementOptionSpec ScrollbarElementOptions[] = { + { "-orient", TK_OPTION_STRING, + Tk_Offset(ScrollbarElement,orientObj), "horizontal" }, + {0,0,0,0} +}; + +static void TroughElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) +{ + ScrollbarElement *scrollbar = elementRecord; + int orientation = TTK_ORIENT_HORIZONTAL; + SInt32 thickness = 15; + + Ttk_GetOrientFromObj(NULL, scrollbar->orientObj, &orientation); + ChkErr(GetThemeMetric, kThemeMetricScrollBarWidth, &thickness); + if (orientation == TTK_ORIENT_HORIZONTAL) { + *minHeight = thickness; + } else { + *minWidth = thickness; + } +} + +static void TroughElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, Ttk_State state) +{ + ScrollbarElement *scrollbar = elementRecord; + int orientation = TTK_ORIENT_HORIZONTAL; + CGRect bounds = BoxToRect(d, b); + Ttk_GetOrientFromObj(NULL, scrollbar->orientObj, &orientation); + if (orientation == TTK_ORIENT_HORIZONTAL) { + bounds = CGRectInset(bounds, 0, 1); + } else { + bounds = CGRectInset(bounds, 1, 0); + } + BEGIN_DRAWING(d) + ChkErr(HIThemeSetFill, kThemeBrushDocumentWindowBackground, NULL, + dc.context, HIOrientation); + CGContextFillRect(dc.context, bounds); + END_DRAWING +} + +static Ttk_ElementSpec TroughElementSpec = { + TK_STYLE_VERSION_2, + sizeof(ScrollbarElement), + ScrollbarElementOptions, + TroughElementSize, + TroughElementDraw +}; + +static void ThumbElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) +{ + ScrollbarElement *scrollbar = elementRecord; + int orientation = TTK_ORIENT_HORIZONTAL; + SInt32 thickness = 15; + + Ttk_GetOrientFromObj(NULL, scrollbar->orientObj, &orientation); + ChkErr(GetThemeMetric, kThemeMetricScrollBarWidth, &thickness); + if (orientation == TTK_ORIENT_HORIZONTAL) { + *minHeight = thickness; + } else { + *minWidth = thickness; + } +} + +static void ThumbElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, Ttk_State state) +{ + ScrollbarElement *scrollbar = elementRecord; + int orientation = TTK_ORIENT_HORIZONTAL; + CGRect bounds = BoxToRect(d, b); + int viewSize = RangeToFactor(100); + HIThemeTrackDrawInfo info = { + .version = 0, + .bounds = bounds, + .min = 0.0, + .max = 100.0, + .attributes = kThemeTrackShowThumb | kThemeTrackThumbRgnIsNotGhost, + .enableState = kThemeTrackActive + }; + Ttk_GetOrientFromObj(NULL, scrollbar->orientObj, &orientation); + if (orientation == TTK_ORIENT_HORIZONTAL) { + info.attributes |= kThemeTrackHorizontal; + } else { + info.attributes &= ~kThemeTrackHorizontal; + } + info.trackInfo.scrollbar.viewsize = viewSize; + info.value = viewSize * (bounds.origin.y / Tk_Height(tkwin)); + if ((state & TTK_STATE_PRESSED) || + (state & TTK_STATE_HOVER) ) { + info.trackInfo.scrollbar.pressState = kThemeThumbPressed; + } else { + info.trackInfo.scrollbar.pressState = 0; + } + BEGIN_DRAWING(d) + if (0) { + HIThemeDrawTrack (&info, 0, dc.context, kHIThemeOrientationInverted); + } else { + HIThemeDrawTrack (&info, 0, dc.context, kHIThemeOrientationNormal); + } + END_DRAWING +} + +static Ttk_ElementSpec ThumbElementSpec = { + TK_STYLE_VERSION_2, + sizeof(ScrollbarElement), + ScrollbarElementOptions, + ThumbElementSize, + ThumbElementDraw +}; + +static Ttk_ElementSpec NoArrowElementSpec = { + TK_STYLE_VERSION_2, + sizeof(NullElement), + TtkNullElementOptions, + TtkNullElementSize, + TtkNullElementDraw +}; + +/*---------------------------------------------------------------------- * +++ Separator element. * * DrawThemeSeparator() guesses the orientation of the line from the width @@ -1945,7 +2076,7 @@ static void DisclosureElementDraw( { if (!(state & TTK_TREEVIEW_STATE_LEAF)) { int triangleState = TkMacOSXInDarkMode(tkwin) ? - kThemeStateInactive : kThemeStateActive; + kThemeStateInactive : kThemeStateActive; CGRect bounds = BoxToRect(d, b); const HIThemeButtonDrawInfo info = { .version = 0, @@ -2009,12 +2140,12 @@ TTK_LAYOUT("Tab", TTK_GROUP("Notebook.padding", TTK_EXPAND|TTK_FILL_BOTH, TTK_NODE("Notebook.label", TTK_EXPAND|TTK_FILL_BOTH)))) -/* Progress bars -- track only */ TTK_LAYOUT("TSpinbox", TTK_NODE("Spinbox.spinbutton", TTK_PACK_RIGHT|TTK_STICK_E) TTK_GROUP("Spinbox.field", TTK_EXPAND|TTK_FILL_X, TTK_NODE("Spinbox.textarea", TTK_EXPAND|TTK_FILL_X))) +/* Progress bars -- track only */ TTK_LAYOUT("TProgressbar", TTK_NODE("Progressbar.track", TTK_EXPAND|TTK_FILL_BOTH)) @@ -2082,30 +2213,47 @@ static int AquaTheme_Init(Tcl_Interp *interp) Ttk_RegisterElementSpec(themePtr, "Notebook.tab", &TabElementSpec, 0); Ttk_RegisterElementSpec(themePtr, "Notebook.client", &PaneElementSpec, 0); - Ttk_RegisterElementSpec(themePtr, "Labelframe.border", &GroupElementSpec,0); - Ttk_RegisterElementSpec(themePtr, "Entry.field", &EntryElementSpec,0); - Ttk_RegisterElementSpec(themePtr, "Spinbox.field", &EntryElementSpec,0); + Ttk_RegisterElementSpec(themePtr, "Labelframe.border", &GroupElementSpec, 0); + Ttk_RegisterElementSpec(themePtr, "Entry.field", &EntryElementSpec, 0); + Ttk_RegisterElementSpec(themePtr, "Spinbox.field", &EntryElementSpec, 0); - Ttk_RegisterElementSpec(themePtr, "separator", &SeparatorElementSpec,0); - Ttk_RegisterElementSpec(themePtr, "hseparator", &SeparatorElementSpec,0); - Ttk_RegisterElementSpec(themePtr, "vseparator", &SeparatorElementSpec,0); + Ttk_RegisterElementSpec(themePtr, "separator", &SeparatorElementSpec, 0); + Ttk_RegisterElementSpec(themePtr, "hseparator", &SeparatorElementSpec, 0); + Ttk_RegisterElementSpec(themePtr, "vseparator", &SeparatorElementSpec, 0); - Ttk_RegisterElementSpec(themePtr, "sizegrip", &SizegripElementSpec,0); + Ttk_RegisterElementSpec(themePtr, "sizegrip", &SizegripElementSpec, 0); /* * <> - * The Progressbar widget adjusts the size of the pbar element. - * In the Aqua theme, the appearance manager computes the bar geometry; - * we do all the drawing in the ".track" element and leave the .pbar out. + * 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". */ - Ttk_RegisterElementSpec(themePtr,"Scale.trough", - &TrackElementSpec, &ScaleData); - Ttk_RegisterElementSpec(themePtr,"Scale.slider", &SliderElementSpec,0); + Ttk_RegisterElementSpec(themePtr,"Progressbar.track", &PbarElementSpec, 0); + Ttk_RegisterElementSpec(themePtr,"Scale.trough", &TrackElementSpec, + &ScaleData); + Ttk_RegisterElementSpec(themePtr,"Scale.slider", &SliderElementSpec, 0); + + Ttk_RegisterElementSpec(themePtr,"Vertical.Scrollbar.trough", &TroughElementSpec, 0); + Ttk_RegisterElementSpec(themePtr,"Vertical.Scrollbar.thumb", &ThumbElementSpec, 0); + Ttk_RegisterElementSpec(themePtr,"Horizontal.Scrollbar.trough", &TroughElementSpec, 0); + Ttk_RegisterElementSpec(themePtr,"Horizontal.Scrollbar.thumb", &ThumbElementSpec, 0); + + /* + * If we are not in Snow Leopard we don't display any buttons. + */ + + Ttk_RegisterElementSpec(themePtr,"Vertical.Scrollbar.uparrow", &NoArrowElementSpec, 0); + Ttk_RegisterElementSpec(themePtr,"Vertical.Scrollbar.downarrow", &NoArrowElementSpec, 0); + Ttk_RegisterElementSpec(themePtr,"Horizontal.Scrollbar.leftarrow", &NoArrowElementSpec, 0); + Ttk_RegisterElementSpec(themePtr,"Horizontal.Scrollbar.rightarrow", &NoArrowElementSpec, 0); + /* * Layouts: */ + Ttk_RegisterLayouts(themePtr, LayoutTable); Tcl_PkgProvide(interp, "ttk::theme::aqua", TTK_VERSION); diff --git a/tests/ttk/scrollbar.test b/tests/ttk/scrollbar.test index 341b5c1..903328e 100644 --- a/tests/ttk/scrollbar.test +++ b/tests/ttk/scrollbar.test @@ -4,16 +4,26 @@ loadTestedCommands testConstraint coreScrollbar [expr {[tk windowingsystem] eq "aqua"}] -test scrollbar-swapout-1 "Use core scrollbars on OSX..." -constraints { - coreScrollbar +# Before 2019 the code in library/ttk/scrollbar.tcl would replace the +# constructor of ttk::scrollbar with the constructor of tk::scrollbar +# unless the -class or -style options were specified.. +# Now there is an implementation of ttk::scrollbar for macOS. The +# tests are left in place, though, except that scrollbar-swapout-1 +# test was changed to expect the class to be TScrollbar instead of +# Scrollbar. + +test scrollbar-swapout-1 "Don't use core scrollbars on OSX..." \ + -constraints { + coreScrollbar } -body { ttk::scrollbar .sb -command "yadda" list [winfo class .sb] [.sb cget -command] -} -result [list Scrollbar yadda] -cleanup { +} -result [list TScrollbar yadda] -cleanup { destroy .sb } -test scrollbar-swapout-2 "... unless -style is specified ..." -constraints { +test scrollbar-swapout-2 "... regardless of whether -style ..." \ +-constraints { coreScrollbar } -body { ttk::style layout Vertical.Custom.TScrollbar \ @@ -24,7 +34,7 @@ test scrollbar-swapout-2 "... unless -style is specified ..." -constraints { destroy .sb } -test scrollbar-swapout-3 "... or -class." -constraints { +test scrollbar-swapout-3 "... or -class is specified." -constraints { coreScrollbar } -body { ttk::scrollbar .sb -command "yadda" -class Custom.TScrollbar @@ -44,13 +54,19 @@ test scrollbar-1.1 "Set method" -body { test scrollbar-1.2 "Set orientation" -body { .tsb configure -orient vertical - set w [winfo reqwidth .tsb] ; set h [winfo reqheight .tsb] + pack .tsb -side right -anchor e -expand 1 -fill y + wm geometry . 200x200 + update + set w [winfo width .tsb] ; set h [winfo height .tsb] expr {$h > $w} } -result 1 test scrollbar-1.3 "Change orientation" -body { .tsb configure -orient horizontal - set w [winfo reqwidth .tsb] ; set h [winfo reqheight .tsb] + pack .tsb -side bottom -anchor s -expand 1 -fill x + wm geometry . 200x200 + update + set w [winfo width .tsb] ; set h [winfo height .tsb] expr {$h < $w} } -result 1 -- cgit v0.12 From dc37e2284b4baccb9a8e7220604bc667d7050129 Mon Sep 17 00:00:00 2001 From: fvogel Date: Thu, 28 Mar 2019 19:34:20 +0000 Subject: Revert previous commit following discussion on tcl-core list. --- doc/scale.n | 4 +--- generic/tkScale.c | 4 ++-- generic/tkScale.h | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/doc/scale.n b/doc/scale.n index c5f22b4..b1f1981 100644 --- a/doc/scale.n +++ b/doc/scale.n @@ -78,9 +78,7 @@ specified by the \fB\-activebackground\fR option. .OP \-tickinterval tickInterval TickInterval Must be a real value. Determines the spacing between numerical -tick marks displayed below or to the left of the slider. The values will all -be displayed with the same number of decimal places, which will be enough to -ensure they are all precise to within 20% of a tick interval. +tick marks displayed below or to the left of the slider. The values will all be displayed with the same number of decimal places, which will be enough to ensure they are all accurate to within 20% of a tick interval. If 0, no tick marks will be displayed. .OP \-to to To Specifies a real value corresponding diff --git a/generic/tkScale.c b/generic/tkScale.c index b28b08d..c5cdaff 100644 --- a/generic/tkScale.c +++ b/generic/tkScale.c @@ -905,11 +905,11 @@ ComputeFormat( /* * Now add more digits until max error is less than - * TICK_VALUES_DISPLAY_PRECISION intervals + * TICK_VALUES_DISPLAY_ACCURACY intervals */ while (MaxTickRoundingError(scalePtr, pow(10, leastSigDigit)) - > fabs(TICK_VALUES_DISPLAY_PRECISION * scalePtr->tickInterval)) { + > fabs(TICK_VALUES_DISPLAY_ACCURACY * scalePtr->tickInterval)) { --leastSigDigit; } numDigits = 1 + mostSigDigit - leastSigDigit; diff --git a/generic/tkScale.h b/generic/tkScale.h index b307aa2..e68b786 100644 --- a/generic/tkScale.h +++ b/generic/tkScale.h @@ -222,7 +222,7 @@ typedef struct TkScale { * accurate to within the following proportion of a tick interval. */ -#define TICK_VALUES_DISPLAY_PRECISION 0.2 +#define TICK_VALUES_DISPLAY_ACCURACY 0.2 /* * Declaration of procedures used in the implementation of the scale widget. -- cgit v0.12 From b917c102071eea765423d2ef6dc04d94ec38169c Mon Sep 17 00:00:00 2001 From: culler Date: Thu, 28 Mar 2019 21:46:00 +0000 Subject: Reworked the drawing procedure for ttk::scrollbar and made it work in Dark Mode and on Snow Leopard. --- macosx/tkMacOSXColor.c | 5 + macosx/ttkMacOSXTheme.c | 268 +++++++++++++++++++++++++++++++++++------------- 2 files changed, 199 insertions(+), 74 deletions(-) diff --git a/macosx/tkMacOSXColor.c b/macosx/tkMacOSXColor.c index 91f0578..5e983e3 100644 --- a/macosx/tkMacOSXColor.c +++ b/macosx/tkMacOSXColor.c @@ -299,8 +299,13 @@ SetCGColorComponents( [NSColorSpace deviceRGBColorSpace]]; break; case 2: +#if MAC_OS_X_VERSION_MIN_REQUIRED > 101000 color = [[NSColor labelColor] colorUsingColorSpace: [NSColorSpace deviceRGBColorSpace]]; +#else + color = [[NSColor textColor] colorUsingColorSpace: + [NSColorSpace deviceRGBColorSpace]]; +#endif break; case 3: color = [[NSColor controlTextColor] colorUsingColorSpace: diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index abed36e..9577e51 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -98,6 +98,34 @@ static Ttk_StateTable ThemeStateTable[] = { */ }; +/* + * NormalizeButtonBounds -- + * + * Apple's Human Interface Guidelines only allow three specific heights for + * most buttons: Regular, small and mini. We always use the regular size. + * However, Ttk may provide an arbitrary bounding rectangle. We always draw + * the button centered vertically on the rectangle, and having the same width + * as the rectangle. This function returns the actual bounding rectangle that + * will be used in drawing the button. + * + * The BevelButton is allowed to have arbitrary size, and also has external + * padding. This is handled separately here. + */ + + +static CGRect NormalizeButtonBounds( + SInt32 heightMetric, + CGRect bounds) +{ + SInt32 height; + if (heightMetric != NoThemeMetric) { + ChkErr(GetThemeMetric, heightMetric, &height); + bounds.origin.y += (bounds.size.height - height)/2; + bounds.size.height = height; + } + return bounds; +} + #if MAC_OS_X_VERSION_MIN_REQUIRED > 1080 /*---------------------------------------------------------------------- * +++ Support for contrasting background colors when GroupBoxes @@ -212,34 +240,6 @@ static void DrawGroupBox( CFRelease(path); } -/* - * NormalizeButtonBounds -- - * - * Apple's Human Interface Guidelines only allow three specific heights for - * most buttons: Regular, small and mini. We always use the regular size. - * However, Ttk may provide an arbitrary bounding rectangle. We always draw - * the button centered vertically on the rectangle, and having the same width - * as the rectangle. This function returns the actual bounding rectangle that - * will be used in drawing the button. - * - * The BevelButton is allowed to have arbitrary size, and also has external - * padding. This is handled separately here. - */ - - -static CGRect NormalizeButtonBounds( - SInt32 heightMetric, - CGRect bounds) -{ - SInt32 height; - if (heightMetric != NoThemeMetric) { - ChkErr(GetThemeMetric, heightMetric, &height); - bounds.origin.y += (bounds.size.height - height)/2; - bounds.size.height = height; - } - return bounds; -} - /* SolidFillRoundedRectangle -- * * Fill a rounded rectangle with a specified solid color. @@ -936,11 +936,14 @@ static void ButtonElementDraw( * HIToolbox to draw it. For PushButtons, we simply draw them in the * active state. */ + +#if MAC_OS_X_VERSION_MIN_REQUIRED > 1080 if (info.kind == kThemePopupButton && (state & TTK_STATE_BACKGROUND)) { CGRect innerBounds = CGRectInset(bounds, 1, 1); NSColor *white = [NSColor whiteColor]; SolidFillRoundedRectangle(dc.context, innerBounds, 4, white); } +#endif /* * A BevelButton with mixed value is drawn borderless, which does make @@ -1288,15 +1291,20 @@ static void ComboboxElementDraw( BEGIN_DRAWING(d) bounds.origin.y += 1; if (TkMacOSXInDarkMode(tkwin)) { +#if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 bounds.size.height += 1; DrawDarkButton(bounds, info.kind, state, dc.context); - } else { +#endif + } else + { +#if MAC_OS_X_VERSION_MIN_REQUIRED > 1080 if ((state & TTK_STATE_BACKGROUND) && !(state & TTK_STATE_DISABLED)) { NSColor *background = [NSColor textBackgroundColor]; CGRect innerBounds = CGRectInset(bounds, 1, 2); SolidFillRoundedRectangle(dc.context, innerBounds, 4, background); } +#endif ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); } END_DRAWING @@ -1629,11 +1637,24 @@ static void TroughElementSize( ChkErr(GetThemeMetric, kThemeMetricScrollBarWidth, &thickness); if (orientation == TTK_ORIENT_HORIZONTAL) { *minHeight = thickness; + if ([NSApp macMinorVersion] > 7) { + *paddingPtr = Ttk_MakePadding(4, 4, 4, 3); + } } else { *minWidth = thickness; + if ([NSApp macMinorVersion] > 7) { + *paddingPtr = Ttk_MakePadding(4, 4, 3, 4); + } } } +static CGFloat lightTrough[4] = {250.0/255, 250.0/255, 250.0/255, 1.0}; +static CGFloat darkTrough[4] = {45.0/255, 46.0/255, 49.0/255, 1.0}; +static CGFloat lightInactiveThumb[4] = {200.0/255, 200.0/255, 200.0/255, 1.0}; +static CGFloat lightActiveThumb[4] = {133.0/255, 133.0/255, 133.0/255, 1.0}; +static CGFloat darkInactiveThumb[4] = {116.0/255, 117.0/255, 118.0/255, 1.0}; +static CGFloat darkActiveThumb[4] = {158.0/255, 158.0/255, 159.0/255, 1.0}; + static void TroughElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) @@ -1641,15 +1662,27 @@ static void TroughElementDraw( ScrollbarElement *scrollbar = elementRecord; int orientation = TTK_ORIENT_HORIZONTAL; CGRect bounds = BoxToRect(d, b); + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + NSColor *troughColor; + CGFloat *rgba = TkMacOSXInDarkMode(tkwin) ? darkTrough : lightTrough; Ttk_GetOrientFromObj(NULL, scrollbar->orientObj, &orientation); if (orientation == TTK_ORIENT_HORIZONTAL) { bounds = CGRectInset(bounds, 0, 1); } else { bounds = CGRectInset(bounds, 1, 0); } + troughColor = [NSColor colorWithColorSpace: deviceRGB + components: rgba + count: 4]; BEGIN_DRAWING(d) - ChkErr(HIThemeSetFill, kThemeBrushDocumentWindowBackground, NULL, - dc.context, HIOrientation); + if ([NSApp macMinorVersion] > 8) { +#if MAC_OS_X_VERSION_MIN_REQUIRED > 1080 + CGContextSetFillColorWithColor(dc.context, troughColor.CGColor); +#endif + } else { + ChkErr(HIThemeSetFill, kThemeBrushDocumentWindowBackground, NULL, + dc.context, HIOrientation); + } CGContextFillRect(dc.context, bounds); END_DRAWING } @@ -1668,14 +1701,12 @@ static void ThumbElementSize( { ScrollbarElement *scrollbar = elementRecord; int orientation = TTK_ORIENT_HORIZONTAL; - SInt32 thickness = 15; Ttk_GetOrientFromObj(NULL, scrollbar->orientObj, &orientation); - ChkErr(GetThemeMetric, kThemeMetricScrollBarWidth, &thickness); if (orientation == TTK_ORIENT_HORIZONTAL) { - *minHeight = thickness; + *minHeight = 8; } else { - *minWidth = thickness; + *minWidth = 8; } } @@ -1685,37 +1716,101 @@ static void ThumbElementDraw( { ScrollbarElement *scrollbar = elementRecord; int orientation = TTK_ORIENT_HORIZONTAL; - CGRect bounds = BoxToRect(d, b); - int viewSize = RangeToFactor(100); - HIThemeTrackDrawInfo info = { - .version = 0, - .bounds = bounds, - .min = 0.0, - .max = 100.0, - .attributes = kThemeTrackShowThumb | kThemeTrackThumbRgnIsNotGhost, - .enableState = kThemeTrackActive - }; Ttk_GetOrientFromObj(NULL, scrollbar->orientObj, &orientation); - if (orientation == TTK_ORIENT_HORIZONTAL) { - info.attributes |= kThemeTrackHorizontal; - } else { - info.attributes &= ~kThemeTrackHorizontal; - } - info.trackInfo.scrollbar.viewsize = viewSize; - info.value = viewSize * (bounds.origin.y / Tk_Height(tkwin)); - if ((state & TTK_STATE_PRESSED) || - (state & TTK_STATE_HOVER) ) { - info.trackInfo.scrollbar.pressState = kThemeThumbPressed; - } else { - info.trackInfo.scrollbar.pressState = 0; - } - BEGIN_DRAWING(d) - if (0) { - HIThemeDrawTrack (&info, 0, dc.context, kHIThemeOrientationInverted); + + /* + * 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) { +#if MAC_OS_X_VERSION_MIN_REQUIRED > 1080 + CGRect thumbBounds = BoxToRect(d, b); + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + NSColor *thumbColor; + CGFloat *rgba; + if ((orientation == TTK_ORIENT_HORIZONTAL && + thumbBounds.size.width >= Tk_Width(tkwin) - 8) || + (orientation == TTK_ORIENT_VERTICAL && + thumbBounds.size.height >= Tk_Height(tkwin) - 8)) { + return; + } + int isDark = TkMacOSXInDarkMode(tkwin); + if ((state & TTK_STATE_PRESSED) || + (state & TTK_STATE_HOVER) ) { + rgba = isDark ? darkActiveThumb : lightActiveThumb; + } else { + rgba = isDark ? darkInactiveThumb : lightInactiveThumb; + } + thumbColor = [NSColor colorWithColorSpace: deviceRGB + components: rgba + count: 4]; + BEGIN_DRAWING(d) + SolidFillRoundedRectangle(dc.context, thumbBounds, 4, thumbColor); + END_DRAWING +#endif } else { - HIThemeDrawTrack (&info, 0, dc.context, kHIThemeOrientationNormal); - } - END_DRAWING + double thumbSize, trackSize, visibleSize, viewSize; + MacDrawable *macWin = (MacDrawable *) Tk_WindowId(tkwin); + CGRect troughBounds = {{macWin->xOff, macWin->yOff}, + {Tk_Width(tkwin), Tk_Height(tkwin)}}; + + /* + * The info struct has integer fields, which will be converted to + * floats in the drawing routine. All of values provided in the info + * struct, namely min, max, value, and viewSize are only defined up to + * an arbitrary scale factor. To avoid roundoff error we scale so that + * the viewSize is a large float which is smaller than the largest int. + */ + + viewSize = RangeToFactor(100.0); + HIThemeTrackDrawInfo info = { + .version = 0, + .bounds = troughBounds, + .min = 0, + .attributes = kThemeTrackShowThumb | kThemeTrackThumbRgnIsNotGhost, + .enableState = kThemeTrackActive + }; + info.trackInfo.scrollbar.viewsize = viewSize*.8; + 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)); + } else { + thumbSize = b.height; + trackSize = troughBounds.size.height; + visibleSize = (thumbSize / trackSize) * viewSize; + info.max = viewSize - visibleSize; + info.value = info.max * (b.y / (trackSize - thumbSize)); + } + if ((state & TTK_STATE_PRESSED) || + (state & TTK_STATE_HOVER) ) { + info.trackInfo.scrollbar.pressState = kThemeThumbPressed; + } else { + info.trackInfo.scrollbar.pressState = 0; + } + if (orientation == TTK_ORIENT_HORIZONTAL) { + info.attributes |= kThemeTrackHorizontal; + } else { + info.attributes &= ~kThemeTrackHorizontal; + } + BEGIN_DRAWING(d) + HIThemeDrawTrack (&info, 0, dc.context, kHIThemeOrientationNormal); + END_DRAWING + } } static Ttk_ElementSpec ThumbElementSpec = { @@ -1726,11 +1821,22 @@ static Ttk_ElementSpec ThumbElementSpec = { ThumbElementDraw }; -static Ttk_ElementSpec NoArrowElementSpec = { +static void ArrowElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) +{ + if ([NSApp macMinorVersion] < 8) { + *minHeight = *minWidth = 14; + } else { + *minHeight = *minWidth = -1; + } +} + +static Ttk_ElementSpec ArrowElementSpec = { TK_STYLE_VERSION_2, - sizeof(NullElement), - TtkNullElementOptions, - TtkNullElementSize, + sizeof(ScrollbarElement), + ScrollbarElementOptions, + ArrowElementSize, TtkNullElementDraw }; @@ -1882,7 +1988,7 @@ static void FillElementDraw( { CGRect bounds = BoxToRect(d, b); BEGIN_DRAWING(d) -#if MAC_OS_X_VERSION_MIN_REQUIRED > 10800 +#if MAC_OS_X_VERSION_MIN_REQUIRED > 1080 NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; NSColor *bgColor; CGFloat fill[4]; @@ -2168,6 +2274,20 @@ TTK_LAYOUT("Item", TTK_NODE("Treeitem.image", TTK_PACK_LEFT) TTK_NODE("Treeitem.text", TTK_PACK_LEFT))) +/* Scrollbar Layout -- Buttons at the bottom (Snow Leopard and Lion only) */ + +TTK_LAYOUT("Vertical.TScrollbar", + TTK_GROUP("Vertical.Scrollbar.trough", TTK_FILL_Y, + TTK_NODE("Vertical.Scrollbar.thumb", TTK_PACK_TOP|TTK_EXPAND|TTK_FILL_BOTH) + TTK_NODE("Vertical.Scrollbar.downarrow", TTK_PACK_BOTTOM) + TTK_NODE("Vertical.Scrollbar.uparrow", TTK_PACK_BOTTOM))) + +TTK_LAYOUT("Horizontal.TScrollbar", + TTK_GROUP("Horizontal.Scrollbar.trough", TTK_FILL_X, + TTK_NODE("Horizontal.Scrollbar.thumb", TTK_PACK_LEFT|TTK_EXPAND|TTK_FILL_BOTH) + TTK_NODE("Horizontal.Scrollbar.rightarrow", TTK_PACK_RIGHT) + TTK_NODE("Horizontal.Scrollbar.leftarrow", TTK_PACK_RIGHT))) + TTK_END_LAYOUT_TABLE /*---------------------------------------------------------------------- @@ -2242,13 +2362,13 @@ static int AquaTheme_Init(Tcl_Interp *interp) Ttk_RegisterElementSpec(themePtr,"Horizontal.Scrollbar.thumb", &ThumbElementSpec, 0); /* - * If we are not in Snow Leopard we don't display any buttons. + * If we are not in Snow Leopard or Lion the arrows won't actually be displayed. */ - Ttk_RegisterElementSpec(themePtr,"Vertical.Scrollbar.uparrow", &NoArrowElementSpec, 0); - Ttk_RegisterElementSpec(themePtr,"Vertical.Scrollbar.downarrow", &NoArrowElementSpec, 0); - Ttk_RegisterElementSpec(themePtr,"Horizontal.Scrollbar.leftarrow", &NoArrowElementSpec, 0); - Ttk_RegisterElementSpec(themePtr,"Horizontal.Scrollbar.rightarrow", &NoArrowElementSpec, 0); + Ttk_RegisterElementSpec(themePtr,"Vertical.Scrollbar.uparrow", &ArrowElementSpec, 0); + Ttk_RegisterElementSpec(themePtr,"Vertical.Scrollbar.downarrow", &ArrowElementSpec, 0); + Ttk_RegisterElementSpec(themePtr,"Horizontal.Scrollbar.leftarrow", &ArrowElementSpec, 0); + Ttk_RegisterElementSpec(themePtr,"Horizontal.Scrollbar.rightarrow", &ArrowElementSpec, 0); /* * Layouts: -- cgit v0.12 From 171f0be2e35714b2024d46d4b8f3a2eabb4c17b7 Mon Sep 17 00:00:00 2001 From: culler Date: Fri, 29 Mar 2019 14:23:46 +0000 Subject: Fix bug [2219588]: ttk::spinbox arrow buttons do not indicate pressed state. --- macosx/ttkMacOSXTheme.c | 97 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 80 insertions(+), 17 deletions(-) diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index 9577e51..38ba621 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -1324,10 +1324,19 @@ static Ttk_ElementSpec ComboboxElementSpec = { * From Apple HIG, part III, section "Controls", "The Stepper Control": * there should be 2 pixels of space between the stepper control (AKA * IncDecButton, AKA "little arrows") and the text field it modifies. + * + * Ttk expects the up and down arrows to be distinct elements but HIToolbox + * draws them as one widget with two different pressed states. We work + * around this by defining them as separate elements in the layout, but + * making each one have a drawing method which also draws the other one. + * The down button does no drawing when not pressed, and when pressed draws + * the entire IncDecButton in its "pressed down" state. The up button draws + * the entire IncDecButton when not pressed and when pressed draws the + * IncDecButton in its "pressed up" state. */ -static Ttk_Padding SpinbuttonMargins = {2,0,2,0}; -static void SpinButtonElementSize( +static Ttk_Padding SpinbuttonMargins = {0, 0, 2, 0}; +static void SpinButtonUpElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) { @@ -1336,20 +1345,24 @@ static void SpinButtonElementSize( ChkErr(GetThemeMetric, kThemeMetricLittleArrowsWidth, &s); *minWidth = s + Ttk_PaddingWidth(SpinbuttonMargins); ChkErr(GetThemeMetric, kThemeMetricLittleArrowsHeight, &s); - *minHeight = s + Ttk_PaddingHeight(SpinbuttonMargins); + *minHeight = (s + Ttk_PaddingHeight(SpinbuttonMargins)) / 2; } -static void SpinButtonElementDraw( +static void SpinButtonUpElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) { CGRect bounds = BoxToRect(d, Ttk_PadBox(b, SpinbuttonMargins)); - /* @@@ can't currently distinguish PressedUp (== Pressed) from PressedDown; - * ignore this bit for now [see #2219588] - */ + int infoState; + bounds.size.height *= 2; + if (state & TTK_STATE_PRESSED) { + infoState = kThemeStatePressedUp; + } else { + infoState = Ttk_StateTableLookup(ThemeStateTable, state); + } const HIThemeButtonDrawInfo info = { .version = 0, - .state = Ttk_StateTableLookup(ThemeStateTable, state & ~TTK_STATE_PRESSED), + .state = infoState, .kind = kThemeIncDecButton, .value = Ttk_StateTableLookup(ButtonValueTable, state), .adornment = kThemeAdornmentNone, @@ -1360,14 +1373,59 @@ static void SpinButtonElementDraw( END_DRAWING } -static Ttk_ElementSpec SpinButtonElementSpec = { +static Ttk_ElementSpec SpinButtonUpElementSpec = { TK_STYLE_VERSION_2, sizeof(NullElement), TtkNullElementOptions, - SpinButtonElementSize, - SpinButtonElementDraw + SpinButtonUpElementSize, + SpinButtonUpElementDraw }; +static void SpinButtonDownElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) +{ + SInt32 s; + + ChkErr(GetThemeMetric, kThemeMetricLittleArrowsWidth, &s); + *minWidth = s + Ttk_PaddingWidth(SpinbuttonMargins); + ChkErr(GetThemeMetric, kThemeMetricLittleArrowsHeight, &s); + *minHeight = (s + Ttk_PaddingHeight(SpinbuttonMargins)) / 2; +} + +static void SpinButtonDownElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, Ttk_State state) +{ + CGRect bounds = BoxToRect(d, Ttk_PadBox(b, SpinbuttonMargins)); + int infoState = 0; + bounds.origin.y -= bounds.size.height; + bounds.size.height *= 2; + if (state & TTK_STATE_PRESSED) { + infoState = kThemeStatePressedDown; + } else { + return; + } + const HIThemeButtonDrawInfo info = { + .version = 0, + .state = infoState, + .kind = kThemeIncDecButton, + .value = Ttk_StateTableLookup(ButtonValueTable, state), + .adornment = kThemeAdornmentNone, + }; + + BEGIN_DRAWING(d) + ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); + END_DRAWING +} + +static Ttk_ElementSpec SpinButtonDownElementSpec = { + TK_STYLE_VERSION_2, + sizeof(NullElement), + TtkNullElementOptions, + SpinButtonDownElementSize, + SpinButtonDownElementDraw +}; /*---------------------------------------------------------------------- * +++ DrawThemeTrack-based elements -- @@ -2246,10 +2304,13 @@ TTK_LAYOUT("Tab", TTK_GROUP("Notebook.padding", TTK_EXPAND|TTK_FILL_BOTH, TTK_NODE("Notebook.label", TTK_EXPAND|TTK_FILL_BOTH)))) -TTK_LAYOUT("TSpinbox", - TTK_NODE("Spinbox.spinbutton", TTK_PACK_RIGHT|TTK_STICK_E) - TTK_GROUP("Spinbox.field", TTK_EXPAND|TTK_FILL_X, - TTK_NODE("Spinbox.textarea", TTK_EXPAND|TTK_FILL_X))) +/* Spinbox -- buttons 2px to the right of the field. */ + TTK_LAYOUT("TSpinbox", + TTK_GROUP("Spinbox.buttons", TTK_PACK_RIGHT, + TTK_NODE("Spinbox.uparrow", TTK_PACK_TOP|TTK_STICK_E) + TTK_NODE("Spinbox.downarrow", TTK_PACK_BOTTOM|TTK_STICK_E)) + TTK_GROUP("Spinbox.field", TTK_EXPAND|TTK_FILL_X, + TTK_NODE("Spinbox.textarea", TTK_EXPAND|TTK_FILL_X))) /* Progress bars -- track only */ TTK_LAYOUT("TProgressbar", @@ -2321,8 +2382,10 @@ static int AquaTheme_Init(Tcl_Interp *interp) &ButtonElementSpec, &BevelButtonParams); Ttk_RegisterElementSpec(themePtr, "Menubutton.button", &ButtonElementSpec, &PopupButtonParams); - Ttk_RegisterElementSpec(themePtr, "Spinbox.spinbutton", - &SpinButtonElementSpec, 0); + Ttk_RegisterElementSpec(themePtr, "Spinbox.uparrow", + &SpinButtonUpElementSpec, 0); + Ttk_RegisterElementSpec(themePtr, "Spinbox.downarrow", + &SpinButtonDownElementSpec, 0); Ttk_RegisterElementSpec(themePtr, "Combobox.button", &ComboboxElementSpec, 0); Ttk_RegisterElementSpec(themePtr, "Treeitem.indicator", -- cgit v0.12 From 56b770981967bb3db527fb6faa775e058bb4c824 Mon Sep 17 00:00:00 2001 From: culler Date: Fri, 29 Mar 2019 14:46:09 +0000 Subject: Make the ttk::spinbutton text field work correctly in Dark Mode. --- library/ttk/aquaTheme.tcl | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/library/ttk/aquaTheme.tcl b/library/ttk/aquaTheme.tcl index 5e04fc6..9168deb 100644 --- a/library/ttk/aquaTheme.tcl +++ b/library/ttk/aquaTheme.tcl @@ -89,6 +89,25 @@ namespace eval ttk::theme::aqua { focus systemSelectedTextBackgroundColor } + # Spinbox + ttk::style configure TSpinbox \ + -foreground systemTextColor \ + -background systemTransparent \ + -selectforeground systemSelectedTextColor \ + -selectbackground systemSelectedTextBackgroundColor + ttk::style map TSpinbox \ + -foreground { + disabled systemDisabledControlTextColor + } \ + -selectforeground { + !active systemTextColor + } \ + -selectbackground { + !active systemTextBackgroundColor + !focus systemTextBackgroundColor + focus systemSelectedTextBackgroundColor + } + # Treeview: ttk::style configure Heading -font TkHeadingFont -foreground black ttk::style configure Treeview -rowheight 18 \ -- cgit v0.12 From 700dfd499cdb162bf67964d0db4a4ed6fae93d43 Mon Sep 17 00:00:00 2001 From: culler Date: Fri, 29 Mar 2019 17:24:33 +0000 Subject: Added a drawing procedure for Spinboxes in Dark Mode. --- library/ttk/aquaTheme.tcl | 2 +- macosx/ttkMacOSXTheme.c | 93 ++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 80 insertions(+), 15 deletions(-) diff --git a/library/ttk/aquaTheme.tcl b/library/ttk/aquaTheme.tcl index 9168deb..646fb83 100644 --- a/library/ttk/aquaTheme.tcl +++ b/library/ttk/aquaTheme.tcl @@ -92,7 +92,7 @@ namespace eval ttk::theme::aqua { # Spinbox ttk::style configure TSpinbox \ -foreground systemTextColor \ - -background systemTransparent \ + -background systemTextBackgroundColor \ -selectforeground systemSelectedTextColor \ -selectbackground systemSelectedTextBackgroundColor ttk::style map TSpinbox \ diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index 38ba621..b2a8f2f 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -375,37 +375,39 @@ static void HighlightButtonBorder( static void DrawUpDownArrows( + CGContextRef context, CGRect bounds, - CGContextRef context) + CGFloat inset, + CGFloat size) { CGFloat x, y; CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0); CGContextSetLineWidth(context, 1.5); - x = bounds.origin.x + 5; + x = bounds.origin.x + inset; y = bounds.origin.y + trunc(bounds.size.height/2); CGContextBeginPath(context); - CGPoint bottomArrow[3] = {{x, y+2}, {x+3.5, y+5.5}, {x+7, y+2}}; + CGPoint bottomArrow[3] = {{x, y+2}, {x+size/2, y+2+size/2}, {x+size, y+2}}; CGContextAddLines(context, bottomArrow, 3); - CGPoint topArrow[3] = {{x, y-2}, {x+3.5, y-5.5}, {x+7, y-2}}; + CGPoint topArrow[3] = {{x, y-2}, {x+size/2, y-2-size/2}, {x+size, y-2}}; CGContextAddLines(context, topArrow, 3); CGContextStrokePath(context); - CGContextRestoreGState(context); } static void DrawDownArrow( + CGContextRef context, CGRect bounds, - CGContextRef context) + CGFloat inset, + CGFloat size) { CGFloat x, y; CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0); CGContextSetLineWidth(context, 1.5); - x = bounds.origin.x + 5; + x = bounds.origin.x + inset; y = bounds.origin.y + trunc(bounds.size.height/2); CGContextBeginPath(context); - CGPoint bottomArrow[3] = {{x, y-3}, {x+3.5, y+3}, {x+7, y-3}}; + CGPoint bottomArrow[3] = {{x, y-size/2}, {x+size/2, y+size/2}, {x+size, y-size/2}}; CGContextAddLines(context, bottomArrow, 3); CGContextStrokePath(context); - CGContextRestoreGState(context); } /* @@ -474,9 +476,9 @@ static void DrawDarkButton( darkSelectedGradient, 2); } if (kind == kThemePopupButton) { - DrawUpDownArrows(arrowBounds, context); + DrawUpDownArrows(context, arrowBounds, 5, 7); } else { - DrawDownArrow(arrowBounds, context); + DrawDownArrow(context, arrowBounds, 5, 7); } } @@ -484,6 +486,62 @@ static void DrawDarkButton( } /* + * DrawDarkIncDecButton -- + * + * This is a standalone drawing procedure which draws an IncDecButton + * (as used in a Spinbox) in the Dark Mode style. + */ + +static void DrawDarkIncDecButton( + CGRect bounds, + ThemeDrawState drawState, + Ttk_State state, + CGContextRef context) +{ + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + NSColor *faceColor; + + bounds = CGRectInset(bounds, 0, -1); + CGContextClipToRect(context, bounds); + FillButtonBackground(context, bounds, 6); + + /* + * Fill the button face with the appropriate color. + */ + + bounds = CGRectInset(bounds, 1, 1); + if (state & TTK_STATE_DISABLED) { + faceColor = [NSColor colorWithColorSpace: deviceRGB + components: darkDisabledButtonFace + count: 4]; + } else { + faceColor = [NSColor colorWithColorSpace: deviceRGB + components: darkButtonFace + count: 4]; + } + SolidFillRoundedRectangle(context, bounds, 4, faceColor); + + /* + * If pressed, paint the appropriate half blue. + */ + + if (state & TTK_STATE_PRESSED) { + CGRect clip = bounds; + clip.size.height /= 2; + CGContextSaveGState(context); + if (drawState == kThemeStatePressedDown) { + clip.origin.y += clip.size.height; + } + CGContextClipToRect(context, clip); + GradientFillRoundedRectangle(context, bounds, 5, + darkSelectedGradient, 2); + CGContextRestoreGState(context); + } + DrawUpDownArrows(context, bounds, 3, 5); + HighlightButtonBorder(context, bounds); +} + +/* * DrawDarkBevelButton -- * * This is a standalone drawing procedure which draws @@ -1367,9 +1425,12 @@ static void SpinButtonUpElementDraw( .value = Ttk_StateTableLookup(ButtonValueTable, state), .adornment = kThemeAdornmentNone, }; - BEGIN_DRAWING(d) - ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); + if (TkMacOSXInDarkMode(tkwin)) { + DrawDarkIncDecButton(bounds, infoState, state, dc.context); + } else { + ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); + } END_DRAWING } @@ -1415,7 +1476,11 @@ static void SpinButtonDownElementDraw( }; BEGIN_DRAWING(d) - ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); + if (TkMacOSXInDarkMode(tkwin)) { + DrawDarkIncDecButton(bounds, infoState, state, dc.context); + } else { + ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); + } END_DRAWING } -- cgit v0.12 From 8c5d63d069fe7f1ddd8bca295e5b07391894fe5d Mon Sep 17 00:00:00 2001 From: culler Date: Fri, 29 Mar 2019 17:37:53 +0000 Subject: Added a comment. --- macosx/ttkMacOSXTheme.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index b2a8f2f..f52b963 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -1390,7 +1390,11 @@ static Ttk_ElementSpec ComboboxElementSpec = { * The down button does no drawing when not pressed, and when pressed draws * the entire IncDecButton in its "pressed down" state. The up button draws * the entire IncDecButton when not pressed and when pressed draws the - * IncDecButton in its "pressed up" state. + * IncDecButton in its "pressed up" state. NOTE: This means that when the + * down button is pressed the IncDecButton will be drawn twice, first + * in unpressed state by the up arrow and then in "pressed down" state by + * the down button. The drawing must be done in that order. So the up + * button must be listed first in the layout. */ static Ttk_Padding SpinbuttonMargins = {0, 0, 2, 0}; -- cgit v0.12 From a88925e14d0096bf75e3338b939fdf6ec49c72b5 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 29 Mar 2019 19:57:06 +0000 Subject: Add calls to TkpInitKeymapInfo() during initialization. Taken from extended bind patch. --- doc/bind.n | 4 ++-- macosx/tkMacOSXXStubs.c | 6 ++++++ unix/tkUnixEvent.c | 6 ++++++ win/tkWinX.c | 5 +++++ 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/doc/bind.n b/doc/bind.n index c260bce..2191369 100644 --- a/doc/bind.n +++ b/doc/bind.n @@ -638,11 +638,11 @@ of events matched) is more specific than a shorter sequence; .IP (c) if the modifiers specified in one pattern are a subset of the modifiers in another pattern, then the pattern with more modifiers -is more specific. +is more specific; .IP (d) a virtual event whose physical pattern matches the sequence is less specific than the same physical pattern that is not associated with a -virtual event. +virtual event; .IP (e) given a sequence that matches two or more virtual events, one of the virtual events will be chosen, but the order is undefined. diff --git a/macosx/tkMacOSXXStubs.c b/macosx/tkMacOSXXStubs.c index cc98e84..448736e 100644 --- a/macosx/tkMacOSXXStubs.c +++ b/macosx/tkMacOSXXStubs.c @@ -225,6 +225,12 @@ TkpOpenDisplay( bzero(gMacDisplay, sizeof(TkDisplay)); gMacDisplay->display = display; [pool drain]; + + /* + * Key map info must be available immediately, because of "send event". + */ + TkpInitKeymapInfo(gMacDisplay); + return gMacDisplay; } diff --git a/unix/tkUnixEvent.c b/unix/tkUnixEvent.c index 111d430..cde3791 100644 --- a/unix/tkUnixEvent.c +++ b/unix/tkUnixEvent.c @@ -186,6 +186,12 @@ TkpOpenDisplay( #endif Tcl_CreateFileHandler(ConnectionNumber(display), TCL_READABLE, DisplayFileProc, dispPtr); + + /* + * Key map info must be available immediately, because of "send event". + */ + TkpInitKeymapInfo(dispPtr); + return dispPtr; } diff --git a/win/tkWinX.c b/win/tkWinX.c index ec1fef3..3737345 100644 --- a/win/tkWinX.c +++ b/win/tkWinX.c @@ -613,6 +613,11 @@ TkpOpenDisplay( tsdPtr->wheelTickPrev = GetTickCount(); tsdPtr->wheelAcc = 0; + /* + * Key map info must be available immediately, because of "send event". + */ + TkpInitKeymapInfo(tsdPtr->winDisplay); + return tsdPtr->winDisplay; } -- cgit v0.12 From 013e787609043566d56a742e5fd5c12a95128e6d Mon Sep 17 00:00:00 2001 From: culler Date: Fri, 29 Mar 2019 21:38:08 +0000 Subject: Fix bug [1001070]: Aqua labels do not display highlight background. --- macosx/tkMacOSXButton.c | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/macosx/tkMacOSXButton.c b/macosx/tkMacOSXButton.c index 484dcf2..705b214 100644 --- a/macosx/tkMacOSXButton.c +++ b/macosx/tkMacOSXButton.c @@ -67,9 +67,28 @@ typedef struct { } MacButton; /* - * Forward declarations for procedures defined later in this file: + * When drawing highlight borders for Buttons or Labels, the function + * Tk_Draw3DRectangle is called with SOLID relief. This in turn calls the + * stubs Tk_3DVerticalBevel and Tk_3DHorizontalBevel. The Mac port does not + * define these stubs itself, but instead uses the ones defined in tkUnix3d.c, + * which gets compiled and linked into the Mac Tk library. One of the + * arguments to these stubs is a pointer to a UnixBorder struct, which is an + * extension of TkBorder containing one additional field which is a graphics + * context to be used when drawing the bevels. The UnixBorder is declared in + * the file tkUnix3d.c and not in any header file. We include the declaration + * here, so that we can draw highlight borders. But this declaration must be + * kept in sync with the one in tkUnix3d.c. */ +#include "tk3d.h" +typedef struct { + TkBorder info; + GC solidGC; /* Used to draw solid relief. */ +} UnixBorder; + +/* + * Forward declarations for procedures defined later in this file: + */ static void ButtonBackgroundDrawCB (const HIRect *btnbounds, MacButton *ptr, SInt16 depth, Boolean isColorDev); @@ -227,8 +246,17 @@ TkpDisplayButton( /* Draw highlight border, if needed. */ if (needhighlight) { - if ((butPtr->flags & GOT_FOCUS)) { - Tk_Draw3DRectangle(tkwin, pixmap, butPtr->normalBorder, 0, 0, + if ((butPtr->flags & GOT_FOCUS || butPtr->type == TYPE_LABEL)) { + GC gc; + UnixBorder border; + if (butPtr->highlightColorPtr) { + gc = Tk_GCForColor(butPtr->highlightColorPtr, pixmap); + } else { + gc = Tk_GCForColor(Tk_3DBorderColor(butPtr->highlightBorder), + pixmap); + } + border.solidGC = gc; + Tk_Draw3DRectangle(tkwin, pixmap, &border, 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), butPtr->highlightWidth, TK_RELIEF_SOLID); } -- cgit v0.12 From f3cda13076d3cb843499495810340da272036737 Mon Sep 17 00:00:00 2001 From: fvogel Date: Fri, 29 Mar 2019 22:05:26 +0000 Subject: Cross-reference UnixBorder structs in different files. --- unix/tkUnix3d.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/unix/tkUnix3d.c b/unix/tkUnix3d.c index 2969de1..3dbd45e 100644 --- a/unix/tkUnix3d.c +++ b/unix/tkUnix3d.c @@ -19,7 +19,8 @@ /* * This structure is used to keep track of the extra colors used by Unix 3D - * borders. + * borders. Warning: The structure of the same name in tkMacOSXButton.c must + * be kept in sync with this one. */ typedef struct { -- cgit v0.12 From ab7aa7d7f951b4cc5821e902bb952901b5b9bf9c Mon Sep 17 00:00:00 2001 From: culler Date: Sat, 30 Mar 2019 14:26:46 +0000 Subject: Keep It Safe and Simple. Just draw the border. Do not use tkUnix3d.c. Also update the manual to document this behavior. --- doc/label.n | 5 +++++ macosx/tkMacOSXButton.c | 41 ++++++++-------------------------------- macosx/tkMacOSXDraw.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++ macosx/tkMacOSXPrivate.h | 2 ++ unix/tkUnix3d.c | 3 +-- 5 files changed, 65 insertions(+), 35 deletions(-) diff --git a/doc/label.n b/doc/label.n index f2ba88c..e4b4749 100644 --- a/doc/label.n +++ b/doc/label.n @@ -68,6 +68,11 @@ one of the characters may optionally be underlined using the \fB\-underline\fR option. The label can be manipulated in a few simple ways, such as changing its relief or text, using the commands described below. +.PP +With respect to the \fB-highlightbackground\fR option, a label is +considered to always have focus, meaning that the highlight border +will always be drawn, provided that \fB-highllightthickness\fR is +positive. .SH "WIDGET COMMAND" .PP The \fBlabel\fR command creates a new Tcl command whose diff --git a/macosx/tkMacOSXButton.c b/macosx/tkMacOSXButton.c index 705b214..23596d4 100644 --- a/macosx/tkMacOSXButton.c +++ b/macosx/tkMacOSXButton.c @@ -67,26 +67,6 @@ typedef struct { } MacButton; /* - * When drawing highlight borders for Buttons or Labels, the function - * Tk_Draw3DRectangle is called with SOLID relief. This in turn calls the - * stubs Tk_3DVerticalBevel and Tk_3DHorizontalBevel. The Mac port does not - * define these stubs itself, but instead uses the ones defined in tkUnix3d.c, - * which gets compiled and linked into the Mac Tk library. One of the - * arguments to these stubs is a pointer to a UnixBorder struct, which is an - * extension of TkBorder containing one additional field which is a graphics - * context to be used when drawing the bevels. The UnixBorder is declared in - * the file tkUnix3d.c and not in any header file. We include the declaration - * here, so that we can draw highlight borders. But this declaration must be - * kept in sync with the one in tkUnix3d.c. - */ - -#include "tk3d.h" -typedef struct { - TkBorder info; - GC solidGC; /* Used to draw solid relief. */ -} UnixBorder; - -/* * Forward declarations for procedures defined later in this file: */ @@ -208,6 +188,12 @@ TkpDisplayButton( return; } pixmap = (Pixmap) Tk_WindowId(tkwin); + + /* + * Set up clipping region. Make sure the we are using the port + * for this button, or we will set the wrong window's clip. + */ + TkMacOSXSetUpClippingRgn(Tk_WindowId(tkwin)); if (TkMacOSXComputeButtonDrawParams(butPtr, dpPtr) ) { @@ -215,13 +201,6 @@ TkpDisplayButton( } else { macButtonPtr->useTkText = 1; } - - - /* - * Set up clipping region. Make sure the we are using the port - * for this button, or we will set the wrong window's clip. - */ - if (macButtonPtr->useTkText) { if (butPtr->type == TYPE_BUTTON) { Tk_Fill3DRectangle(tkwin, pixmap, butPtr->highlightBorder, 0, 0, @@ -248,17 +227,13 @@ TkpDisplayButton( if (needhighlight) { if ((butPtr->flags & GOT_FOCUS || butPtr->type == TYPE_LABEL)) { GC gc; - UnixBorder border; if (butPtr->highlightColorPtr) { - gc = Tk_GCForColor(butPtr->highlightColorPtr, pixmap); + gc = Tk_GCForColor(butPtr->highlightColorPtr, pixmap); } else { gc = Tk_GCForColor(Tk_3DBorderColor(butPtr->highlightBorder), pixmap); } - border.solidGC = gc; - Tk_Draw3DRectangle(tkwin, pixmap, &border, 0, 0, - Tk_Width(tkwin), Tk_Height(tkwin), - butPtr->highlightWidth, TK_RELIEF_SOLID); + TkMacOSXDrawSolidBorder(tkwin, gc, 0, butPtr->highlightWidth); } } } diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c index faad137..598b581 100644 --- a/macosx/tkMacOSXDraw.c +++ b/macosx/tkMacOSXDraw.c @@ -1027,6 +1027,55 @@ XFillRectangles( /* *---------------------------------------------------------------------- * + * TkMacOSXDrawSolidBorder -- + * + * Draws a border rectangle of specified thickness inside the bounding + * rectangle of a Tk Window. The border rectangle can be inset within the + * bounding rectangle. For a highlight border the inset should be 0, but + * for a solid border around the actual window the inset should equal the + * thickness of the highlight border. The color of the border rectangle + * is the foreground color of the graphics context passed to the function. + * + * Results: + * None. + * + * Side effects: + * Draws a rectangular border inside the bounding rectangle of a window. + * + *---------------------------------------------------------------------- + */ + +MODULE_SCOPE void +TkMacOSXDrawSolidBorder( + Tk_Window tkwin, + GC gc, + int inset, + int thickness) +{ + Drawable d = Tk_WindowId(tkwin); + MacDrawable *macWin = (MacDrawable *) d; + TkMacOSXDrawingContext dc; + CGRect outerRect, innerRect; + + if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) { + return; + } + if (dc.context) { + outerRect = CGRectMake(Tk_X(tkwin), Tk_Y(tkwin), + Tk_Width(tkwin), Tk_Height(tkwin)); + outerRect = CGRectInset(outerRect, inset, inset); + innerRect = CGRectInset(outerRect, thickness, thickness); + CGContextBeginPath(dc.context); + CGContextAddRect(dc.context, outerRect); + CGContextAddRect(dc.context, innerRect); + CGContextEOFillPath(dc.context); + } + TkMacOSXRestoreDrawingContext(&dc); +} + +/* + *---------------------------------------------------------------------- + * * XDrawArc -- * * Draw an arc. diff --git a/macosx/tkMacOSXPrivate.h b/macosx/tkMacOSXPrivate.h index 105317d..668562a 100644 --- a/macosx/tkMacOSXPrivate.h +++ b/macosx/tkMacOSXPrivate.h @@ -233,6 +233,8 @@ MODULE_SCOPE int TkMacOSXStandardAboutPanelObjCmd(ClientData clientData, MODULE_SCOPE int TkMacOSXIconBitmapObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); +MODULE_SCOPE void TkMacOSXDrawSolidBorder(Tk_Window tkwin, GC gc, + int inset, int thickness); #pragma mark Private Objective-C Classes diff --git a/unix/tkUnix3d.c b/unix/tkUnix3d.c index 3dbd45e..2969de1 100644 --- a/unix/tkUnix3d.c +++ b/unix/tkUnix3d.c @@ -19,8 +19,7 @@ /* * This structure is used to keep track of the extra colors used by Unix 3D - * borders. Warning: The structure of the same name in tkMacOSXButton.c must - * be kept in sync with this one. + * borders. */ typedef struct { -- cgit v0.12 From 49ca784286da252d1760ebf60e203489f7c8f777 Mon Sep 17 00:00:00 2001 From: fvogel Date: Sat, 30 Mar 2019 17:00:39 +0000 Subject: Fix [da3914eba2]: 'identify element' on ttk::treeview does not identify images added via 'insert ... -image ...' --- generic/ttk/ttkTreeview.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/generic/ttk/ttkTreeview.c b/generic/ttk/ttkTreeview.c index b6616e1..68a9b6d 100644 --- a/generic/ttk/ttkTreeview.c +++ b/generic/ttk/ttkTreeview.c @@ -2233,7 +2233,9 @@ static int TreeviewHorribleIdentify( Ttk_Element element; BoundingBox(tv, item, NULL, &itemBox); - PrepareItem(tv, item, &displayItem); /*@@@ FIX: -text, etc*/ + PrepareItem(tv, item, &displayItem); + if (item->textObj) { displayItem.textObj = item->textObj; } + if (item->imageObj) { displayItem.imageObj = item->imageObj; } Ttk_RebindSublayout(layout, &displayItem); Ttk_PlaceLayout(layout, ItemState(tv,item), itemBox); element = Ttk_IdentifyElement(layout, x, y); @@ -2345,7 +2347,9 @@ static int TreeviewIdentifyCommand( return TCL_OK; } - PrepareItem(tv, item, &displayItem); /*@@@ FIX: fill in -text,etc */ + PrepareItem(tv, item, &displayItem); + if (item->textObj) { displayItem.textObj = item->textObj; } + if (item->imageObj) { displayItem.imageObj = item->imageObj; } Ttk_RebindSublayout(layout, &displayItem); Ttk_PlaceLayout(layout, ItemState(tv,item), bbox); element = Ttk_IdentifyElement(layout, x, y); -- cgit v0.12 From 761cdb86562088f0dd44c45d314dce97acd38a79 Mon Sep 17 00:00:00 2001 From: culler Date: Sat, 30 Mar 2019 17:29:31 +0000 Subject: Correctly distinguish between -highlightcolor and -highlightbackground and revert unnecessary changes to the label manual. --- doc/label.n | 5 ----- macosx/tkMacOSXButton.c | 15 +++++++-------- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/doc/label.n b/doc/label.n index e4b4749..f2ba88c 100644 --- a/doc/label.n +++ b/doc/label.n @@ -68,11 +68,6 @@ one of the characters may optionally be underlined using the \fB\-underline\fR option. The label can be manipulated in a few simple ways, such as changing its relief or text, using the commands described below. -.PP -With respect to the \fB-highlightbackground\fR option, a label is -considered to always have focus, meaning that the highlight border -will always be drawn, provided that \fB-highllightthickness\fR is -positive. .SH "WIDGET COMMAND" .PP The \fBlabel\fR command creates a new Tcl command whose diff --git a/macosx/tkMacOSXButton.c b/macosx/tkMacOSXButton.c index 23596d4..8ccfdb3 100644 --- a/macosx/tkMacOSXButton.c +++ b/macosx/tkMacOSXButton.c @@ -225,14 +225,13 @@ TkpDisplayButton( /* Draw highlight border, if needed. */ if (needhighlight) { - if ((butPtr->flags & GOT_FOCUS || butPtr->type == TYPE_LABEL)) { - GC gc; - if (butPtr->highlightColorPtr) { - gc = Tk_GCForColor(butPtr->highlightColorPtr, pixmap); - } else { - gc = Tk_GCForColor(Tk_3DBorderColor(butPtr->highlightBorder), - pixmap); - } + GC gc = NULL; + if ((butPtr->flags & GOT_FOCUS) && butPtr->highlightColorPtr) { + gc = Tk_GCForColor(butPtr->highlightColorPtr, pixmap); + } else if (butPtr->type == TYPE_LABEL) { + gc = Tk_GCForColor(Tk_3DBorderColor(butPtr->highlightBorder), pixmap); + } + if (gc) { TkMacOSXDrawSolidBorder(tkwin, gc, 0, butPtr->highlightWidth); } } -- cgit v0.12 From 4773fcfe6b551fe3907dec1f63dcbc69af4777a5 Mon Sep 17 00:00:00 2001 From: culler Date: Sat, 30 Mar 2019 18:46:43 +0000 Subject: Added missing map for the Treeview background in selected state. --- library/ttk/aquaTheme.tcl | 8 ++++++-- macosx/ttkMacOSXTheme.c | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/library/ttk/aquaTheme.tcl b/library/ttk/aquaTheme.tcl index 646fb83..1e7745a 100644 --- a/library/ttk/aquaTheme.tcl +++ b/library/ttk/aquaTheme.tcl @@ -111,9 +111,13 @@ namespace eval ttk::theme::aqua { # Treeview: ttk::style configure Heading -font TkHeadingFont -foreground black ttk::style configure Treeview -rowheight 18 \ - -fieldbackground systemTextBackgroundColor \ -background systemTextBackgroundColor \ - -foreground systemTextColor + -foreground systemTextColor \ + -fieldbackground systemTextBackgroundColor + ttk::style map Treeview \ + -background { + selected systemSelectedTextBackgroundColor + } # Enable animation for ttk::progressbar widget: ttk::style configure TProgressbar -period 100 -maxphase 255 diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index f52b963..e481f64 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -2389,7 +2389,7 @@ TTK_LAYOUT("TProgressbar", TTK_LAYOUT("Treeview", TTK_GROUP("Treeview.field", TTK_FILL_BOTH, TTK_GROUP("Treeview.padding", TTK_FILL_BOTH, - TTK_NODE("Treeview.treearea", TTK_FILL_BOTH)))) + TTK_NODE("Treeview.treearea", TTK_FILL_BOTH)))) /* Tree heading -- no border, fixed height */ TTK_LAYOUT("Heading", -- cgit v0.12 From ade11f80ecb09290cd8272d7d58f55dac2e508de Mon Sep 17 00:00:00 2001 From: culler Date: Sat, 30 Mar 2019 19:40:20 +0000 Subject: Remove extraneous CGContextSaveGState with no matching CGContextRestoreGState. --- macosx/ttkMacOSXTheme.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index e481f64..c68f7d3 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -465,7 +465,6 @@ static void DrawDarkButton( CGRect arrowBounds = bounds; arrowBounds.size.width = 16; arrowBounds.origin.x += bounds.size.width - 16; - CGContextSaveGState(context); /* * If the toplevel is front, paint the button blue. @@ -956,12 +955,12 @@ static void ButtonElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) { - BEGIN_DRAWING(d) ThemeButtonParams *params = clientData; CGRect bounds = BoxToRect(d, b); HIThemeButtonDrawInfo info = computeButtonDrawInfo(params, state, tkwin); bounds = NormalizeButtonBounds(params->heightMetric, bounds); - + + BEGIN_DRAWING(d) if (TkMacOSXInDarkMode(tkwin)) { #if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 switch (info.kind) { -- cgit v0.12 From 8139b018a833b0ef8c1263ff3e6b90a45fcbaf99 Mon Sep 17 00:00:00 2001 From: fvogel Date: Sun, 31 Mar 2019 11:01:32 +0000 Subject: Remove an unused variable, squelching a compiler warning. --- macosx/tkMacOSXDraw.c | 1 - 1 file changed, 1 deletion(-) diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c index 598b581..013f654 100644 --- a/macosx/tkMacOSXDraw.c +++ b/macosx/tkMacOSXDraw.c @@ -1053,7 +1053,6 @@ TkMacOSXDrawSolidBorder( int thickness) { Drawable d = Tk_WindowId(tkwin); - MacDrawable *macWin = (MacDrawable *) d; TkMacOSXDrawingContext dc; CGRect outerRect, innerRect; -- cgit v0.12 From d84fefbe9128b55dfa168232174559c52e11011e Mon Sep 17 00:00:00 2001 From: fvogel Date: Sun, 31 Mar 2019 12:52:10 +0000 Subject: Make labels, checkbuttons and radiobuttons honor -highlightbackground and -highlightcolor options on Windows. --- win/tkWinButton.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/win/tkWinButton.c b/win/tkWinButton.c index ee0ce82..f101f89 100644 --- a/win/tkWinButton.c +++ b/win/tkWinButton.c @@ -410,7 +410,7 @@ TkpDisplayButton( ? butPtr->highlightWidth : 0); offset = 1; } else { - defaultWidth = 0; + defaultWidth = butPtr->highlightWidth;; if ((butPtr->type >= TYPE_CHECK_BUTTON) && !butPtr->indicatorOn) { offset = 1; } else { @@ -759,17 +759,23 @@ TkpDisplayButton( butPtr->borderWidth, relief); } if (defaultWidth != 0) { + int highlightColor = + (int) Tk_3DBorderColor(butPtr->highlightBorder)->pixel; + dc = TkWinGetDrawableDC(butPtr->display, pixmap, &state); + if (butPtr->flags & GOT_FOCUS) { + highlightColor = (int) butPtr->highlightColorPtr->pixel; + } TkWinFillRect(dc, 0, 0, Tk_Width(tkwin), defaultWidth, - (int) butPtr->highlightColorPtr->pixel); + highlightColor); TkWinFillRect(dc, 0, 0, defaultWidth, Tk_Height(tkwin), - (int) butPtr->highlightColorPtr->pixel); + highlightColor); TkWinFillRect(dc, 0, Tk_Height(tkwin) - defaultWidth, Tk_Width(tkwin), defaultWidth, - (int) butPtr->highlightColorPtr->pixel); + highlightColor); TkWinFillRect(dc, Tk_Width(tkwin) - defaultWidth, 0, defaultWidth, Tk_Height(tkwin), - (int) butPtr->highlightColorPtr->pixel); + highlightColor); TkWinReleaseDrawableDC(pixmap, dc, &state); } -- cgit v0.12 From 8cf4a9bdbf03c6a9b09e09554c470e7f2e13abdf Mon Sep 17 00:00:00 2001 From: fvogel Date: Sun, 31 Mar 2019 14:34:16 +0000 Subject: Restore behavior of checkbuttons and radiobuttons on Windows. They again do not take -highlightbackground into account, in an attempt to follow platform specific conventions. The code now only changes this for labels. --- win/tkWinButton.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/win/tkWinButton.c b/win/tkWinButton.c index f101f89..6024b02 100644 --- a/win/tkWinButton.c +++ b/win/tkWinButton.c @@ -405,12 +405,15 @@ TkpDisplayButton( * Compute width of default ring and offset for pushed buttons. */ - if (butPtr->type == TYPE_BUTTON) { + if (butPtr->type == TYPE_LABEL) { + defaultWidth = butPtr->highlightWidth; + offset = 0; + } else if (butPtr->type == TYPE_BUTTON) { defaultWidth = ((butPtr->defaultState == DEFAULT_ACTIVE) ? butPtr->highlightWidth : 0); offset = 1; } else { - defaultWidth = butPtr->highlightWidth;; + defaultWidth = 0; if ((butPtr->type >= TYPE_CHECK_BUTTON) && !butPtr->indicatorOn) { offset = 1; } else { -- cgit v0.12 From a46a024f97912319754e4dae155b18f796b56b0d Mon Sep 17 00:00:00 2001 From: fvogel Date: Sun, 31 Mar 2019 14:43:09 +0000 Subject: *Really* don't change the behavior for *buttons, even with they have -default active --- win/tkWinButton.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/win/tkWinButton.c b/win/tkWinButton.c index 6024b02..d03a391 100644 --- a/win/tkWinButton.c +++ b/win/tkWinButton.c @@ -762,11 +762,12 @@ TkpDisplayButton( butPtr->borderWidth, relief); } if (defaultWidth != 0) { - int highlightColor = - (int) Tk_3DBorderColor(butPtr->highlightBorder)->pixel; + int highlightColor; dc = TkWinGetDrawableDC(butPtr->display, pixmap, &state); - if (butPtr->flags & GOT_FOCUS) { + if (butPtr->type == TYPE_LABEL) { + highlightColor = (int) Tk_3DBorderColor(butPtr->highlightBorder)->pixel; + } else { highlightColor = (int) butPtr->highlightColorPtr->pixel; } TkWinFillRect(dc, 0, 0, Tk_Width(tkwin), defaultWidth, -- cgit v0.12 From 1203c84117410cd64aba7bee09446665f14792f9 Mon Sep 17 00:00:00 2001 From: culler Date: Sun, 31 Mar 2019 16:33:50 +0000 Subject: Make menubuttons honor the -highlightcolor option on macOS. --- macosx/tkMacOSXMenubutton.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/macosx/tkMacOSXMenubutton.c b/macosx/tkMacOSXMenubutton.c index b2b4b76..5b39e19 100644 --- a/macosx/tkMacOSXMenubutton.c +++ b/macosx/tkMacOSXMenubutton.c @@ -190,11 +190,10 @@ TkpDisplayMenuButton( /* Draw highlight border, if needed. */ if (butPtr->highlightWidth < 3) { - if ((butPtr->flags & GOT_FOCUS)) { - Tk_Draw3DRectangle(tkwin, pixmap, butPtr->normalBorder, 0, 0, - Tk_Width(tkwin), Tk_Height(tkwin), - butPtr->highlightWidth, TK_RELIEF_SOLID); - } + if (butPtr->flags & GOT_FOCUS) { + GC gc = Tk_GCForColor(butPtr->highlightColorPtr, pixmap); + TkMacOSXDrawSolidBorder(tkwin, gc, 0, butPtr->highlightWidth); + } } } -- cgit v0.12 From 992e83396570dcf0c161abd79226964eb535ad57 Mon Sep 17 00:00:00 2001 From: culler Date: Sun, 31 Mar 2019 16:34:59 +0000 Subject: Fix indentation. --- macosx/tkMacOSXMenubutton.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/macosx/tkMacOSXMenubutton.c b/macosx/tkMacOSXMenubutton.c index 5b39e19..f52b98e 100644 --- a/macosx/tkMacOSXMenubutton.c +++ b/macosx/tkMacOSXMenubutton.c @@ -191,8 +191,8 @@ TkpDisplayMenuButton( /* Draw highlight border, if needed. */ if (butPtr->highlightWidth < 3) { if (butPtr->flags & GOT_FOCUS) { - GC gc = Tk_GCForColor(butPtr->highlightColorPtr, pixmap); - TkMacOSXDrawSolidBorder(tkwin, gc, 0, butPtr->highlightWidth); + GC gc = Tk_GCForColor(butPtr->highlightColorPtr, pixmap); + TkMacOSXDrawSolidBorder(tkwin, gc, 0, butPtr->highlightWidth); } } } -- cgit v0.12 From c01cc1fe20294b8c83dba11c2be15caff3cdce61 Mon Sep 17 00:00:00 2001 From: culler Date: Mon, 1 Apr 2019 15:03:24 +0000 Subject: Use geometry masters, not parents, to find the nesting depth. --- generic/tk.h | 2 ++ generic/tkGeometry.c | 4 ++++ generic/tkInt.h | 1 + generic/tkWindow.c | 1 + library/ttk/aquaTheme.tcl | 2 +- macosx/ttkMacOSXTheme.c | 9 ++++----- 6 files changed, 13 insertions(+), 6 deletions(-) diff --git a/generic/tk.h b/generic/tk.h index c94882c..53de668 100644 --- a/generic/tk.h +++ b/generic/tk.h @@ -761,6 +761,7 @@ typedef XActivateDeactivateEvent XDeactivateEvent; #define Tk_MinReqHeight(tkwin) (((Tk_FakeWin *) (tkwin))->minReqHeight) #define Tk_Parent(tkwin) (((Tk_FakeWin *) (tkwin))->parentPtr) #define Tk_Colormap(tkwin) (((Tk_FakeWin *) (tkwin))->atts.colormap) +#define Tk_GeomMaster(tkwin) (((Tk_FakeWin *) (tkwin))->geomMasterPtr) /* * The structure below is needed by the macros above so that they can access @@ -802,6 +803,7 @@ typedef struct Tk_FakeWin { char *dummy13; /* selHandlerList */ char *dummy14; /* geomMgrPtr */ ClientData dummy15; /* geomData */ + Tk_Window geomMasterPtr; int reqWidth, reqHeight; int internalBorderLeft; char *dummy16; /* wmInfoPtr */ diff --git a/generic/tkGeometry.c b/generic/tkGeometry.c index 2e0009a..a9c134b 100644 --- a/generic/tkGeometry.c +++ b/generic/tkGeometry.c @@ -425,6 +425,8 @@ Tk_MaintainGeometry( Tk_Window ancestor, parent; TkDisplay *dispPtr = ((TkWindow *) master)->dispPtr; + Tk_GeomMaster(slave) = master; + if (master == Tk_Parent(slave)) { /* * If the slave is a direct descendant of the master, don't bother @@ -570,6 +572,8 @@ Tk_UnmaintainGeometry( Tk_Window ancestor; TkDisplay *dispPtr = ((TkWindow *) slave)->dispPtr; + Tk_GeomMaster(slave) = NULL; + if (master == Tk_Parent(slave)) { /* * If the slave is a direct descendant of the master, diff --git a/generic/tkInt.h b/generic/tkInt.h index 4b5aebb..554e10d 100644 --- a/generic/tkInt.h +++ b/generic/tkInt.h @@ -769,6 +769,7 @@ typedef struct TkWindow { /* Information about geometry manager for this * window. */ ClientData geomData; /* Argument for geometry manager functions. */ + Tk_Window *geomMasterPtr; /* Tk_MaintainGeometry maintains this field. */ int reqWidth, reqHeight; /* Arguments from last call to * Tk_GeometryRequest, or 0's if * Tk_GeometryRequest hasn't been called. */ diff --git a/generic/tkWindow.c b/generic/tkWindow.c index 868a8fa..606acb4 100644 --- a/generic/tkWindow.c +++ b/generic/tkWindow.c @@ -664,6 +664,7 @@ TkAllocWindow( winPtr->selHandlerList = NULL; winPtr->geomMgrPtr = NULL; winPtr->geomData = NULL; + winPtr->geomMasterPtr = NULL; winPtr->reqWidth = winPtr->reqHeight = 1; winPtr->internalBorderLeft = 0; winPtr->wmInfoPtr = NULL; diff --git a/library/ttk/aquaTheme.tcl b/library/ttk/aquaTheme.tcl index 1e7745a..8379c49 100644 --- a/library/ttk/aquaTheme.tcl +++ b/library/ttk/aquaTheme.tcl @@ -7,7 +7,7 @@ namespace eval ttk::theme::aqua { ttk::style configure . \ -font TkDefaultFont \ - -background systemWindowBody \ + -background systemTtkBackground \ -foreground systemLabelColor \ -selectbackground systemHighlight \ -selectforeground systemLabelColor \ diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index c68f7d3..99ec71b 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -156,7 +156,6 @@ static int GetBoxColor( int depth, CGFloat *fill) { - TkWindow *winPtr = (TkWindow *)tkwin; NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; if ([NSApp macMinorVersion] > 13) { NSColor *windowColor = [[NSColor windowBackgroundColor] @@ -173,10 +172,10 @@ static int GetBoxColor( * Compute the nesting depth of the widget. */ - for (TkWindow *topPtr = winPtr->parentPtr; topPtr != NULL; - topPtr = topPtr->parentPtr) { - if (topPtr->privatePtr && - (topPtr->privatePtr->flags & TTK_HAS_DARKER_BG)) { + for (TkWindow *masterPtr = (TkWindow *)Tk_GeomMaster(tkwin); masterPtr != NULL; + masterPtr = (TkWindow *)Tk_GeomMaster(masterPtr)) { + if (masterPtr->privatePtr && + (masterPtr->privatePtr->flags & TTK_HAS_DARKER_BG)) { depth++; } if (depth > 7) { -- cgit v0.12 From 56ebb6174e3cd45b91131ce91694df8a78d97406 Mon Sep 17 00:00:00 2001 From: culler Date: Mon, 1 Apr 2019 17:18:37 +0000 Subject: Oops. Following those underscore conventions is tricky. --- generic/tkInt.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/generic/tkInt.h b/generic/tkInt.h index 554e10d..1ee86be 100644 --- a/generic/tkInt.h +++ b/generic/tkInt.h @@ -769,7 +769,8 @@ typedef struct TkWindow { /* Information about geometry manager for this * window. */ ClientData geomData; /* Argument for geometry manager functions. */ - Tk_Window *geomMasterPtr; /* Tk_MaintainGeometry maintains this field. */ + struct TkWindow *geomMasterPtr; + /* Master assigned by Tk_MaintainGeometry.*/ int reqWidth, reqHeight; /* Arguments from last call to * Tk_GeometryRequest, or 0's if * Tk_GeometryRequest hasn't been called. */ -- cgit v0.12 From 4f918fe4d09e9c1afec0aafc2871d56da93d23fb Mon Sep 17 00:00:00 2001 From: culler Date: Tue, 2 Apr 2019 17:47:41 +0000 Subject: Sync with geom-master-slave. --- generic/tk.h | 2 -- generic/tkGeometry.c | 4 ---- generic/tkInt.h | 2 -- generic/tkWindow.c | 1 - 4 files changed, 9 deletions(-) diff --git a/generic/tk.h b/generic/tk.h index 53de668..c94882c 100644 --- a/generic/tk.h +++ b/generic/tk.h @@ -761,7 +761,6 @@ typedef XActivateDeactivateEvent XDeactivateEvent; #define Tk_MinReqHeight(tkwin) (((Tk_FakeWin *) (tkwin))->minReqHeight) #define Tk_Parent(tkwin) (((Tk_FakeWin *) (tkwin))->parentPtr) #define Tk_Colormap(tkwin) (((Tk_FakeWin *) (tkwin))->atts.colormap) -#define Tk_GeomMaster(tkwin) (((Tk_FakeWin *) (tkwin))->geomMasterPtr) /* * The structure below is needed by the macros above so that they can access @@ -803,7 +802,6 @@ typedef struct Tk_FakeWin { char *dummy13; /* selHandlerList */ char *dummy14; /* geomMgrPtr */ ClientData dummy15; /* geomData */ - Tk_Window geomMasterPtr; int reqWidth, reqHeight; int internalBorderLeft; char *dummy16; /* wmInfoPtr */ diff --git a/generic/tkGeometry.c b/generic/tkGeometry.c index a9c134b..2e0009a 100644 --- a/generic/tkGeometry.c +++ b/generic/tkGeometry.c @@ -425,8 +425,6 @@ Tk_MaintainGeometry( Tk_Window ancestor, parent; TkDisplay *dispPtr = ((TkWindow *) master)->dispPtr; - Tk_GeomMaster(slave) = master; - if (master == Tk_Parent(slave)) { /* * If the slave is a direct descendant of the master, don't bother @@ -572,8 +570,6 @@ Tk_UnmaintainGeometry( Tk_Window ancestor; TkDisplay *dispPtr = ((TkWindow *) slave)->dispPtr; - Tk_GeomMaster(slave) = NULL; - if (master == Tk_Parent(slave)) { /* * If the slave is a direct descendant of the master, diff --git a/generic/tkInt.h b/generic/tkInt.h index 1ee86be..4b5aebb 100644 --- a/generic/tkInt.h +++ b/generic/tkInt.h @@ -769,8 +769,6 @@ typedef struct TkWindow { /* Information about geometry manager for this * window. */ ClientData geomData; /* Argument for geometry manager functions. */ - struct TkWindow *geomMasterPtr; - /* Master assigned by Tk_MaintainGeometry.*/ int reqWidth, reqHeight; /* Arguments from last call to * Tk_GeometryRequest, or 0's if * Tk_GeometryRequest hasn't been called. */ diff --git a/generic/tkWindow.c b/generic/tkWindow.c index 606acb4..868a8fa 100644 --- a/generic/tkWindow.c +++ b/generic/tkWindow.c @@ -664,7 +664,6 @@ TkAllocWindow( winPtr->selHandlerList = NULL; winPtr->geomMgrPtr = NULL; winPtr->geomData = NULL; - winPtr->geomMasterPtr = NULL; winPtr->reqWidth = winPtr->reqHeight = 1; winPtr->internalBorderLeft = 0; winPtr->wmInfoPtr = NULL; -- cgit v0.12 From 91172dfcd45a3cf4a60fcd083f9e96202b2adefb Mon Sep 17 00:00:00 2001 From: culler Date: Tue, 2 Apr 2019 18:48:44 +0000 Subject: Really sync with geom-master-slave. --- generic/tk.h | 12 +++++++----- generic/tkGeometry.c | 28 ++++++++++++++++------------ generic/tkInt.h | 4 +++- generic/tkWindow.c | 9 +++++---- 4 files changed, 31 insertions(+), 22 deletions(-) diff --git a/generic/tk.h b/generic/tk.h index c94882c..2162346 100644 --- a/generic/tk.h +++ b/generic/tk.h @@ -761,6 +761,7 @@ typedef XActivateDeactivateEvent XDeactivateEvent; #define Tk_MinReqHeight(tkwin) (((Tk_FakeWin *) (tkwin))->minReqHeight) #define Tk_Parent(tkwin) (((Tk_FakeWin *) (tkwin))->parentPtr) #define Tk_Colormap(tkwin) (((Tk_FakeWin *) (tkwin))->atts.colormap) +#define Tk_GeomMaster(tkwin) (((Tk_FakeWin *) (tkwin))->geomMasterPtr) /* * The structure below is needed by the macros above so that they can access @@ -802,18 +803,19 @@ typedef struct Tk_FakeWin { char *dummy13; /* selHandlerList */ char *dummy14; /* geomMgrPtr */ ClientData dummy15; /* geomData */ + char *dummy16; /* geomMgrName */ + Tk_Window geomMasterPtr; int reqWidth, reqHeight; int internalBorderLeft; - char *dummy16; /* wmInfoPtr */ - char *dummy17; /* classProcPtr */ - ClientData dummy18; /* instanceData */ - char *dummy19; /* privatePtr */ + char *dummy17; /* wmInfoPtr */ + char *dummy18; /* classProcPtr */ + ClientData dummy19; /* instanceData */ + char *dummy20; /* privatePtr */ int internalBorderRight; int internalBorderTop; int internalBorderBottom; int minReqWidth; int minReqHeight; - char *dummy20; /* geometryMaster */ #ifdef TK_USE_INPUT_METHODS int dummy21; #endif /* TK_USE_INPUT_METHODS */ diff --git a/generic/tkGeometry.c b/generic/tkGeometry.c index 2e0009a..f65dc84 100644 --- a/generic/tkGeometry.c +++ b/generic/tkGeometry.c @@ -327,23 +327,23 @@ TkSetGeometryMaster( { register TkWindow *winPtr = (TkWindow *) tkwin; - if (winPtr->geometryMaster != NULL && - strcmp(winPtr->geometryMaster, master) == 0) { + if (winPtr->geomMgrName != NULL && + strcmp(winPtr->geomMgrName, master) == 0) { return TCL_OK; } - if (winPtr->geometryMaster != NULL) { + if (winPtr->geomMgrName != NULL) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "cannot use geometry manager %s inside %s which already" " has slaves managed by %s", - master, Tk_PathName(tkwin), winPtr->geometryMaster)); + master, Tk_PathName(tkwin), winPtr->geomMgrName)); Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "FIGHT", NULL); } return TCL_ERROR; } - winPtr->geometryMaster = ckalloc(strlen(master) + 1); - strcpy(winPtr->geometryMaster, master); + winPtr->geomMgrName = ckalloc(strlen(master) + 1); + strcpy(winPtr->geomMgrName, master); return TCL_OK; } @@ -372,14 +372,14 @@ TkFreeGeometryMaster( { register TkWindow *winPtr = (TkWindow *) tkwin; - if (winPtr->geometryMaster != NULL && - strcmp(winPtr->geometryMaster, master) != 0) { + if (winPtr->geomMgrName != NULL && + strcmp(winPtr->geomMgrName, master) != 0) { Tcl_Panic("Trying to free %s from geometry manager %s", - winPtr->geometryMaster, master); + winPtr->geomMgrName, master); } - if (winPtr->geometryMaster != NULL) { - ckfree(winPtr->geometryMaster); - winPtr->geometryMaster = NULL; + if (winPtr->geomMgrName != NULL) { + ckfree(winPtr->geomMgrName); + winPtr->geomMgrName = NULL; } } @@ -425,6 +425,8 @@ Tk_MaintainGeometry( Tk_Window ancestor, parent; TkDisplay *dispPtr = ((TkWindow *) master)->dispPtr; + Tk_GeomMaster(slave) = master; + if (master == Tk_Parent(slave)) { /* * If the slave is a direct descendant of the master, don't bother @@ -570,6 +572,8 @@ Tk_UnmaintainGeometry( Tk_Window ancestor; TkDisplay *dispPtr = ((TkWindow *) slave)->dispPtr; + Tk_GeomMaster(slave) = NULL; + if (master == Tk_Parent(slave)) { /* * If the slave is a direct descendant of the master, diff --git a/generic/tkInt.h b/generic/tkInt.h index 4b5aebb..c50a75c 100644 --- a/generic/tkInt.h +++ b/generic/tkInt.h @@ -769,6 +769,9 @@ typedef struct TkWindow { /* Information about geometry manager for this * window. */ ClientData geomData; /* Argument for geometry manager functions. */ + char *geomMgrName; /* Records the name of the geometry manager. */ + struct TkWindow *geomMasterPtr; + /* The master assigned by Tk_MaintainGeometry.*/ int reqWidth, reqHeight; /* Arguments from last call to * Tk_GeometryRequest, or 0's if * Tk_GeometryRequest hasn't been called. */ @@ -812,7 +815,6 @@ typedef struct TkWindow { int minReqWidth; /* Minimum requested width. */ int minReqHeight; /* Minimum requested height. */ - char *geometryMaster; #ifdef TK_USE_INPUT_METHODS int ximGeneration; /* Used to invalidate XIC */ #endif /* TK_USE_INPUT_METHODS */ diff --git a/generic/tkWindow.c b/generic/tkWindow.c index 868a8fa..04c7ea2 100644 --- a/generic/tkWindow.c +++ b/generic/tkWindow.c @@ -664,6 +664,8 @@ TkAllocWindow( winPtr->selHandlerList = NULL; winPtr->geomMgrPtr = NULL; winPtr->geomData = NULL; + winPtr->geomMgrName = NULL; + winPtr->geomMasterPtr = NULL; winPtr->reqWidth = winPtr->reqHeight = 1; winPtr->internalBorderLeft = 0; winPtr->wmInfoPtr = NULL; @@ -675,7 +677,6 @@ TkAllocWindow( winPtr->internalBorderBottom = 0; winPtr->minReqWidth = 0; winPtr->minReqHeight = 0; - winPtr->geometryMaster = NULL; return winPtr; } @@ -1460,9 +1461,9 @@ Tk_DestroyWindow( TkOptionDeadWindow(winPtr); TkSelDeadWindow(winPtr); TkGrabDeadWindow(winPtr); - if (winPtr->geometryMaster != NULL) { - ckfree(winPtr->geometryMaster); - winPtr->geometryMaster = NULL; + if (winPtr->geomMgrName != NULL) { + ckfree(winPtr->geomMgrName); + winPtr->geomMgrName = NULL; } if (winPtr->mainPtr != NULL) { if (winPtr->pathName != NULL) { -- cgit v0.12 From 04bf6f37b10cf10187fa12370fa5ef2daccb6b15 Mon Sep 17 00:00:00 2001 From: culler Date: Thu, 4 Apr 2019 17:02:00 +0000 Subject: Rework how contrasting backgrounds are handled. --- generic/tk.h | 11 +++--- generic/tkGeometry.c | 4 +- generic/tkInt.h | 5 ++- generic/tkWindow.c | 2 +- macosx/tkMacOSXInt.h | 12 +++++- macosx/ttkMacOSXTheme.c | 101 ++++++++++++++++++++++++------------------------ 6 files changed, 74 insertions(+), 61 deletions(-) diff --git a/generic/tk.h b/generic/tk.h index 2162346..966a453 100644 --- a/generic/tk.h +++ b/generic/tk.h @@ -761,7 +761,6 @@ typedef XActivateDeactivateEvent XDeactivateEvent; #define Tk_MinReqHeight(tkwin) (((Tk_FakeWin *) (tkwin))->minReqHeight) #define Tk_Parent(tkwin) (((Tk_FakeWin *) (tkwin))->parentPtr) #define Tk_Colormap(tkwin) (((Tk_FakeWin *) (tkwin))->atts.colormap) -#define Tk_GeomMaster(tkwin) (((Tk_FakeWin *) (tkwin))->geomMasterPtr) /* * The structure below is needed by the macros above so that they can access @@ -804,13 +803,13 @@ typedef struct Tk_FakeWin { char *dummy14; /* geomMgrPtr */ ClientData dummy15; /* geomData */ char *dummy16; /* geomMgrName */ - Tk_Window geomMasterPtr; + Tk_Window dummy17; /* maintainerPtr */ int reqWidth, reqHeight; int internalBorderLeft; - char *dummy17; /* wmInfoPtr */ - char *dummy18; /* classProcPtr */ - ClientData dummy19; /* instanceData */ - char *dummy20; /* privatePtr */ + char *dummy18; /* wmInfoPtr */ + char *dummy19; /* classProcPtr */ + ClientData dummy20; /* instanceData */ + char *dummy21; /* privatePtr */ int internalBorderRight; int internalBorderTop; int internalBorderBottom; diff --git a/generic/tkGeometry.c b/generic/tkGeometry.c index f65dc84..11db8e8 100644 --- a/generic/tkGeometry.c +++ b/generic/tkGeometry.c @@ -425,7 +425,7 @@ Tk_MaintainGeometry( Tk_Window ancestor, parent; TkDisplay *dispPtr = ((TkWindow *) master)->dispPtr; - Tk_GeomMaster(slave) = master; + ((TkWindow *)slave)->maintainerPtr = (TkWindow *)master; if (master == Tk_Parent(slave)) { /* @@ -572,7 +572,7 @@ Tk_UnmaintainGeometry( Tk_Window ancestor; TkDisplay *dispPtr = ((TkWindow *) slave)->dispPtr; - Tk_GeomMaster(slave) = NULL; + ((TkWindow *)slave)->maintainerPtr = NULL; if (master == Tk_Parent(slave)) { /* diff --git a/generic/tkInt.h b/generic/tkInt.h index c50a75c..2020486 100644 --- a/generic/tkInt.h +++ b/generic/tkInt.h @@ -323,6 +323,9 @@ typedef struct TkDisplay { * by that master. */ int geomInit; +#define Tk_GetGeomMaster(tkwin) (((TkWindow *)tkwin)->maintainerPtr != NULL ? \ + ((TkWindow *)tkwin)->maintainerPtr : ((TkWindow *)tkwin)->parentPtr) + /* * Information used by tkGet.c only: */ @@ -770,7 +773,7 @@ typedef struct TkWindow { * window. */ ClientData geomData; /* Argument for geometry manager functions. */ char *geomMgrName; /* Records the name of the geometry manager. */ - struct TkWindow *geomMasterPtr; + struct TkWindow *maintainerPtr; /* The master assigned by Tk_MaintainGeometry.*/ int reqWidth, reqHeight; /* Arguments from last call to * Tk_GeometryRequest, or 0's if diff --git a/generic/tkWindow.c b/generic/tkWindow.c index 04c7ea2..917d3bd 100644 --- a/generic/tkWindow.c +++ b/generic/tkWindow.c @@ -665,7 +665,7 @@ TkAllocWindow( winPtr->geomMgrPtr = NULL; winPtr->geomData = NULL; winPtr->geomMgrName = NULL; - winPtr->geomMasterPtr = NULL; + winPtr->maintainerPtr = NULL; winPtr->reqWidth = winPtr->reqHeight = 1; winPtr->internalBorderLeft = 0; winPtr->wmInfoPtr = NULL; diff --git a/macosx/tkMacOSXInt.h b/macosx/tkMacOSXInt.h index ce79498..22d7d2c 100644 --- a/macosx/tkMacOSXInt.h +++ b/macosx/tkMacOSXInt.h @@ -71,6 +71,7 @@ struct TkWindowPrivate { * gone. */ struct TkWindowPrivate *toplevel; /* Pointer to the toplevel datastruct. */ + CGFloat fillRGBA[4]; /* Background used by the ttk FillElement */ int flags; /* Various state see defines below. */ }; typedef struct TkWindowPrivate MacDrawable; @@ -86,7 +87,7 @@ typedef struct TkWindowPrivate MacDrawable; #define TK_IS_PIXMAP 0x10 #define TK_IS_BW_PIXMAP 0x20 #define TK_DO_NOT_DRAW 0x40 -#define TTK_HAS_DARKER_BG 0x80 +#define TTK_HAS_CONTRASTING_BG 0x80 /* * I am reserving TK_EMBEDDED = 0x100 in the MacDrawable flags @@ -211,3 +212,12 @@ MODULE_SCOPE Bool TkMacOSXInDarkMode(Tk_Window tkwin); #include "tkIntPlatDecls.h" #endif /* _TKMACINT */ + +/* + * Local Variables: + * mode: objc + * c-basic-offset: 4 + * fill-column: 79 + * coding: utf-8 + * End: + */ diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index 99ec71b..94c074f 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -144,59 +144,61 @@ static CGRect NormalizeButtonBounds( static CGFloat windowBackground[4] = {235.0/255, 235.0/255, 235.0/255, 1.0}; /* - * GetBoxColor -- + * GetBackgroundColor -- * - * Compute a contrasting box color, based on nesting depth, and save the - * RGBA components in an array. Used by the Fill and Background elements. + * 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 used by the Fill and Background elements. */ -static int GetBoxColor( +static void GetBackgroundColor( CGContextRef context, Tk_Window tkwin, - int depth, - CGFloat *fill) + int contrast, + CGFloat *rgba) { - NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; - if ([NSApp macMinorVersion] > 13) { - NSColor *windowColor = [[NSColor windowBackgroundColor] - colorUsingColorSpace: deviceRGB]; - [windowColor getComponents: fill]; - } else { - for (int i = 0; i < 4; i++) { - fill[i] = windowBackground[i]; + TkWindow *winPtr = (TkWindow *)tkwin; + TkWindow *masterPtr = (TkWindow *)Tk_GetGeomMaster(tkwin); + while (masterPtr != NULL) { + if (masterPtr->privatePtr->flags & TTK_HAS_CONTRASTING_BG) { + break; } + masterPtr = (TkWindow *)Tk_GetGeomMaster(masterPtr); } - int isDark = (fill[0] + fill[1] + fill[2] < 1.5); - - /* - * Compute the nesting depth of the widget. - */ - - for (TkWindow *masterPtr = (TkWindow *)Tk_GeomMaster(tkwin); masterPtr != NULL; - masterPtr = (TkWindow *)Tk_GeomMaster(masterPtr)) { - if (masterPtr->privatePtr && - (masterPtr->privatePtr->flags & TTK_HAS_DARKER_BG)) { - depth++; + if (masterPtr) { + for (int i = 0; i < 4; i++) { + rgba[i] = masterPtr->privatePtr->fillRGBA[i]; } - if (depth > 7) { - break; + } else { + if ([NSApp macMinorVersion] > 13) { + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + NSColor *windowColor = [[NSColor windowBackgroundColor] + colorUsingColorSpace: deviceRGB]; + [windowColor getComponents: rgba]; + } else { + for (int i = 0; i < 4; i++) { + rgba[i] = windowBackground[i]; + } } } - - /* - * Increase the contrast by one step for each level of nesting. - */ - - if (isDark) { - for (int i=0; i<3; i++) { - fill[i] += (1.0 + depth*7.0)/255.0; + if (contrast) { + int isDark = (rgba[0] + rgba[1] + rgba[2] < 1.5); + if (isDark) { + for (int i=0; i<3; i++) { + rgba[i] += 8.0/255.0; + } + } else { + for (int i=0; i<3; i++) { + rgba[i] -= 8.0/255.0; + } } - } else { - for (int i=0; i<3; i++) { - fill[i] -= (depth*8.0)/255.0; + winPtr->privatePtr->flags |= TTK_HAS_CONTRASTING_BG; + for (int i = 0; i < 4; i++) { + winPtr->privatePtr->fillRGBA[i] = rgba[i]; } } - return depth; } /* @@ -216,7 +218,7 @@ static void DrawGroupBox( NSColor *borderColor, *bgColor; static CGFloat border[4] = {1.0, 1.0, 1.0, 0.25}; CGFloat fill[4]; - GetBoxColor(context, tkwin, 1, fill); + GetBackgroundColor(context, tkwin, 1, fill); bgColor = [NSColor colorWithColorSpace: deviceRGB components: fill count: 4]; CGContextSetFillColorSpace(context, deviceRGB.CGColorSpace); @@ -816,6 +818,10 @@ static void DrawDarkSeparator( * +++ Button element: Used for elements drawn with DrawThemeButton. */ +/* + * When Ttk draws the various types of buttons, a pointer to one of these + * is passed as the clientData. + */ typedef struct { ThemeButtonKind kind; @@ -1174,9 +1180,6 @@ static void PaneElementDraw( #endif END_DRAWING [TkMacOSXDrawableView(macWin) setNeedsDisplay:YES]; - if (macWin != NULL) { - macWin->flags |= TTK_HAS_DARKER_BG; - } } static Ttk_ElementSpec PaneElementSpec = { @@ -1209,7 +1212,6 @@ static void GroupElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) { - TkWindow *winPtr = (TkWindow *)tkwin; CGRect bounds = BoxToRect(d, b); BEGIN_DRAWING(d) @@ -1224,9 +1226,6 @@ static void GroupElementDraw( ChkErr(HIThemeDrawGroupBox, &bounds, &info, dc.context, HIOrientation); #endif END_DRAWING - if (winPtr->privatePtr != NULL) { - winPtr->privatePtr->flags |= TTK_HAS_DARKER_BG; - } } static Ttk_ElementSpec GroupElementSpec = { @@ -2112,26 +2111,28 @@ static void FillElementDraw( Drawable d, Ttk_Box b, Ttk_State state) { CGRect bounds = BoxToRect(d, b); - BEGIN_DRAWING(d) #if MAC_OS_X_VERSION_MIN_REQUIRED > 1080 NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; NSColor *bgColor; CGFloat fill[4]; - GetBoxColor(dc.context, tkwin, 0, fill); + BEGIN_DRAWING(d) + GetBackgroundColor(dc.context, tkwin, 0, fill); bgColor = [NSColor colorWithColorSpace: deviceRGB components: fill count: 4]; CGContextSetFillColorSpace(dc.context, deviceRGB.CGColorSpace); CGContextSetFillColorWithColor(dc.context, bgColor.CGColor); CGContextFillRect(dc.context, bounds); + END_DRAWING #else ThemeBrush brush = (state & TTK_STATE_BACKGROUND) ? kThemeBrushModelessDialogBackgroundInactive : kThemeBrushModelessDialogBackgroundActive; + BEGIN_DRAWING(d) ChkErr(HIThemeSetFill, brush, NULL, dc.context, HIOrientation); //QDSetPatternOrigin(PatternOrigin(tkwin, d)); CGContextFillRect(dc.context, bounds); -#endif END_DRAWING +#endif } static void BackgroundElementDraw( -- cgit v0.12 From 081ca218bb45dcb50deb08f5674ed98c317f18b6 Mon Sep 17 00:00:00 2001 From: culler Date: Fri, 5 Apr 2019 19:55:57 +0000 Subject: Fix bug [897ffea89f]: Tk allows management loops --- generic/tk.h | 11 ++++++----- generic/tkGeometry.c | 26 ++++++++++++++------------ generic/tkGrid.c | 22 ++++++++++++++-------- generic/tkInt.h | 9 ++++++++- generic/tkPack.c | 19 +++++++++++++++++++ generic/tkPlace.c | 19 +++++++++++++++++++ generic/tkWindow.c | 9 +++++---- tests/grid.test | 26 ++++++++++++++++++++++++++ tests/pack.test | 23 +++++++++++++++++++++++ tests/place.test | 21 ++++++++++++++++++++- 10 files changed, 154 insertions(+), 31 deletions(-) diff --git a/generic/tk.h b/generic/tk.h index c94882c..966a453 100644 --- a/generic/tk.h +++ b/generic/tk.h @@ -802,18 +802,19 @@ typedef struct Tk_FakeWin { char *dummy13; /* selHandlerList */ char *dummy14; /* geomMgrPtr */ ClientData dummy15; /* geomData */ + char *dummy16; /* geomMgrName */ + Tk_Window dummy17; /* maintainerPtr */ int reqWidth, reqHeight; int internalBorderLeft; - char *dummy16; /* wmInfoPtr */ - char *dummy17; /* classProcPtr */ - ClientData dummy18; /* instanceData */ - char *dummy19; /* privatePtr */ + char *dummy18; /* wmInfoPtr */ + char *dummy19; /* classProcPtr */ + ClientData dummy20; /* instanceData */ + char *dummy21; /* privatePtr */ int internalBorderRight; int internalBorderTop; int internalBorderBottom; int minReqWidth; int minReqHeight; - char *dummy20; /* geometryMaster */ #ifdef TK_USE_INPUT_METHODS int dummy21; #endif /* TK_USE_INPUT_METHODS */ diff --git a/generic/tkGeometry.c b/generic/tkGeometry.c index 2e0009a..ecacae9 100644 --- a/generic/tkGeometry.c +++ b/generic/tkGeometry.c @@ -327,23 +327,23 @@ TkSetGeometryMaster( { register TkWindow *winPtr = (TkWindow *) tkwin; - if (winPtr->geometryMaster != NULL && - strcmp(winPtr->geometryMaster, master) == 0) { + if (winPtr->geomMgrName != NULL && + strcmp(winPtr->geomMgrName, master) == 0) { return TCL_OK; } - if (winPtr->geometryMaster != NULL) { + if (winPtr->geomMgrName != NULL) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "cannot use geometry manager %s inside %s which already" " has slaves managed by %s", - master, Tk_PathName(tkwin), winPtr->geometryMaster)); + master, Tk_PathName(tkwin), winPtr->geomMgrName)); Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "FIGHT", NULL); } return TCL_ERROR; } - winPtr->geometryMaster = ckalloc(strlen(master) + 1); - strcpy(winPtr->geometryMaster, master); + winPtr->geomMgrName = ckalloc(strlen(master) + 1); + strcpy(winPtr->geomMgrName, master); return TCL_OK; } @@ -372,14 +372,14 @@ TkFreeGeometryMaster( { register TkWindow *winPtr = (TkWindow *) tkwin; - if (winPtr->geometryMaster != NULL && - strcmp(winPtr->geometryMaster, master) != 0) { + if (winPtr->geomMgrName != NULL && + strcmp(winPtr->geomMgrName, master) != 0) { Tcl_Panic("Trying to free %s from geometry manager %s", - winPtr->geometryMaster, master); + winPtr->geomMgrName, master); } - if (winPtr->geometryMaster != NULL) { - ckfree(winPtr->geometryMaster); - winPtr->geometryMaster = NULL; + if (winPtr->geomMgrName != NULL) { + ckfree(winPtr->geomMgrName); + winPtr->geomMgrName = NULL; } } @@ -425,6 +425,7 @@ Tk_MaintainGeometry( Tk_Window ancestor, parent; TkDisplay *dispPtr = ((TkWindow *) master)->dispPtr; + ((TkWindow *)slave)->maintainerPtr = (TkWindow *)master; if (master == Tk_Parent(slave)) { /* * If the slave is a direct descendant of the master, don't bother @@ -570,6 +571,7 @@ Tk_UnmaintainGeometry( Tk_Window ancestor; TkDisplay *dispPtr = ((TkWindow *) slave)->dispPtr; + ((TkWindow *)slave)->maintainerPtr = NULL; if (master == Tk_Parent(slave)) { /* * If the slave is a direct descendant of the master, diff --git a/generic/tkGrid.c b/generic/tkGrid.c index 20e66b6..5264b02 100644 --- a/generic/tkGrid.c +++ b/generic/tkGrid.c @@ -3352,17 +3352,23 @@ ConfigureSlaves( } /* - * Try to make sure our master isn't managed by us. + * Check for management loops. */ - if (masterPtr->masterPtr == slavePtr) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( + for (TkWindow *master = (TkWindow *)masterPtr->tkwin; master != NULL; + master = (TkWindow *)Tk_GetGeomMaster(master)) { + if (master == (TkWindow *)slave) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't put %s inside %s, would cause management loop", - Tcl_GetString(objv[j]), Tk_PathName(masterPtr->tkwin))); - Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "LOOP", NULL); - Unlink(slavePtr); - return TCL_ERROR; - } + Tcl_GetString(objv[j]), Tk_PathName(masterPtr->tkwin))); + Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "LOOP", NULL); + Unlink(slavePtr); + return TCL_ERROR; + } + } + if (masterPtr->tkwin != Tk_Parent(slave)) { + ((TkWindow *)slave)->maintainerPtr = (TkWindow *)masterPtr->tkwin; + } Tk_ManageGeometry(slave, &gridMgrType, slavePtr); diff --git a/generic/tkInt.h b/generic/tkInt.h index 4b5aebb..d77c7a9 100644 --- a/generic/tkInt.h +++ b/generic/tkInt.h @@ -323,6 +323,9 @@ typedef struct TkDisplay { * by that master. */ int geomInit; +#define Tk_GetGeomMaster(tkwin) (((TkWindow *)tkwin)->maintainerPtr != NULL ? \ + ((TkWindow *)tkwin)->maintainerPtr : ((TkWindow *)tkwin)->parentPtr) + /* * Information used by tkGet.c only: */ @@ -769,6 +772,11 @@ typedef struct TkWindow { /* Information about geometry manager for this * window. */ ClientData geomData; /* Argument for geometry manager functions. */ + char *geomMgrName; /* Records the name of the geometry manager. */ + struct TkWindow *maintainerPtr; + /* The geometry master for this window. The + * value is NULL if the window has no master or + * if its master is its parent. */ int reqWidth, reqHeight; /* Arguments from last call to * Tk_GeometryRequest, or 0's if * Tk_GeometryRequest hasn't been called. */ @@ -812,7 +820,6 @@ typedef struct TkWindow { int minReqWidth; /* Minimum requested width. */ int minReqHeight; /* Minimum requested height. */ - char *geometryMaster; #ifdef TK_USE_INPUT_METHODS int ximGeneration; /* Used to invalidate XIC */ #endif /* TK_USE_INPUT_METHODS */ diff --git a/generic/tkPack.c b/generic/tkPack.c index 071a537..8d49629 100644 --- a/generic/tkPack.c +++ b/generic/tkPack.c @@ -1799,6 +1799,25 @@ ConfigureSlaves( } /* + * Check for management loops. + */ + + for (TkWindow *master = (TkWindow *)masterPtr->tkwin; master != NULL; + master = (TkWindow *)Tk_GetGeomMaster(master)) { + if (master == (TkWindow *)slave) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "can't put %s inside %s, would cause management loop", + Tcl_GetString(objv[j]), Tk_PathName(masterPtr->tkwin))); + Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "LOOP", NULL); + Unlink(slavePtr); + return TCL_ERROR; + } + } + if (masterPtr->tkwin != Tk_Parent(slave)) { + ((TkWindow *)slave)->maintainerPtr = (TkWindow *)masterPtr->tkwin; + } + + /* * Unpack the slave if it's currently packed, then position it after * prevPtr. */ diff --git a/generic/tkPlace.c b/generic/tkPlace.c index 8eee5a1..89976b5 100644 --- a/generic/tkPlace.c +++ b/generic/tkPlace.c @@ -694,6 +694,25 @@ ConfigureSlave( Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "LOOP", NULL); goto error; } + + /* + * Check for management loops. + */ + + for (TkWindow *master = (TkWindow *)tkwin; master != NULL; + master = (TkWindow *)Tk_GetGeomMaster(master)) { + if (master == (TkWindow *)slavePtr->tkwin) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "can't put %s inside %s, would cause management loop", + Tk_PathName(slavePtr->tkwin), Tk_PathName(tkwin))); + Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "LOOP", NULL); + goto error; + } + } + if (tkwin != Tk_Parent(slavePtr->tkwin)) { + ((TkWindow *)slavePtr->tkwin)->maintainerPtr = (TkWindow *)tkwin; + } + if ((slavePtr->masterPtr != NULL) && (slavePtr->masterPtr->tkwin == tkwin)) { /* diff --git a/generic/tkWindow.c b/generic/tkWindow.c index 868a8fa..917d3bd 100644 --- a/generic/tkWindow.c +++ b/generic/tkWindow.c @@ -664,6 +664,8 @@ TkAllocWindow( winPtr->selHandlerList = NULL; winPtr->geomMgrPtr = NULL; winPtr->geomData = NULL; + winPtr->geomMgrName = NULL; + winPtr->maintainerPtr = NULL; winPtr->reqWidth = winPtr->reqHeight = 1; winPtr->internalBorderLeft = 0; winPtr->wmInfoPtr = NULL; @@ -675,7 +677,6 @@ TkAllocWindow( winPtr->internalBorderBottom = 0; winPtr->minReqWidth = 0; winPtr->minReqHeight = 0; - winPtr->geometryMaster = NULL; return winPtr; } @@ -1460,9 +1461,9 @@ Tk_DestroyWindow( TkOptionDeadWindow(winPtr); TkSelDeadWindow(winPtr); TkGrabDeadWindow(winPtr); - if (winPtr->geometryMaster != NULL) { - ckfree(winPtr->geometryMaster); - winPtr->geometryMaster = NULL; + if (winPtr->geomMgrName != NULL) { + ckfree(winPtr->geomMgrName); + winPtr->geomMgrName = NULL; } if (winPtr->mainPtr != NULL) { if (winPtr->pathName != NULL) { diff --git a/tests/grid.test b/tests/grid.test index cba69db..cc445e3 100644 --- a/tests/grid.test +++ b/tests/grid.test @@ -80,6 +80,7 @@ test grid-1.9 {basic argument checking} -body { grid_reset 1.9 } -returnCodes ok -result {} + test grid-2.1 {bbox} -body { grid bbox . } -result {0 0 0 0} @@ -192,6 +193,31 @@ test grid-3.9 {configure: basic argument checking} -body { } -cleanup { grid_reset 3.9 } -returnCodes error -result {invalid window shortcut, "y" should be '-', 'x', or '^'} +test grid-3.10 {configure: basic argument checking} -body { + frame .f + grid .f -in .f +} -cleanup { + grid_reset 3.10 +} -returnCodes error -result {window can't be managed in itself} +test grid-3.11 {configure: basic argument checking} -body { + frame .f1 + frame .f2 + grid .f1 -in .f2 + grid .f2 -in .f1 + update +} -cleanup { + grid_reset 3.11 +} -returnCodes error -result {can't put .f2 inside .f1, would cause management loop} +test grid-3.12 {configure: basic argument checking} -body { + frame .f1 + frame .f2 + frame .f3 + grid .f1 -in .f2 + grid .f2 -in .f3 + grid .f3 -in .f1 +} -cleanup { + grid_reset 3.12 +} -returnCodes error -result {can't put .f3 inside .f1, would cause management loop} test grid-4.1 {forget: basic argument checking} -body { grid forget foo diff --git a/tests/pack.test b/tests/pack.test index efb262b..cc517ed 100644 --- a/tests/pack.test +++ b/tests/pack.test @@ -976,6 +976,29 @@ test pack-10.4 {bad -in window does not change master} -setup { winfo manager .pack.a pack .pack.a -in .pack.a } -returnCodes error -result {can't pack .pack.a inside itself} +test pack-10.5 {prevent management loops} -body { + frame .f1 + frame .f2 + pack .f1 -in .f2 + pack .f2 -in .f1 +} -cleanup { + destroy .f1 + destroy .f2 +} -returnCodes error -result {can't put .f2 inside .f1, would cause management loop} +test pack-10.6 {prevent management loops} -body { + frame .f1 + frame .f2 + frame .f3 + puts "packing frames" + pack .f1 -in .f2 + pack .f2 -in .f3 +# update idletasks + pack .f3 -in .f1 +} -cleanup { + destroy .f1 + destroy .f2 + destroy .f3 +} -returnCodes error -result {can't put .f3 inside .f1, would cause management loop} test pack-11.1 {info option} -setup { diff --git a/tests/place.test b/tests/place.test index ddfa64c..62e0ed2 100644 --- a/tests/place.test +++ b/tests/place.test @@ -118,7 +118,26 @@ test place-4.4 {ConfigureSlave procedure, bad -in option} -setup { } -body { place .t.f2 -in . } -returnCodes error -result {can't place .t.f2 relative to .} - +test place-4.5 {ConfigureSlave procedure, bad -in option} -setup { +} -body { + frame .t.f1 + place .t.f1 -in .t.f1 +} -returnCodes error -result {can't place .t.f1 relative to itself} +test place-4.6 {prevent management loops} -setup { + place forget .t.f1 +} -body { + place .t.f1 -in .t.f2 + place .t.f2 -in .t.f1 +} -returnCodes error -result {can't put .t.f2 inside .t.f1, would cause management loop} +test place-4.7 {prevent management loops} -setup { + place forget .t.f1 + place forget .t.f2 +} -body { + frame .t.f3 + place .t.f1 -in .t.f2 + place .t.f2 -in .t.f3 + place .t.f3 -in .t.f1 +} -returnCodes error -result {can't put .t.f3 inside .t.f1, would cause management loop} test place-5.1 {ConfigureSlave procedure, -relwidth option} -body { place .t.f2 -relwidth abcd -- cgit v0.12 From 09c8d9c9eb2e971bcec74214a9479f224f1747e5 Mon Sep 17 00:00:00 2001 From: culler Date: Fri, 5 Apr 2019 20:28:32 +0000 Subject: Remove debugging commands accidentally left in the new tests --- tests/grid.test | 1 - tests/pack.test | 2 -- 2 files changed, 3 deletions(-) diff --git a/tests/grid.test b/tests/grid.test index cc445e3..e901a93 100644 --- a/tests/grid.test +++ b/tests/grid.test @@ -204,7 +204,6 @@ test grid-3.11 {configure: basic argument checking} -body { frame .f2 grid .f1 -in .f2 grid .f2 -in .f1 - update } -cleanup { grid_reset 3.11 } -returnCodes error -result {can't put .f2 inside .f1, would cause management loop} diff --git a/tests/pack.test b/tests/pack.test index cc517ed..e2efb4d 100644 --- a/tests/pack.test +++ b/tests/pack.test @@ -989,10 +989,8 @@ test pack-10.6 {prevent management loops} -body { frame .f1 frame .f2 frame .f3 - puts "packing frames" pack .f1 -in .f2 pack .f2 -in .f3 -# update idletasks pack .f3 -in .f1 } -cleanup { destroy .f1 -- cgit v0.12 From f86e6f1667a038b6c3119f4a033b798a280ae0e5 Mon Sep 17 00:00:00 2001 From: fvogel Date: Fri, 5 Apr 2019 21:17:13 +0000 Subject: Let the branch compile with MSVC. --- generic/tkGrid.c | 3 ++- generic/tkPack.c | 3 ++- generic/tkPlace.c | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/generic/tkGrid.c b/generic/tkGrid.c index 5264b02..81fb4f7 100644 --- a/generic/tkGrid.c +++ b/generic/tkGrid.c @@ -2938,6 +2938,7 @@ ConfigureSlaves( Gridder *masterPtr = NULL; Gridder *slavePtr; Tk_Window other, slave, parent, ancestor; + TkWindow *master; int i, j, tmp; int numWindows; int width; @@ -3355,7 +3356,7 @@ ConfigureSlaves( * Check for management loops. */ - for (TkWindow *master = (TkWindow *)masterPtr->tkwin; master != NULL; + for (master = (TkWindow *)masterPtr->tkwin; master != NULL; master = (TkWindow *)Tk_GetGeomMaster(master)) { if (master == (TkWindow *)slave) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( diff --git a/generic/tkPack.c b/generic/tkPack.c index 8d49629..9ffcf45 100644 --- a/generic/tkPack.c +++ b/generic/tkPack.c @@ -1522,6 +1522,7 @@ ConfigureSlaves( { Packer *masterPtr, *slavePtr, *prevPtr, *otherPtr; Tk_Window other, slave, parent, ancestor; + TkWindow *master; int i, j, numWindows, tmp, positionGiven; const char *string; static const char *const optionStrings[] = { @@ -1802,7 +1803,7 @@ ConfigureSlaves( * Check for management loops. */ - for (TkWindow *master = (TkWindow *)masterPtr->tkwin; master != NULL; + for (master = (TkWindow *)masterPtr->tkwin; master != NULL; master = (TkWindow *)Tk_GetGeomMaster(master)) { if (master == (TkWindow *)slave) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( diff --git a/generic/tkPlace.c b/generic/tkPlace.c index 89976b5..28f94c0 100644 --- a/generic/tkPlace.c +++ b/generic/tkPlace.c @@ -617,6 +617,7 @@ ConfigureSlave( int mask; Slave *slavePtr; Tk_Window masterWin = (Tk_Window) NULL; + TkWindow *master; if (Tk_TopWinHierarchy(tkwin)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( @@ -699,7 +700,7 @@ ConfigureSlave( * Check for management loops. */ - for (TkWindow *master = (TkWindow *)tkwin; master != NULL; + for (master = (TkWindow *)tkwin; master != NULL; master = (TkWindow *)Tk_GetGeomMaster(master)) { if (master == (TkWindow *)slavePtr->tkwin) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( -- cgit v0.12 From e5d4eeb37219de1ae1083da63410504618ed3557 Mon Sep 17 00:00:00 2001 From: culler Date: Sat, 6 Apr 2019 05:13:05 +0000 Subject: Added a drawing procedure for Entry widgets in dark mode. --- generic/tkGeometry.c | 2 +- generic/tkInt.h | 2 +- macosx/ttkMacOSXTheme.c | 105 ++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 86 insertions(+), 23 deletions(-) diff --git a/generic/tkGeometry.c b/generic/tkGeometry.c index 11db8e8..8184737 100644 --- a/generic/tkGeometry.c +++ b/generic/tkGeometry.c @@ -426,7 +426,7 @@ Tk_MaintainGeometry( TkDisplay *dispPtr = ((TkWindow *) master)->dispPtr; ((TkWindow *)slave)->maintainerPtr = (TkWindow *)master; - + if (master == Tk_Parent(slave)) { /* * If the slave is a direct descendant of the master, don't bother diff --git a/generic/tkInt.h b/generic/tkInt.h index 2020486..53e1698 100644 --- a/generic/tkInt.h +++ b/generic/tkInt.h @@ -323,7 +323,7 @@ typedef struct TkDisplay { * by that master. */ int geomInit; -#define Tk_GetGeomMaster(tkwin) (((TkWindow *)tkwin)->maintainerPtr != NULL ? \ +#define TkGetGeomMaster(tkwin) (((TkWindow *)tkwin)->maintainerPtr != NULL ? \ ((TkWindow *)tkwin)->maintainerPtr : ((TkWindow *)tkwin)->parentPtr) /* diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index 94c074f..c249051 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -150,7 +150,8 @@ static CGFloat windowBackground[4] = {235.0/255, 235.0/255, 235.0/255, 1.0}; * 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 used by the Fill and Background elements. + * DarkAqua appearance. This is primarily used by the Fill and Background + * elements. */ static void GetBackgroundColor( @@ -160,12 +161,12 @@ static void GetBackgroundColor( CGFloat *rgba) { TkWindow *winPtr = (TkWindow *)tkwin; - TkWindow *masterPtr = (TkWindow *)Tk_GetGeomMaster(tkwin); + TkWindow *masterPtr = (TkWindow *)TkGetGeomMaster(tkwin); while (masterPtr != NULL) { if (masterPtr->privatePtr->flags & TTK_HAS_CONTRASTING_BG) { break; } - masterPtr = (TkWindow *)Tk_GetGeomMaster(masterPtr); + masterPtr = (TkWindow *)TkGetGeomMaster(masterPtr); } if (masterPtr) { for (int i = 0; i < 4; i++) { @@ -312,6 +313,9 @@ static CGFloat darkDisabledButtonFace[4] = {86.0/255, 87.0/255, 89.0/255, 1.0}; static CGFloat darkInactiveSelectedTab[4] = {159.0/255, 160.0/255, 161.0/255, 1.0}; static CGFloat darkTabSeparator[4] = {0.0, 0.0, 0.0, 0.25}; static CGFloat darkTrack[4] = {1.0, 1.0, 1.0, 0.25}; +static CGFloat darkFrameTop[4] = {1.0, 1.0, 1.0, 0.0625}; +static CGFloat darkFrameBottom[4] = {1.0, 1.0, 1.0, 0.125}; +static CGFloat darkFrameAccent[4] = {0.0, 0.0, 0.0, 0.0625}; static CGFloat darkTopGradient[8] = {1.0, 1.0, 1.0, 0.3, 1.0, 1.0, 1.0, 0.0}; static CGFloat darkBackgroundGradient[8] = {0.0, 0.0, 0.0, 0.1, @@ -471,7 +475,8 @@ static void DrawDarkButton( * If the toplevel is front, paint the button blue. */ - if (!(state & TTK_STATE_BACKGROUND)) { + if (!(state & TTK_STATE_BACKGROUND) && + !(state & TTK_STATE_DISABLED)) { GradientFillRoundedRectangle(context, arrowBounds, 4, darkSelectedGradient, 2); } @@ -812,6 +817,56 @@ static void DrawDarkSeparator( CGContextFillRect(context, bounds); } +/* + * DrawDarkFrame -- + * + * This is a standalone drawing procedure which draws various + * types of borders in Dark Mode. + */ + +static void DrawDarkFrame( + CGRect bounds, + CGContextRef context, + HIThemeFrameKind kind) +{ + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + NSColor *stroke; + CGContextSetStrokeColorSpace(context, deviceRGB.CGColorSpace); + CGFloat x = bounds.origin.x, y = bounds.origin.y; + CGFloat w = bounds.size.width, h = bounds.size.height; + CGPoint topPart[4] = {{x, y + h - 1}, {x, y}, {x + w, y}, {x + w, y + h - 1}}; + CGPoint bottom[2] = {{x, y + h}, {x + w, y + h}}; + CGPoint accent[2] = {{x, y + 1}, {x + w, y + 1}}; + switch(kind) { + case kHIThemeFrameTextFieldSquare: + CGContextSaveGState(context); + CGContextSetShouldAntialias(context, false); + stroke = [NSColor colorWithColorSpace: deviceRGB + components: darkFrameTop + count: 4]; + CGContextSetStrokeColorWithColor(context, stroke.CGColor); + CGContextBeginPath(context); + CGContextAddLines(context, topPart, 4); + CGContextStrokePath(context); + stroke = [NSColor colorWithColorSpace: deviceRGB + components: darkFrameBottom + count: 4]; + CGContextSetStrokeColorWithColor(context, stroke.CGColor); + CGContextAddLines(context, bottom, 2); + CGContextStrokePath(context); + stroke = [NSColor colorWithColorSpace: deviceRGB + components: darkFrameAccent + count: 4]; + CGContextSetStrokeColorWithColor(context, stroke.CGColor); + CGContextAddLines(context, accent, 2); + CGContextStrokePath(context); + CGContextRestoreGState(context); + break; + default: + break; + } +} + #endif /* MAC_OS_X_VERSION_MIN_REQUIRED >101300 */ /*---------------------------------------------------------------------- @@ -1263,27 +1318,35 @@ static void EntryElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) { - EntryElement *e = elementRecord; - Tk_3DBorder backgroundPtr = Tk_Get3DBorderFromObj(tkwin,e->backgroundObj); Ttk_Box inner = Ttk_PadBox(b, Ttk_UniformPadding(3)); CGRect bounds = BoxToRect(d, inner); - const HIThemeFrameDrawInfo info = { - .version = 0, - .kind = kHIThemeFrameTextFieldSquare, - .state = Ttk_StateTableLookup(ThemeStateTable, state), - .isFocused = state & TTK_STATE_FOCUS, - }; - - /* - * Erase w/background color: - */ - - XFillRectangle(Tk_Display(tkwin), d, - Tk_3DBorderGC(tkwin, backgroundPtr, TK_3D_FLAT_GC), - inner.x, inner.y, inner.width, inner.height); + NSColor *background; BEGIN_DRAWING(d) - ChkErr(HIThemeDrawFrame, &bounds, &info, dc.context, HIOrientation); + if (TkMacOSXInDarkMode(tkwin)) { +#if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + CGFloat fill[4]; + GetBackgroundColor(dc.context, tkwin, 1, fill); + background = [NSColor colorWithColorSpace: deviceRGB + components: fill + count: 4]; + CGContextSetFillColorWithColor(dc.context, background.CGColor); + CGContextFillRect(dc.context, bounds); + DrawDarkFrame(bounds, dc.context, kHIThemeFrameTextFieldSquare); +#endif + } else { + const HIThemeFrameDrawInfo info = { + .version = 0, + .kind = kHIThemeFrameTextFieldSquare, + .state = Ttk_StateTableLookup(ThemeStateTable, state), + .isFocused = state & TTK_STATE_FOCUS, + }; + background = [NSColor textBackgroundColor]; + CGContextSetFillColorWithColor(dc.context, background.CGColor); + CGContextFillRect(dc.context, bounds); + ChkErr(HIThemeDrawFrame, &bounds, &info, dc.context, HIOrientation); + } /*if (state & TTK_STATE_FOCUS) { ChkErr(DrawThemeFocusRect, &bounds, 1); }*/ -- cgit v0.12 From 735733f4486f003380329dab135b932ce9c8b24f Mon Sep 17 00:00:00 2001 From: culler Date: Sat, 6 Apr 2019 20:06:26 +0000 Subject: Rename Tk_GetGeomMaster to TkGetGeomMaster and remove extraneous call to Unlink in tkPack.c. --- generic/tkGrid.c | 2 +- generic/tkInt.h | 2 +- generic/tkPack.c | 3 +-- generic/tkPlace.c | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/generic/tkGrid.c b/generic/tkGrid.c index 81fb4f7..4e0882a 100644 --- a/generic/tkGrid.c +++ b/generic/tkGrid.c @@ -3357,7 +3357,7 @@ ConfigureSlaves( */ for (master = (TkWindow *)masterPtr->tkwin; master != NULL; - master = (TkWindow *)Tk_GetGeomMaster(master)) { + master = (TkWindow *)TkGetGeomMaster(master)) { if (master == (TkWindow *)slave) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't put %s inside %s, would cause management loop", diff --git a/generic/tkInt.h b/generic/tkInt.h index d77c7a9..df0f645 100644 --- a/generic/tkInt.h +++ b/generic/tkInt.h @@ -323,7 +323,7 @@ typedef struct TkDisplay { * by that master. */ int geomInit; -#define Tk_GetGeomMaster(tkwin) (((TkWindow *)tkwin)->maintainerPtr != NULL ? \ +#define TkGetGeomMaster(tkwin) (((TkWindow *)tkwin)->maintainerPtr != NULL ? \ ((TkWindow *)tkwin)->maintainerPtr : ((TkWindow *)tkwin)->parentPtr) /* diff --git a/generic/tkPack.c b/generic/tkPack.c index 9ffcf45..9005d7f 100644 --- a/generic/tkPack.c +++ b/generic/tkPack.c @@ -1804,13 +1804,12 @@ ConfigureSlaves( */ for (master = (TkWindow *)masterPtr->tkwin; master != NULL; - master = (TkWindow *)Tk_GetGeomMaster(master)) { + master = (TkWindow *)TkGetGeomMaster(master)) { if (master == (TkWindow *)slave) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't put %s inside %s, would cause management loop", Tcl_GetString(objv[j]), Tk_PathName(masterPtr->tkwin))); Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "LOOP", NULL); - Unlink(slavePtr); return TCL_ERROR; } } diff --git a/generic/tkPlace.c b/generic/tkPlace.c index 28f94c0..1a52114 100644 --- a/generic/tkPlace.c +++ b/generic/tkPlace.c @@ -701,7 +701,7 @@ ConfigureSlave( */ for (master = (TkWindow *)tkwin; master != NULL; - master = (TkWindow *)Tk_GetGeomMaster(master)) { + master = (TkWindow *)TkGetGeomMaster(master)) { if (master == (TkWindow *)slavePtr->tkwin) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't put %s inside %s, would cause management loop", -- cgit v0.12 From b55c03bb23a82c579ecc2a5f74665e4f4bd2e937 Mon Sep 17 00:00:00 2001 From: fvogel Date: Sun, 7 Apr 2019 08:54:46 +0000 Subject: Better test descriptions for the new tests in grid.test --- tests/grid.test | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/grid.test b/tests/grid.test index e901a93..62474ff 100644 --- a/tests/grid.test +++ b/tests/grid.test @@ -193,13 +193,13 @@ test grid-3.9 {configure: basic argument checking} -body { } -cleanup { grid_reset 3.9 } -returnCodes error -result {invalid window shortcut, "y" should be '-', 'x', or '^'} -test grid-3.10 {configure: basic argument checking} -body { +test grid-3.10 {ConfigureSlave procedure, bad -in option} -body { frame .f grid .f -in .f } -cleanup { grid_reset 3.10 } -returnCodes error -result {window can't be managed in itself} -test grid-3.11 {configure: basic argument checking} -body { +test grid-3.11 {prevent management loops} -body { frame .f1 frame .f2 grid .f1 -in .f2 @@ -207,7 +207,7 @@ test grid-3.11 {configure: basic argument checking} -body { } -cleanup { grid_reset 3.11 } -returnCodes error -result {can't put .f2 inside .f1, would cause management loop} -test grid-3.12 {configure: basic argument checking} -body { +test grid-3.12 {prevent management loops} -body { frame .f1 frame .f2 frame .f3 -- cgit v0.12 From fef2b60c135e004625e5774b7e6acb128fb1a285 Mon Sep 17 00:00:00 2001 From: dgp Date: Mon, 8 Apr 2019 13:06:24 +0000 Subject: unbreak the header --- generic/tk.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generic/tk.h b/generic/tk.h index 966a453..ba099ca 100644 --- a/generic/tk.h +++ b/generic/tk.h @@ -816,7 +816,7 @@ typedef struct Tk_FakeWin { int minReqWidth; int minReqHeight; #ifdef TK_USE_INPUT_METHODS - int dummy21; + int dummy22; #endif /* TK_USE_INPUT_METHODS */ } Tk_FakeWin; -- cgit v0.12 From 5d5e59d73025a9282d60db4092a176d307a9f63e Mon Sep 17 00:00:00 2001 From: culler Date: Mon, 8 Apr 2019 19:19:00 +0000 Subject: Make Treeview headings look correct in both light and dark modes. Make ordinary ttk widgets respond to dark mode by using semantic color defaults. --- library/demos/ttkpane.tcl | 2 +- library/ttk/aquaTheme.tcl | 5 +- macosx/tkMacOSXButton.c | 10 ++ macosx/tkMacOSXDefault.h | 39 +++--- macosx/ttkMacOSXTheme.c | 294 ++++++++++++++++++++++++++++++++++++++-------- 5 files changed, 282 insertions(+), 68 deletions(-) diff --git a/library/demos/ttkpane.tcl b/library/demos/ttkpane.tcl index 7575d76..3f88987 100644 --- a/library/demos/ttkpane.tcl +++ b/library/demos/ttkpane.tcl @@ -104,7 +104,7 @@ if {[tk windowingsystem] ne "aqua"} { pack $w.outer -fill both -expand 1 } else { text $w.txt -wrap word -yscroll "$w.sb set" -width 30 -borderwidth 0 - scrollbar $w.sb -orient vertical -command "$w.txt yview" + ttk::scrollbar $w.sb -orient vertical -command "$w.txt yview" pack $w.sb -side right -fill y -in $w.outer.inRight.bot pack $w.txt -fill both -expand 1 -in $w.outer.inRight.bot pack $w.outer -fill both -expand 1 -padx 10 -pady {6 10} diff --git a/library/ttk/aquaTheme.tcl b/library/ttk/aquaTheme.tcl index 8379c49..77ece22 100644 --- a/library/ttk/aquaTheme.tcl +++ b/library/ttk/aquaTheme.tcl @@ -109,7 +109,10 @@ namespace eval ttk::theme::aqua { } # Treeview: - ttk::style configure Heading -font TkHeadingFont -foreground black + ttk::style configure Heading \ + -font TkHeadingFont \ + -foreground systemTextColor \ + -background systemTtkBackground ttk::style configure Treeview -rowheight 18 \ -background systemTextBackgroundColor \ -foreground systemTextColor \ diff --git a/macosx/tkMacOSXButton.c b/macosx/tkMacOSXButton.c index a335703..0458a2c 100644 --- a/macosx/tkMacOSXButton.c +++ b/macosx/tkMacOSXButton.c @@ -770,6 +770,16 @@ TkMacOSXDrawButton( hiinfo.animation.time.start = hiinfo.animation.time.current; } + /* + * To avoid buttons with white text on a white background, we always + * set the state to inactive in Dark Mode. It isn't perfect but + * it is usable. Using a ttk::button would be a better choice, + * however. + */ + + if (TkMacOSXInDarkMode(butPtr->tkwin)) { + hiinfo.state = kThemeStateInactive; + } HIThemeDrawButton(&cntrRect, &hiinfo, dc.context, kHIThemeOrientationNormal, &contHIRec); diff --git a/macosx/tkMacOSXDefault.h b/macosx/tkMacOSXDefault.h index dd6be69..61fee2d 100644 --- a/macosx/tkMacOSXDefault.h +++ b/macosx/tkMacOSXDefault.h @@ -23,7 +23,9 @@ /* * The definitions below provide symbolic names for the default colors. * NORMAL_BG - Normal background color. + * NORMAL_FG - Normal foreground color. * ACTIVE_BG - Background color when widget is active. + * ACTIVE_FG - Foreground color when widget is active. * SELECT_BG - Background color for selected text. * SELECT_FG - Foreground color for selected text. * TROUGH - Background color for troughs in scales and scrollbars. @@ -33,12 +35,13 @@ #define BLACK "Black" #define WHITE "White" -#define NORMAL_BG "systemWindowBody" -#define ACTIVE_BG "systemButtonFacePressed" -#define ACTIVE_FG "systemPushButtonPressedText" -#define SELECT_BG "systemHighlight" -#define SELECT_FG NULL -#define INACTIVE_SELECT_BG "systemHighlightSecondary" +#define NORMAL_BG "systemTextBackgroundColor" +#define NORMAL_FG "systemTextColor" +#define ACTIVE_BG "systemTextBackgroundColor" +#define ACTIVE_FG "systemTextColor" +#define SELECT_BG "systemSelectedTextBackgroundColor" +#define SELECT_FG "systemSelectedTextColor" +#define INACTIVE_SELECT_BG "systemSelectedTextBackgroundColor" #define TROUGH "#c3c3c3" #define INDICATOR "#b03060" #define DISABLED "#a3a3a3" @@ -54,7 +57,7 @@ #define DEF_CHKRAD_ACTIVE_FG_COLOR DEF_BUTTON_ACTIVE_FG_COLOR #define DEF_BUTTON_ACTIVE_FG_MONO WHITE /* #define DEF_BUTTON_BG_COLOR "systemButtonFace"*/ -#define DEF_BUTTON_BG_COLOR WHITE +#define DEF_BUTTON_BG_COLOR NORMAL_BG #define DEF_BUTTON_BG_MONO WHITE #define DEF_BUTTON_BITMAP "" #define DEF_BUTTON_BORDER_WIDTH "2" @@ -64,7 +67,7 @@ #define DEF_BUTTON_DEFAULT "disabled" #define DEF_BUTTON_DISABLED_FG_COLOR DISABLED #define DEF_BUTTON_DISABLED_FG_MONO "" -#define DEF_BUTTON_FG "systemButtonText" +#define DEF_BUTTON_FG NORMAL_FG #define DEF_CHKRAD_FG DEF_BUTTON_FG #define DEF_BUTTON_FONT "TkDefaultFont" #define DEF_BUTTON_HEIGHT "0" @@ -178,12 +181,12 @@ #define DEF_ENTRY_DISABLED_FG DISABLED #define DEF_ENTRY_EXPORT_SELECTION "1" #define DEF_ENTRY_FONT "TkTextFont" -#define DEF_ENTRY_FG BLACK +#define DEF_ENTRY_FG NORMAL_FG #define DEF_ENTRY_HIGHLIGHT_BG NORMAL_BG #define DEF_ENTRY_HIGHLIGHT BLACK /* #define DEF_ENTRY_HIGHLIGHT_WIDTH "3" */ #define DEF_ENTRY_HIGHLIGHT_WIDTH "3" -#define DEF_ENTRY_INSERT_BG BLACK +#define DEF_ENTRY_INSERT_BG NORMAL_FG #define DEF_ENTRY_INSERT_BD_COLOR "0" #define DEF_ENTRY_INSERT_BD_MONO "0" #define DEF_ENTRY_INSERT_OFF_TIME "300" @@ -237,7 +240,7 @@ #define DEF_LABELFRAME_BORDER_WIDTH "2" #define DEF_LABELFRAME_CLASS "Labelframe" #define DEF_LABELFRAME_RELIEF "groove" -#define DEF_LABELFRAME_FG "systemButtonText" +#define DEF_LABELFRAME_FG NORMAL_FG #define DEF_LABELFRAME_FONT "TkDefaultFont" #define DEF_LABELFRAME_TEXT "" #define DEF_LABELFRAME_LABELANCHOR "nw" @@ -247,14 +250,14 @@ */ #define DEF_LISTBOX_ACTIVE_STYLE "dotbox" -#define DEF_LISTBOX_BG_COLOR WHITE +#define DEF_LISTBOX_BG_COLOR NORMAL_BG #define DEF_LISTBOX_BG_MONO WHITE #define DEF_LISTBOX_BORDER_WIDTH "1" #define DEF_LISTBOX_CURSOR "" #define DEF_LISTBOX_DISABLED_FG DISABLED #define DEF_LISTBOX_EXPORT_SELECTION "1" #define DEF_LISTBOX_FONT "TkTextFont" -#define DEF_LISTBOX_FG BLACK +#define DEF_LISTBOX_FG NORMAL_FG #define DEF_LISTBOX_HEIGHT "10" #define DEF_LISTBOX_HIGHLIGHT_BG NORMAL_BG #define DEF_LISTBOX_HIGHLIGHT BLACK @@ -348,7 +351,7 @@ #define DEF_MENUBUTTON_DISABLED_FG_COLOR DISABLED #define DEF_MENUBUTTON_DISABLED_FG_MONO "" #define DEF_MENUBUTTON_FONT "TkDefaultFont" -#define DEF_MENUBUTTON_FG BLACK +#define DEF_MENUBUTTON_FG NORMAL_FG #define DEF_MENUBUTTON_HEIGHT "0" #define DEF_MENUBUTTON_HIGHLIGHT_BG_COLOR DEF_MENUBUTTON_BG_COLOR #define DEF_MENUBUTTON_HIGHLIGHT_BG_MONO DEF_MENUBUTTON_BG_MONO @@ -379,7 +382,7 @@ #define DEF_MESSAGE_BG_MONO WHITE #define DEF_MESSAGE_BORDER_WIDTH "1" #define DEF_MESSAGE_CURSOR "" -#define DEF_MESSAGE_FG BLACK +#define DEF_MESSAGE_FG NORMAL_FG #define DEF_MESSAGE_FONT "TkDefaultFont" #define DEF_MESSAGE_HIGHLIGHT_BG NORMAL_BG #define DEF_MESSAGE_HIGHLIGHT BLACK @@ -443,7 +446,7 @@ #define DEF_SCALE_CURSOR "" #define DEF_SCALE_DIGITS "0" #define DEF_SCALE_FONT "TkDefaultFont" -#define DEF_SCALE_FG_COLOR BLACK +#define DEF_SCALE_FG_COLOR NORMAL_FG #define DEF_SCALE_FG_MONO BLACK #define DEF_SCALE_FROM "0" #define DEF_SCALE_HIGHLIGHT_BG_COLOR DEF_SCALE_BG_COLOR @@ -505,14 +508,14 @@ #define DEF_TEXT_BLOCK_CURSOR "0" #define DEF_TEXT_BORDER_WIDTH "0" #define DEF_TEXT_CURSOR "xterm" -#define DEF_TEXT_FG BLACK +#define DEF_TEXT_FG NORMAL_FG #define DEF_TEXT_EXPORT_SELECTION "1" #define DEF_TEXT_FONT "TkFixedFont" #define DEF_TEXT_HEIGHT "24" #define DEF_TEXT_HIGHLIGHT_BG NORMAL_BG #define DEF_TEXT_HIGHLIGHT BLACK #define DEF_TEXT_HIGHLIGHT_WIDTH "3" -#define DEF_TEXT_INSERT_BG BLACK +#define DEF_TEXT_INSERT_BG NORMAL_FG #define DEF_TEXT_INSERT_BD_COLOR "0" #define DEF_TEXT_INSERT_BD_MONO "0" #define DEF_TEXT_INSERT_OFF_TIME "300" diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index c249051..b278794 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -54,6 +54,7 @@ #define TTK_STATE_FIRST_TAB TTK_STATE_USER1 #define TTK_STATE_LAST_TAB TTK_STATE_USER2 +#define TTK_TREEVIEW_STATE_SORTARROW TTK_STATE_USER1 /*---------------------------------------------------------------------- * +++ Utilities. @@ -142,6 +143,8 @@ static CGRect NormalizeButtonBounds( */ static CGFloat windowBackground[4] = {235.0/255, 235.0/255, 235.0/255, 1.0}; +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 -- @@ -290,6 +293,139 @@ static void GradientFillRoundedRectangle( CFRelease(gradient); } + +static void DrawUpDownArrows( + CGContextRef context, + CGRect bounds, + CGFloat inset, + CGFloat size, + CGFloat *rgba) +{ + CGFloat x, y; + CGContextSetRGBStrokeColor(context, rgba[0], rgba[1], rgba[2], rgba[3]); + CGContextSetLineWidth(context, 1.5); + x = bounds.origin.x + inset; + y = bounds.origin.y + trunc(bounds.size.height/2); + CGContextBeginPath(context); + CGPoint bottomArrow[3] = {{x, y+2}, {x+size/2, y+2+size/2}, {x+size, y+2}}; + CGContextAddLines(context, bottomArrow, 3); + CGPoint topArrow[3] = {{x, y-2}, {x+size/2, y-2-size/2}, {x+size, y-2}}; + CGContextAddLines(context, topArrow, 3); + CGContextStrokePath(context); +} + +static void DrawDownArrow( + CGContextRef context, + CGRect bounds, + CGFloat inset, + CGFloat size, + CGFloat *rgba) +{ + CGFloat x, y; + CGContextSetRGBStrokeColor(context, rgba[0], rgba[1], rgba[2], rgba[3]); + CGContextSetLineWidth(context, 1.5); + x = bounds.origin.x + inset; + y = bounds.origin.y + trunc(bounds.size.height/2); + CGContextBeginPath(context); + CGPoint arrow[3] = {{x, y-size/4}, {x+size/2, y+size/4}, {x+size, y-size/4}}; + CGContextAddLines(context, arrow, 3); + CGContextStrokePath(context); +} + +static void DrawUpArrow( + CGContextRef context, + CGRect bounds, + CGFloat inset, + CGFloat size, + CGFloat *rgba) +{ + CGFloat x, y; + CGContextSetRGBStrokeColor(context, rgba[0], rgba[1], rgba[2], rgba[3]); + CGContextSetLineWidth(context, 1.5); + x = bounds.origin.x + inset; + y = bounds.origin.y + trunc(bounds.size.height/2); + CGContextBeginPath(context); + CGPoint arrow[3] = {{x, y+size/4}, {x+size/2, y-size/4}, {x+size, y+size/4}}; + CGContextAddLines(context, arrow, 3); + CGContextStrokePath(context); +} + +/* + * DrawListHeader -- + * + * This is a standalone drawing procedure which draws column + * headers for a Treeview in the Aqua appearance. The HITheme + * headers have not matched the native ones since OSX 10.8. + * Note that the header image is ignored, but we draw arrows + * according to the state. + */ + +static void DrawListHeader( + CGRect bounds, + CGContextRef context, + Tk_Window tkwin, + int state) +{ + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + NSColor *strokeColor, *bgColor; + static CGFloat borderRGBA[4] = {200.0/255, 200.0/255, 200.0/255, 1.0}; + static CGFloat separatorRGBA[4] = {220.0/255, 220.0/255, 220.0/255, 1.0}; + static CGFloat activeBgRGBA[4] = {238.0/255, 238.0/255, 238.0/255, 1.0}; + static CGFloat inactiveBgRGBA[4] = {246.0/255, 246.0/255, 246.0/255, 1.0}; + + /* + * Apple changes the background of a list header when the window is not + * active. But Ttk does not indicate that in the state of a TreeHeader. + * So we have to query the Apple window manager. + */ + + NSWindow *win = TkMacOSXDrawableWindow(Tk_WindowId(tkwin)); + CGFloat *bgRGBA = [win isKeyWindow] ? activeBgRGBA : inactiveBgRGBA; + CGFloat x = bounds.origin.x, y = bounds.origin.y; + CGFloat w = bounds.size.width, h = bounds.size.height; + CGPoint top[2] = {{x, y + 1}, {x + w, y + 1}}; + CGPoint bottom[2] = {{x, y + h}, {x + w, y + h}}; + CGPoint separator[2] = {{x + w - 1, y + 3}, {x + w - 1, y + h - 3}}; + + bgColor = [NSColor colorWithColorSpace: deviceRGB + components: bgRGBA + count: 4]; + CGContextSaveGState(context); + CGContextSetShouldAntialias(context, false); + CGContextSetFillColorSpace(context, deviceRGB.CGColorSpace); + CGContextSetStrokeColorSpace(context, deviceRGB.CGColorSpace); + CGContextBeginPath(context); + CGContextSetFillColorWithColor(context, bgColor.CGColor); + CGContextAddRect(context, bounds); + CGContextFillPath(context); + strokeColor = [NSColor colorWithColorSpace: deviceRGB + components: separatorRGBA + count: 4]; + CGContextSetStrokeColorWithColor(context, strokeColor.CGColor); + CGContextAddLines(context, separator, 2); + CGContextStrokePath(context); + strokeColor = [NSColor colorWithColorSpace: deviceRGB + components: borderRGBA + count: 4]; + CGContextSetStrokeColorWithColor(context, strokeColor.CGColor); + CGContextAddLines(context, top, 2); + CGContextStrokePath(context); + CGContextAddLines(context, bottom, 2); + CGContextStrokePath(context); + CGContextRestoreGState(context); + + if (state & TTK_TREEVIEW_STATE_SORTARROW) { + CGRect arrowBounds = bounds; + arrowBounds.origin.x = bounds.origin.x + bounds.size.width - 16; + arrowBounds.size.width = 16; + if (state & TTK_STATE_ALTERNATE) { + DrawUpArrow(context, arrowBounds, 3, 8, blackRGBA); + } else if (state & TTK_STATE_SELECTED) { + DrawDownArrow(context, arrowBounds, 3, 8, blackRGBA); + } + } +} + #endif /* MAC_OS_X_VERSION_MIN_REQUIRED > 1080 */ #if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 @@ -378,43 +514,6 @@ static void HighlightButtonBorder( CFRelease(topGradient); } - -static void DrawUpDownArrows( - CGContextRef context, - CGRect bounds, - CGFloat inset, - CGFloat size) -{ - CGFloat x, y; - CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0); - CGContextSetLineWidth(context, 1.5); - x = bounds.origin.x + inset; - y = bounds.origin.y + trunc(bounds.size.height/2); - CGContextBeginPath(context); - CGPoint bottomArrow[3] = {{x, y+2}, {x+size/2, y+2+size/2}, {x+size, y+2}}; - CGContextAddLines(context, bottomArrow, 3); - CGPoint topArrow[3] = {{x, y-2}, {x+size/2, y-2-size/2}, {x+size, y-2}}; - CGContextAddLines(context, topArrow, 3); - CGContextStrokePath(context); -} - -static void DrawDownArrow( - CGContextRef context, - CGRect bounds, - CGFloat inset, - CGFloat size) -{ - CGFloat x, y; - CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0); - CGContextSetLineWidth(context, 1.5); - x = bounds.origin.x + inset; - y = bounds.origin.y + trunc(bounds.size.height/2); - CGContextBeginPath(context); - CGPoint bottomArrow[3] = {{x, y-size/2}, {x+size/2, y+size/2}, {x+size, y-size/2}}; - CGContextAddLines(context, bottomArrow, 3); - CGContextStrokePath(context); -} - /* * DrawDarkButton -- * @@ -481,9 +580,9 @@ static void DrawDarkButton( darkSelectedGradient, 2); } if (kind == kThemePopupButton) { - DrawUpDownArrows(context, arrowBounds, 5, 7); + DrawUpDownArrows(context, arrowBounds, 3, 7, whiteRGBA); } else { - DrawDownArrow(context, arrowBounds, 5, 7); + DrawDownArrow(context, arrowBounds, 4, 8, whiteRGBA); } } @@ -542,7 +641,7 @@ static void DrawDarkIncDecButton( darkSelectedGradient, 2); CGContextRestoreGState(context); } - DrawUpDownArrows(context, bounds, 3, 5); + DrawUpDownArrows(context, bounds, 3, 5, whiteRGBA); HighlightButtonBorder(context, bounds); } @@ -841,11 +940,11 @@ static void DrawDarkFrame( case kHIThemeFrameTextFieldSquare: CGContextSaveGState(context); CGContextSetShouldAntialias(context, false); + CGContextBeginPath(context); stroke = [NSColor colorWithColorSpace: deviceRGB components: darkFrameTop count: 4]; CGContextSetStrokeColorWithColor(context, stroke.CGColor); - CGContextBeginPath(context); CGContextAddLines(context, topPart, 4); CGContextStrokePath(context); stroke = [NSColor colorWithColorSpace: deviceRGB @@ -866,7 +965,56 @@ static void DrawDarkFrame( break; } } - + +/* + * DrawListHeader -- + * + * This is a standalone drawing procedure which draws column + * headers for a Treeview in the Dark Mode. + */ + +static void DrawDarkListHeader( + CGRect bounds, + CGContextRef context, + Tk_Window tkwin, + int state) +{ + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + NSColor *stroke; + CGContextSetStrokeColorSpace(context, deviceRGB.CGColorSpace); + CGFloat x = bounds.origin.x, y = bounds.origin.y; + CGFloat w = bounds.size.width, h = bounds.size.height; + CGPoint top[2] = {{x, y}, {x + w, y}}; + CGPoint bottom[2] = {{x, y + h}, {x + w, y + h}}; + CGPoint separator[2] = {{x + w, y + 3}, {x + w, y + h - 3}}; + + CGContextSaveGState(context); + CGContextSetShouldAntialias(context, false); + stroke = [NSColor colorWithColorSpace: deviceRGB + components: darkFrameBottom + count: 4]; + CGContextSetStrokeColorWithColor(context, stroke.CGColor); + CGContextBeginPath(context); + CGContextAddLines(context, top, 2); + CGContextStrokePath(context); + CGContextAddLines(context, bottom, 2); + CGContextStrokePath(context); + CGContextAddLines(context, separator, 2); + CGContextStrokePath(context); + CGContextRestoreGState(context); + + if (state & TTK_TREEVIEW_STATE_SORTARROW) { + CGRect arrowBounds = bounds; + arrowBounds.origin.x = bounds.origin.x + bounds.size.width - 16; + arrowBounds.size.width = 16; + if (state & TTK_STATE_ALTERNATE) { + DrawUpArrow(context, arrowBounds, 3, 8, whiteRGBA); + } else if (state & TTK_STATE_SELECTED) { + DrawDownArrow(context, arrowBounds, 3, 8, whiteRGBA); + } + } +} + #endif /* MAC_OS_X_VERSION_MIN_REQUIRED >101300 */ /*---------------------------------------------------------------------- @@ -1057,8 +1205,8 @@ static void ButtonElementDraw( #if MAC_OS_X_VERSION_MIN_REQUIRED > 1080 if (info.kind == kThemePopupButton && (state & TTK_STATE_BACKGROUND)) { CGRect innerBounds = CGRectInset(bounds, 1, 1); - NSColor *white = [NSColor whiteColor]; - SolidFillRoundedRectangle(dc.context, innerBounds, 4, white); + NSColor *whiteRGBA = [NSColor whiteColor]; + SolidFillRoundedRectangle(dc.context, innerBounds, 4, whiteRGBA); } #endif @@ -1303,7 +1451,7 @@ typedef struct { static Ttk_ElementOptionSpec EntryElementOptions[] = { { "-background", TK_OPTION_BORDER, - Tk_Offset(EntryElement,backgroundObj), "white" }, + Tk_Offset(EntryElement,backgroundObj), "whiteRGBA" }, {0} }; @@ -2298,7 +2446,6 @@ static Ttk_ElementSpec FieldElementSpec = { * Redefine the header to use a kThemeListHeaderButton. */ -#define TTK_TREEVIEW_STATE_SORTARROW TTK_STATE_USER1 static Ttk_StateTable TreeHeaderValueTable[] = { { kThemeButtonOn, TTK_STATE_ALTERNATE}, { kThemeButtonOn, TTK_STATE_SELECTED}, @@ -2315,6 +2462,41 @@ static Ttk_StateTable TreeHeaderAdornmentTable[] = { { kThemeAdornmentNone, 0} }; +static void TreeAreaElementSize ( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) +{ + /* + * Padding is needed to get the heading text to align correctly, since the + * widget expects the heading to be the same height as a row. + */ + + if ([NSApp macMinorVersion] > 8) { + paddingPtr->top = 4; + } +} + +static Ttk_ElementSpec TreeAreaElementSpec = { + TK_STYLE_VERSION_2, + sizeof(NullElement), + TtkNullElementOptions, + TreeAreaElementSize, + TtkNullElementDraw +}; + +static void TreeHeaderElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) +{ + if ([NSApp macMinorVersion] > 8) { + *minHeight = 24; + + } else { + ButtonElementSize(clientData, elementRecord, tkwin, minWidth, + minHeight, paddingPtr); + } +} + static void TreeHeaderElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) @@ -2330,7 +2512,22 @@ static void TreeHeaderElementDraw( }; BEGIN_DRAWING(d) - ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); + if ([NSApp macMinorVersion] > 8) { + + /* + * Compensate for the padding added in TreeHeaderElementSize, so + * the larger heading will be drawn at the top of the widget. + */ + + bounds.origin.y -= 4; + if (TkMacOSXInDarkMode(tkwin)) { + DrawDarkListHeader(bounds, dc.context, tkwin, state); + } else { + DrawListHeader(bounds, dc.context, tkwin, state); + } + } else { + ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); + } END_DRAWING } @@ -2338,7 +2535,7 @@ static Ttk_ElementSpec TreeHeaderElementSpec = { TK_STYLE_VERSION_2, sizeof(NullElement), TtkNullElementOptions, - ButtonElementSize, + TreeHeaderElementSize, TreeHeaderElementDraw }; @@ -2524,6 +2721,7 @@ static int AquaTheme_Init(Tcl_Interp *interp) Ttk_RegisterElementSpec(themePtr, "Treeheading.cell", &TreeHeaderElementSpec, &ListHeaderParams); + Ttk_RegisterElementSpec(themePtr, "Treeview.treearea", &TreeAreaElementSpec, 0); Ttk_RegisterElementSpec(themePtr, "Notebook.tab", &TabElementSpec, 0); Ttk_RegisterElementSpec(themePtr, "Notebook.client", &PaneElementSpec, 0); -- cgit v0.12 From 7c1acea352995895a3152bfa54230a3b6e3091f6 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 8 Apr 2019 21:20:37 +0000 Subject: Put new fields always at the end of struct TkWindow, so existing fields keep the same offset in the struct: We don't want to recompile Tk extensions using tkInt.h directly .... --- generic/tk.h | 16 ++++++++-------- generic/tkInt.h | 10 +++++----- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/generic/tk.h b/generic/tk.h index ba099ca..9312235 100644 --- a/generic/tk.h +++ b/generic/tk.h @@ -676,7 +676,7 @@ typedef struct { * request. */ Display *display; /* Display the event was read from. */ Window event; /* Window on which event was requested. */ - Window root; /* Root window that the event occured on. */ + Window root; /* Root window that the event occurred on. */ Window subwindow; /* Child window. */ Time time; /* Milliseconds. */ int x, y; /* Pointer x, y coordinates in event @@ -802,22 +802,22 @@ typedef struct Tk_FakeWin { char *dummy13; /* selHandlerList */ char *dummy14; /* geomMgrPtr */ ClientData dummy15; /* geomData */ - char *dummy16; /* geomMgrName */ - Tk_Window dummy17; /* maintainerPtr */ int reqWidth, reqHeight; int internalBorderLeft; - char *dummy18; /* wmInfoPtr */ - char *dummy19; /* classProcPtr */ - ClientData dummy20; /* instanceData */ - char *dummy21; /* privatePtr */ + char *dummy16; /* wmInfoPtr */ + char *dummy17; /* classProcPtr */ + ClientData dummy18; /* instanceData */ + char *dummy19; /* privatePtr */ int internalBorderRight; int internalBorderTop; int internalBorderBottom; int minReqWidth; int minReqHeight; #ifdef TK_USE_INPUT_METHODS - int dummy22; + int dummy20; #endif /* TK_USE_INPUT_METHODS */ + char *dummy21; /* geomMgrName */ + Tk_Window dummy22; /* maintainerPtr */ } Tk_FakeWin; /* diff --git a/generic/tkInt.h b/generic/tkInt.h index df0f645..a80d209 100644 --- a/generic/tkInt.h +++ b/generic/tkInt.h @@ -772,11 +772,6 @@ typedef struct TkWindow { /* Information about geometry manager for this * window. */ ClientData geomData; /* Argument for geometry manager functions. */ - char *geomMgrName; /* Records the name of the geometry manager. */ - struct TkWindow *maintainerPtr; - /* The geometry master for this window. The - * value is NULL if the window has no master or - * if its master is its parent. */ int reqWidth, reqHeight; /* Arguments from last call to * Tk_GeometryRequest, or 0's if * Tk_GeometryRequest hasn't been called. */ @@ -823,6 +818,11 @@ typedef struct TkWindow { #ifdef TK_USE_INPUT_METHODS int ximGeneration; /* Used to invalidate XIC */ #endif /* TK_USE_INPUT_METHODS */ + char *geomMgrName; /* Records the name of the geometry manager. */ + struct TkWindow *maintainerPtr; + /* The geometry master for this window. The + * value is NULL if the window has no master or + * if its master is its parent. */ } TkWindow; /* -- cgit v0.12 From 16e5962b61d6bd5bbfebcbb4b1efad6a813fd6df Mon Sep 17 00:00:00 2001 From: culler Date: Wed, 10 Apr 2019 02:08:14 +0000 Subject: Update README. --- macosx/README | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/macosx/README b/macosx/README index c79c372..cca90c5 100644 --- a/macosx/README +++ b/macosx/README @@ -285,8 +285,42 @@ ensure that we maintain consistency, changing the tabbingIdentifier of a window which is already displayed as a tab will also cause it to become a separate window. - -4. Building Tcl/Tk on macOS +4. Ttk, Dark Mode and semantic colors +--------------------------------------- + +With the release of OSX 10.14 (Mojave), Apple introduced the DarkAqua +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, and systemLabelColor. +All of these except systemLabelColor, which was introduced in 10.10, were +present in OSX 10.0. 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. + +Apple's tab view and GroupBox objects delimit their content by +displaying it within a rounded rectangle with a background color that +contrasts with the background of the containing object. This means +that the background color of a Ttk widget depends on how deeply it is +nested inside of other widgets that use contrasting backgrounds. To +support this, there are 8 contrasting system colors named +systemTtkBackground, systemTtkBackground1, ... , systemTtkBackground7. +The systemTtkBackground color is the standard background for a dialog +window and the others match the contrasting background colors for +backgrounds which are nested to the corresponding depth. + +5. Building Tcl/Tk on macOS ------------------------------ - At least macOS 10.3 is required to build Tcl and TkX11, and macOS 10.6 -- cgit v0.12 From 4a859d21b93649274665f6221db407fd429a2942 Mon Sep 17 00:00:00 2001 From: culler Date: Wed, 10 Apr 2019 18:47:11 +0000 Subject: Make -fieldbackground work for ttk::entry and ttk::spinbox, but retain the old behavior of -background if -fieldbackground is not specified. --- doc/ttk_entry.n | 6 +++--- doc/ttk_spinbox.n | 8 ++++---- macosx/ttkMacOSXTheme.c | 44 ++++++++++++++++++++++++++++++++++++++------ 3 files changed, 45 insertions(+), 13 deletions(-) diff --git a/doc/ttk_entry.n b/doc/ttk_entry.n index d752670..3a30e4d 100644 --- a/doc/ttk_entry.n +++ b/doc/ttk_entry.n @@ -472,7 +472,9 @@ are: .PP \fB\-background\fP \fIcolor\fP .RS -When using the aqua theme (Mac OS X), changes the \fB\-fieldbackground\fP. +For backwards compatibility, when using the aqua theme (for macOS), this +option behaves as an alias for the \fB\-fieldbackground\fP provided that no +value is specified for \fB\-fieldbackground\fP. Otherwise it is ignored. .RE \fB\-bordercolor\fP \fIcolor\fP .br @@ -480,8 +482,6 @@ When using the aqua theme (Mac OS X), changes the \fB\-fieldbackground\fP. .br \fB\-fieldbackground\fP \fIcolor\fP .RS -Does not work with the aqua theme (Mac OS X). -.br Some themes use a graphical background and their field background colors cannot be changed. .RE \fB\-foreground\fP \fIcolor\fP diff --git a/doc/ttk_spinbox.n b/doc/ttk_spinbox.n index 325d4d8..9ae9881 100644 --- a/doc/ttk_spinbox.n +++ b/doc/ttk_spinbox.n @@ -95,16 +95,16 @@ are: .br \fB\-background\fP \fIcolor\fP .RS -When using the aqua theme (Mac OS X), changes the \fB\-fieldbackground\fP. +For backwards compatibility, when using the aqua theme (for macOS), this +option behaves as an alias for the \fB\-fieldbackground\fP provided that no +value is specified for \fB\-fieldbackground\fP. Otherwise it is ignored. .RE \fB\-bordercolor\fP \fIcolor\fP .br \fB\-darkcolor\fP \fIcolor\fP .br \fB\-fieldbackground\fP \fIcolor\fP -.RS -Does not work with the aqua theme (Mac OS X). -.RE +.br \fB\-foreground\fP \fIcolor\fP .br \fB\-lightcolor\fP \fIcolor\fP diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index b278794..65e6d18 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -1447,11 +1447,16 @@ static Ttk_ElementSpec GroupElementSpec = { typedef struct { Tcl_Obj *backgroundObj; + Tcl_Obj *fieldbackgroundObj; } EntryElement; +#define ENTRY_DEFAULT_BACKGROUND "systemTextBackgroundColor" + static Ttk_ElementOptionSpec EntryElementOptions[] = { { "-background", TK_OPTION_BORDER, - Tk_Offset(EntryElement,backgroundObj), "whiteRGBA" }, + Tk_Offset(EntryElement,backgroundObj), ENTRY_DEFAULT_BACKGROUND }, + { "-fieldbackground", TK_OPTION_BORDER, + Tk_Offset(EntryElement,fieldbackgroundObj), ENTRY_DEFAULT_BACKGROUND }, {0} }; @@ -1466,13 +1471,16 @@ static void EntryElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) { + EntryElement *e = elementRecord; Ttk_Box inner = Ttk_PadBox(b, Ttk_UniformPadding(3)); CGRect bounds = BoxToRect(d, inner); NSColor *background; + Tk_3DBorder backgroundPtr = NULL; + static char *defaultBG = ENTRY_DEFAULT_BACKGROUND; - BEGIN_DRAWING(d) if (TkMacOSXInDarkMode(tkwin)) { #if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 + BEGIN_DRAWING(d) NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; CGFloat fill[4]; GetBackgroundColor(dc.context, tkwin, 1, fill); @@ -1482,6 +1490,7 @@ static void EntryElementDraw( CGContextSetFillColorWithColor(dc.context, background.CGColor); CGContextFillRect(dc.context, bounds); DrawDarkFrame(bounds, dc.context, kHIThemeFrameTextFieldSquare); + END_DRAWING #endif } else { const HIThemeFrameDrawInfo info = { @@ -1490,15 +1499,38 @@ static void EntryElementDraw( .state = Ttk_StateTableLookup(ThemeStateTable, state), .isFocused = state & TTK_STATE_FOCUS, }; - background = [NSColor textBackgroundColor]; - CGContextSetFillColorWithColor(dc.context, background.CGColor); - CGContextFillRect(dc.context, bounds); + + /* + * Earlier versions of the Aqua theme ignored the -fieldbackground + * option and used the -background as if it were -fieldbackground. + * Here we are enabling -fieldbackground. For backwards compatibility, + * if -fieldbackground is set to the default color and -background + * is set to a different color then we use -background as -fieldbackground. + */ + + if (0 != strcmp(Tcl_GetString(e->fieldbackgroundObj), defaultBG)) { + backgroundPtr = Tk_Get3DBorderFromObj(tkwin,e->fieldbackgroundObj); + } else if (0 != strcmp(Tcl_GetString(e->backgroundObj), defaultBG)) { + backgroundPtr = Tk_Get3DBorderFromObj(tkwin,e->backgroundObj); + } + if (backgroundPtr != NULL) { + XFillRectangle(Tk_Display(tkwin), d, + Tk_3DBorderGC(tkwin, backgroundPtr, TK_3D_FLAT_GC), + inner.x, inner.y, inner.width, inner.height); + } + BEGIN_DRAWING(d) + if (backgroundPtr == NULL) { + CGRect innerRect = CGRectInset(bounds, 3, 3); + background = [NSColor textBackgroundColor]; + CGContextSetFillColorWithColor(dc.context, background.CGColor); + CGContextFillRect(dc.context, bounds); + } ChkErr(HIThemeDrawFrame, &bounds, &info, dc.context, HIOrientation); + END_DRAWING } /*if (state & TTK_STATE_FOCUS) { ChkErr(DrawThemeFocusRect, &bounds, 1); }*/ - END_DRAWING } static Ttk_ElementSpec EntryElementSpec = { -- cgit v0.12 From 913da88ce3f1ecc4a95e4b21dfa50c69ed753aad Mon Sep 17 00:00:00 2001 From: culler Date: Wed, 10 Apr 2019 19:41:49 +0000 Subject: Remove unused variable. --- macosx/ttkMacOSXTheme.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index 65e6d18..02dd7e4 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -1379,7 +1379,7 @@ static void PaneElementDraw( }; bounds.origin.y -= kThemeMetricTabFrameOverlap; bounds.size.height += kThemeMetricTabFrameOverlap; - ChkErr(HIThemeDrawTabPane, &bounds, &info, dc.context, HIOrientation); + ChkErr(HIThemeDrawTabPane, &bounds, &info, dc.context, HIOrieRectntation); #endif END_DRAWING [TkMacOSXDrawableView(macWin) setNeedsDisplay:YES]; @@ -1520,7 +1520,6 @@ static void EntryElementDraw( } BEGIN_DRAWING(d) if (backgroundPtr == NULL) { - CGRect innerRect = CGRectInset(bounds, 3, 3); background = [NSColor textBackgroundColor]; CGContextSetFillColorWithColor(dc.context, background.CGColor); CGContextFillRect(dc.context, bounds); -- cgit v0.12 From d95284c405fba9c6f6222e1af119f5ba73b4443a Mon Sep 17 00:00:00 2001 From: fvogel Date: Wed, 10 Apr 2019 19:50:53 +0000 Subject: Fix [368fa4561e]: ttk::treeview open/closed indicators can be toggled while hidden --- library/ttk/treeview.tcl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/library/ttk/treeview.tcl b/library/ttk/treeview.tcl index 1ed87db..6a6f5d4 100644 --- a/library/ttk/treeview.tcl +++ b/library/ttk/treeview.tcl @@ -336,6 +336,12 @@ proc ttk::treeview::CloseItem {w item} { ## Toggle -- toggle opened/closed state of item # proc ttk::treeview::Toggle {w item} { + # don't allow toggling on indicators that + # are not present in front of leaf items + if {[$w children $item] == {}} { + return + } + # not a leaf, toggle! if {[$w item $item -open]} { CloseItem $w $item } else { -- cgit v0.12 From c40319586abe475d1861ac8925b4fcef35f56c32 Mon Sep 17 00:00:00 2001 From: culler Date: Thu, 11 Apr 2019 03:47:02 +0000 Subject: Synchronize the generic tk headers with core-8-6-branch. --- generic/tk.h | 16 ++++++++-------- generic/tkInt.h | 8 +++++--- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/generic/tk.h b/generic/tk.h index 966a453..9312235 100644 --- a/generic/tk.h +++ b/generic/tk.h @@ -676,7 +676,7 @@ typedef struct { * request. */ Display *display; /* Display the event was read from. */ Window event; /* Window on which event was requested. */ - Window root; /* Root window that the event occured on. */ + Window root; /* Root window that the event occurred on. */ Window subwindow; /* Child window. */ Time time; /* Milliseconds. */ int x, y; /* Pointer x, y coordinates in event @@ -802,22 +802,22 @@ typedef struct Tk_FakeWin { char *dummy13; /* selHandlerList */ char *dummy14; /* geomMgrPtr */ ClientData dummy15; /* geomData */ - char *dummy16; /* geomMgrName */ - Tk_Window dummy17; /* maintainerPtr */ int reqWidth, reqHeight; int internalBorderLeft; - char *dummy18; /* wmInfoPtr */ - char *dummy19; /* classProcPtr */ - ClientData dummy20; /* instanceData */ - char *dummy21; /* privatePtr */ + char *dummy16; /* wmInfoPtr */ + char *dummy17; /* classProcPtr */ + ClientData dummy18; /* instanceData */ + char *dummy19; /* privatePtr */ int internalBorderRight; int internalBorderTop; int internalBorderBottom; int minReqWidth; int minReqHeight; #ifdef TK_USE_INPUT_METHODS - int dummy21; + int dummy20; #endif /* TK_USE_INPUT_METHODS */ + char *dummy21; /* geomMgrName */ + Tk_Window dummy22; /* maintainerPtr */ } Tk_FakeWin; /* diff --git a/generic/tkInt.h b/generic/tkInt.h index 53e1698..a80d209 100644 --- a/generic/tkInt.h +++ b/generic/tkInt.h @@ -772,9 +772,6 @@ typedef struct TkWindow { /* Information about geometry manager for this * window. */ ClientData geomData; /* Argument for geometry manager functions. */ - char *geomMgrName; /* Records the name of the geometry manager. */ - struct TkWindow *maintainerPtr; - /* The master assigned by Tk_MaintainGeometry.*/ int reqWidth, reqHeight; /* Arguments from last call to * Tk_GeometryRequest, or 0's if * Tk_GeometryRequest hasn't been called. */ @@ -821,6 +818,11 @@ typedef struct TkWindow { #ifdef TK_USE_INPUT_METHODS int ximGeneration; /* Used to invalidate XIC */ #endif /* TK_USE_INPUT_METHODS */ + char *geomMgrName; /* Records the name of the geometry manager. */ + struct TkWindow *maintainerPtr; + /* The geometry master for this window. The + * value is NULL if the window has no master or + * if its master is its parent. */ } TkWindow; /* -- cgit v0.12 From bd94fcc850895e865fc697674defc0591842d754 Mon Sep 17 00:00:00 2001 From: culler Date: Thu, 11 Apr 2019 13:43:21 +0000 Subject: Add the formatting changes and conditional code for OSX 10.12 to core-8-6-branch. --- macosx/tkMacOSXMouseEvent.c | 56 +++--- macosx/tkMacOSXWm.c | 299 ++++++++++++++++------------- macosx/ttkMacOSXTheme.c | 448 +++++++++++++++++++++++--------------------- 3 files changed, 429 insertions(+), 374 deletions(-) diff --git a/macosx/tkMacOSXMouseEvent.c b/macosx/tkMacOSXMouseEvent.c index ec713d4..2848a52 100644 --- a/macosx/tkMacOSXMouseEvent.c +++ b/macosx/tkMacOSXMouseEvent.c @@ -24,11 +24,12 @@ typedef struct { Point global; Point local; } MouseEventData; -static Tk_Window captureWinPtr = NULL; /* Current capture window; may be NULL. */ +static Tk_Window captureWinPtr = NULL; /* Current capture window; may be + * NULL. */ static int GenerateButtonEvent(MouseEventData *medPtr); static unsigned int ButtonModifiers2State(UInt32 buttonState, - UInt32 keyModifiers); + UInt32 keyModifiers); #pragma mark TKApplication(TKMouseEvent) @@ -48,14 +49,15 @@ enum { @implementation TKApplication(TKMouseEvent) - (NSEvent *) tkProcessMouseEvent: (NSEvent *) theEvent { - NSWindow* eventWindow = [theEvent window]; - NSEventType eventType = [theEvent type]; + NSWindow *eventWindow = [theEvent window]; + NSEventType eventType = [theEvent type]; TkWindow *winPtr, *grabWinPtr; Tk_Window tkwin; #if 0 - NSTrackingArea *trackingArea = nil; + NSTrackingArea *trackingArea = nil; NSInteger eventNumber, clickCount, buttonNumber; #endif + #ifdef TK_MAC_DEBUG_EVENTS TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, theEvent); #endif @@ -76,12 +78,15 @@ enum { case NSTabletPoint: case NSTabletProximity: case NSScrollWheel: - break; + break; default: /* Unrecognized mouse event. */ return theEvent; } - /* Remember the window in case we need it next time. */ + /* + * Remember the window in case we need it next time. + */ + if (eventWindow && eventWindow != _windowWithMouse) { if (_windowWithMouse) { [_windowWithMouse release]; @@ -91,8 +96,8 @@ enum { } /* - * Compute the mouse position in Tk screen coordinates (global) and in - * the Tk coordinates of its containing Tk Window. + * Compute the mouse position in Tk screen coordinates (global) and in the + * Tk coordinates of its containing Tk Window. */ NSPoint global, local = [theEvent locationInWindow]; @@ -106,7 +111,6 @@ enum { eventWindow = _windowWithMouse; } if (eventWindow) { - /* * Set the local mouse position to its NSWindow flipped coordinates, * with the origin at top left, and the global mouse position to the @@ -116,9 +120,7 @@ enum { global = [eventWindow tkConvertPointToScreen: local]; local.y = [eventWindow frame].size.height - local.y; global.y = tkMacOSXZeroScreenHeight - global.y; - } else { - /* * As a last resort, with no NSWindow to work with, set both local and * global to the screen coordinates. @@ -135,13 +137,15 @@ enum { winPtr = TkMacOSXGetTkWindow(eventWindow); if (winPtr == NULL) { tkwin = TkMacOSXGetCapture(); - winPtr = (TkWindow *)tkwin; + winPtr = (TkWindow *) tkwin; } else { tkwin = (Tk_Window) winPtr; } if (!tkwin) { +#ifdef TK_MAC_DEBUG_EVENTS TkMacOSXDbgMsg("tkwin == NULL"); - return theEvent; /* Give up. No window for this event. */ +#endif + return theEvent; /* Give up. No window for this event. */ } /* @@ -150,9 +154,9 @@ enum { grabWinPtr = winPtr->dispPtr->grabWinPtr; if (grabWinPtr && - grabWinPtr != winPtr && - !winPtr->dispPtr->grabFlags && /* this means the grab is local. */ - grabWinPtr->mainPtr == winPtr->mainPtr) { + grabWinPtr != winPtr && + !winPtr->dispPtr->grabFlags && /* this means the grab is local. */ + grabWinPtr->mainPtr == winPtr->mainPtr) { return theEvent; } @@ -184,7 +188,7 @@ enum { EventRef eventRef = (EventRef)[theEvent eventRef]; UInt32 buttons; OSStatus err = GetEventParameter(eventRef, kEventParamMouseChord, - typeUInt32, NULL, sizeof(UInt32), NULL, &buttons); + typeUInt32, NULL, sizeof(UInt32), NULL, &buttons); if (err == noErr) { state |= (buttons & ((1<<5) - 1)) << 8; @@ -227,17 +231,16 @@ enum { } if (eventType != NSScrollWheel) { - /* * For normal mouse events, Tk_UpdatePointer will send the XEvent. */ #ifdef TK_MAC_DEBUG_EVENTS - TKLog(@"UpdatePointer %p x %f.0 y %f.0 %d", tkwin, global.x, global.y, state); + TKLog(@"UpdatePointer %p x %f.0 y %f.0 %d", + tkwin, global.x, global.y, state); #endif Tk_UpdatePointer(tkwin, global.x, global.y, state); } else { - /* * For scroll wheel events we need to send the XEvent here. */ @@ -258,7 +261,7 @@ enum { delta = [theEvent deltaY]; if (delta != 0.0) { coarseDelta = (delta > -1.0 && delta < 1.0) ? - (signbit(delta) ? -1 : 1) : lround(delta); + (signbit(delta) ? -1 : 1) : lround(delta); xEvent.xbutton.state = state; xEvent.xkey.keycode = coarseDelta; xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin)); @@ -267,7 +270,7 @@ enum { delta = [theEvent deltaX]; if (delta != 0.0) { coarseDelta = (delta > -1.0 && delta < 1.0) ? - (signbit(delta) ? -1 : 1) : lround(delta); + (signbit(delta) ? -1 : 1) : lround(delta); xEvent.xbutton.state = state | ShiftMask; xEvent.xkey.keycode = coarseDelta; xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin)); @@ -627,10 +630,8 @@ TkpWarpPointer( buttonState = [NSEvent pressedMouseButtons]; CGEventType type = kCGEventMouseMoved; - CGEventRef theEvent = CGEventCreateMouseEvent(NULL, - type, - pt, - buttonState); + CGEventRef theEvent = CGEventCreateMouseEvent(NULL, type, pt, + buttonState); CGWarpMouseCursorPosition(pt); CGEventPost(kCGHIDEventTap, theEvent); CFRelease(theEvent); @@ -685,7 +686,6 @@ TkMacOSXGetCapture(void) } - /* * Local Variables: * mode: objc diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index 2b4384a..a426664 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -55,7 +55,6 @@ | tkCanJoinAllSpacesAttribute | tkMoveToActiveSpaceAttribute \ | tkNonactivatingPanelAttribute | tkHUDWindowAttribute) - static const struct { const UInt64 validAttrs, defaultAttrs, forceOnAttrs, forceOffAttrs; int flags; NSUInteger styleMask; @@ -397,7 +396,9 @@ static void RemoveTransient(TkWindow *winPtr); } else { frameRect = [self frameRectForContentRect:NSZeroRect]; } + WmInfo *wmPtr = winPtr->wmInfoPtr; + wmPtr->xInParent = -frameRect.origin.x; wmPtr->yInParent = frameRect.origin.y + frameRect.size.height; wmPtr->parentWidth = winPtr->changes.width + frameRect.size.width; @@ -498,7 +499,6 @@ static void RemoveTransient(TkWindow *winPtr); [super dealloc]; } - #endif @end @@ -624,7 +624,8 @@ FrontWindowAtPoint( WmInfo *wmPtr = winPtr->wmInfoPtr; NSRect windowFrame = [w frame]; NSRect contentFrame = [w frame]; - contentFrame.size.height = [[w contentView] frame].size.height; + + contentFrame.size.height = [[w contentView] frame].size.height; /* * For consistency with other platforms, points in the * title bar are not considered to be contained in the @@ -632,7 +633,7 @@ FrontWindowAtPoint( */ if ((wmPtr->hints.initial_state == NormalState || - wmPtr->hints.initial_state == ZoomState)) { + wmPtr->hints.initial_state == ZoomState)) { if (NSMouseInRect(p, contentFrame, NO)) { return winPtr; } else if (NSMouseInRect(p, windowFrame, NO)) { @@ -940,9 +941,10 @@ TkWmDeadWindow( */ for (Transient *transientPtr = wmPtr->transientPtr; - transientPtr != NULL; transientPtr = transientPtr->nextPtr) { + transientPtr != NULL; transientPtr = transientPtr->nextPtr) { TkWindow *winPtr2 = transientPtr->winPtr; - TkWindow *masterPtr = (TkWindow *)TkGetTransientMaster(winPtr2); + TkWindow *masterPtr = (TkWindow *) TkGetTransientMaster(winPtr2); + if (masterPtr == winPtr) { wmPtr2 = winPtr2->wmInfoPtr; wmPtr2->master = NULL; @@ -951,6 +953,7 @@ TkWmDeadWindow( while (wmPtr->transientPtr != NULL) { Transient *transientPtr = wmPtr->transientPtr; + wmPtr->transientPtr = transientPtr->nextPtr; ckfree(transientPtr); } @@ -964,8 +967,9 @@ TkWmDeadWindow( NSWindow *window = wmPtr->window; - if (window && !Tk_IsEmbedded(winPtr) ) { + if (window && !Tk_IsEmbedded(winPtr)) { NSWindow *parent = [window parentWindow]; + if (parent) { [parent removeChildWindow:window]; } @@ -991,15 +995,16 @@ TkWmDeadWindow( NSArray *windows = [NSApp orderedWindows]; for (id nswindow in windows) { TkWindow *winPtr2 = TkMacOSXGetTkWindow(nswindow); + if (winPtr2 && nswindow != window) { WmInfo *wmPtr = winPtr2->wmInfoPtr; BOOL minimized = (wmPtr->hints.initial_state == IconicState || wmPtr->hints.initial_state == WithdrawnState); /* - * If no windows are left on the screen and the next - * window is iconified or withdrawn, we don't want to - * make it be the KeyWindow because that would cause - * it to be displayed on the screen. + * If no windows are left on the screen and the next window is + * iconified or withdrawn, we don't want to make it be the + * KeyWindow because that would cause it to be displayed on the + * screen. */ if ([nswindow canBecomeKeyWindow] && !minimized) { [nswindow makeKeyAndOrderFront:NSApp]; @@ -1529,7 +1534,7 @@ WmAttributesCmd( WmGetAttribute(winPtr, macWindow, attribute)); } Tcl_SetObjResult(interp, result); - } else if (objc == 4) { /* wm attributes $win -attribute */ + } else if (objc == 4) { /* wm attributes $win -attribute */ if (Tcl_GetIndexFromObjStruct(interp, objv[3], WmAttributeNames, sizeof(char *), "attribute", 0, &attribute) != TCL_OK) { return TCL_ERROR; @@ -1819,13 +1824,14 @@ WmDeiconifyCmd( */ for (Transient *transientPtr = wmPtr->transientPtr; - transientPtr != NULL; transientPtr = transientPtr->nextPtr) { + transientPtr != NULL; transientPtr = transientPtr->nextPtr) { TkWindow *winPtr2 = transientPtr->winPtr; WmInfo *wmPtr2 = winPtr2->wmInfoPtr; - TkWindow *masterPtr = (TkWindow *)TkGetTransientMaster(winPtr2); + TkWindow *masterPtr = (TkWindow *) TkGetTransientMaster(winPtr2); + if (masterPtr == winPtr) { - if ((wmPtr2->hints.initial_state == WithdrawnState && - (transientPtr->flags & WITHDRAWN_BY_MASTER) != 0)) { + if ((wmPtr2->hints.initial_state == WithdrawnState) && + ((transientPtr->flags & WITHDRAWN_BY_MASTER) != 0)) { TkpWmSetState(winPtr2, NormalState); transientPtr->flags &= ~WITHDRAWN_BY_MASTER; } @@ -2361,11 +2367,11 @@ WmIconifyCmd( */ for (Transient *transientPtr = wmPtr->transientPtr; - transientPtr != NULL; transientPtr = transientPtr->nextPtr) { + transientPtr != NULL; transientPtr = transientPtr->nextPtr) { TkWindow *winPtr2 = transientPtr->winPtr; - TkWindow *masterPtr = (TkWindow *)TkGetTransientMaster(winPtr2); + TkWindow *masterPtr = (TkWindow *) TkGetTransientMaster(winPtr2); if (masterPtr == winPtr && - winPtr2->wmInfoPtr->hints.initial_state != WithdrawnState) { + winPtr2->wmInfoPtr->hints.initial_state != WithdrawnState) { TkpWmSetState(winPtr2, WithdrawnState); transientPtr->flags |= WITHDRAWN_BY_MASTER; } @@ -2521,7 +2527,10 @@ WmIconphotoCmd( return TCL_ERROR; } - /*Parse args.*/ + /* + * Parse args. + */ + if (strcmp(Tcl_GetString(objv[3]), "-default") == 0) { isDefault = 1; if (objc == 4) { @@ -2531,16 +2540,22 @@ WmIconphotoCmd( } } - /*Get icon name. We only use the first icon name because macOS does not - support multiple images in Tk photos.*/ + /* + * Get icon name. We only use the first icon name because macOS does not + * support multiple images in Tk photos. + */ + char *icon; if (strcmp(Tcl_GetString(objv[3]), "-default") == 0) { icon = Tcl_GetString(objv[4]); - } else { + } else { icon = Tcl_GetString(objv[3]); } - /*Get image and convert to NSImage that can be displayed as icon.*/ + /* + * Get image and convert to NSImage that can be displayed as icon. + */ + tk_icon = Tk_GetImage(interp, tkwin, icon, NULL, NULL); if (tk_icon == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( @@ -2552,7 +2567,8 @@ WmIconphotoCmd( NSImage *newIcon; Tk_SizeOfImage(tk_icon, &width, &height); - newIcon = TkMacOSXGetNSImageWithTkImage(winPtr->display, tk_icon, width, height); + newIcon = TkMacOSXGetNSImageWithTkImage(winPtr->display, tk_icon, + width, height); Tk_FreeImage(tk_icon); if (newIcon == NULL) { return TCL_ERROR; @@ -2708,14 +2724,13 @@ WmIconwindowCmd( wmPtr->icon = tkwin2; wmPtr2->iconFor = (Tk_Window) winPtr; if (!(wmPtr2->flags & WM_NEVER_MAPPED)) { - /* * If the window is in normal or zoomed state, the icon should be * unmapped. */ if (wmPtr->hints.initial_state == NormalState || - wmPtr->hints.initial_state == ZoomState) { + wmPtr->hints.initial_state == ZoomState) { Tk_UnmapWindow(tkwin2); } } @@ -3086,7 +3101,7 @@ WmProtocolCmd( */ for (protPtr = wmPtr->protPtr, prevPtr = NULL; protPtr != NULL; - prevPtr = protPtr, protPtr = protPtr->nextPtr) { + prevPtr = protPtr, protPtr = protPtr->nextPtr) { if (protPtr->protocol == protocol) { if (prevPtr == NULL) { wmPtr->protPtr = protPtr->nextPtr; @@ -3612,7 +3627,7 @@ WmTransientCmd( } wmPtr2 = masterPtr->wmInfoPtr; - /* Under some circumstances, wmPtr2 is NULL here */ + /* Under some circumstances, wmPtr2 is NULL here. */ if (wmPtr2 != NULL && wmPtr2->iconFor != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't make \"%s\" a master: it is an icon for %s", @@ -3622,7 +3637,7 @@ WmTransientCmd( } for (w = masterPtr; w != NULL && w->wmInfoPtr != NULL; - w = (TkWindow *)w->wmInfoPtr->master) { + w = (TkWindow *)w->wmInfoPtr->master) { if (w == winPtr) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "setting \"%s\" as master creates a transient/master cycle", @@ -3635,7 +3650,7 @@ WmTransientCmd( /* * Add the transient to the master's list, if it not already there. */ - + for (transient = wmPtr2->transientPtr; transient != NULL && transient->winPtr != winPtr; transient = transient->nextPtr) {} @@ -3652,13 +3667,13 @@ WmTransientCmd( */ if ((wmPtr2->hints.initial_state == WithdrawnState || - wmPtr2->hints.initial_state == IconicState) && - wmPtr->hints.initial_state != WithdrawnState){ + wmPtr2->hints.initial_state == IconicState) && + wmPtr->hints.initial_state != WithdrawnState) { TkpWmSetState(winPtr, WithdrawnState); transient->flags |= WITHDRAWN_BY_MASTER; } - wmPtr->master = (Tk_Window)masterPtr; + wmPtr->master = (Tk_Window) masterPtr; } ApplyMasterOverrideChanges(winPtr, NULL); return TCL_OK; @@ -3669,16 +3684,16 @@ WmTransientCmd( * * RemoveTransient -- * - * Clears the transient's master record and removes the transient - * from the master's list. + * Clears the transient's master record and removes the transient from the + * master's list. * * Results: * None * * Side effects: * References to a master are removed from the transient's wmInfo - * structure and references to the transient are removed from its - * master's wmInfo. + * structure and references to the transient are removed from its master's + * wmInfo. * *---------------------------------------------------------------------- */ @@ -3689,8 +3704,8 @@ RemoveTransient( { WmInfo *wmPtr = winPtr->wmInfoPtr, *wmPtr2; TkWindow *masterPtr; - Transient *T, *temp; - + Transient *transPtr, *temp; + if (wmPtr == NULL || wmPtr->master == NULL) { return; } @@ -3700,23 +3715,23 @@ RemoveTransient( return; } wmPtr->master = NULL; - T = wmPtr2->transientPtr; - while (T != NULL) { - if (T->winPtr != winPtr) { + transPtr = wmPtr2->transientPtr; + while (transPtr != NULL) { + if (transPtr->winPtr != winPtr) { break; } - temp = T->nextPtr; - ckfree(T); - T = temp; + temp = transPtr->nextPtr; + ckfree(transPtr); + transPtr = temp; } - wmPtr2->transientPtr = T; - while (T != NULL) { - if (T->nextPtr && T->nextPtr->winPtr == winPtr) { - temp = T->nextPtr; - T->nextPtr = temp->nextPtr; + wmPtr2->transientPtr = transPtr; + while (transPtr != NULL) { + if (transPtr->nextPtr && transPtr->nextPtr->winPtr == winPtr) { + temp = transPtr->nextPtr; + transPtr->nextPtr = temp->nextPtr; ckfree(temp); } else { - T = T->nextPtr; + transPtr = transPtr->nextPtr; } } } @@ -3771,11 +3786,12 @@ WmWithdrawCmd( * If this window has a transient, the transient must also be withdrawn. */ for (Transient *transientPtr = wmPtr->transientPtr; - transientPtr != NULL; transientPtr = transientPtr->nextPtr) { + transientPtr != NULL; transientPtr = transientPtr->nextPtr) { TkWindow *winPtr2 = transientPtr->winPtr; - TkWindow *masterPtr = (TkWindow *)TkGetTransientMaster(winPtr2); + TkWindow *masterPtr = (TkWindow *) TkGetTransientMaster(winPtr2); + if (masterPtr == winPtr && - winPtr2->wmInfoPtr->hints.initial_state != WithdrawnState) { + winPtr2->wmInfoPtr->hints.initial_state != WithdrawnState) { TkpWmSetState(winPtr2, WithdrawnState); transientPtr->flags |= WITHDRAWN_BY_MASTER; } @@ -3873,14 +3889,13 @@ Tk_SetGrid( /* * If gridding was previously off, then forget about any window size - * requests made by the user or via "wm geometry": these are in pixel - * units and there's no easy way to translate them to grid units since the - * new requested size of the top-level window in pixels may not yet have - * been registered yet (it may filter up the hierarchy in DoWhenIdle - * handlers). However, if the window has never been mapped yet then just - * leave the window size alone: assume that it is intended to be in grid - * units but just happened to have been specified before this procedure - * was called. + * requests made by the user or via "wm geometry": these are in pixel units + * and there's no easy way to translate them to grid units since the new + * requested size of the top-level window in pixels may not yet have been + * registered yet (it may filter up the hierarchy in DoWhenIdle handlers). + * However, if the window has never been mapped yet then just leave the + * window size alone: assume that it is intended to be in grid units but + * just happened to have been specified before this procedure was called. */ if ((wmPtr->gridWin == NULL) && !(wmPtr->flags & WM_NEVER_MAPPED)) { @@ -4945,9 +4960,10 @@ TkWmRestackToplevel( /* * If the Tk windows has no drawable, or is withdrawn do nothing. */ + if (winPtr->window == None || - wmPtr == NULL || - wmPtr->hints.initial_state == WithdrawnState) { + wmPtr == NULL || + wmPtr->hints.initial_state == WithdrawnState) { return; } macWindow = TkMacOSXDrawableWindow(winPtr->window); @@ -4956,30 +4972,33 @@ TkWmRestackToplevel( } if (otherPtr) { /* - * When otherPtr is non-NULL, if the other window has no - * drawable or is withdrawn, do nothing. + * When otherPtr is non-NULL, if the other window has no drawable or is + * withdrawn, do nothing. */ + WmInfo *otherWmPtr = otherPtr->wmInfoPtr; if (winPtr->window == None || - otherWmPtr == NULL || - otherWmPtr->hints.initial_state == WithdrawnState) { - return; + otherWmPtr == NULL || + otherWmPtr->hints.initial_state == WithdrawnState) { + return; } otherMacWindow = TkMacOSXDrawableWindow(otherPtr->window); if (otherMacWindow == nil) { return; - } else { - /* - * If the other window is OK, get its number. - */ - otherNumber = [otherMacWindow windowNumber]; } + + /* + * If the other window is OK, get its number. + */ + + otherNumber = [otherMacWindow windowNumber]; } /* - * Just let the Mac window manager deal with all the subtleties - * of keeping track of off-screen windows, etc. + * Just let the Mac window manager deal with all the subtleties of keeping + * track of off-screen windows, etc. */ + [macWindow orderWindow:macAboveBelow relativeTo:otherNumber]; } @@ -5178,8 +5197,8 @@ TkGetPointerCoords( * * This function calculates the initial bounds for a new Mac toplevel * window. Unless the geometry is specified by the user this code will - * auto place the windows in a cascade diagonially across the main - * monitor of the Mac. + * auto place the windows in a cascade diagonially across the main monitor + * of the Mac. * * Results: * Window bounds. @@ -5420,7 +5439,6 @@ TkMacOSXIsWindowZoomed( NSWindow *macWindow = TkMacOSXDrawableWindow(winPtr->window); return [macWindow isZoomed]; } - /* *---------------------------------------------------------------------- @@ -5514,7 +5532,6 @@ TkUnsupported1ObjCmd( return TCL_ERROR; } - winPtr = (TkWindow *) Tk_NameToWindow(interp, Tcl_GetString(objv[2]), tkwin); if (winPtr == NULL) { @@ -5558,12 +5575,14 @@ TkUnsupported1ObjCmd( return TCL_ERROR; } if ((objc < 3) || (objc > 4)) { - Tcl_WrongNumArgs(interp, 2, objv, "appearance window ?appearancename?"); + Tcl_WrongNumArgs(interp, 2, objv, + "appearance window ?appearancename?"); return TCL_ERROR; } if (objc == 4 && [NSApp macMinorVersion] < 14) { Tcl_SetObjResult(interp, Tcl_NewStringObj( - "Window appearances cannot be changed before OSX 10.14.", -1)); + "Window appearances cannot be changed before OSX 10.14.", + -1)); Tcl_SetErrorCode(interp, "TK", "WINDOWSTYLE", "APPEARANCE", NULL); return TCL_ERROR; } @@ -5764,8 +5783,9 @@ WmWinStyle( * This procedure is invoked to process the * "::tk::unsupported::MacWindowStyle tabbingid" subcommand. The command * allows you to get or set the tabbingIdentifier for the NSWindow - * associated with a Tk Window. The syntax is: - * tk::unsupported::MacWindowStyle tabbingid window ?newId? + * associated with a Tk Window. The syntax is: + * + * tk::unsupported::MacWindowStyle tabbingid window ?newId? * * Results: * Returns the tabbingIdentifier of the window prior to calling this @@ -5779,7 +5799,6 @@ WmWinStyle( * window. Note, however, that changing the tabbingIdentifier of a window * which is already a tab does not cause it to become a separate window. * - * *---------------------------------------------------------------------- */ @@ -5816,7 +5835,11 @@ WmWinTabbingId( * same frame must have the same tabbingIdentifier. */ - if ([idString compare:newIdString] != NSOrderedSame && [win tab]) { + if ([idString compare:newIdString] != NSOrderedSame +#if MAC_OS_X_VERSION_MIN_REQUIRED > 101200 + && [win tab] +#endif + ) { [win moveTabToNewWindow:nil]; } return TCL_OK; @@ -5832,9 +5855,11 @@ WmWinTabbingId( * * This procedure is invoked to process the * "::tk::unsupported::MacWindowStyle appearance" subcommand. The command - * allows you to get or set the appearance for the NSWindow - * associated with a Tk Window. The syntax is: - * tk::unsupported::MacWindowStyle tabbingid window ?newAppearance? + * allows you to get or set the appearance for the NSWindow associated + * with a Tk Window. The syntax is: + * + * tk::unsupported::MacWindowStyle tabbingid window ?newAppearance? + * * Allowed appearance names are "aqua", "darkaqua", and "auto". * * Results: @@ -5843,15 +5868,14 @@ WmWinTabbingId( * * Side effects: * The underlying NSWindow's appearance property is set to the specified - * value if the optional newAppearance argument is supplied. Otherwise - * the window's appearance property is not changed. If the appearance is - * set to aqua or darkaqua then the window will use the associated + * value if the optional newAppearance argument is supplied. Otherwise the + * window's appearance property is not changed. If the appearance is set + * to aqua or darkaqua then the window will use the associated * NSAppearance even if the user has selected a different appearance with * the system preferences. If it is set to auto then the appearance * property is set to nil, meaning that the preferences will determine the * appearance. * - * *---------------------------------------------------------------------- */ @@ -5870,7 +5894,11 @@ WmWinAppearance( APPEARANCE_AQUA, APPEARANCE_DARKAQUA, APPEARANCE_AUTO }; Tcl_Obj *result = NULL; +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 NSAppearanceName appearance; +#else + NSString *appearance; +#endif const char *resultString; NSWindow *win = TkMacOSXDrawableWindow(winPtr->window); if (win) { @@ -5882,7 +5910,7 @@ WmWinAppearance( #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 } else if (appearance == NSAppearanceNameDarkAqua) { resultString = appearanceStrings[APPEARANCE_DARKAQUA]; -#endif +#endif } else { resultString = "unrecognized"; } @@ -5989,8 +6017,8 @@ TkMacOSXMakeRealWindowExist( macWin = (MacDrawable *) winPtr->window; /* - * If this is embedded, make sure its container's toplevel exists, - * then return... + * If this is embedded, make sure its container's toplevel exists, then + * return... */ if (Tk_IsEmbedded(winPtr)) { @@ -6019,8 +6047,8 @@ TkMacOSXMakeRealWindowExist( } /* - * If this is an override-redirect window, the NSWindow is created - * first as a document window then converted to a simple window. + * If this is an override-redirect window, the NSWindow is created first as + * a document window then converted to a simple window. */ if (overrideRedirect) { @@ -6074,8 +6102,8 @@ TkMacOSXMakeRealWindowExist( if ((styleMask & (NSTexturedBackgroundWindowMask|NSHUDWindowMask)) && !(styleMask & NSDocModalWindowMask)) { /* - * Workaround for [Bug 2824538]: Textured windows are draggable - * from opaque content. + * Workaround for [Bug 2824538]: Textured windows are draggable from + * opaque content. */ [window setMovableByWindowBackground:NO]; } @@ -6084,7 +6112,7 @@ TkMacOSXMakeRealWindowExist( macWin->view = window.contentView; TkMacOSXApplyWindowAttributes(winPtr, window); NSRect geometry = InitialWindowBounds(winPtr, window); - geometry.size.width += structureRect.size.width; + geometry.size.width += structureRect.size.width; geometry.size.height += structureRect.size.height; geometry.origin.y = tkMacOSXZeroScreenHeight - (geometry.origin.y + geometry.size.height); @@ -6094,6 +6122,7 @@ TkMacOSXMakeRealWindowExist( macWin->flags |= TK_HOST_EXISTS; if (overrideRedirect) { XSetWindowAttributes atts; + atts.override_redirect = True; Tk_ChangeWindowAttributes((Tk_Window) winPtr, CWOverrideRedirect, &atts); ApplyMasterOverrideChanges(winPtr, NULL); @@ -6123,6 +6152,7 @@ TkpDisplayWindow(Tk_Window tkwin) { if (![NSApp isDrawing]) { TkWindow *winPtr = (TkWindow*)tkwin; NSWindow *w = TkMacOSXDrawableWindow(winPtr->window); + [[w contentView] setNeedsDisplay: YES]; } } @@ -6517,13 +6547,14 @@ TkpChangeFocus( return 0; } - if (Tk_IsTopLevel(winPtr) && !Tk_IsEmbedded(winPtr) ){ + if (Tk_IsTopLevel(winPtr) && !Tk_IsEmbedded(winPtr)) { NSWindow *win = TkMacOSXDrawableWindow(winPtr->window); + TkWmRestackToplevel(winPtr, Above, NULL); - if (force ) { + if (force) { [NSApp activateIgnoringOtherApps:YES]; } - if ( win && [win canBecomeKeyWindow] ) { + if (win && [win canBecomeKeyWindow]) { [win makeKeyAndOrderFront:NSApp]; } } @@ -6682,6 +6713,7 @@ TkMacOSXApplyWindowAttributes( NSWindow *macWindow) { WmInfo *wmPtr = winPtr->wmInfoPtr; + ApplyWindowAttributeFlagChanges(winPtr, macWindow, 0, 0, 0, 1); if (wmPtr->master != NULL || winPtr->atts.override_redirect) { ApplyMasterOverrideChanges(winPtr, macWindow); @@ -6721,18 +6753,16 @@ ApplyWindowAttributeFlagChanges( if (changedAttributes || wmPtr->flags != oldFlags || initial) { if (!macWindow) { if (winPtr->window == None) { - if (create) { - Tk_MakeWindowExist((Tk_Window) winPtr); - } else { + if (!create) { return; } + Tk_MakeWindowExist((Tk_Window) winPtr); } if (!TkMacOSXHostToplevelExists(winPtr)) { - if (create) { - TkMacOSXMakeRealWindowExist(winPtr); - } else { + if (!create) { return; } + TkMacOSXMakeRealWindowExist(winPtr); } macWindow = TkMacOSXDrawableWindow(winPtr->window); } @@ -6769,6 +6799,7 @@ ApplyWindowAttributeFlagChanges( if ((newAttributes & kWindowToolbarButtonAttribute) && ![macWindow toolbar]) { NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier:@""]; + [toolbar setVisible:NO]; [macWindow setToolbar:toolbar]; [toolbar release]; @@ -6812,26 +6843,26 @@ ApplyWindowAttributeFlagChanges( #if !(MAC_OS_X_VERSION_MAX_ALLOWED < 101000) if (!(macWindow.styleMask & NSUtilityWindowMask)) { - /* * Exclude overrideredirect, transient, and "help"-styled * windows from moving into their own fullscreen space. - * */ if ((winPtr->atts.override_redirect) || - (wmPtr->master != NULL) || - (winPtr->wmInfoPtr->macClass == kHelpWindowClass)) { + (wmPtr->master != NULL) || + (winPtr->wmInfoPtr->macClass == kHelpWindowClass)) { b |= (NSWindowCollectionBehaviorCanJoinAllSpaces | - NSWindowCollectionBehaviorFullScreenAuxiliary); + NSWindowCollectionBehaviorFullScreenAuxiliary); } else { - NSSize screenSize = [[macWindow screen]frame].size; + NSSize screenSize = [[macWindow screen] frame].size; b |= NSWindowCollectionBehaviorFullScreenPrimary; - /* The default max size has height less than the screen height. - * This causes the window manager to refuse to allow the window - * to be resized when it is a split window. To work around - * this we make the max size equal to the screen size. + /* + * The default max size has height less than the screen + * height. This causes the window manager to refuse to + * allow the window to be resized when it is a split + * window. To work around this we make the max size equal + * to the screen size. */ [macWindow setMaxFullScreenContentSize:screenSize]; @@ -6864,6 +6895,7 @@ ApplyWindowAttributeFlagChanges( */ NSRect structureRect = [macWindow frameRectForContentRect:NSZeroRect]; + wmPtr->xInParent = -structureRect.origin.x; wmPtr->yInParent = structureRect.origin.y + structureRect.size.height; wmPtr->parentWidth = winPtr->changes.width + structureRect.size.width; @@ -6963,6 +6995,7 @@ ApplyMasterOverrideChanges( } } else { const char *title = winPtr->wmInfoPtr->titleUid; + if (!title) { title = winPtr->nameUid; } @@ -6972,11 +7005,12 @@ ApplyMasterOverrideChanges( wmPtr->flags &= ~WM_TOPMOST; } if (wmPtr->master != None) { - TkWindow *masterWinPtr = (TkWindow *)wmPtr->master; - if (masterWinPtr && masterWinPtr->window != None && - TkMacOSXHostToplevelExists(masterWinPtr)) { + TkWindow *masterWinPtr = (TkWindow *) wmPtr->master; + + if (masterWinPtr && (masterWinPtr->window != None) + && TkMacOSXHostToplevelExists(masterWinPtr)) { NSWindow *masterMacWin = TkMacOSXDrawableWindow( - masterWinPtr->window); + masterWinPtr->window); /* * Try to add the transient window as a child window of the @@ -6987,10 +7021,8 @@ ApplyMasterOverrideChanges( * zombie. So we only do this if the parent is visible. */ - if (masterMacWin && - [masterMacWin isVisible] && - (winPtr->flags & TK_MAPPED)) { - + if (masterMacWin && [masterMacWin isVisible] + && (winPtr->flags & TK_MAPPED)) { /* * If the transient is already a child of some other window, * remove it. @@ -7002,8 +7034,8 @@ ApplyMasterOverrideChanges( } [masterMacWin addChildWindow:macWindow - ordered:NSWindowAbove]; - } + ordered:NSWindowAbove]; + } } } else { parentWindow = [macWindow parentWindow]; @@ -7211,7 +7243,10 @@ RemapWindows( #endif } - /* Repeat for all the children */ + /* + * Repeat for all the children. + */ + for (childPtr = winPtr->childList; childPtr != NULL; childPtr = childPtr->nextPtr) { RemapWindows(childPtr, (MacDrawable *) winPtr->window); diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index 02dd7e4..b0ac075 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -21,14 +21,12 @@ * Notes: * "Active" means different things in Mac and Tk terminology -- * On Aqua, widgets are "Active" if they belong to the foreground window, - * "Inactive" if they are in a background window. - * Tk uses the term "active" to mean that the mouse cursor - * is over a widget; aka "hover", "prelight", or "hot-tracked". - * Aqua doesn't use this kind of feedback. + * "Inactive" if they are in a background window. Tk uses the term + * "active" to mean that the mouse cursor is over a widget; aka "hover", + * "prelight", or "hot-tracked". Aqua doesn't use this kind of feedback. * - * The QuickDraw/Carbon coordinate system is relative to the - * top-level window, not to the Tk_Window. BoxToRect() - * accounts for this. + * The QuickDraw/Carbon coordinate system is relative to the top-level + * window, not to the Tk_Window. BoxToRect() accounts for this. */ #include "tkMacOSXPrivate.h" @@ -113,7 +111,6 @@ static Ttk_StateTable ThemeStateTable[] = { * padding. This is handled separately here. */ - static CGRect NormalizeButtonBounds( SInt32 heightMetric, CGRect bounds) @@ -129,32 +126,32 @@ static CGRect NormalizeButtonBounds( #if MAC_OS_X_VERSION_MIN_REQUIRED > 1080 /*---------------------------------------------------------------------- - * +++ Support for contrasting background colors when GroupBoxes - * or Tabbed panes are nested inside each other. Early versions - * of macOS used ridged borders, so do not need contrasting backgrounds. + * +++ Support for contrasting background colors when GroupBoxes or Tabbed + * panes are nested inside each other. Early versions of macOS used ridged + * borders, so do not need contrasting backgrounds. */ /* * For systems older than 10.14, [NSColor windowBackGroundColor] generates - * garbage when called from this function. In 10.14 it works correctly, - * and must be used in order to have a background color which responds - * to Dark Mode. So we use this hard-wired RGBA color on the older systems - * which don't support Dark Mode anyway. + * garbage when called from this function. In 10.14 it works correctly, and + * must be used in order to have a background color which responds to Dark + * Mode. So we use this hard-wired RGBA color on the older systems which don't + * support Dark Mode anyway. */ static CGFloat windowBackground[4] = {235.0/255, 235.0/255, 235.0/255, 1.0}; 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. + * 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( @@ -163,8 +160,8 @@ static void GetBackgroundColor( int contrast, CGFloat *rgba) { - TkWindow *winPtr = (TkWindow *)tkwin; - TkWindow *masterPtr = (TkWindow *)TkGetGeomMaster(tkwin); + TkWindow *winPtr = (TkWindow *) tkwin; + TkWindow *masterPtr = (TkWindow *) TkGetGeomMaster(tkwin); while (masterPtr != NULL) { if (masterPtr->privatePtr->flags & TTK_HAS_CONTRASTING_BG) { break; @@ -188,7 +185,8 @@ static void GetBackgroundColor( } } if (contrast) { - int isDark = (rgba[0] + rgba[1] + rgba[2] < 1.5); + int isDark = (rgba[0] + rgba[1] + rgba[2] < 1.5); + if (isDark) { for (int i=0; i<3; i++) { rgba[i] += 8.0/255.0; @@ -205,11 +203,11 @@ static void GetBackgroundColor( } } -/* +/*---------------------------------------------------------------------- * DrawGroupBox -- * - * This is a standalone drawing procedure which draws the contrasting - * rounded rectangular box for LabelFrames and Notebook panes. + * This is a standalone drawing procedure which draws the contrasting + * rounded rectangular box for LabelFrames and Notebook panes. */ static void DrawGroupBox( @@ -245,16 +243,17 @@ static void DrawGroupBox( CFRelease(path); } -/* SolidFillRoundedRectangle -- +/*---------------------------------------------------------------------- + * SolidFillRoundedRectangle -- * - * Fill a rounded rectangle with a specified solid color. + * Fill a rounded rectangle with a specified solid color. */ static void SolidFillRoundedRectangle( - CGContextRef context, - CGRect bounds, - CGFloat radius, - NSColor *color) + CGContextRef context, + CGRect bounds, + CGFloat radius, + NSColor *color) { CGPathRef path; CGContextSetFillColorWithColor(context, color.CGColor); @@ -265,25 +264,27 @@ static void SolidFillRoundedRectangle( CFRelease(path); } - -/* GradientFillRoundedRectangle -- +/*---------------------------------------------------------------------- + * GradientFillRoundedRectangle -- * - * Fill a rounded rectangle with a specified gradient. + * Fill a rounded rectangle with a specified gradient. */ static void GradientFillRoundedRectangle( - CGContextRef context, - CGRect bounds, - CGFloat radius, - CGFloat* colors, - int numColors) + CGContextRef context, + CGRect bounds, + CGFloat radius, + CGFloat* colors, + int numColors) { NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; CGPathRef path; - CGPoint end = {bounds.origin.x, - bounds.origin.y + bounds.size.height}; + CGPoint end = { + bounds.origin.x, + bounds.origin.y + bounds.size.height + }; CGGradientRef gradient = CGGradientCreateWithColorComponents( - deviceRGB.CGColorSpace, colors, NULL, numColors); + deviceRGB.CGColorSpace, colors, NULL, numColors); path = CGPathCreateWithRoundedRect(bounds, radius, radius, NULL); CGContextBeginPath(context); CGContextAddPath(context, path); @@ -293,7 +294,6 @@ static void GradientFillRoundedRectangle( CFRelease(gradient); } - static void DrawUpDownArrows( CGContextRef context, CGRect bounds, @@ -327,7 +327,9 @@ static void DrawDownArrow( x = bounds.origin.x + inset; y = bounds.origin.y + trunc(bounds.size.height/2); CGContextBeginPath(context); - CGPoint arrow[3] = {{x, y-size/4}, {x+size/2, y+size/4}, {x+size, y-size/4}}; + CGPoint arrow[3] = { + {x, y-size/4}, {x+size/2, y+size/4}, {x+size, y-size/4} + }; CGContextAddLines(context, arrow, 3); CGContextStrokePath(context); } @@ -345,19 +347,20 @@ static void DrawUpArrow( x = bounds.origin.x + inset; y = bounds.origin.y + trunc(bounds.size.height/2); CGContextBeginPath(context); - CGPoint arrow[3] = {{x, y+size/4}, {x+size/2, y-size/4}, {x+size, y+size/4}}; + CGPoint arrow[3] = { + {x, y+size/4}, {x+size/2, y-size/4}, {x+size, y+size/4} + }; CGContextAddLines(context, arrow, 3); CGContextStrokePath(context); } -/* +/*---------------------------------------------------------------------- * DrawListHeader -- * - * This is a standalone drawing procedure which draws column - * headers for a Treeview in the Aqua appearance. The HITheme - * headers have not matched the native ones since OSX 10.8. - * Note that the header image is ignored, but we draw arrows - * according to the state. + * This is a standalone drawing procedure which draws column headers for a + * Treeview in the Aqua appearance. The HITheme headers have not matched + * the native ones since OSX 10.8. Note that the header image is ignored, + * but we draw arrows according to the state. */ static void DrawListHeader( @@ -439,7 +442,7 @@ static void DrawListHeader( */ /* - * Colors and gradients used in Dark Mode. + * Colors and gradients used in Dark Mode. */ static CGFloat darkButtonFace[4] = {112.0/255, 113.0/255, 115.0/255, 1.0}; @@ -461,7 +464,8 @@ static CGFloat darkInactiveGradient[8] = {89.0/255, 90.0/255, 93.0/255, 1.0, static CGFloat darkSelectedGradient[8] = {23.0/255, 111.0/255, 232.0/255, 1.0, 20.0/255, 94.0/255, 206.0/255, 1.0}; -/* FillButtonBackground -- +/*---------------------------------------------------------------------- + * FillButtonBackground -- * * Fills a rounded rectangle with a transparent black gradient. */ @@ -474,20 +478,23 @@ static void FillButtonBackground( CGPathRef path; NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; CGGradientRef backgroundGradient = CGGradientCreateWithColorComponents( - deviceRGB.CGColorSpace, darkBackgroundGradient, NULL, 2); - CGPoint backgroundEnd = {bounds.origin.x, - bounds.origin.y + bounds.size.height}; + deviceRGB.CGColorSpace, darkBackgroundGradient, NULL, 2); + CGPoint backgroundEnd = { + bounds.origin.x, + bounds.origin.y + bounds.size.height + }; CGContextBeginPath(context); path = CGPathCreateWithRoundedRect(bounds, radius, radius, NULL); CGContextAddPath(context, path); CGContextClip(context); CGContextDrawLinearGradient(context, backgroundGradient, - bounds.origin, backgroundEnd, 0); + bounds.origin, backgroundEnd, 0); CFRelease(path); CFRelease(backgroundGradient); } -/* HighlightButtonBorder -- +/*---------------------------------------------------------------------- + * HighlightButtonBorder -- * * Accent the top border of a rounded rectangle with a transparent * white gradient. @@ -500,13 +507,13 @@ static void HighlightButtonBorder( NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; CGPoint topEnd = {bounds.origin.x, bounds.origin.y + 3}; CGGradientRef topGradient = CGGradientCreateWithColorComponents( - deviceRGB.CGColorSpace, darkTopGradient, NULL, 2); + deviceRGB.CGColorSpace, darkTopGradient, NULL, 2); CGContextSaveGState(context); CGContextBeginPath(context); CGContextAddArc(context, bounds.origin.x + 4, bounds.origin.y + 4, - 4, PI, 3*PI/2, 0); + 4, PI, 3*PI/2, 0); CGContextAddArc(context, bounds.origin.x + bounds.size.width - 4, - bounds.origin.y + 4, 4, 3*PI/2, 0, 0); + bounds.origin.y + 4, 4, 3*PI/2, 0, 0); CGContextReplacePathWithStrokedPath(context); CGContextClip(context); CGContextDrawLinearGradient(context, topGradient, bounds.origin, topEnd, 0.0); @@ -514,11 +521,11 @@ static void HighlightButtonBorder( CFRelease(topGradient); } -/* +/*---------------------------------------------------------------------- * DrawDarkButton -- * - * This is a standalone drawing procedure which draws PushButtons and - * PopupButtons in the Dark Mode style. + * This is a standalone drawing procedure which draws PushButtons and + * PopupButtons in the Dark Mode style. */ static void DrawDarkButton( @@ -547,7 +554,7 @@ static void DrawDarkButton( bounds = CGRectInset(bounds, 1, 1); if (kind == kThemePushButton && (state & TTK_STATE_PRESSED)) { GradientFillRoundedRectangle(context, bounds, 4, - darkSelectedGradient, 2); + darkSelectedGradient, 2); } else { if (state & TTK_STATE_DISABLED) { faceColor = [NSColor colorWithColorSpace: deviceRGB @@ -589,11 +596,11 @@ static void DrawDarkButton( HighlightButtonBorder(context, bounds); } -/* +/*---------------------------------------------------------------------- * DrawDarkIncDecButton -- * - * This is a standalone drawing procedure which draws an IncDecButton - * (as used in a Spinbox) in the Dark Mode style. + * This is a standalone drawing procedure which draws an IncDecButton + * (as used in a Spinbox) in the Dark Mode style. */ static void DrawDarkIncDecButton( @@ -645,11 +652,11 @@ static void DrawDarkIncDecButton( HighlightButtonBorder(context, bounds); } -/* +/*---------------------------------------------------------------------- * DrawDarkBevelButton -- * - * This is a standalone drawing procedure which draws - * RoundedBevelButtons in the Dark Mode style. + * This is a standalone drawing procedure which draws RoundedBevelButtons + * in the Dark Mode style. */ static void DrawDarkBevelButton( @@ -672,7 +679,7 @@ static void DrawDarkBevelButton( components: darkPressedBevelFace count: 4]; } else if ((state & TTK_STATE_DISABLED) || - (state & TTK_STATE_ALTERNATE)){ + (state & TTK_STATE_ALTERNATE)) { faceColor = [NSColor colorWithColorSpace: deviceRGB components: darkDisabledButtonFace count: 4]; @@ -689,11 +696,11 @@ static void DrawDarkBevelButton( HighlightButtonBorder(context, bounds); } -/* +/*---------------------------------------------------------------------- * DrawDarkCheckBox -- * - * This is a standalone drawing procedure which draws Checkboxes - * in the Dark Mode style. + * This is a standalone drawing procedure which draws Checkboxes in the + * Dark Mode style. */ static void DrawDarkCheckBox( @@ -713,16 +720,16 @@ static void DrawDarkCheckBox( FillButtonBackground(context, bounds, 4); bounds = CGRectInset(bounds, 1, 1); if (!(state & TTK_STATE_BACKGROUND) && - !(state & TTK_STATE_DISABLED) && - ((state & TTK_STATE_SELECTED) || (state & TTK_STATE_ALTERNATE))) { + !(state & TTK_STATE_DISABLED) && + ((state & TTK_STATE_SELECTED) || (state & TTK_STATE_ALTERNATE))) { GradientFillRoundedRectangle(context, bounds, 3, - darkSelectedGradient, 2); + darkSelectedGradient, 2); } else { GradientFillRoundedRectangle(context, bounds, 3, - darkInactiveGradient, 2); + darkInactiveGradient, 2); } HighlightButtonBorder(context, bounds); - if ((state & TTK_STATE_SELECTED) || (state & TTK_STATE_ALTERNATE)) { + if ((state & TTK_STATE_SELECTED) || (state & TTK_STATE_ALTERNATE)) { CGContextSetStrokeColorSpace(context, deviceRGB.CGColorSpace); if (state & TTK_STATE_DISABLED) { stroke = [NSColor disabledControlTextColor]; @@ -746,7 +753,7 @@ static void DrawDarkCheckBox( } } -/* +/*---------------------------------------------------------------------- * DrawDarkRadioButton -- * * This is a standalone drawing procedure which draws RadioButtons @@ -770,16 +777,16 @@ static void DrawDarkRadioButton( FillButtonBackground(context, bounds, 9); bounds = CGRectInset(bounds, 1, 1); if (!(state & TTK_STATE_BACKGROUND) && - !(state & TTK_STATE_DISABLED) && - ((state & TTK_STATE_SELECTED) || (state & TTK_STATE_ALTERNATE))) { + !(state & TTK_STATE_DISABLED) && + ((state & TTK_STATE_SELECTED) || (state & TTK_STATE_ALTERNATE))) { GradientFillRoundedRectangle(context, bounds, 8, - darkSelectedGradient, 2); + darkSelectedGradient, 2); } else { GradientFillRoundedRectangle(context, bounds, 8, - darkInactiveGradient, 2); + darkInactiveGradient, 2); } HighlightButtonBorder(context, bounds); - if ((state & TTK_STATE_SELECTED) || (state & TTK_STATE_ALTERNATE)) { + if ((state & TTK_STATE_SELECTED) || (state & TTK_STATE_ALTERNATE)) { CGContextSetStrokeColorSpace(context, deviceRGB.CGColorSpace); if (state & TTK_STATE_DISABLED) { fill = [NSColor disabledControlTextColor]; @@ -799,7 +806,7 @@ static void DrawDarkRadioButton( } } -/* +/*---------------------------------------------------------------------- * DrawDarkTab -- * * This is a standalone drawing procedure which draws Tabbed Pane @@ -833,9 +840,8 @@ static void DrawDarkTab( } /* - * Fill the tab face with the appropriate color or gradient. Use a - * solid color if the tab is not selected, otherwise use a blue or - * gray gradient. + * Fill the tab face with the appropriate color or gradient. Use a solid + * color if the tab is not selected, otherwise use a blue or gray gradient. */ bounds = CGRectInset(bounds, 1, 1); @@ -872,7 +878,6 @@ static void DrawDarkTab( CGContextRestoreGState(context); } } else { - /* * This is the selected tab; paint it blue. If it is first, cover up * the separator line drawn by the second one. (The selected tab is @@ -895,7 +900,7 @@ static void DrawDarkTab( } } -/* +/*---------------------------------------------------------------------- * DrawDarkSeparator -- * * This is a standalone drawing procedure which draws a separator widget @@ -916,7 +921,7 @@ static void DrawDarkSeparator( CGContextFillRect(context, bounds); } -/* +/*---------------------------------------------------------------------- * DrawDarkFrame -- * * This is a standalone drawing procedure which draws various @@ -933,7 +938,9 @@ static void DrawDarkFrame( CGContextSetStrokeColorSpace(context, deviceRGB.CGColorSpace); CGFloat x = bounds.origin.x, y = bounds.origin.y; CGFloat w = bounds.size.width, h = bounds.size.height; - CGPoint topPart[4] = {{x, y + h - 1}, {x, y}, {x + w, y}, {x + w, y + h - 1}}; + CGPoint topPart[4] = { + {x, y + h - 1}, {x, y}, {x + w, y}, {x + w, y + h - 1} + }; CGPoint bottom[2] = {{x, y + h}, {x + w, y + h}}; CGPoint accent[2] = {{x, y + 1}, {x + w, y + 1}}; switch(kind) { @@ -966,7 +973,7 @@ static void DrawDarkFrame( } } -/* +/*---------------------------------------------------------------------- * DrawListHeader -- * * This is a standalone drawing procedure which draws column @@ -1005,6 +1012,7 @@ static void DrawDarkListHeader( if (state & TTK_TREEVIEW_STATE_SORTARROW) { CGRect arrowBounds = bounds; + arrowBounds.origin.x = bounds.origin.x + bounds.size.width - 16; arrowBounds.size.width = 16; if (state & TTK_STATE_ALTERNATE) { @@ -1053,9 +1061,10 @@ static Ttk_StateTable ButtonAdornmentTable[] = { { kThemeAdornmentDefault, TTK_STATE_ALTERNATE, 0 }, { kThemeAdornmentNone, TTK_STATE_ALTERNATE, 0 }, { kThemeAdornmentFocus, TTK_STATE_FOCUS, 0 }, - { kThemeAdornmentNone, 0, 0 }}; + { kThemeAdornmentNone, 0, 0 } +}; -/* +/*---------------------------------------------------------------------- * computeButtonDrawInfo -- * Fill in an appearance manager HIThemeButtonDrawInfo record. */ @@ -1066,8 +1075,8 @@ static inline HIThemeButtonDrawInfo computeButtonDrawInfo( Tk_Window tkwin) { /* - * See ButtonElementDraw for the explanation of why we always draw - * PushButtons in the active state. + * See ButtonElementDraw for the explanation of why we always draw + * PushButtons in the active state. */ SInt32 HIThemeState; @@ -1108,10 +1117,10 @@ static void ButtonElementMinSize( *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. + * 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; @@ -1129,7 +1138,7 @@ static void ButtonElementSize( int verticalPad; ButtonElementMinSize(clientData, elementRecord, tkwin, - minWidth, minHeight, paddingPtr); + minWidth, minHeight, paddingPtr); /* * Given a hypothetical bounding rectangle for a button, HIToolbox will @@ -1149,12 +1158,12 @@ static void ButtonElementSize( */ ChkErr(HIThemeGetButtonContentBounds, - &scratchBounds, &info, &contentBounds); + &scratchBounds, &info, &contentBounds); ChkErr(HIThemeGetButtonBackgroundBounds, - &scratchBounds, &info, &backgroundBounds); + &scratchBounds, &info, &backgroundBounds); paddingPtr->left = contentBounds.origin.x - backgroundBounds.origin.x; - paddingPtr->right = (CGRectGetMaxX(backgroundBounds) - - CGRectGetMaxX(contentBounds)); + paddingPtr->right = + CGRectGetMaxX(backgroundBounds) - CGRectGetMaxX(contentBounds); verticalPad = backgroundBounds.size.height - contentBounds.size.height; paddingPtr->top = paddingPtr->bottom = verticalPad / 2; } @@ -1186,20 +1195,21 @@ static void ButtonElementDraw( DrawDarkBevelButton(bounds, state, dc.context); break; default: - ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); + ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, + HIOrientation, NULL); } #endif } else { /* - * Apple's PushButton and PopupButton do not change their fill color - * when the window is inactive. However, except in 10.7 (Lion), the - * color of the arrow button on a PopupButton does change. For some - * reason HITheme fills inactive buttons with a transparent color that - * allows the window background to show through, leading to - * inconsistent behavior. We work around this by filling behind an - * inactive PopupButton with a text background color before asking - * HIToolbox to draw it. For PushButtons, we simply draw them in the - * active state. + * Apple's PushButton and PopupButton do not change their fill color + * when the window is inactive. However, except in 10.7 (Lion), the + * color of the arrow button on a PopupButton does change. For some + * reason HITheme fills inactive buttons with a transparent color that + * allows the window background to show through, leading to + * inconsistent behavior. We work around this by filling behind an + * inactive PopupButton with a text background color before asking + * HIToolbox to draw it. For PushButtons, we simply draw them in the + * active state. */ #if MAC_OS_X_VERSION_MIN_REQUIRED > 1080 @@ -1220,7 +1230,8 @@ static void ButtonElementDraw( info.value = kThemeButtonOff; info.state = kThemeStateInactive; } - ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); + ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, + NULL); } END_DRAWING } @@ -1292,6 +1303,7 @@ static Ttk_StateTable TabPositionTable[] = { * the tab view, leave enough space below the tab view so the controls are 20 * pixels above the bottom edge of the window and 12 pixels between the tab * view and the controls. + * * If you choose to extend the tab view sides and bottom so that they meet the * window sides and bottom, you should leave a margin of at least 20 pixels * between the content in the tab view and the tab-view edges. @@ -1397,11 +1409,11 @@ static Ttk_ElementSpec PaneElementSpec = { * Labelframe borders: * Use "primary group box ..." * Quoth DrawThemePrimaryGroup reference: - * "The primary group box frame is drawn inside the specified - * rectangle and is a maximum of 2 pixels thick." + * "The primary group box frame is drawn inside the specified rectangle and is + * a maximum of 2 pixels thick." * - * "Maximum of 2 pixels thick" is apparently a lie; - * looks more like 4 to me with shading. + * "Maximum of 2 pixels thick" is apparently a lie; looks more like 4 to me + * with shading. */ static void GroupElementSize( @@ -1476,7 +1488,7 @@ static void EntryElementDraw( CGRect bounds = BoxToRect(d, inner); NSColor *background; Tk_3DBorder backgroundPtr = NULL; - static char *defaultBG = ENTRY_DEFAULT_BACKGROUND; + static const char *defaultBG = ENTRY_DEFAULT_BACKGROUND; if (TkMacOSXInDarkMode(tkwin)) { #if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 @@ -1504,8 +1516,9 @@ static void EntryElementDraw( * Earlier versions of the Aqua theme ignored the -fieldbackground * option and used the -background as if it were -fieldbackground. * Here we are enabling -fieldbackground. For backwards compatibility, - * if -fieldbackground is set to the default color and -background - * is set to a different color then we use -background as -fieldbackground. + * if -fieldbackground is set to the default color and -background is + * set to a different color then we use -background as + * -fieldbackground. */ if (0 != strcmp(Tcl_GetString(e->fieldbackgroundObj), defaultBG)) { @@ -1515,8 +1528,8 @@ static void EntryElementDraw( } if (backgroundPtr != NULL) { XFillRectangle(Tk_Display(tkwin), d, - Tk_3DBorderGC(tkwin, backgroundPtr, TK_3D_FLAT_GC), - inner.x, inner.y, inner.width, inner.height); + Tk_3DBorderGC(tkwin, backgroundPtr, TK_3D_FLAT_GC), + inner.x, inner.y, inner.width, inner.height); } BEGIN_DRAWING(d) if (backgroundPtr == NULL) { @@ -1544,21 +1557,20 @@ static Ttk_ElementSpec EntryElementSpec = { * +++ Combobox: * * NOTES: - * The HIToolbox has incomplete and inconsistent support for ComboBoxes. - * There is no constant available to get the height of a ComboBox with - * GetThemeMetric. In fact, ComboBoxes are the same (fixed) height as - * PopupButtons and PushButtons, but they have no shadow at the bottom. - * As a result, they are drawn 1 pixel above the center of the bounds - * rectangle rather than being centered like the other buttons. One - * can request background bounds for a ComboBox, and it is reported with - * height 23, while the actual button face, including its 1-pixel border - * has height 21. Attempting to request the content bounds returns a - * 0 x 0 rectangle. Measurement indicates that the arrow button has - * width 18. + * The HIToolbox has incomplete and inconsistent support for ComboBoxes. + * There is no constant available to get the height of a ComboBox with + * GetThemeMetric. In fact, ComboBoxes are the same (fixed) height as + * PopupButtons and PushButtons, but they have no shadow at the bottom. + * As a result, they are drawn 1 pixel above the center of the bounds + * rectangle rather than being centered like the other buttons. One can + * request background bounds for a ComboBox, and it is reported with + * height 23, while the actual button face, including its 1-pixel border + * has height 21. Attempting to request the content bounds returns a 0x0 + * rectangle. Measurement indicates that the arrow button has width 18. * - * With no help available from HIToolbox, we have to use hard-wired - * constants for the padding. We shift the bounding rectangle downward - * by 1 pixel to account for the fact that the button is not centered. + * With no help available from HIToolbox, we have to use hard-wired + * constants for the padding. We shift the bounding rectangle downward by + * 1 pixel to account for the fact that the button is not centered. */ static Ttk_Padding ComboboxPadding = {4, 2, 20, 2 }; @@ -1618,22 +1630,22 @@ static Ttk_ElementSpec ComboboxElementSpec = { /*---------------------------------------------------------------------- * +++ Spinbuttons. * - * From Apple HIG, part III, section "Controls", "The Stepper Control": - * there should be 2 pixels of space between the stepper control (AKA - * IncDecButton, AKA "little arrows") and the text field it modifies. + * From Apple HIG, part III, section "Controls", "The Stepper Control": + * there should be 2 pixels of space between the stepper control (AKA + * IncDecButton, AKA "little arrows") and the text field it modifies. * - * Ttk expects the up and down arrows to be distinct elements but HIToolbox - * draws them as one widget with two different pressed states. We work - * around this by defining them as separate elements in the layout, but - * making each one have a drawing method which also draws the other one. - * The down button does no drawing when not pressed, and when pressed draws - * the entire IncDecButton in its "pressed down" state. The up button draws - * the entire IncDecButton when not pressed and when pressed draws the - * IncDecButton in its "pressed up" state. NOTE: This means that when the - * down button is pressed the IncDecButton will be drawn twice, first - * in unpressed state by the up arrow and then in "pressed down" state by - * the down button. The drawing must be done in that order. So the up - * button must be listed first in the layout. + * Ttk expects the up and down arrows to be distinct elements but + * HIToolbox draws them as one widget with two different pressed states. + * We work around this by defining them as separate elements in the + * layout, but making each one have a drawing method which also draws the + * other one. The down button does no drawing when not pressed, and when + * pressed draws the entire IncDecButton in its "pressed down" state. The + * up button draws the entire IncDecButton when not pressed and when + * pressed draws the IncDecButton in its "pressed up" state. NOTE: This + * means that when the down button is pressed the IncDecButton will be + * drawn twice, first in unpressed state by the up arrow and then in + * "pressed down" state by the down button. The drawing must be done in + * that order. So the up button must be listed first in the layout. */ static Ttk_Padding SpinbuttonMargins = {0, 0, 2, 0}; @@ -1669,9 +1681,12 @@ static void SpinButtonUpElementDraw( .adornment = kThemeAdornmentNone, }; BEGIN_DRAWING(d) +#if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 if (TkMacOSXInDarkMode(tkwin)) { DrawDarkIncDecButton(bounds, infoState, state, dc.context); - } else { + } else +#endif + { ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); } END_DRAWING @@ -1719,9 +1734,12 @@ static void SpinButtonDownElementDraw( }; BEGIN_DRAWING(d) +#if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 if (TkMacOSXInDarkMode(tkwin)) { DrawDarkIncDecButton(bounds, infoState, state, dc.context); - } else { + } else +#endif + { ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); } END_DRAWING @@ -1741,8 +1759,8 @@ static Ttk_ElementSpec SpinButtonDownElementSpec = { */ /* - * Apple does not change the appearance of a slider when the window - * becomes inactive. So we shouldn't either. + * Apple does not change the appearance of a slider when the window becomes + * inactive. So we shouldn't either. */ static Ttk_StateTable ThemeTrackEnableTable[] = { @@ -1761,7 +1779,6 @@ static TrackElementData ScaleData = { kThemeSlider, kThemeMetricHSliderHeight }; - typedef struct { Tcl_Obj *fromObj; /* minimum value */ Tcl_Obj *toObj; /* maximum value */ @@ -1860,9 +1877,8 @@ static Ttk_ElementSpec TrackElementSpec = { * and uses it for hit detection. In the Aqua theme, the slider is actually * drawn as part of the trough element. * - * Also buggy: The geometry here is a Wild-Assed-Guess; I can't - * figure out how to get the Appearance Manager to tell me the - * slider size. + * Also buggy: The geometry here is a Wild-Assed-Guess; I can't figure out how + * to get the Appearance Manager to tell me the slider size. */ static void SliderElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, @@ -1913,7 +1929,7 @@ static void PbarElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) { - SInt32 size = 24; /* @@@ Check HIG for correct default */ + SInt32 size = 24; /* @@@ Check HIG for correct default */ ChkErr(GetThemeMetric, kThemeMetricLargeProgressBarThickness, &size); *minWidth = *minHeight = size; @@ -1982,7 +1998,7 @@ static Ttk_ElementSpec PbarElementSpec = { typedef struct { - Tcl_Obj *orientObj; + Tcl_Obj *orientObj; } ScrollbarElement; static Ttk_ElementOptionSpec ScrollbarElementOptions[] = { @@ -2286,7 +2302,8 @@ static void SizegripElementDraw( HIThemeGrowBoxDrawInfo info = { .version = 0, /* Grow box only supports kThemeStateActive, kThemeStateInactive */ - .state = Ttk_StateTableLookup(ThemeStateTable, state & TTK_STATE_BACKGROUND), + .state = Ttk_StateTableLookup(ThemeStateTable, + state & TTK_STATE_BACKGROUND), .kind = kHIThemeGrowBoxKindNormal, .direction = sizegripGrowDirection, .size = kHIThemeGrowBoxSizeNormal, @@ -2308,46 +2325,46 @@ static Ttk_ElementSpec SizegripElementSpec = { /*---------------------------------------------------------------------- * +++ Background and fill elements. * - * Before drawing any ttk widget, its bounding rectangle is filled with a - * background color. This color must match the background color of the - * containing widget to avoid looking ugly. The need for care when doing - * this is exacerbated by the fact that ttk enforces its "native look" by - * not allowing user control of the background or highlight colors of ttk - * widgets. + * Before drawing any ttk widget, its bounding rectangle is filled with a + * background color. This color must match the background color of the + * containing widget to avoid looking ugly. The need for care when doing + * this is exacerbated by the fact that ttk enforces its "native look" by + * not allowing user control of the background or highlight colors of ttk + * widgets. * - * 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. + * 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 system background color. If widgets - * inside the box were drawn with the system background color the - * backgrounds would match. But this produces a GroupBox with no contrast, - * the only visual clue being a faint highlighting around the top of the - * GroupBox. Moreover, the TabbedPane does not have an Opaque version, so - * while it is drawn inside a contrasting rounded rectangle, the widgets - * inside the pane needed to be enclosed in a frame with the system - * background color. This added a visual artifact since the frame's - * background color does not match the Pane's background color. That code - * has now been replaced with the standalone drawing procedure - * macOSXDrawGroupBox, which draws a rounded rectangle with an appropriate - * contrasting background 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 + * system background color. If widgets inside the box were drawn with the + * system background color the backgrounds would match. But this produces + * a GroupBox with no contrast, the only visual clue being a faint + * highlighting around the top of the GroupBox. Moreover, the TabbedPane + * does not have an Opaque version, so while it is drawn inside a + * contrasting rounded rectangle, the widgets inside the pane needed to be + * enclosed in a frame with the system background color. This added a + * visual artifact since the frame's background color does not match the + * Pane's background color. That code has now been replaced with the + * standalone drawing procedure macOSXDrawGroupBox, which draws a rounded + * rectangle with an appropriate contrasting background color. * - * Patterned backgrounds, which are now obsolete, should be aligned with the - * coordinate system of the top-level window. Apparently failing to do this - * used to cause graphics anomalies when drawing into an off-screen graphics - * port. The code for handling this is currently commented out. + * Patterned backgrounds, which are now obsolete, should be aligned with + * the coordinate system of the top-level window. Apparently failing to + * do this used to cause graphics anomalies when drawing into an + * off-screen graphics port. The code for handling this is currently + * commented out. */ - static void FillElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) @@ -2460,8 +2477,8 @@ static void FieldElementDraw( FieldElement *e = elementRecord; Tk_3DBorder backgroundPtr = Tk_Get3DBorderFromObj(tkwin,e->backgroundObj); XFillRectangle(Tk_Display(tkwin), d, - Tk_3DBorderGC(tkwin, backgroundPtr, TK_3D_FLAT_GC), - b.x, b.y, b.width, b.height); + Tk_3DBorderGC(tkwin, backgroundPtr, TK_3D_FLAT_GC), + b.x, b.y, b.width, b.height); } static Ttk_ElementSpec FieldElementSpec = { @@ -2502,8 +2519,8 @@ static void TreeAreaElementSize ( * widget expects the heading to be the same height as a row. */ - if ([NSApp macMinorVersion] > 8) { - paddingPtr->top = 4; + if ([NSApp macMinorVersion] > 8) { + paddingPtr->top = 4; } } @@ -2521,10 +2538,9 @@ static void TreeHeaderElementSize( { if ([NSApp macMinorVersion] > 8) { *minHeight = 24; - } else { ButtonElementSize(clientData, elementRecord, tkwin, minWidth, - minHeight, paddingPtr); + minHeight, paddingPtr); } } @@ -2551,9 +2567,12 @@ static void TreeHeaderElementDraw( */ bounds.origin.y -= 4; +#if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 if (TkMacOSXInDarkMode(tkwin)) { DrawDarkListHeader(bounds, dc.context, tkwin, state); - } else { + } else +#endif + { DrawListHeader(bounds, dc.context, tkwin, state); } } else { @@ -2785,7 +2804,8 @@ static int AquaTheme_Init(Tcl_Interp *interp) Ttk_RegisterElementSpec(themePtr,"Horizontal.Scrollbar.thumb", &ThumbElementSpec, 0); /* - * If we are not in Snow Leopard or Lion the arrows won't actually be displayed. + * If we are not in Snow Leopard or Lion the arrows won't actually be + * displayed. */ Ttk_RegisterElementSpec(themePtr,"Vertical.Scrollbar.uparrow", &ArrowElementSpec, 0); -- cgit v0.12 From 68457210ab2ba459c2964532adf30c6dcfce13f8 Mon Sep 17 00:00:00 2001 From: culler Date: Thu, 11 Apr 2019 14:14:11 +0000 Subject: Remove a call to NSView.setNeedsDisplay which was meant to fix [4d2e8d4d5c] but does not. --- macosx/ttkMacOSXTheme.c | 1 - 1 file changed, 1 deletion(-) diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index b0ac075..54c3df2 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -1394,7 +1394,6 @@ static void PaneElementDraw( ChkErr(HIThemeDrawTabPane, &bounds, &info, dc.context, HIOrieRectntation); #endif END_DRAWING - [TkMacOSXDrawableView(macWin) setNeedsDisplay:YES]; } static Ttk_ElementSpec PaneElementSpec = { -- cgit v0.12 From 06eae3afe11df81ccf06822a9e6d186b657138ba Mon Sep 17 00:00:00 2001 From: culler Date: Fri, 12 Apr 2019 15:49:41 +0000 Subject: Fix the build for OSX 10.6 (Snow Leopard). --- macosx/tkMacOSXColor.c | 40 ++++++++++++++++++++++++---------------- macosx/ttkMacOSXTheme.c | 15 +++++++++------ 2 files changed, 33 insertions(+), 22 deletions(-) diff --git a/macosx/tkMacOSXColor.c b/macosx/tkMacOSXColor.c index 5e983e3..0a25490 100644 --- a/macosx/tkMacOSXColor.c +++ b/macosx/tkMacOSXColor.c @@ -257,6 +257,8 @@ GetEntryFromPixelCode( *---------------------------------------------------------------------- */ +static NSColorSpace* deviceRGB = NULL; + static OSStatus SetCGColorComponents( struct SystemColorMapEntry entry, @@ -266,11 +268,17 @@ SetCGColorComponents( OSStatus err = noErr; NSColor *bgColor, *color; CGFloat rgba[4] = {0, 0, 0, 1}; - static CGColorSpaceRef deviceRGBSpace = NULL; - if (!deviceRGBSpace) { - deviceRGBSpace = CGColorSpaceCreateDeviceRGB(); + if (!deviceRGB) { + deviceRGB = [NSColorSpace deviceRGBColorSpace]; } + /* + * 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); @@ -282,7 +290,7 @@ SetCGColorComponents( break; case ttkBackground: bgColor = [[NSColor windowBackgroundColor] colorUsingColorSpace: - [NSColorSpace deviceRGBColorSpace]]; + deviceRGB]; [bgColor getComponents: rgba]; for (int i=0; i<3; i++) { rgba[i] -= entry.value*(8.0/255.0); @@ -292,45 +300,45 @@ SetCGColorComponents( switch (entry.value) { case 0: color = [[NSColor textColor] colorUsingColorSpace: - [NSColorSpace deviceRGBColorSpace]]; + deviceRGB]; break; case 1: color = [[NSColor selectedTextColor] colorUsingColorSpace: - [NSColorSpace deviceRGBColorSpace]]; + deviceRGB]; break; case 2: #if MAC_OS_X_VERSION_MIN_REQUIRED > 101000 color = [[NSColor labelColor] colorUsingColorSpace: - [NSColorSpace deviceRGBColorSpace]]; + deviceRGB]; #else color = [[NSColor textColor] colorUsingColorSpace: - [NSColorSpace deviceRGBColorSpace]]; + deviceRGB]; #endif break; case 3: color = [[NSColor controlTextColor] colorUsingColorSpace: - [NSColorSpace deviceRGBColorSpace]]; + deviceRGB]; break; case 4: color = [[NSColor disabledControlTextColor] colorUsingColorSpace: - [NSColorSpace deviceRGBColorSpace]]; + deviceRGB]; break; case 5: color = [[NSColor textBackgroundColor] colorUsingColorSpace: - [NSColorSpace deviceRGBColorSpace]]; + deviceRGB]; break; case 6: color = [[NSColor selectedTextBackgroundColor] colorUsingColorSpace: - [NSColorSpace deviceRGBColorSpace]]; + deviceRGB]; break; default: if ([NSApp macMinorVersion] < 10) { color = [[NSColor textColor] colorUsingColorSpace: - [NSColorSpace deviceRGBColorSpace]]; + deviceRGB]; } else { #if MAC_OS_X_VERSION_MIN_REQUIRED >= 101000 color = [[NSColor labelColor] colorUsingColorSpace: - [NSColorSpace deviceRGBColorSpace]]; + deviceRGB]; #endif break; } @@ -352,7 +360,8 @@ SetCGColorComponents( default: break; } - *c = CGColorCreate(deviceRGBSpace, rgba ); + *c = CGColorCreate(deviceRGB.CGColorSpace, rgba ); + [pool drain]; return err; } @@ -684,7 +693,6 @@ TkpGetColor( 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); diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index 54c3df2..84e5b5f 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -1372,8 +1372,6 @@ static void PaneElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) { - TkWindow *winPtr = (TkWindow *)tkwin; - MacDrawable *macWin = winPtr->privatePtr; CGRect bounds = BoxToRect(d, b); bounds.origin.y -= kThemeMetricTabFrameOverlap; bounds.size.height += kThemeMetricTabFrameOverlap; @@ -1391,7 +1389,7 @@ static void PaneElementDraw( }; bounds.origin.y -= kThemeMetricTabFrameOverlap; bounds.size.height += kThemeMetricTabFrameOverlap; - ChkErr(HIThemeDrawTabPane, &bounds, &info, dc.context, HIOrieRectntation); + ChkErr(HIThemeDrawTabPane, &bounds, &info, dc.context, HIOrientation); #endif END_DRAWING } @@ -1533,7 +1531,11 @@ static void EntryElementDraw( BEGIN_DRAWING(d) if (backgroundPtr == NULL) { background = [NSColor textBackgroundColor]; +#if MAC_OS_X_VERSION_MIN_REQUIRED > 1080 CGContextSetFillColorWithColor(dc.context, background.CGColor); +#else + CGContextSetRGBFillColor(dc.context, 1.0, 1.0, 1.0, 1.0); +#endif CGContextFillRect(dc.context, bounds); } ChkErr(HIThemeDrawFrame, &bounds, &info, dc.context, HIOrientation); @@ -2559,6 +2561,7 @@ static void TreeHeaderElementDraw( BEGIN_DRAWING(d) if ([NSApp macMinorVersion] > 8) { +#if MAC_OS_X_VERSION_MIN_REQUIRED > 1080 /* * Compensate for the padding added in TreeHeaderElementSize, so @@ -2566,14 +2569,14 @@ static void TreeHeaderElementDraw( */ bounds.origin.y -= 4; -#if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 if (TkMacOSXInDarkMode(tkwin)) { +#if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 DrawDarkListHeader(bounds, dc.context, tkwin, state); - } else #endif - { + } else { DrawListHeader(bounds, dc.context, tkwin, state); } +#endif /* MAC_OS_X_VERSION_MIN_REQUIRED > 1080 */ } else { ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); } -- cgit v0.12 From 0b924bbd8939f5da89d90aa327dd711182020fe7 Mon Sep 17 00:00:00 2001 From: culler Date: Fri, 12 Apr 2019 16:50:12 +0000 Subject: Fix the build for OSX 10.9 (Mavericks) --- macosx/tkMacOSXWm.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index a426664..fa2acf7 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -5886,7 +5886,7 @@ WmWinAppearance( int objc, /* Number of arguments. */ Tcl_Obj * const objv[]) /* Argument objects. */ { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1090 +#if MAC_OS_X_VERSION_MAX_ALLOWED > 1090 static const char *const appearanceStrings[] = { "aqua", "darkaqua", "auto", NULL }; @@ -5902,6 +5902,7 @@ WmWinAppearance( const char *resultString; NSWindow *win = TkMacOSXDrawableWindow(winPtr->window); if (win) { +#if MAC_OS_X_VERSION_MAX_ALLOWED > 1090 appearance = win.appearance.name; if (appearance == nil) { resultString = appearanceStrings[APPEARANCE_AUTO]; @@ -5914,6 +5915,9 @@ WmWinAppearance( } else { resultString = "unrecognized"; } +#else + resultString = appearanceStrings[APPEARANCE_AQUA]; +#endif result = Tcl_NewStringObj(resultString, strlen(resultString)); } if (result == NULL) { -- cgit v0.12 From 5fcdcad94218bd7dd8c25afc41d6d7218d6355f5 Mon Sep 17 00:00:00 2001 From: culler Date: Fri, 12 Apr 2019 19:06:01 +0000 Subject: Add update calls in frame.test for consistent results in OSX 10.12-10.14. --- tests/frame.test | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/frame.test b/tests/frame.test index c7b0ed8..b601137 100644 --- a/tests/frame.test +++ b/tests/frame.test @@ -662,8 +662,10 @@ test frame-3.9 {TkCreateFrame procedure, -use option} -constraints { } -body { toplevel .t -container 1 -width 300 -height 120 wm geometry .t +0+0 + update toplevel .x -width 140 -height 300 -use [winfo id .t] -bg green tkwait visibility .x + update list [expr {[winfo rootx .x] - [winfo rootx .t]}] \ [expr {[winfo rooty .x] - [winfo rooty .t]}] \ [winfo width .t] [winfo height .t] @@ -678,8 +680,10 @@ test frame-3.10 {TkCreateFrame procedure, -use option} -constraints { toplevel .t -container 1 -width 300 -height 120 wm geometry .t +0+0 option add *x.use [winfo id .t] + update toplevel .x -width 140 -height 300 -bg green tkwait visibility .x + update list [expr {[winfo rootx .x] - [winfo rootx .t]}] \ [expr {[winfo rooty .x] - [winfo rooty .t]}] \ [winfo width .t] [winfo height .t] -- cgit v0.12 From 1c8361c420075b482b5eee473b2958e7b8e6b934 Mon Sep 17 00:00:00 2001 From: culler Date: Fri, 12 Apr 2019 21:10:03 +0000 Subject: Adjust for the new ttk widgets. --- library/ttk/menubutton.tcl | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/library/ttk/menubutton.tcl b/library/ttk/menubutton.tcl index 9d12b05..43b3cd8 100644 --- a/library/ttk/menubutton.tcl +++ b/library/ttk/menubutton.tcl @@ -74,35 +74,41 @@ if {[tk windowingsystem] eq "x11"} { if {[tk windowingsystem] eq "aqua"} { proc ::ttk::menubutton::PostPosition {mb menu} { - set mh [expr {[winfo reqheight $menu] - 6}] - set bh [expr {[winfo height $mb] + 1}] - set mw [expr {[winfo reqwidth $menu] - 2}] - set bw [expr {[winfo width $mb] -1}] - set dF [expr {[winfo width $mb] - [winfo reqwidth $menu] -9}] + set menuPad 5 + set buttonPad 1 + set bevelPad 4 + set mh [winfo reqheight $menu] + set bh [expr {[winfo height $mb]} + $buttonPad] + set bbh [expr {[winfo height $mb]} + $bevelPad] + set mw [winfo reqwidth $menu] + set bw [winfo width $mb] + set dF [expr {[winfo width $mb] - [winfo reqwidth $menu] - $menuPad}] set entry "" set entry [::tk::MenuFindName $menu [$mb cget -text]] if {$entry eq ""} { set entry 0 } set x [winfo rootx $mb] - set y [expr {2 + [winfo rooty $mb]}] + set y [winfo rooty $mb] switch [$mb cget -direction] { above { set entry "" - incr y -$mh + incr y [expr {-$mh + 2 * $menuPad}] } below { set entry "" incr y $bh } left { + incr y $menuPad incr x -$mw } right { + incr y $menuPad incr x $bw } default { - incr x $dF + incr y $bbh } } return [list $x $y $entry] -- cgit v0.12 From dc7c77df50b0292e2af09effaa5661007f239162 Mon Sep 17 00:00:00 2001 From: dkf Date: Fri, 12 Apr 2019 22:25:19 +0000 Subject: Added note that ttk::frames aren't interactive by default. --- doc/ttk_frame.n | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/ttk_frame.n b/doc/ttk_frame.n index 8702592..572f10c 100644 --- a/doc/ttk_frame.n +++ b/doc/ttk_frame.n @@ -58,6 +58,10 @@ Some options are only available for specific themes. .PP See the \fBttk::style\fP manual page for information on how to configure ttk styles. +.SH BINDINGS +.PP +When a new \fBttk::frame\fR is created, it has no default event bindings; +\fBttk::frame\fRs are not intended to be interactive. .SH "SEE ALSO" ttk::widget(n), ttk::labelframe(n), frame(n) .SH "KEYWORDS" -- cgit v0.12 From a955dbaac96f1fbdba1e1b4b197703ac45a2e5f0 Mon Sep 17 00:00:00 2001 From: dkf Date: Sat, 13 Apr 2019 16:27:50 +0000 Subject: Doc tweak for frames and toplevels --- doc/frame.n | 4 ++++ doc/toplevel.n | 12 +++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/doc/frame.n b/doc/frame.n index 72a22db..f2fbd96 100644 --- a/doc/frame.n +++ b/doc/frame.n @@ -99,21 +99,25 @@ The \fBframe\fR command creates a new Tcl command whose name is the same as the path name of the frame's window. This command may be used to invoke various operations on the widget. It has the following general form: +.PP .CS \fIpathName option \fR?\fIarg arg ...\fR? .CE +.PP \fIPathName\fR is the name of the command, which is the same as the frame widget's path name. \fIOption\fR and the \fIarg\fRs determine the exact behavior of the command. The following commands are possible for frame widgets: .TP \fIpathName \fBcget\fR \fIoption\fR +. Returns the current value of the configuration option given by \fIoption\fR. \fIOption\fR may have any of the values accepted by the \fBframe\fR command. .TP \fIpathName \fBconfigure\fR ?\fIoption\fR? \fI?value option value ...\fR? +. Query or modify the configuration options of the widget. If no \fIoption\fR is specified, returns a list describing all of the available options for \fIpathName\fR (see \fBTk_ConfigureInfo\fR for diff --git a/doc/toplevel.n b/doc/toplevel.n index 271d9f1..84fab14 100644 --- a/doc/toplevel.n +++ b/doc/toplevel.n @@ -104,9 +104,9 @@ to configure aspects of the toplevel such as its background color and relief. The \fBtoplevel\fR command returns the path name of the new window. .PP -A toplevel is similar to a frame except that it is created as a +A toplevel is similar to a \fBframe\fR except that it is created as a top-level window: its X parent is the root window of a screen -rather than the logical parent from its path name. The primary +rather than the logical parent from its Tk path name. The primary purpose of a toplevel is to serve as a container for dialog boxes and other collections of widgets. The only visible features of a toplevel are its background color and an optional 3-D border @@ -117,21 +117,25 @@ The \fBtoplevel\fR command creates a new Tcl command whose name is the same as the path name of the toplevel's window. This command may be used to invoke various operations on the widget. It has the following general form: +.PP .CS \fIpathName option \fR?\fIarg arg ...\fR? .CE +.PP \fIPathName\fR is the name of the command, which is the same as the toplevel widget's path name. \fIOption\fR and the \fIarg\fRs determine the exact behavior of the command. The following commands are possible for toplevel widgets: .TP \fIpathName \fBcget \fIoption\fR +. Returns the current value of the configuration option given by \fIoption\fR. \fIOption\fR may have any of the values accepted by the \fBtoplevel\fR command. .TP \fIpathName \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR? +. Query or modify the configuration options of the widget. If no \fIoption\fR is specified, returns a list describing all of the available options for \fIpathName\fR (see \fBTk_ConfigureInfo\fR for @@ -148,8 +152,10 @@ command. .PP When a new toplevel is created, it has no default event bindings: toplevels are not intended to be interactive. +.PP +Be aware that bindings on toplevels may receive events from subwidgets. .SH "SEE ALSO" -frame(n) +bind(n), bindtags(n), frame(n), wm(n) .SH KEYWORDS toplevel, widget '\" Local Variables: -- cgit v0.12 From 3a81c1fb68b1e2b976651df7359209916ea5be63 Mon Sep 17 00:00:00 2001 From: fvogel Date: Sat, 13 Apr 2019 16:44:20 +0000 Subject: Add test treeview-368fa4561e checking for non-regression regarding [368fa4561e] --- tests/ttk/treeview.test | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/ttk/treeview.test b/tests/ttk/treeview.test index aa7e64a..be82f68 100644 --- a/tests/ttk/treeview.test +++ b/tests/ttk/treeview.test @@ -636,4 +636,21 @@ test treeview-3085489-2 "tag remove, no -tags" -setup { destroy .tv } -result [list] +test treeview-368fa4561e "indicators cannot be clicked on leafs" -setup { + pack [ttk::treeview .tv] + .tv insert {} end -id foo -text "<-- (1) Click the blank space to my left" + update +} -body { + foreach {x y w h} [.tv bbox foo #0] {} + set res [.tv item foo -open] + # using $h even for x computation is intentional here in order to simulate + # a mouse click on the (invisible since we're on a leaf) indicator + event generate .tv \ + -x [expr ($x + $h / 2)] \ + -y [expr ($y + $h / 2)] + lappend res [.tv item foo -open] + .tv insert foo end -text "sub" + lappend res [.tv item foo -open] +} -result {0 0 0} + tcltest::cleanupTests -- cgit v0.12 From a231332e57a1d87c18d3e76889cc32749851f591 Mon Sep 17 00:00:00 2001 From: culler Date: Sun, 14 Apr 2019 17:29:55 +0000 Subject: For Aqua, rename systemTtkBackground to systemWindowBackgroundColor to match the NSColor name. Document the new colors. --- doc/colors.n | 39 ++++++++++++++++++++++++++++++++++++--- library/ttk/aquaTheme.tcl | 4 ++-- macosx/README | 9 +++++---- macosx/tkMacOSXColor.c | 26 ++++++++++++++++---------- 4 files changed, 59 insertions(+), 19 deletions(-) diff --git a/doc/colors.n b/doc/colors.n index dc7007b..18f73b7 100644 --- a/doc/colors.n +++ b/doc/colors.n @@ -784,9 +784,10 @@ YellowGreen 154 205 50 .TP \fBMac OS X\fR . -On Mac OS X, the following additional system colors are available -(note that the actual color values depend on the currently active OS theme, -and typically many of these will in fact be patterns rather than pure colors): +On macOS, the following additional system colors are available. +This first group contains all colors available in the HIToolbox library. +(Note that in some cases the actual color values may depend on the +current Appearance.) .RS .DS systemActiveAreaFill @@ -925,7 +926,39 @@ systemWindowHeaderBackground systemWindowHeaderInactiveText .DE .RE +. +The second group of MacOS colors below are based on Apple's "semantic" +NScolors. On OSX 10.14 (Mojave) and later these colors change value +when Dark Mode is enabled. However, the change is only observable +when the Apple window manager is drawing to the screen. So the +\fBwinfo rgb\fR command will return the color coordinates used in the +standard Aqua mode, even if Dark Mode has been selected in the system +preferences. The numbered systemWindowBackgroundColors are used in +the \fBttk::notebook\fR and \fBttk::labelframe\fR widgets to provide a +contrasting background. Each numbered color constrasts with its +predecessor. +.RS +.DS +systemControlTextColor +systemDisabledControlTextColor +systemLabelColor +systemSelectedTextBackgroundColor +systemSelectedTextColor +systemTextBackgroundColor +systemTextColor +systemWindowBackgroundColor +systemWindowBackgroundColor1 +systemWindowBackgroundColor2 +systemWindowBackgroundColor3 +systemWindowBackgroundColor4 +systemWindowBackgroundColor5 +systemWindowBackgroundColor6 +systemWindowBackgroundColor7 +.DE +.RE .TP + + \fBWindows\fR . On Windows, the following additional system colors are available diff --git a/library/ttk/aquaTheme.tcl b/library/ttk/aquaTheme.tcl index 77ece22..4b0740f 100644 --- a/library/ttk/aquaTheme.tcl +++ b/library/ttk/aquaTheme.tcl @@ -7,7 +7,7 @@ namespace eval ttk::theme::aqua { ttk::style configure . \ -font TkDefaultFont \ - -background systemTtkBackground \ + -background systemWindowBackgroundColor \ -foreground systemLabelColor \ -selectbackground systemHighlight \ -selectforeground systemLabelColor \ @@ -112,7 +112,7 @@ namespace eval ttk::theme::aqua { ttk::style configure Heading \ -font TkHeadingFont \ -foreground systemTextColor \ - -background systemTtkBackground + -background systemWindowBackgroundColor ttk::style configure Treeview -rowheight 18 \ -background systemTextBackgroundColor \ -foreground systemTextColor \ diff --git a/macosx/README b/macosx/README index cca90c5..12a7117 100644 --- a/macosx/README +++ b/macosx/README @@ -315,10 +315,11 @@ contrasts with the background of the containing object. This means that the background color of a Ttk widget depends on how deeply it is nested inside of other widgets that use contrasting backgrounds. To support this, there are 8 contrasting system colors named -systemTtkBackground, systemTtkBackground1, ... , systemTtkBackground7. -The systemTtkBackground color is the standard background for a dialog -window and the others match the contrasting background colors for -backgrounds which are nested to the corresponding depth. +systemWindowBackgroundColor, and systemWindowBackgroundColor1 - 7. +The systemWindowBackgroundColor is the standard background for a +dialog window and the others match the contrasting background colors +used in ttk::notebooks and ttk::labelframes which are nested to the +corresponding depth. 5. Building Tcl/Tk on macOS ------------------------------ diff --git a/macosx/tkMacOSXColor.c b/macosx/tkMacOSXColor.c index 0a25490..a368e8c 100644 --- a/macosx/tkMacOSXColor.c +++ b/macosx/tkMacOSXColor.c @@ -189,14 +189,14 @@ static const struct SystemColorMapEntry systemColorMap[] = { { "ListViewWindowHeaderBackground", HIBackground, kThemeBackgroundListViewWindowHeader }, /* 163 */ { "SecondaryGroupBoxBackground", HIBackground, kThemeBackgroundSecondaryGroupBox }, /* 164 */ { "MetalBackground", HIBackground, kThemeBackgroundMetal }, /* 165 */ - { "TtkBackground", ttkBackground, 0 }, /* 166 */ - { "TtkBackground1", ttkBackground, 1 }, /* 167 */ - { "TtkBackground2", ttkBackground, 2 }, /* 168 */ - { "TtkBackground3", ttkBackground, 3 }, /* 169 */ - { "TtkBackground4", ttkBackground, 4 }, /* 170 */ - { "TtkBackground5", ttkBackground, 5 }, /* 171 */ - { "TtkBackground6", ttkBackground, 6 }, /* 172 */ - { "TtkBackground7", ttkBackground, 7 }, /* 173 */ + { "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 */ @@ -292,8 +292,14 @@ SetCGColorComponents( bgColor = [[NSColor windowBackgroundColor] colorUsingColorSpace: deviceRGB]; [bgColor getComponents: rgba]; - for (int i=0; i<3; i++) { - rgba[i] -= entry.value*(8.0/255.0); + if (rgba[0] + rgba[1] + rgba[2] < 1.5) { + for (int i=0; i<3; i++) { + rgba[i] += entry.value*8.0/255.0; + } + } else { + for (int i=0; i<3; i++) { + rgba[i] -= entry.value*8.0/255.0; + } } break; case semantic: -- cgit v0.12 From 8eec3e9e63a26229b33ad826f232a3a0cceb9851 Mon Sep 17 00:00:00 2001 From: culler Date: Sun, 14 Apr 2019 20:01:55 +0000 Subject: For Aqua, add systemControlAccentColor; simulate the color for older systems. --- doc/colors.n | 1 + macosx/README | 29 ++++++++++++++++------------- macosx/tkMacOSXColor.c | 33 +++++++++++++++++++++++++++++++-- 3 files changed, 48 insertions(+), 15 deletions(-) diff --git a/doc/colors.n b/doc/colors.n index 18f73b7..41d6ed0 100644 --- a/doc/colors.n +++ b/doc/colors.n @@ -939,6 +939,7 @@ contrasting background. Each numbered color constrasts with its predecessor. .RS .DS +systemControlAccentColor systemControlTextColor systemDisabledControlTextColor systemLabelColor diff --git a/macosx/README b/macosx/README index 12a7117..fd54c2d 100644 --- a/macosx/README +++ b/macosx/README @@ -289,19 +289,22 @@ window. --------------------------------------- With the release of OSX 10.14 (Mojave), Apple introduced the DarkAqua -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, and systemLabelColor. -All of these except systemLabelColor, which was introduced in 10.10, were -present in OSX 10.0. 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. +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 diff --git a/macosx/tkMacOSXColor.c b/macosx/tkMacOSXColor.c index a368e8c..3885a77 100644 --- a/macosx/tkMacOSXColor.c +++ b/macosx/tkMacOSXColor.c @@ -189,6 +189,11 @@ static const struct SystemColorMapEntry systemColorMap[] = { { "ListViewWindowHeaderBackground", HIBackground, kThemeBackgroundListViewWindowHeader }, /* 163 */ { "SecondaryGroupBoxBackground", HIBackground, kThemeBackgroundSecondaryGroupBox }, /* 164 */ { "MetalBackground", HIBackground, kThemeBackgroundMetal }, /* 165 */ + + /* + * Colors based on "semantic" NSColors. + */ + { "WindowBackgroundColor", ttkBackground, 0 }, /* 166 */ { "WindowBackgroundColor1", ttkBackground, 1 }, /* 167 */ { "WindowBackgroundColor2", ttkBackground, 2 }, /* 168 */ @@ -204,10 +209,11 @@ static const struct SystemColorMapEntry systemColorMap[] = { { "DisabledControlTextColor", semantic, 4 }, /* 178 */ { "TextBackgroundColor", semantic, 5 }, /* 179 */ { "SelectedTextBackgroundColor", semantic, 6 }, /* 180 */ + { "ControlAccentColor", semantic, 7 }, /* 181 */ { NULL, 0, 0 } }; #define FIRST_SEMANTIC_COLOR 166 -#define MAX_PIXELCODE 180 +#define MAX_PIXELCODE 181 /* *---------------------------------------------------------------------- @@ -258,6 +264,8 @@ GetEntryFromPixelCode( */ static NSColorSpace* deviceRGB = NULL; +static CGFloat blueAccentRGBA[4] = {0, 122.0/255, 1.0, 1.0}; +static CGFloat graphiteAccentRGBA[4] = {152.0/255, 152.0/255, 152.0/255, 1.0}; static OSStatus SetCGColorComponents( @@ -268,6 +276,7 @@ SetCGColorComponents( OSStatus err = noErr; NSColor *bgColor, *color; CGFloat rgba[4] = {0, 0, 0, 1}; + NSInteger colorVariant = 1; if (!deviceRGB) { deviceRGB = [NSColorSpace deviceRGBColorSpace]; } @@ -337,12 +346,32 @@ SetCGColorComponents( color = [[NSColor selectedTextBackgroundColor] colorUsingColorSpace: deviceRGB]; break; + case 7: + if ([NSApp macMinorVersion] < 14) { + colorVariant = [[NSUserDefaults standardUserDefaults] + integerForKey:@"AppleAquaColorVariant"]; + if (colorVariant == 6) { + color = [NSColor colorWithColorSpace: deviceRGB + components: graphiteAccentRGBA + count: 4]; + } else { + color = [NSColor colorWithColorSpace: deviceRGB + components: blueAccentRGBA + count: 4]; + } + } else { +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 + color = [[NSColor controlAccentColor] colorUsingColorSpace: + deviceRGB]; +#endif + } + break; default: if ([NSApp macMinorVersion] < 10) { color = [[NSColor textColor] colorUsingColorSpace: deviceRGB]; } else { -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101000 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000 color = [[NSColor labelColor] colorUsingColorSpace: deviceRGB]; #endif -- cgit v0.12 From 1b1e4cc61c4f9772610d0e1c4c539d2562203ac6 Mon Sep 17 00:00:00 2001 From: culler Date: Sun, 14 Apr 2019 22:21:17 +0000 Subject: Implement "tk::unsupported::MacWindowStyle isdark" to determine whether an Aqua toplevel is currently being displayed in Dark Mode. --- macosx/README | 17 ++++++++++++----- macosx/tkMacOSXWindowEvent.c | 13 ++++--------- macosx/tkMacOSXWm.c | 12 +++++++++--- 3 files changed, 25 insertions(+), 17 deletions(-) diff --git a/macosx/README b/macosx/README index fd54c2d..37225c8 100644 --- a/macosx/README +++ b/macosx/README @@ -184,12 +184,13 @@ Note that not all attributes are valid for all window classes. Support for the support for some legacy Carbon-specific classes and attributes was removed (they are still accepted by the command but no longer have any effect). -- Another command available in the tk::unsupported::MacWindowStyle namespace is -tk::unsupported::MacWindowStyle tabbingid window ?newId? which can be used to -get or set the tabbingIdentifier for the NSWindow associated with a Tk Window. -See section 3 for details. +- Another command available in the tk::unsupported::MacWindowStyle namespace is: + tk::unsupported::MacWindowStyle tabbingid window ?newId? +which can be used to get or set the tabbingIdentifier for the NSWindow +associated with a Tk Window. See section 3 for details. -- A command tk::unsupported::MacWindowStyle appearance window ?newAappearance? +- The command: + tk::unsupported::MacWindowStyle appearance window ?newAappearance? is available when Tk is built and run on macOS 10.14 (Mojave) or later. In that case the Ttk widgets all support the "Dark Mode" appearance which was introduced in 10.14. The command accepts the following values for the optional @@ -199,6 +200,12 @@ appearance independent of any preferences settings. If it is set to "auto" the appearance will be determined by the preferences. This command can be used to opt out of Dark Mode on a per-window basis. +- To determine the current appearance of a window in macOS 10.14 (Mojave) and +higher, one can use the command: + tk::unsupported::MacWindowStyle isdark +The boolean return value is true if the window is currently displayed with the +dark appearance. + - If you want to use Remote Debugging with Xcode, you need to set the environment variable XCNOSTDIN to 1 in the Executable editor for Wish. That will cause us to force closing stdin & stdout. Otherwise, given how Xcode launches diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c index 212381e..54e1272 100644 --- a/macosx/tkMacOSXWindowEvent.c +++ b/macosx/tkMacOSXWindowEvent.c @@ -1070,7 +1070,6 @@ ConfigureRestrictProc( { XVirtualEvent event; int x, y; - NSString *osxMode = [[NSUserDefaults standardUserDefaults] stringForKey:@"AppleInterfaceStyle"]; NSWindow *w = [self window]; TkWindow *winPtr = TkMacOSXGetTkWindow(w); Tk_Window tkwin = (Tk_Window) winPtr; @@ -1091,16 +1090,12 @@ ConfigureRestrictProc( &event.x_root, &event.y_root, &x, &y, &event.state); Tk_TopCoordsToWindow(tkwin, x, y, &event.x, &event.y); event.same_screen = true; - if (osxMode == nil) { - event.name = Tk_GetUid("LightAqua"); - Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL); - return; - } - if ([osxMode isEqual:@"Dark"]) { + if (TkMacOSXInDarkMode(tkwin)) { event.name = Tk_GetUid("DarkAqua"); - Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL); - return; + } else { + event.name = Tk_GetUid("LightAqua"); } + Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL); } /* diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index fa2acf7..504c73f 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -1021,7 +1021,6 @@ TkWmDeadWindow( while (Tk_DoOneEvent(TK_WINDOW_EVENTS|TK_DONT_WAIT)) {} } [NSApp _resetAutoreleasePool]; - #if DEBUG_ZOMBIES > 0 fprintf(stderr, "================= Pool dump ===================\n"); [NSAutoreleasePool showPools]; @@ -5518,10 +5517,10 @@ TkUnsupported1ObjCmd( Tcl_Obj *const objv[]) /* Argument objects. */ { static const char *const subcmds[] = { - "style", "tabbingid", "appearance", NULL + "style", "tabbingid", "appearance", "isdark", NULL }; enum SubCmds { - TKMWS_STYLE, TKMWS_TABID, TKMWS_APPEARANCE + TKMWS_STYLE, TKMWS_TABID, TKMWS_APPEARANCE, TKMWS_ISDARK }; Tk_Window tkwin = clientData; TkWindow *winPtr; @@ -5587,6 +5586,13 @@ TkUnsupported1ObjCmd( return TCL_ERROR; } return WmWinAppearance(interp, winPtr, objc, objv); + case TKMWS_ISDARK: + if ((objc != 3)) { + Tcl_WrongNumArgs(interp, 2, objv, "isdark window"); + return TCL_ERROR; + } + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(TkMacOSXInDarkMode(tkwin))); + return TCL_OK; default: return TCL_ERROR; } -- cgit v0.12 From aabd71aac31bdb206f316717019b6db250bc91d8 Mon Sep 17 00:00:00 2001 From: culler Date: Mon, 15 Apr 2019 18:00:29 +0000 Subject: For Aqua, simulate systemWindowBackgroundColor in older OS versions. Adjust conditional code and formatting. --- macosx/tkMacOSXColor.c | 111 ++++++++++++++++++++++++++--------------------- macosx/ttkMacOSXTheme.c | 112 ++++++++++++++++++++++++------------------------ 2 files changed, 119 insertions(+), 104 deletions(-) diff --git a/macosx/tkMacOSXColor.c b/macosx/tkMacOSXColor.c index 3885a77..ae9e9df 100644 --- a/macosx/tkMacOSXColor.c +++ b/macosx/tkMacOSXColor.c @@ -266,6 +266,7 @@ GetEntryFromPixelCode( static NSColorSpace* deviceRGB = NULL; static CGFloat blueAccentRGBA[4] = {0, 122.0/255, 1.0, 1.0}; static CGFloat graphiteAccentRGBA[4] = {152.0/255, 152.0/255, 152.0/255, 1.0}; +static CGFloat windowBackground[4] = {236.0/255, 236.0/255, 236.0/255, 1.0}; static OSStatus SetCGColorComponents( @@ -277,13 +278,14 @@ SetCGColorComponents( NSColor *bgColor, *color; CGFloat rgba[4] = {0, 0, 0, 1}; NSInteger colorVariant = 1; + if (!deviceRGB) { deviceRGB = [NSColorSpace deviceRGBColorSpace]; } /* - * This function is called before our autorelease pool is set up, - * so it needs its own pool. + * This function is called before our autorelease pool is set up, + * so it needs its own pool. */ NSAutoreleasePool *pool = [NSAutoreleasePool new]; @@ -298,9 +300,21 @@ SetCGColorComponents( rgba[2] = ((pixel ) & 0xff) / 255.0; break; case ttkBackground: - bgColor = [[NSColor windowBackgroundColor] colorUsingColorSpace: - deviceRGB]; - [bgColor getComponents: rgba]; + + /* + * Prior to OSX 10.14, getComponents returns black when applied to + * windowBackGroundColor. + */ + + if ([NSApp macMinorVersion] < 14) { + for (int i=0; i<3; i++) { + rgba[i] = windowBackground[i]; + } + } else { + bgColor = [[NSColor windowBackgroundColor] colorUsingColorSpace: + deviceRGB]; + [bgColor getComponents: rgba]; + } if (rgba[0] + rgba[1] + rgba[2] < 1.5) { for (int i=0; i<3; i++) { rgba[i] += entry.value*8.0/255.0; @@ -314,20 +328,16 @@ SetCGColorComponents( case semantic: switch (entry.value) { case 0: - color = [[NSColor textColor] colorUsingColorSpace: - deviceRGB]; + color = [[NSColor textColor] colorUsingColorSpace: deviceRGB]; break; case 1: - color = [[NSColor selectedTextColor] colorUsingColorSpace: - deviceRGB]; + color = [[NSColor selectedTextColor] colorUsingColorSpace: deviceRGB]; break; case 2: #if MAC_OS_X_VERSION_MIN_REQUIRED > 101000 - color = [[NSColor labelColor] colorUsingColorSpace: - deviceRGB]; + color = [[NSColor labelColor] colorUsingColorSpace: deviceRGB]; #else - color = [[NSColor textColor] colorUsingColorSpace: - deviceRGB]; + color = [[NSColor textColor] colorUsingColorSpace: deviceRGB]; #endif break; case 3: @@ -347,36 +357,35 @@ SetCGColorComponents( deviceRGB]; break; case 7: - if ([NSApp macMinorVersion] < 14) { - colorVariant = [[NSUserDefaults standardUserDefaults] - integerForKey:@"AppleAquaColorVariant"]; - if (colorVariant == 6) { - color = [NSColor colorWithColorSpace: deviceRGB - components: graphiteAccentRGBA - count: 4]; - } else { - color = [NSColor colorWithColorSpace: deviceRGB - components: blueAccentRGBA - count: 4]; - } - } else { #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 + if ([NSApp macMinorVersion] >= 14) { color = [[NSColor controlAccentColor] colorUsingColorSpace: deviceRGB]; + break; + } #endif + colorVariant = [[NSUserDefaults standardUserDefaults] + integerForKey:@"AppleAquaColorVariant"]; + if (colorVariant == 6) { + color = [NSColor colorWithColorSpace: deviceRGB + components: graphiteAccentRGBA + count: 4]; + } else { + color = [NSColor colorWithColorSpace: deviceRGB + components: blueAccentRGBA + count: 4]; } break; default: - if ([NSApp macMinorVersion] < 10) { - color = [[NSColor textColor] colorUsingColorSpace: - deviceRGB]; - } else { #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000 + if ([NSApp macMinorVersion] >= 10) { color = [[NSColor labelColor] colorUsingColorSpace: deviceRGB]; -#endif break; } +#endif + color = [[NSColor textColor] colorUsingColorSpace: deviceRGB]; + break; } [color getComponents: rgba]; break; @@ -395,7 +404,7 @@ SetCGColorComponents( default: break; } - *c = CGColorCreate(deviceRGB.CGColorSpace, rgba ); + *c = CGColorCreate(deviceRGB.CGColorSpace, rgba); [pool drain]; return err; } @@ -417,21 +426,20 @@ SetCGColorComponents( */ MODULE_SCOPE Bool -TkMacOSXInDarkMode(Tk_Window tkwin) { -#if MAC_OS_X_VERSION_MIN_REQUIRED < 101300 - return false; -#else - static NSAppearanceName darkAqua = @"NSAppearanceNameDarkAqua"; - TkWindow *winPtr = (TkWindow*)tkwin; - NSView *view = TkMacOSXDrawableView(winPtr->privatePtr); - if (view && [view.effectiveAppearance.name isEqualToString:darkAqua]) { - return True; - } else { - return false; +TkMacOSXInDarkMode(Tk_Window tkwin) +{ + int result = false; +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 + if ([NSApp macMinorVersion] >= 14) { + static NSAppearanceName darkAqua = @"NSAppearanceNameDarkAqua"; + TkWindow *winPtr = (TkWindow*) tkwin; + NSView *view = TkMacOSXDrawableView(winPtr->privatePtr); + result = (view && + [view.effectiveAppearance.name isEqualToString:darkAqua]); } #endif + return result; } - /* *---------------------------------------------------------------------- @@ -462,6 +470,7 @@ TkSetMacColor( CGColorRef *color = (CGColorRef*)macColor; OSStatus err = -1; struct SystemColorMapEntry entry; + if (GetEntryFromPixelCode((pixel >> 24) & 0xff, &entry)) { err = ChkErr(SetCGColorComponents, entry, pixel, color); } @@ -607,6 +616,7 @@ TkMacOSXGetNSColor( if (cgColor) { NSColorSpace *colorSpace = [[NSColorSpace alloc] initWithCGColorSpace:CGColorGetColorSpace(cgColor)]; + nsColor = [NSColor colorWithColorSpace:colorSpace components:CGColorGetComponents(cgColor) count:CGColorGetNumberOfComponents(cgColor)]; @@ -648,6 +658,7 @@ TkMacOSXSetColorInContext( int code = (pixel >> 24) & 0xff; HIThemeBackgroundDrawInfo info = { 0, kThemeStateActive, entry.value }; static CGColorSpaceRef deviceRGBSpace = NULL; + if (!deviceRGBSpace) { deviceRGBSpace = CGColorSpaceCreateDeviceRGB(); } @@ -728,14 +739,16 @@ TkpGetColor( 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); + sizeof(struct SystemColorMapEntry), NULL, TCL_EXACT, &idx); Tcl_DecrRefCount(strPtr); if (result == TCL_OK) { OSStatus err; CGColorRef c; unsigned char pixelCode = idx + MIN_PIXELCODE; struct SystemColorMapEntry entry = systemColorMap[idx]; + err = ChkErr(SetCGColorComponents, entry, 0, &c); if (err == noErr) { const size_t n = CGColorGetNumberOfComponents(c); @@ -751,12 +764,12 @@ TkpGetColor( color.red = color.green = color.blue = rgba[0] * 65535.0; break; default: - Tcl_Panic("CGColor with %d components", (int) n); + 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)); + | ((color.red >> 8) & 0xff)) << 8) + | ((color.green >> 8) & 0xff)) << 8) + | ((color.blue >> 8) & 0xff)); CGColorRelease(c); goto validXColor; } diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index 84e5b5f..12667e1 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -124,7 +124,7 @@ static CGRect NormalizeButtonBounds( return bounds; } -#if MAC_OS_X_VERSION_MIN_REQUIRED > 1080 +#if MAC_OS_X_VERSION_MAX_ALLOWED > 1080 /*---------------------------------------------------------------------- * +++ Support for contrasting background colors when GroupBoxes or Tabbed * panes are nested inside each other. Early versions of macOS used ridged @@ -139,8 +139,7 @@ static CGRect NormalizeButtonBounds( * support Dark Mode anyway. */ -static CGFloat windowBackground[4] = {235.0/255, 235.0/255, 235.0/255, 1.0}; -static CGFloat whiteRGBA[4] = {1.0, 1.0, 1.0, 1.0}; +static CGFloat windowBackground[4] = {236.0/255, 236.0/255, 236.0/255, 1.0}; static CGFloat blackRGBA[4] = {0.0, 0.0, 0.0, 1.0}; /*---------------------------------------------------------------------- @@ -264,56 +263,6 @@ static void SolidFillRoundedRectangle( CFRelease(path); } -/*---------------------------------------------------------------------- - * GradientFillRoundedRectangle -- - * - * Fill a rounded rectangle with a specified gradient. - */ - -static void GradientFillRoundedRectangle( - CGContextRef context, - CGRect bounds, - CGFloat radius, - CGFloat* colors, - int numColors) -{ - NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; - CGPathRef path; - CGPoint end = { - bounds.origin.x, - bounds.origin.y + bounds.size.height - }; - CGGradientRef gradient = CGGradientCreateWithColorComponents( - deviceRGB.CGColorSpace, colors, NULL, numColors); - path = CGPathCreateWithRoundedRect(bounds, radius, radius, NULL); - CGContextBeginPath(context); - CGContextAddPath(context, path); - CGContextClip(context); - CGContextDrawLinearGradient(context, gradient, bounds.origin, end, 0); - CFRelease(path); - CFRelease(gradient); -} - -static void DrawUpDownArrows( - CGContextRef context, - CGRect bounds, - CGFloat inset, - CGFloat size, - CGFloat *rgba) -{ - CGFloat x, y; - CGContextSetRGBStrokeColor(context, rgba[0], rgba[1], rgba[2], rgba[3]); - CGContextSetLineWidth(context, 1.5); - x = bounds.origin.x + inset; - y = bounds.origin.y + trunc(bounds.size.height/2); - CGContextBeginPath(context); - CGPoint bottomArrow[3] = {{x, y+2}, {x+size/2, y+2+size/2}, {x+size, y+2}}; - CGContextAddLines(context, bottomArrow, 3); - CGPoint topArrow[3] = {{x, y-2}, {x+size/2, y-2-size/2}, {x+size, y-2}}; - CGContextAddLines(context, topArrow, 3); - CGContextStrokePath(context); -} - static void DrawDownArrow( CGContextRef context, CGRect bounds, @@ -429,9 +378,9 @@ static void DrawListHeader( } } -#endif /* MAC_OS_X_VERSION_MIN_REQUIRED > 1080 */ +#endif /* MAC_OS_X_VERSION_MAX_ALLOWED > 1080 */ -#if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 +#if MAC_OS_X_VERSION_MAX_ALLOWED > 101300 /*---------------------------------------------------------------------- * +++ Drawing procedures for widgets in Apple's "Dark Mode" (10.14 and up). * @@ -464,6 +413,57 @@ static CGFloat darkInactiveGradient[8] = {89.0/255, 90.0/255, 93.0/255, 1.0, static CGFloat darkSelectedGradient[8] = {23.0/255, 111.0/255, 232.0/255, 1.0, 20.0/255, 94.0/255, 206.0/255, 1.0}; + +/*---------------------------------------------------------------------- + * GradientFillRoundedRectangle -- + * + * Fill a rounded rectangle with a specified gradient. + */ + +static void GradientFillRoundedRectangle( + CGContextRef context, + CGRect bounds, + CGFloat radius, + CGFloat* colors, + int numColors) +{ + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + CGPathRef path; + CGPoint end = { + bounds.origin.x, + bounds.origin.y + bounds.size.height + }; + CGGradientRef gradient = CGGradientCreateWithColorComponents( + deviceRGB.CGColorSpace, colors, NULL, numColors); + path = CGPathCreateWithRoundedRect(bounds, radius, radius, NULL); + CGContextBeginPath(context); + CGContextAddPath(context, path); + CGContextClip(context); + CGContextDrawLinearGradient(context, gradient, bounds.origin, end, 0); + CFRelease(path); + CFRelease(gradient); +} + +static void DrawUpDownArrows( + CGContextRef context, + CGRect bounds, + CGFloat inset, + CGFloat size, + CGFloat *rgba) +{ + CGFloat x, y; + CGContextSetRGBStrokeColor(context, rgba[0], rgba[1], rgba[2], rgba[3]); + CGContextSetLineWidth(context, 1.5); + x = bounds.origin.x + inset; + y = bounds.origin.y + trunc(bounds.size.height/2); + CGContextBeginPath(context); + CGPoint bottomArrow[3] = {{x, y+2}, {x+size/2, y+2+size/2}, {x+size, y+2}}; + CGContextAddLines(context, bottomArrow, 3); + CGPoint topArrow[3] = {{x, y-2}, {x+size/2, y-2-size/2}, {x+size, y-2}}; + CGContextAddLines(context, topArrow, 3); + CGContextStrokePath(context); +} + /*---------------------------------------------------------------------- * FillButtonBackground -- * @@ -528,6 +528,8 @@ static void HighlightButtonBorder( * PopupButtons in the Dark Mode style. */ +static CGFloat whiteRGBA[4] = {1.0, 1.0, 1.0, 1.0}; + static void DrawDarkButton( CGRect bounds, ThemeButtonKind kind, -- cgit v0.12 From 3c20b73064392e201bf678e471789379e5b27c53 Mon Sep 17 00:00:00 2001 From: culler Date: Mon, 15 Apr 2019 18:05:53 +0000 Subject: Add missing blank line. --- macosx/tkMacOSXColor.c | 1 + 1 file changed, 1 insertion(+) diff --git a/macosx/tkMacOSXColor.c b/macosx/tkMacOSXColor.c index ae9e9df..e89d42d 100644 --- a/macosx/tkMacOSXColor.c +++ b/macosx/tkMacOSXColor.c @@ -429,6 +429,7 @@ MODULE_SCOPE Bool TkMacOSXInDarkMode(Tk_Window tkwin) { int result = false; + #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 if ([NSApp macMinorVersion] >= 14) { static NSAppearanceName darkAqua = @"NSAppearanceNameDarkAqua"; -- cgit v0.12 From c7e4427914c39b33a76da2dc61a174c6481dd4fe Mon Sep 17 00:00:00 2001 From: culler Date: Mon, 15 Apr 2019 19:31:55 +0000 Subject: Less intrusive fix for test frame-3.9. --- tests/frame.test | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/frame.test b/tests/frame.test index b601137..45a91b3 100644 --- a/tests/frame.test +++ b/tests/frame.test @@ -662,10 +662,9 @@ test frame-3.9 {TkCreateFrame procedure, -use option} -constraints { } -body { toplevel .t -container 1 -width 300 -height 120 wm geometry .t +0+0 - update toplevel .x -width 140 -height 300 -use [winfo id .t] -bg green tkwait visibility .x - update + update idletasks list [expr {[winfo rootx .x] - [winfo rootx .t]}] \ [expr {[winfo rooty .x] - [winfo rooty .t]}] \ [winfo width .t] [winfo height .t] -- cgit v0.12 From 9b521b370e0520f6a489be15b65269a33761501a Mon Sep 17 00:00:00 2001 From: culler Date: Mon, 15 Apr 2019 20:48:29 +0000 Subject: Adjust conditional code to fix compiler warnings on macOS 10.9. --- macosx/ttkMacOSXTheme.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index 12667e1..a890b63 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -1378,9 +1378,11 @@ static void PaneElementDraw( bounds.origin.y -= kThemeMetricTabFrameOverlap; bounds.size.height += kThemeMetricTabFrameOverlap; BEGIN_DRAWING(d) -#if MAC_OS_X_VERSION_MIN_REQUIRED > 10800 + if ([NSApp macMinorVersion] > 9) { +#if MAC_OS_X_VERSION_MAX_ALLOWED > 1080 DrawGroupBox(bounds, dc.context, tkwin); -#else +#endif + } else { HIThemeTabPaneDrawInfo info = { .version = 1, .state = Ttk_StateTableLookup(ThemeStateTable, state), @@ -1392,7 +1394,7 @@ static void PaneElementDraw( bounds.origin.y -= kThemeMetricTabFrameOverlap; bounds.size.height += kThemeMetricTabFrameOverlap; ChkErr(HIThemeDrawTabPane, &bounds, &info, dc.context, HIOrientation); -#endif + } END_DRAWING } @@ -1429,16 +1431,18 @@ static void GroupElementDraw( CGRect bounds = BoxToRect(d, b); BEGIN_DRAWING(d) -#if MAC_OS_X_VERSION_MIN_REQUIRED > 10800 + if ([NSApp macMinorVersion] > 9) { +#if MAC_OS_X_VERSION_MAX_ALLOWED > 1080 DrawGroupBox(bounds, dc.context, tkwin); -#else +#endif + } else { const HIThemeGroupBoxDrawInfo info = { .version = 0, .state = Ttk_StateTableLookup(ThemeStateTable, state), .kind = kHIThemeGroupBoxKindPrimaryOpaque, }; ChkErr(HIThemeDrawGroupBox, &bounds, &info, dc.context, HIOrientation); -#endif + } END_DRAWING } -- cgit v0.12 From 7eaee2f2e59cbbb043964d94313d3f22a6d877a5 Mon Sep 17 00:00:00 2001 From: culler Date: Wed, 17 Apr 2019 14:05:33 +0000 Subject: Mitigate future merge conflict headaches. --- macosx/tkMacOSXButton.c | 688 +++++++++++++++++++++---------------------- macosx/tkMacOSXClipboard.c | 8 +- macosx/tkMacOSXCursor.c | 18 +- macosx/tkMacOSXDialog.c | 408 ++++++++++++++++--------- macosx/tkMacOSXDraw.c | 465 ++++++++++++++++------------- macosx/tkMacOSXEmbed.c | 55 ++-- macosx/tkMacOSXFont.c | 193 ++++++------ macosx/tkMacOSXImage.c | 145 ++++----- macosx/tkMacOSXInit.c | 19 +- macosx/tkMacOSXKeyEvent.c | 562 +++++++++++++++++++---------------- macosx/tkMacOSXMenu.c | 142 ++++----- macosx/tkMacOSXMenubutton.c | 415 +++++++++++++------------- macosx/tkMacOSXMenus.c | 1 - macosx/tkMacOSXNotify.c | 103 ++++--- macosx/tkMacOSXRegion.c | 16 +- macosx/tkMacOSXScale.c | 108 ++++--- macosx/tkMacOSXScrlbr.c | 395 +++++++++++++------------ macosx/tkMacOSXSend.c | 4 +- macosx/tkMacOSXSubwindows.c | 115 ++++---- macosx/tkMacOSXWindowEvent.c | 64 ++-- macosx/tkMacOSXWm.c | 82 +++--- macosx/ttkMacOSXTheme.c | 450 +++++++++++++++++----------- 22 files changed, 2426 insertions(+), 2030 deletions(-) diff --git a/macosx/tkMacOSXButton.c b/macosx/tkMacOSXButton.c index ad963e1..ac3c122 100644 --- a/macosx/tkMacOSXButton.c +++ b/macosx/tkMacOSXButton.c @@ -1,8 +1,8 @@ /* * tkMacOSXButton.c -- * - * This file implements the Macintosh specific portion of the - * button widgets. + * This file implements the Macintosh specific portion of the button + * widgets. * * Copyright (c) 1996-1997 by Sun Microsystems, Inc. * Copyright 2001, Apple Computer, Inc. @@ -70,20 +70,23 @@ typedef struct { * Forward declarations for procedures defined later in this file: */ - -static void ButtonBackgroundDrawCB (const HIRect *btnbounds, MacButton *ptr, - SInt16 depth, Boolean isColorDev); -static void ButtonContentDrawCB (const HIRect *bounds, ThemeButtonKind kind, - const HIThemeButtonDrawInfo *info, MacButton *ptr, SInt16 depth, - Boolean isColorDev); -static void ButtonEventProc(ClientData clientData, XEvent *eventPtr); -static void TkMacOSXComputeButtonParams (TkButton * butPtr, ThemeButtonKind* btnkind, - HIThemeButtonDrawInfo* drawinfo); -static int TkMacOSXComputeButtonDrawParams (TkButton * butPtr, DrawParams * dpPtr); -static void TkMacOSXDrawButton (MacButton *butPtr, GC gc, Pixmap pixmap); -static void DrawButtonImageAndText(TkButton* butPtr); -static void PulseDefaultButtonProc(ClientData clientData); - +static void ButtonBackgroundDrawCB(const HIRect *btnbounds, + MacButton *ptr, SInt16 depth, Boolean isColorDev); +static void ButtonContentDrawCB(const HIRect *bounds, + ThemeButtonKind kind, + const HIThemeButtonDrawInfo *info, MacButton *ptr, + SInt16 depth, Boolean isColorDev); +static void ButtonEventProc(ClientData clientData, + XEvent *eventPtr); +static void TkMacOSXComputeButtonParams(TkButton *butPtr, + ThemeButtonKind *btnkind, + HIThemeButtonDrawInfo *drawinfo); +static int TkMacOSXComputeButtonDrawParams(TkButton *butPtr, + DrawParams * dpPtr); +static void TkMacOSXDrawButton(MacButton *butPtr, GC gc, + Pixmap pixmap); +static void DrawButtonImageAndText(TkButton *butPtr); +static void PulseDefaultButtonProc(ClientData clientData); /* * The class procedure table for the button widgets. @@ -95,15 +98,15 @@ const Tk_ClassProcs tkpButtonProcs = { }; static int bCount; - + /* *---------------------------------------------------------------------- * * TkpButtonSetDefaults -- * - * This procedure is invoked before option tables are created for - * buttons. It modifies some of the default values to match the current - * values defined for this platform. + * This procedure is invoked before option tables are created for buttons. + * It modifies some of the default values to match the current values + * defined for this platform. * * Results: * Some of the default values in *specPtr are modified. @@ -117,9 +120,8 @@ static int bCount; void TkpButtonSetDefaults() { -/*No-op.*/ + /*No-op.*/ } - /* *---------------------------------------------------------------------- @@ -141,10 +143,10 @@ TkButton * TkpCreateButton( Tk_Window tkwin) { - MacButton *macButtonPtr = (MacButton *) ckalloc(sizeof(MacButton)); + MacButton *macButtonPtr = ckalloc(sizeof(MacButton)); Tk_CreateEventHandler(tkwin, ActivateMask, - ButtonEventProc, (ClientData) macButtonPtr); + ButtonEventProc, macButtonPtr); macButtonPtr->id = bCount++; macButtonPtr->flags = FIRST_DRAW; macButtonPtr->btnkind = kThemePushButton; @@ -152,7 +154,7 @@ TkpCreateButton( bzero(&macButtonPtr->drawinfo, sizeof(macButtonPtr->drawinfo)); bzero(&macButtonPtr->lastdrawinfo, sizeof(macButtonPtr->lastdrawinfo)); - return (TkButton *)macButtonPtr; + return (TkButton *) macButtonPtr; } /* @@ -160,15 +162,15 @@ TkpCreateButton( * * TkpDisplayButton -- * - * This procedure is invoked to display a button widget. It is - * normally invoked as an idle handler. + * This procedure is invoked to display a button widget. It is normally + * invoked as an idle handler. * * Results: * None. * * Side effects: - * Commands are output to X to display the button in its - * current mode. The REDRAW_PENDING flag is cleared. + * Commands are output to X to display the button in its current mode. The + * REDRAW_PENDING flag is cleared. * *---------------------------------------------------------------------- */ @@ -177,8 +179,8 @@ void TkpDisplayButton( ClientData clientData) /* Information about widget. */ { - MacButton *macButtonPtr = (MacButton *) clientData; - TkButton *butPtr = (TkButton *) clientData; + MacButton *macButtonPtr = clientData; + TkButton *butPtr = clientData; Tk_Window tkwin = butPtr->tkwin; Pixmap pixmap; DrawParams* dpPtr = &macButtonPtr->drawParams; @@ -191,16 +193,15 @@ TkpDisplayButton( pixmap = (Pixmap) Tk_WindowId(tkwin); TkMacOSXSetUpClippingRgn(Tk_WindowId(tkwin)); - if (TkMacOSXComputeButtonDrawParams(butPtr, dpPtr) ) { + if (TkMacOSXComputeButtonDrawParams(butPtr, dpPtr)) { macButtonPtr->useTkText = 0; } else { macButtonPtr->useTkText = 1; } - /* - * Set up clipping region. Make sure the we are using the port - * for this button, or we will set the wrong window's clip. + * Set up clipping region. Make sure the we are using the port for this + * button, or we will set the wrong window's clip. */ if (macButtonPtr->useTkText) { @@ -212,26 +213,36 @@ TkpDisplayButton( Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT); } - /* Display image or bitmap or text for labels or custom controls. */ + /* + * Display image or bitmap or text for labels or custom controls. + */ + DrawButtonImageAndText(butPtr); - needhighlight = 1; + needhighlight = 1; } else { - /* Draw the native portion of the buttons. */ + /* + * Draw the native portion of the buttons. + */ + TkMacOSXDrawButton(macButtonPtr, dpPtr->gc, pixmap); - /* Draw highlight border, if needed. */ + /* + * Ask for the highlight border, if needed. + */ + if (butPtr->highlightWidth < 3) { needhighlight = 1; } } - /* Draw highlight border, if needed. */ - if (needhighlight) { - if ((butPtr->flags & GOT_FOCUS)) { - Tk_Draw3DRectangle(tkwin, pixmap, butPtr->normalBorder, 0, 0, + /* + * Draw highlight border. + */ + + if (needhighlight && (butPtr->flags & GOT_FOCUS)) { + Tk_Draw3DRectangle(tkwin, pixmap, butPtr->normalBorder, 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), butPtr->highlightWidth, TK_RELIEF_SOLID); - } } } @@ -240,9 +251,9 @@ TkpDisplayButton( * * TkpComputeButtonGeometry -- * - * After changes in a button's text or bitmap, this procedure - * recomputes the button's geometry and passes this information - * along to the geometry manager for the window. + * After changes in a button's text or bitmap, this procedure recomputes + * the button's geometry and passes this information along to the geometry + * manager for the window. * * Results: * None. @@ -259,7 +270,7 @@ TkpComputeButtonGeometry( { int width = 0, height = 0, charWidth = 1, haveImage = 0, haveText = 0; int txtWidth = 0, txtHeight = 0; - MacButton *mbPtr = (MacButton*)butPtr; + MacButton *mbPtr = (MacButton *) butPtr; Tk_FontMetrics fm; char *text = Tcl_GetString(butPtr->textPtr); @@ -270,21 +281,27 @@ TkpComputeButtonGeometry( */ if (butPtr->indicatorOn) { - switch (butPtr->type) { - case TYPE_RADIO_BUTTON: - GetThemeMetric(kThemeMetricRadioButtonWidth, (SInt32 *)&butPtr->indicatorDiameter); - break; - case TYPE_CHECK_BUTTON: - GetThemeMetric(kThemeMetricCheckBoxWidth, (SInt32 *)&butPtr->indicatorDiameter); - break; - default: - break; - } - /* Allow 2px extra space next to the indicator. */ - butPtr->indicatorSpace = butPtr->indicatorDiameter + 2; + switch (butPtr->type) { + case TYPE_RADIO_BUTTON: + GetThemeMetric(kThemeMetricRadioButtonWidth, + (SInt32 *) &butPtr->indicatorDiameter); + break; + case TYPE_CHECK_BUTTON: + GetThemeMetric(kThemeMetricCheckBoxWidth, + (SInt32 *) &butPtr->indicatorDiameter); + break; + default: + break; + } + + /* + * Allow 2px extra space next to the indicator. + */ + + butPtr->indicatorSpace = butPtr->indicatorDiameter + 2; } else { - butPtr->indicatorSpace = 0; - butPtr->indicatorDiameter = 0; + butPtr->indicatorSpace = 0; + butPtr->indicatorDiameter = 0; } if (butPtr->image != NULL) { @@ -308,44 +325,43 @@ TkpComputeButtonGeometry( if (haveImage && haveText) { /* Image and Text */ switch ((enum compound) butPtr->compound) { - case COMPOUND_TOP: - case COMPOUND_BOTTOM: - - /* - * Image is above or below text. - */ - - height += txtHeight + butPtr->padY; - width = (width > txtWidth ? width : txtWidth); - break; - case COMPOUND_LEFT: - case COMPOUND_RIGHT: - - /* - * Image is left or right of text. - */ - - width += txtWidth + 2*butPtr->padX; - height = (height > txtHeight ? height : txtHeight); - break; - case COMPOUND_CENTER: - - /* - * Image and text are superimposed. - */ - - width = (width > txtWidth ? width : txtWidth); - height = (height > txtHeight ? height : txtHeight); - break; - default: - break; + case COMPOUND_TOP: + case COMPOUND_BOTTOM: + /* + * Image is above or below text. + */ + + height += txtHeight + butPtr->padY; + width = (width > txtWidth ? width : txtWidth); + break; + case COMPOUND_LEFT: + case COMPOUND_RIGHT: + /* + * Image is left or right of text. + */ + + width += txtWidth + 2*butPtr->padX; + height = (height > txtHeight ? height : txtHeight); + break; + case COMPOUND_CENTER: + /* + * Image and text are superimposed. + */ + + width = (width > txtWidth ? width : txtWidth); + height = (height > txtHeight ? height : txtHeight); + break; + default: + break; } width += butPtr->indicatorSpace; } else if (haveImage) { /* Image only */ width = butPtr->width > 0 ? butPtr->width : width + butPtr->indicatorSpace; height = butPtr->height > 0 ? butPtr->height : height; if (butPtr->type == TYPE_BUTTON) { - /* Allow room to shift the image. */ + /* + * Allow room to shift the image. + */ width += 2; height += 2; } @@ -375,19 +391,19 @@ TkpComputeButtonGeometry( width += butPtr->inset*2; height += butPtr->inset*2; if ([NSApp macMinorVersion] == 6) { - width += 12; + width += 12; } if (mbPtr->btnkind == kThemePushButton) { HIRect tmpRect; HIRect contBounds; /* - * A PushButton has a minimum size. We make sure that we - * are not underestimating the size by requesting the content - * size of a Pushbutton whose overall size is our content size - * expanded by the standard padding. + * A PushButton has a minimum size. We make sure that we are not + * underestimating the size by requesting the content size of a + * Pushbutton whose overall size is our content size expanded by the + * standard padding. */ - + tmpRect = CGRectMake(0, 0, width + 2*HI_PADX, height + 2*HI_PADY); HIThemeGetButtonContentBounds(&tmpRect, &mbPtr->drawinfo, &contBounds); if (height < contBounds.size.height) { @@ -402,51 +418,43 @@ TkpComputeButtonGeometry( Tk_GeometryRequest(butPtr->tkwin, width, height); Tk_SetInternalBorder(butPtr->tkwin, butPtr->inset); } - + /* *---------------------------------------------------------------------- * * DrawButtonImageAndText -- * - * Draws the image and text associated with a button or label. + * Draws the image and text associated with a button or label. * * Results: - * None. + * None. * * Side effects: - * The image and text are drawn. + * The image and text are drawn. * *---------------------------------------------------------------------- */ static void DrawButtonImageAndText( - TkButton* butPtr) + TkButton *butPtr) { - MacButton *mbPtr = (MacButton*)butPtr; - Tk_Window tkwin = butPtr->tkwin; - Pixmap pixmap; - int haveImage = 0; - int haveText = 0; - int imageWidth = 0; - int imageHeight = 0; - int imageXOffset = 0; - int imageYOffset = 0; - int textXOffset = 0; - int textYOffset = 0; - int width = 0; - int height = 0; - int fullWidth = 0; - int fullHeight = 0; - int pressed = 0; - + MacButton *mbPtr = (MacButton *) butPtr; + Tk_Window tkwin = butPtr->tkwin; + Pixmap pixmap; + int haveImage = 0, haveText = 0, pressed = 0; + int imageWidth = 0, imageHeight = 0; + int imageXOffset = 0, imageYOffset = 0; + int textXOffset = 0, textYOffset = 0; + int width = 0, height = 0; + int fullWidth = 0, fullHeight = 0; if (tkwin == NULL || !Tk_IsMapped(tkwin)) { return; } - DrawParams* dpPtr = &mbPtr->drawParams; - pixmap = (Pixmap)Tk_WindowId(tkwin); + DrawParams *dpPtr = &mbPtr->drawParams; + pixmap = (Pixmap) Tk_WindowId(tkwin); if (butPtr->image != None) { Tk_SizeOfImage(butPtr->image, &width, &height); @@ -456,74 +464,68 @@ DrawButtonImageAndText( haveImage = 1; } - imageWidth = width; + imageWidth = width; imageHeight = height; if (mbPtr->drawinfo.state == kThemeStatePressed) { - /* Offset bitmaps by a bit when the button is pressed. */ + /* + * Offset bitmaps by a bit when the button is pressed. + */ + pressed = 1; } haveText = (butPtr->textWidth != 0 && butPtr->textHeight != 0); if (haveImage && haveText) { /* Image and Text */ - int x; - int y; - textXOffset = 0; - textYOffset = 0; - fullWidth = 0; - fullHeight = 0; + int x, y; switch ((enum compound) butPtr->compound) { case COMPOUND_TOP: - case COMPOUND_BOTTOM: { - /* Image is above or below text */ - if (butPtr->compound == COMPOUND_TOP) { - textYOffset = height + butPtr->padY; - } else { - imageYOffset = butPtr->textHeight + butPtr->padY; - } - fullHeight = height + butPtr->textHeight + butPtr->padY; - fullWidth = (width > butPtr->textWidth ? width : - butPtr->textWidth); - textXOffset = (fullWidth - butPtr->textWidth)/2; - imageXOffset = (fullWidth - width)/2; - break; - } + case COMPOUND_BOTTOM: + /* Image is above or below text */ + if (butPtr->compound == COMPOUND_TOP) { + textYOffset = height + butPtr->padY; + } else { + imageYOffset = butPtr->textHeight + butPtr->padY; + } + fullHeight = height + butPtr->textHeight + butPtr->padY; + fullWidth = (width > butPtr->textWidth ? width : butPtr->textWidth); + textXOffset = (fullWidth - butPtr->textWidth)/2; + imageXOffset = (fullWidth - width)/2; + break; case COMPOUND_LEFT: - case COMPOUND_RIGHT: { - /* - * Image is left or right of text - */ - - if (butPtr->compound == COMPOUND_LEFT) { - textXOffset = width + butPtr->padX; - } else { - imageXOffset = butPtr->textWidth + butPtr->padX; - } - fullWidth = butPtr->textWidth + butPtr->padX + width; - fullHeight = (height > butPtr->textHeight ? height : - butPtr->textHeight); - textYOffset = (fullHeight - butPtr->textHeight)/2; - imageYOffset = (fullHeight - height)/2; - break; - } - case COMPOUND_CENTER: { - /* - * Image and text are superimposed - */ - - fullWidth = (width > butPtr->textWidth ? width : - butPtr->textWidth); - fullHeight = (height > butPtr->textHeight ? height : - butPtr->textHeight); - textXOffset = (fullWidth - butPtr->textWidth)/2; - imageXOffset = (fullWidth - width)/2; - textYOffset = (fullHeight - butPtr->textHeight)/2; - imageYOffset = (fullHeight - height)/2; - break; - } + case COMPOUND_RIGHT: + /* + * Image is left or right of text + */ + + if (butPtr->compound == COMPOUND_LEFT) { + textXOffset = width + butPtr->padX; + } else { + imageXOffset = butPtr->textWidth + butPtr->padX; + } + fullWidth = butPtr->textWidth + butPtr->padX + width; + fullHeight = (height > butPtr->textHeight ? height : + butPtr->textHeight); + textYOffset = (fullHeight - butPtr->textHeight)/2; + imageYOffset = (fullHeight - height)/2; + break; + case COMPOUND_CENTER: + /* + * Image and text are superimposed + */ + + fullWidth = (width > butPtr->textWidth ? width : + butPtr->textWidth); + fullHeight = (height > butPtr->textHeight ? height : + butPtr->textHeight); + textXOffset = (fullWidth - butPtr->textWidth)/2; + imageXOffset = (fullWidth - width)/2; + textYOffset = (fullHeight - butPtr->textHeight)/2; + imageYOffset = (fullHeight - height)/2; + break; default: - break; + break; } TkComputeAnchor(butPtr->anchor, tkwin, @@ -547,25 +549,25 @@ DrawButtonImageAndText( imageYOffset += y; if (butPtr->image != NULL) { - if ((butPtr->selectImage != NULL) && - (butPtr->flags & SELECTED)) { - Tk_RedrawImage(butPtr->selectImage, 0, 0, - width, height, pixmap, imageXOffset, imageYOffset); - } else if ((butPtr->tristateImage != NULL) && - (butPtr->flags & TRISTATED)) { - Tk_RedrawImage(butPtr->tristateImage, 0, 0, - width, height, pixmap, imageXOffset, imageYOffset); - } else { - Tk_RedrawImage(butPtr->image, 0, 0, width, - height, pixmap, imageXOffset, imageYOffset); - } + if ((butPtr->selectImage != NULL) && + (butPtr->flags & SELECTED)) { + Tk_RedrawImage(butPtr->selectImage, 0, 0, + width, height, pixmap, imageXOffset, imageYOffset); + } else if ((butPtr->tristateImage != NULL) && + (butPtr->flags & TRISTATED)) { + Tk_RedrawImage(butPtr->tristateImage, 0, 0, + width, height, pixmap, imageXOffset, imageYOffset); + } else { + Tk_RedrawImage(butPtr->image, 0, 0, width, + height, pixmap, imageXOffset, imageYOffset); + } } else { - XSetClipOrigin(butPtr->display, dpPtr->gc, - imageXOffset, imageYOffset); - XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, dpPtr->gc, - 0, 0, (unsigned int) width, (unsigned int) height, - imageXOffset, imageYOffset, 1); - XSetClipOrigin(butPtr->display, dpPtr->gc, 0, 0); + XSetClipOrigin(butPtr->display, dpPtr->gc, + imageXOffset, imageYOffset); + XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, dpPtr->gc, + 0, 0, (unsigned int) width, (unsigned int) height, + imageXOffset, imageYOffset, 1); + XSetClipOrigin(butPtr->display, dpPtr->gc, 0, 0); } y += 1; /* Tweak to match native buttons. */ @@ -577,60 +579,57 @@ DrawButtonImageAndText( x + textXOffset, y + textYOffset, butPtr->underline); } else if (haveImage) { /* Image only */ - int x = 0; - int y; + int x = 0, y; + TkComputeAnchor(butPtr->anchor, tkwin, - butPtr->padX + butPtr->borderWidth, - butPtr->padY + butPtr->borderWidth, - width + butPtr->indicatorSpace, - height, &x, &y); + butPtr->padX + butPtr->borderWidth, + butPtr->padY + butPtr->borderWidth, + width + butPtr->indicatorSpace, height, &x, &y); x += butPtr->indicatorSpace; if (pressed) { - x += dpPtr->offset; - y += dpPtr->offset; + x += dpPtr->offset; + y += dpPtr->offset; } imageXOffset += x; imageYOffset += y; if (butPtr->image != NULL) { - - if ((butPtr->selectImage != NULL) && - (butPtr->flags & SELECTED)) { - Tk_RedrawImage(butPtr->selectImage, 0, 0, width, - height, pixmap, imageXOffset, imageYOffset); - } else if ((butPtr->tristateImage != NULL) && - (butPtr->flags & TRISTATED)) { - Tk_RedrawImage(butPtr->tristateImage, 0, 0, width, - height, pixmap, imageXOffset, imageYOffset); - } else { - Tk_RedrawImage(butPtr->image, 0, 0, width, height, - pixmap, imageXOffset, imageYOffset); - } + if ((butPtr->selectImage != NULL) && + (butPtr->flags & SELECTED)) { + Tk_RedrawImage(butPtr->selectImage, 0, 0, width, + height, pixmap, imageXOffset, imageYOffset); + } else if ((butPtr->tristateImage != NULL) && + (butPtr->flags & TRISTATED)) { + Tk_RedrawImage(butPtr->tristateImage, 0, 0, width, + height, pixmap, imageXOffset, imageYOffset); + } else { + Tk_RedrawImage(butPtr->image, 0, 0, width, height, + pixmap, imageXOffset, imageYOffset); + } } else { - XSetClipOrigin(butPtr->display, dpPtr->gc, x, y); - XCopyPlane(butPtr->display, butPtr->bitmap, - pixmap, dpPtr->gc, - 0, 0, (unsigned int) width, - (unsigned int) height, - imageXOffset, imageYOffset, 1); - XSetClipOrigin(butPtr->display, dpPtr->gc, 0, 0); + XSetClipOrigin(butPtr->display, dpPtr->gc, x, y); + XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, dpPtr->gc, + 0, 0, (unsigned int) width, (unsigned int) height, + imageXOffset, imageYOffset, 1); + XSetClipOrigin(butPtr->display, dpPtr->gc, 0, 0); } } else { /* Text only */ int x, y; + TkComputeAnchor(butPtr->anchor, tkwin, butPtr->padX, butPtr->padY, - butPtr->textWidth + butPtr->indicatorSpace, - butPtr->textHeight, &x, &y); + butPtr->textWidth + butPtr->indicatorSpace, + butPtr->textHeight, &x, &y); x += butPtr->indicatorSpace; y += 1; /* Tweak to match native buttons */ - Tk_DrawTextLayout(butPtr->display, pixmap, dpPtr->gc, butPtr->textLayout, - x, y, 0, -1); + Tk_DrawTextLayout(butPtr->display, pixmap, dpPtr->gc, + butPtr->textLayout, x, y, 0, -1); } /* * If the button is disabled with a stipple rather than a special - * foreground color, generate the stippled effect. If the widget - * is selected and we use a different background color when selected, - * must temporarily modify the GC so the stippling is the right color. + * foreground color, generate the stippled effect. If the widget is + * selected and we use a different background color when selected, must + * temporarily modify the GC so the stippling is the right color. */ if (mbPtr->useTkText) { @@ -668,18 +667,15 @@ DrawButtonImageAndText( */ if (dpPtr->relief != TK_RELIEF_FLAT) { - int inset = butPtr->highlightWidth; - Tk_Draw3DRectangle(tkwin, pixmap, dpPtr->border, inset, inset, - Tk_Width(tkwin) - 2*inset, Tk_Height(tkwin) - 2*inset, - butPtr->borderWidth, dpPtr->relief); + int inset = butPtr->highlightWidth; + + Tk_Draw3DRectangle(tkwin, pixmap, dpPtr->border, inset, inset, + Tk_Width(tkwin) - 2*inset, Tk_Height(tkwin) - 2*inset, + butPtr->borderWidth, dpPtr->relief); } } - - } - - - - +} + /* *---------------------------------------------------------------------- * @@ -701,6 +697,7 @@ TkpDestroyButton( TkButton *butPtr) { MacButton *mbPtr = (MacButton *) butPtr; /* Mac button. */ + if (mbPtr->defaultPulseHandler) { Tcl_DeleteTimerHandler(mbPtr->defaultPulseHandler); } @@ -711,9 +708,8 @@ TkpDestroyButton( * * TkMacOSXDrawButton -- * - * This function draws the tk button using Mac controls - * In addition, this code may apply custom colors passed - * in the TkButton. + * This function draws the tk button using Mac controls. In addition, + * this code may apply custom colors passed in the TkButton. * * Results: * None. @@ -732,23 +728,19 @@ TkMacOSXDrawButton( Pixmap pixmap) /* The pixmap we are drawing into - needed * for the bevel button */ { - TkButton * butPtr = ( TkButton *)mbPtr; - TkWindow * winPtr; - HIRect cntrRect; + TkButton *butPtr = (TkButton *) mbPtr; + TkWindow *winPtr = (TkWindow *) butPtr->tkwin; + HIRect cntrRect; TkMacOSXDrawingContext dc; - DrawParams* dpPtr = &mbPtr->drawParams; + DrawParams *dpPtr = &mbPtr->drawParams; int useNewerHITools = 1; - winPtr = (TkWindow *)butPtr->tkwin; - TkMacOSXComputeButtonParams(butPtr, &mbPtr->btnkind, &mbPtr->drawinfo); - cntrRect = CGRectMake(winPtr->privatePtr->xOff, - winPtr->privatePtr->yOff, - Tk_Width(butPtr->tkwin), - Tk_Height(butPtr->tkwin)); + cntrRect = CGRectMake(winPtr->privatePtr->xOff, winPtr->privatePtr->yOff, + Tk_Width(butPtr->tkwin), Tk_Height(butPtr->tkwin)); - cntrRect = CGRectInset(cntrRect, butPtr->inset, butPtr->inset); + cntrRect = CGRectInset(cntrRect, butPtr->inset, butPtr->inset); if (useNewerHITools == 1) { HIRect contHIRec; @@ -762,7 +754,7 @@ TkMacOSXDrawButton( hiinfo.version = 0; hiinfo.state = mbPtr->drawinfo.state; - hiinfo.kind = mbPtr->btnkind; + hiinfo.kind = mbPtr->btnkind; hiinfo.value = mbPtr->drawinfo.value; hiinfo.adornment = mbPtr->drawinfo.adornment; hiinfo.animation.time.current = CFAbsoluteTimeGetCurrent(); @@ -772,21 +764,19 @@ TkMacOSXDrawButton( /* * To avoid buttons with white text on a white background, we always - * set the state to inactive in Dark Mode. It isn't perfect but - * it is usable. Using a ttk::button would be a better choice, - * however. + * set the state to inactive in Dark Mode. It isn't perfect but it is + * usable. Using a ttk::button would be a better choice, however. */ if (TkMacOSXInDarkMode(butPtr->tkwin)) { hiinfo.state = kThemeStateInactive; } - HIThemeDrawButton(&cntrRect, &hiinfo, dc.context, kHIThemeOrientationNormal, - &contHIRec); + HIThemeDrawButton(&cntrRect, &hiinfo, dc.context, + kHIThemeOrientationNormal, &contHIRec); TkMacOSXRestoreDrawingContext(&dc); ButtonContentDrawCB(&contHIRec, mbPtr->btnkind, &mbPtr->drawinfo, - (MacButton *)mbPtr, 32, true); - + (MacButton *) mbPtr, 32, true); } else { if (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, 1, &dc)) { return; @@ -802,8 +792,8 @@ TkMacOSXDrawButton( * * ButtonBackgroundDrawCB -- * - * This function draws the background that - * lies under checkboxes and radiobuttons. + * This function draws the background that lies under checkboxes and + * radiobuttons. * * Results: * None. @@ -813,32 +803,33 @@ TkMacOSXDrawButton( * *-------------------------------------------------------------- */ + static void -ButtonBackgroundDrawCB ( - const HIRect * btnbounds, +ButtonBackgroundDrawCB( + const HIRect *btnbounds, MacButton *ptr, SInt16 depth, Boolean isColorDev) { - MacButton* mbPtr = (MacButton*)ptr; - TkButton* butPtr = (TkButton*)mbPtr; - Tk_Window tkwin = butPtr->tkwin; + MacButton *mbPtr = (MacButton *) ptr; + TkButton *butPtr = (TkButton *) mbPtr; + Tk_Window tkwin = butPtr->tkwin; Pixmap pixmap; int usehlborder = 0; if (tkwin == NULL || !Tk_IsMapped(tkwin)) { return; } - pixmap = (Pixmap)Tk_WindowId(tkwin); + pixmap = (Pixmap) Tk_WindowId(tkwin); if (butPtr->type != TYPE_LABEL) { switch (mbPtr->btnkind) { - case kThemeSmallBevelButton: - case kThemeBevelButton: - case kThemeRoundedBevelButton: - case kThemePushButton: - usehlborder = 1; - break; + case kThemeSmallBevelButton: + case kThemeBevelButton: + case kThemeRoundedBevelButton: + case kThemePushButton: + usehlborder = 1; + break; } } if (usehlborder) { @@ -874,17 +865,18 @@ ButtonContentDrawCB ( SInt16 depth, Boolean isColorDev) { - TkButton *butPtr = (TkButton *)ptr; - Tk_Window tkwin = butPtr->tkwin; + TkButton *butPtr = (TkButton *) ptr; + Tk_Window tkwin = butPtr->tkwin; if (tkwin == NULL || !Tk_IsMapped(tkwin)) { return; } /* - * Overlay Tk elements over button native region: drawing elements - * within button boundaries/native region causes unpredictable metrics. + * Overlay Tk elements over button native region: drawing elements within + * button boundaries/native region causes unpredictable metrics. */ + DrawButtonImageAndText( butPtr); } @@ -893,8 +885,8 @@ ButtonContentDrawCB ( * * ButtonEventProc -- * - * This procedure is invoked by the Tk dispatcher for various - * events on buttons. + * This procedure is invoked by the Tk dispatcher for various events on + * buttons. * * Results: * None. @@ -910,8 +902,8 @@ ButtonEventProc( ClientData clientData, /* Information about window. */ XEvent *eventPtr) /* Information about event. */ { - TkButton *buttonPtr = (TkButton *) clientData; - MacButton *mbPtr = (MacButton *) clientData; + TkButton *buttonPtr = clientData; + MacButton *mbPtr = clientData; if (eventPtr->type == ActivateNotify || eventPtr->type == DeactivateNotify) { @@ -924,7 +916,7 @@ ButtonEventProc( mbPtr->flags &= ~ACTIVE; } if ((buttonPtr->flags & REDRAW_PENDING) == 0) { - Tcl_DoWhenIdle(TkpDisplayButton, (ClientData) buttonPtr); + Tcl_DoWhenIdle(TkpDisplayButton, buttonPtr); buttonPtr->flags |= REDRAW_PENDING; } } @@ -935,9 +927,9 @@ ButtonEventProc( * * TkMacOSXComputeButtonParams -- * - * This procedure computes the various parameters used - * when creating a Carbon Appearance control. - * These are determined by the various tk button parameters + * This procedure computes the various parameters used when creating a + * Carbon Appearance control. These are determined by the various tk + * button parameters * * Results: * None. @@ -950,11 +942,11 @@ ButtonEventProc( static void TkMacOSXComputeButtonParams( - TkButton * butPtr, - ThemeButtonKind* btnkind, - HIThemeButtonDrawInfo *drawinfo) + TkButton *butPtr, + ThemeButtonKind *btnkind, + HIThemeButtonDrawInfo *drawinfo) { - MacButton *mbPtr = (MacButton *)butPtr; + MacButton *mbPtr = (MacButton *) butPtr; if (butPtr->borderWidth <= 2) { *btnkind = kThemeSmallBevelButton; @@ -968,47 +960,46 @@ TkMacOSXComputeButtonParams( if ((butPtr->image == None) && (butPtr->bitmap == None)) { switch (butPtr->type) { - case TYPE_BUTTON: - *btnkind = kThemePushButton; - break; - case TYPE_RADIO_BUTTON: - if (butPtr->borderWidth <= 1) { - *btnkind = kThemeSmallRadioButton; - } else { - *btnkind = kThemeRadioButton; - } - break; - case TYPE_CHECK_BUTTON: - if (butPtr->borderWidth <= 1) { - *btnkind = kThemeSmallCheckBox; - } else { - *btnkind = kThemeCheckBox; - } - break; + case TYPE_BUTTON: + *btnkind = kThemePushButton; + break; + case TYPE_RADIO_BUTTON: + if (butPtr->borderWidth <= 1) { + *btnkind = kThemeSmallRadioButton; + } else { + *btnkind = kThemeRadioButton; + } + break; + case TYPE_CHECK_BUTTON: + if (butPtr->borderWidth <= 1) { + *btnkind = kThemeSmallCheckBox; + } else { + *btnkind = kThemeCheckBox; + } + break; } } if (butPtr->indicatorOn) { switch (butPtr->type) { - case TYPE_RADIO_BUTTON: - if (butPtr->borderWidth <= 1) { - *btnkind = kThemeSmallRadioButton; - } else { - *btnkind = kThemeRadioButton; - } - break; - case TYPE_CHECK_BUTTON: - if (butPtr->borderWidth <= 1) { - *btnkind = kThemeSmallCheckBox; - } else { - *btnkind = kThemeCheckBox; - } - break; + case TYPE_RADIO_BUTTON: + if (butPtr->borderWidth <= 1) { + *btnkind = kThemeSmallRadioButton; + } else { + *btnkind = kThemeRadioButton; + } + break; + case TYPE_CHECK_BUTTON: + if (butPtr->borderWidth <= 1) { + *btnkind = kThemeSmallCheckBox; + } else { + *btnkind = kThemeCheckBox; + } + break; } } else { if (butPtr->type == TYPE_RADIO_BUTTON || - butPtr->type == TYPE_CHECK_BUTTON - ) { + butPtr->type == TYPE_CHECK_BUTTON) { if (*btnkind == kThemePushButton) { *btnkind = kThemeBevelButton; } @@ -1050,8 +1041,7 @@ TkMacOSXComputeButtonParams( drawinfo->adornment |= kThemeAdornmentDefault; if (!mbPtr->defaultPulseHandler) { mbPtr->defaultPulseHandler = Tcl_CreateTimerHandler( - PULSE_TIMER_MSECS, PulseDefaultButtonProc, - (ClientData) butPtr); + PULSE_TIMER_MSECS, PulseDefaultButtonProc, butPtr); } } else if (mbPtr->defaultPulseHandler) { Tcl_DeleteTimerHandler(mbPtr->defaultPulseHandler); @@ -1068,9 +1058,8 @@ TkMacOSXComputeButtonParams( * * TkMacOSXComputeButtonDrawParams -- * - * This procedure computes the various parameters used - * when drawing a button - * These are determined by the various tk button parameters + * This procedure computes the various parameters used when drawing a + * button. These are determined by the various tk button parameters * * Results: * 1 if control will be used, 0 otherwise. @@ -1086,7 +1075,7 @@ TkMacOSXComputeButtonDrawParams( TkButton *butPtr, DrawParams *dpPtr) { - MacButton *mbPtr = (MacButton *)butPtr; + MacButton *mbPtr = (MacButton *) butPtr; dpPtr->hasImageOrBitmap = ((butPtr->image != NULL) || (butPtr->bitmap != None)); @@ -1095,12 +1084,12 @@ TkMacOSXComputeButtonDrawParams( dpPtr->offset = 0; if (dpPtr->hasImageOrBitmap) { switch (mbPtr->btnkind) { - case kThemeSmallBevelButton: - case kThemeBevelButton: - case kThemeRoundedBevelButton: - case kThemePushButton: - dpPtr->offset = 1; - break; + case kThemeSmallBevelButton: + case kThemeBevelButton: + case kThemeRoundedBevelButton: + case kThemePushButton: + dpPtr->offset = 1; + break; } } } @@ -1121,8 +1110,8 @@ TkMacOSXComputeButtonDrawParams( } /* - * Override the relief specified for the button if this is a - * checkbutton or radiobutton and there's no indicator. + * Override the relief specified for the button if this is a checkbutton or + * radiobutton and there's no indicator. */ dpPtr->relief = butPtr->relief; @@ -1134,22 +1123,18 @@ TkMacOSXComputeButtonDrawParams( } } - if (butPtr->type != TYPE_LABEL && - (butPtr->type == TYPE_BUTTON || - butPtr->indicatorOn || - dpPtr->hasImageOrBitmap)) { - + if (butPtr->type != TYPE_LABEL && (butPtr->type == TYPE_BUTTON || + butPtr->indicatorOn || dpPtr->hasImageOrBitmap)) { /* * Draw this widget as a native control. */ - + return 1; } else { - /* * Draw this widget from scratch. */ - + return 0; } } @@ -1173,12 +1158,13 @@ TkMacOSXComputeButtonDrawParams( static void PulseDefaultButtonProc(ClientData clientData) { - MacButton *mbPtr = (MacButton *)clientData; + MacButton *mbPtr = clientData; + TkpDisplayButton(clientData); mbPtr->defaultPulseHandler = Tcl_CreateTimerHandler( PULSE_TIMER_MSECS, PulseDefaultButtonProc, clientData); } - + /* * Local Variables: * mode: objc diff --git a/macosx/tkMacOSXClipboard.c b/macosx/tkMacOSXClipboard.c index efd3c69..6cbcdf6 100644 --- a/macosx/tkMacOSXClipboard.c +++ b/macosx/tkMacOSXClipboard.c @@ -123,8 +123,9 @@ TkSelGetSelection( { int result = TCL_ERROR; TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; + int haveExternalClip = + ([[NSPasteboard generalPasteboard] changeCount] != changeCount); - int haveExternalClip = ([[NSPasteboard generalPasteboard] changeCount] != changeCount); if (dispPtr && (haveExternalClip || dispPtr->clipboardActive) && selection == dispPtr->clipboardAtom && (target == XA_STRING || target == dispPtr->utf8Atom)) { @@ -177,6 +178,7 @@ XSetSelectionOwner( clipboardOwner = owner ? Tk_IdToWindow(display, owner) : NULL; if (!dispPtr->clipboardActive) { NSPasteboard *pb = [NSPasteboard generalPasteboard]; + changeCount = [pb declareTypes:[NSArray array] owner:NSApp]; } } @@ -188,8 +190,8 @@ XSetSelectionOwner( * * TkMacOSXSelDeadWindow -- * - * This function is invoked just before a TkWindow is deleted. It - * performs selection-related cleanup. + * This function is invoked just before a TkWindow is deleted. It performs + * selection-related cleanup. * * Results: * None. diff --git a/macosx/tkMacOSXCursor.c b/macosx/tkMacOSXCursor.c index b6394b7..03d13dd 100644 --- a/macosx/tkMacOSXCursor.c +++ b/macosx/tkMacOSXCursor.c @@ -185,7 +185,7 @@ static const struct CursorName cursorNames[] = { * Declarations of static variables used in this file. */ -static TkMacOSXCursor * gCurrentCursor = NULL; +static TkMacOSXCursor *gCurrentCursor = NULL; /* A pointer to the current cursor. */ static int gResizeOverride = false; /* A boolean indicating whether we should use @@ -194,7 +194,7 @@ static int gTkOwnsCursor = true;/* A boolean indicating whether Tk owns the * cursor. If not (for instance, in the case * where a Tk window is embedded in another * app's window, and the cursor is out of the - * tk window, we will not attempt to adjust + * Tk window, we will not attempt to adjust * the cursor. */ /* @@ -278,6 +278,7 @@ FindCursorByName( kCGColorSpaceGenericGray); CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, bitmap, pix*pix/8, NULL); + if (provider) { img = CGImageCreate(pix, pix, 1, 1, pix/8, colorspace, kCGBitmapByteOrderDefault, provider, decodeWB, 0, @@ -299,14 +300,21 @@ FindCursorByName( initWithCGImage:maskedImg]; CFRelease(maskedImg); } - if (mask) { CFRelease(mask); } - if (img) { CFRelease(img); } - if (colorspace) { CFRelease(colorspace); } + if (mask) { + CFRelease(mask); + } + if (img) { + CFRelease(img); + } + if (colorspace) { + CFRelease(colorspace); + } if (bitmapImageRep) { image = [[NSImage alloc] initWithSize:NSMakeSize(pix, pix)]; [image addRepresentation:bitmapImageRep]; [bitmapImageRep release]; } + uint16_t *hotSpotData = (uint16_t*)(bitmap + 2*pix*pix/8); hotSpot.y = CFSwapInt16BigToHost(*hotSpotData++); hotSpot.x = CFSwapInt16BigToHost(*hotSpotData); diff --git a/macosx/tkMacOSXDialog.c b/macosx/tkMacOSXDialog.c index c3778f1..a7997f2 100644 --- a/macosx/tkMacOSXDialog.c +++ b/macosx/tkMacOSXDialog.c @@ -22,31 +22,39 @@ #else #define modalOK NSModalResponseOK #define modalCancel NSModalResponseCancel -#endif +#endif // MAC_OS_X_VERSION_MIN_REQUIRED < 1090 #define modalOther -1 #define modalError -2 -/*Vars for filtering in "open file" and "save file" dialogs.*/ -typedef struct { - bool doFileTypes; // show the accessory view which displays the filter menu - bool preselectFilter; // a filter was selected by the typevariable - bool userHasSelectedFilter; // The user has changed the filter in the accessory view - - NSMutableArray *fileTypeNames; // array of names, e.g. "Text document" - NSMutableArray *fileTypeExtensions; // array of allowed extensions per name, e.g. "txt", "doc" - NSMutableArray *fileTypeLabels; // displayed string, e.g. "Text document (.txt, .doc)" - NSMutableArray *fileTypeAllowsAll; // boolean if the all pattern (*.*) is included - - NSMutableArray *allowedExtensions; // set of all allowed extensions - bool allowedExtensionsAllowAll; // set of all allowed extensions includes *.* +/* + * Vars for filtering in "open file" and "save file" dialogs. + */ - NSUInteger fileTypeIndex; // index of currently selected filter +typedef struct { + bool doFileTypes; /* Show the accessory view which + * displays the filter menu */ + bool preselectFilter; /* A filter was selected by the + * typevariable. */ + bool userHasSelectedFilter; /* The user has changed the filter in + * the accessory view. */ + NSMutableArray *fileTypeNames; /* Array of names, e.g. "Text + * document". */ + NSMutableArray *fileTypeExtensions; /* Array of allowed extensions per + * name, e.g. "txt", "doc". */ + NSMutableArray *fileTypeLabels; /* Displayed string, e.g. "Text + * document (.txt, .doc)". */ + NSMutableArray *fileTypeAllowsAll; /* Boolean if the all pattern (*.*) is + * included. */ + NSMutableArray *allowedExtensions; /* Set of all allowed extensions. */ + bool allowedExtensionsAllowAll; /* Set of all allowed extensions + * includes *.* */ + NSUInteger fileTypeIndex; /* Index of currently selected + * filter. */ } filepanelFilterInfo; -filepanelFilterInfo filterInfo; - -NSOpenPanel *openpanel; -NSSavePanel *savepanel; +static filepanelFilterInfo filterInfo; +static NSOpenPanel *openpanel; +static NSSavePanel *savepanel; static const char *const colorOptionStrings[] = { "-initialcolor", "-parent", "-title", NULL @@ -166,10 +174,15 @@ static const short alertNativeButtonIndexAndTypeToButtonIndex[][3] = { }; /* - * Construct a file URL from directory and filename. Either may - * be nil. If both are nil, returns nil. + * Construct a file URL from directory and filename. Either may be nil. If both + * are nil, returns nil. */ -static NSURL *getFileURL(NSString *directory, NSString *filename) { + +static NSURL * +getFileURL( + NSString *directory, + NSString *filename) +{ NSURL *url = nil; if (directory) { url = [NSURL fileURLWithPath:directory isDirectory:YES]; @@ -229,7 +242,6 @@ static NSURL *getFileURL(NSString *directory, NSString *filename) { } } - - (void) tkAlertDidEnd: (NSAlert *) alert returnCode: (NSInteger) returnCode contextInfo: (void *) contextInfo { @@ -272,12 +284,18 @@ static NSURL *getFileURL(NSString *directory, NSString *filename) { if ([[filterInfo.fileTypeAllowsAll objectAtIndex:filterInfo.fileTypeIndex] boolValue]) { [openpanel setAllowsOtherFileTypes:YES]; - /* setAllowsOtherFileTypes might have no effect; it's inherited from the - * NSSavePanel, where it has the effect that it does not append an extension - * Setting the allowed file types to nil allows selecting any file */ + + /* + * setAllowsOtherFileTypes might have no effect; it's inherited from + * the NSSavePanel, where it has the effect that it does not append an + * extension. Setting the allowed file types to nil allows selecting + * any file. + */ + [openpanel setAllowedFileTypes:nil]; } else { - NSMutableArray *allowedtypes = [filterInfo.fileTypeExtensions objectAtIndex:filterInfo.fileTypeIndex]; + NSMutableArray *allowedtypes = + [filterInfo.fileTypeExtensions objectAtIndex:filterInfo.fileTypeIndex]; [openpanel setAllowedFileTypes:allowedtypes]; [openpanel setAllowsOtherFileTypes:NO]; } @@ -293,7 +311,8 @@ static NSURL *getFileURL(NSString *directory, NSString *filename) { [savepanel setAllowsOtherFileTypes:YES]; [savepanel setAllowedFileTypes:nil]; } else { - NSMutableArray *allowedtypes = [filterInfo.fileTypeExtensions objectAtIndex:filterInfo.fileTypeIndex]; + NSMutableArray *allowedtypes = + [filterInfo.fileTypeExtensions objectAtIndex:filterInfo.fileTypeIndex]; [savepanel setAllowedFileTypes:allowedtypes]; [savepanel setAllowsOtherFileTypes:NO]; } @@ -384,6 +403,7 @@ Tk_ChooseColorObjCmd( [colorPanel _setUseModalAppearance:YES]; if (title) { NSString *s = [[NSString alloc] initWithUTF8String:title]; + [colorPanel setTitle:s]; [s release]; } @@ -415,9 +435,17 @@ end: return result; } -/* dissect the -filetype nested lists and store the information - * in the filterInfo structure */ -int parseFileFilters(Tcl_Interp *interp, Tcl_Obj *fileTypesPtr, Tcl_Obj *typeVariablePtr) { +/* + * Dissect the -filetype nested lists and store the information in the + * filterInfo structure. + */ + +static int +parseFileFilters( + Tcl_Interp *interp, + Tcl_Obj *fileTypesPtr, + Tcl_Obj *typeVariablePtr) +{ if (!fileTypesPtr) { filterInfo.doFileTypes = false; @@ -425,6 +453,7 @@ int parseFileFilters(Tcl_Interp *interp, Tcl_Obj *fileTypesPtr, Tcl_Obj *typeVar } FileFilterList fl; + TkInitFileFilters(&fl); if (TkGetFileFilters(interp, &fl, fileTypesPtr, 0) != TCL_OK) { TkFreeFileFilters(&fl); @@ -445,11 +474,12 @@ int parseFileFilters(Tcl_Interp *interp, Tcl_Obj *fileTypesPtr, Tcl_Obj *typeVar if (filterInfo.doFileTypes) { for (FileFilter *filterPtr = fl.filters; filterPtr; filterPtr = filterPtr->next) { - NSString * name = [[NSString alloc] initWithUTF8String: filterPtr -> name]; + NSString *name = [[NSString alloc] initWithUTF8String: filterPtr->name]; + [filterInfo.fileTypeNames addObject:name]; [name release]; - NSMutableArray * clauseextensions = [NSMutableArray array]; - NSMutableArray * displayextensions = [NSMutableArray array]; + NSMutableArray *clauseextensions = [NSMutableArray array]; + NSMutableArray *displayextensions = [NSMutableArray array]; bool allowsAll = NO; for (FileFilterClause *clausePtr = filterPtr->clauses; clausePtr; @@ -460,7 +490,7 @@ int parseFileFilters(Tcl_Interp *interp, Tcl_Obj *fileTypesPtr, Tcl_Obj *typeVar const char *str = globPtr->pattern; while (*str && (*str == '*' || *str == '.')) { str++; - } + } if (*str) { NSString *extension = [[NSString alloc] initWithUTF8String:str]; if (![filterInfo.allowedExtensions containsObject:extension]) { @@ -472,7 +502,10 @@ int parseFileFilters(Tcl_Interp *interp, Tcl_Obj *fileTypesPtr, Tcl_Obj *typeVar [extension release]; } else { - // it is the all pattern (*, .* or *.*) + /* + * It is the all pattern (*, .* or *.*) + */ + allowsAll = YES; filterInfo.allowedExtensionsAllowAll = YES; [displayextensions addObject:@"*"]; @@ -482,27 +515,39 @@ int parseFileFilters(Tcl_Interp *interp, Tcl_Obj *fileTypesPtr, Tcl_Obj *typeVar [filterInfo.fileTypeExtensions addObject:clauseextensions]; [filterInfo.fileTypeAllowsAll addObject:[NSNumber numberWithBool:allowsAll]]; - NSMutableString * label = [[NSMutableString alloc] initWithString:name]; + NSMutableString *label = [[NSMutableString alloc] initWithString:name]; [label appendString:@" ("]; [label appendString:[displayextensions componentsJoinedByString:@", "]]; [label appendString:@")"]; [filterInfo.fileTypeLabels addObject:label]; [label release]; - } - /* Check if the typevariable exists and matches one of the names */ + /* + * Check if the typevariable exists and matches one of the names. + */ + filterInfo.preselectFilter = false; filterInfo.userHasSelectedFilter = false; if (typeVariablePtr) { - /* extract the variable content as a NSString */ - Tcl_Obj *selectedFileTypeObj = Tcl_ObjGetVar2(interp, typeVariablePtr, NULL, TCL_GLOBAL_ONLY); + /* + * Extract the variable content as a NSString. + */ + + Tcl_Obj *selectedFileTypeObj = Tcl_ObjGetVar2(interp, + typeVariablePtr, NULL, TCL_GLOBAL_ONLY); + + /* + * Check that the typevariable exists. + */ - /* check that the typevariable exists */ if (selectedFileTypeObj != NULL) { - const char *selectedFileType = Tcl_GetString(selectedFileTypeObj); - NSString *selectedFileTypeStr = [[NSString alloc] initWithUTF8String:selectedFileType]; - NSUInteger index = [filterInfo.fileTypeNames indexOfObject:selectedFileTypeStr]; + const char *selectedFileType = + Tcl_GetString(selectedFileTypeObj); + NSString *selectedFileTypeStr = + [[NSString alloc] initWithUTF8String:selectedFileType]; + NSUInteger index = + [filterInfo.fileTypeNames indexOfObject:selectedFileTypeStr]; if (index != NSNotFound) { filterInfo.fileTypeIndex = index; @@ -517,17 +562,24 @@ int parseFileFilters(Tcl_Interp *interp, Tcl_Obj *fileTypesPtr, Tcl_Obj *typeVar return TCL_OK; } -bool filterCompatible(NSString *extension, int filterIndex) { - NSMutableArray *allowedExtensions = [filterInfo.fileTypeExtensions objectAtIndex: filterIndex]; +static bool +filterCompatible( + NSString *extension, + int filterIndex) +{ + NSMutableArray *allowedExtensions = + [filterInfo.fileTypeExtensions objectAtIndex: filterIndex]; + + /* + * If this contains the all pattern, accept any extension. + */ - /* If this contains the all pattern, accept any extension */ if ([[filterInfo.fileTypeAllowsAll objectAtIndex:filterIndex] boolValue]) { return true; } return [allowedExtensions containsObject: extension]; } - /* *---------------------------------------------------------------------- @@ -631,13 +683,16 @@ Tk_GetOpenFileObjCmd( if (title) { [openpanel setTitle:title]; - /* From OSX 10.11, the title string is silently ignored in the open panel. - * Prepend the title to the message in this case - * NOTE should be conditional on OSX version, but - * -mmacosx-version-min does not revert this behaviour*/ + /* + * From OSX 10.11, the title string is silently ignored in the open + * panel. Prepend the title to the message in this case. NOTE should + * be conditional on OSX version, but -mmacosx-version-min does not + * revert this behaviour + */ if (message) { - NSString *fullmessage = [[NSString alloc] initWithFormat:@"%@\n%@",title,message]; + NSString *fullmessage = + [[NSString alloc] initWithFormat:@"%@\n%@", title, message]; [message release]; [title release]; message = fullmessage; @@ -658,15 +713,20 @@ Tk_GetOpenFileObjCmd( } if (filterInfo.doFileTypes) { - NSView *accessoryView = [[NSView alloc] initWithFrame:NSMakeRect(0.0, 0.0, 300, 32.0)]; - NSTextField *label = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 60, 22)]; + NSView *accessoryView = [[NSView alloc] + initWithFrame:NSMakeRect(0.0, 0.0, 300, 32.0)]; + NSTextField *label = [[NSTextField alloc] + initWithFrame:NSMakeRect(0, 0, 60, 22)]; + [label setEditable:NO]; [label setStringValue:@"Filter:"]; [label setBordered:NO]; [label setBezeled:NO]; [label setDrawsBackground:NO]; - NSPopUpButton *popupButton = [[NSPopUpButton alloc] initWithFrame:NSMakeRect(50.0, 2, 240, 22.0) pullsDown:NO]; + NSPopUpButton *popupButton = [[NSPopUpButton alloc] + initWithFrame:NSMakeRect(50.0, 2, 240, 22.0) pullsDown:NO]; + [popupButton addItemsWithTitles:filterInfo.fileTypeLabels]; [popupButton setAction:@selector(selectFormat:)]; @@ -674,10 +734,16 @@ Tk_GetOpenFileObjCmd( [accessoryView addSubview:popupButton]; if (filterInfo.preselectFilter) { - /* A specific filter was selected from the typevariable. Select it and - * open the accessory view */ + /* + * A specific filter was selected from the typevariable. Select it + * and open the accessory view. + */ + [popupButton selectItemAtIndex:filterInfo.fileTypeIndex]; - /* on OSX > 10.11, the optons are not visible by default. Ergo allow all file types + + /* + * On OSX > 10.11, the options are not visible by default. Ergo + * allow all file types [openpanel setAllowedFileTypes:filterInfo.fileTypeExtensions[filterInfo.fileTypeIndex]]; */ [openpanel setAllowedFileTypes:filterInfo.allowedExtensions]; @@ -693,7 +759,10 @@ Tk_GetOpenFileObjCmd( [openpanel setAccessoryView:accessoryView]; } else { - /* No filters are given. Allow picking all files */ + /* + * No filters are given. Allow picking all files. + */ + [openpanel setAllowsOtherFileTypes:YES]; } @@ -711,20 +780,24 @@ Tk_GetOpenFileObjCmd( parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window); if (haveParentOption && parent && ![parent attachedSheet]) { parentIsKey = [parent isKeyWindow]; - if (directory || filename ) { - NSURL * fileURL = getFileURL(directory, filename); + if (directory || filename) { + NSURL *fileURL = getFileURL(directory, filename); + [openpanel setDirectoryURL:fileURL]; } [openpanel beginSheetModalForWindow:parent - completionHandler:^(NSInteger returnCode) - { [NSApp tkFilePanelDidEnd:openpanel + completionHandler:^(NSInteger returnCode) { + [NSApp tkFilePanelDidEnd:openpanel returnCode:returnCode - contextInfo:callbackInfo ]; } ]; - modalReturnCode = cmdObj ? modalOther : [NSApp runModalForWindow:openpanel]; + contextInfo:callbackInfo ]; + }]; + modalReturnCode = cmdObj ? modalOther : + [NSApp runModalForWindow:openpanel]; } else { - if (directory || filename ) { - NSURL * fileURL = getFileURL(directory, filename); + if (directory || filename) { + NSURL *fileURL = getFileURL(directory, filename); + [openpanel setDirectoryURL:fileURL]; } @@ -737,38 +810,50 @@ Tk_GetOpenFileObjCmd( [parent makeKeyWindow]; } - if ((typeVariablePtr && (modalReturnCode == NSOKButton)) && - filterInfo.doFileTypes) { + if ((typeVariablePtr && (modalReturnCode == NSOKButton)) + && filterInfo.doFileTypes) { /* - * The -typevariable must be set to the selected file type, if the dialog was not cancelled + * The -typevariable must be set to the selected file type, if the + * dialog was not cancelled. */ + NSUInteger selectedFilterIndex = filterInfo.fileTypeIndex; NSString *selectedFilter = NULL; + if (filterInfo.userHasSelectedFilter) { selectedFilterIndex = filterInfo.fileTypeIndex; selectedFilter = [filterInfo.fileTypeNames objectAtIndex:selectedFilterIndex]; } else { - /* Difficult case: the user has not touched the filter settings, but we must - * return something in the typevariable. First check if the preselected type is compatible - * with the selected file, otherwise choose the first compatible type from the list, - * finally fall back to the empty string */ + /* + * Difficult case: the user has not touched the filter settings, + * but we must return something in the typevariable. First check if + * the preselected type is compatible with the selected file, + * otherwise choose the first compatible type from the list, + * finally fall back to the empty string. + */ + NSURL *selectedFile; + if (multiple) { - // Use the first file in the case of multiple selection - // Anyway it is not overly useful here + /* + * Use the first file in the case of multiple selection. + * Anyway it is not overly useful here. + */ selectedFile = [[openpanel URLs] objectAtIndex:0]; } else { selectedFile = [openpanel URL]; } NSString *extension = [selectedFile pathExtension]; + if (filterInfo.preselectFilter && - filterCompatible(extension, filterInfo.fileTypeIndex)) { + filterCompatible(extension, filterInfo.fileTypeIndex)) { selectedFilterIndex = filterInfo.fileTypeIndex; // The preselection from the typevariable selectedFilter = [filterInfo.fileTypeNames objectAtIndex:selectedFilterIndex]; } else { // scan the list NSUInteger i; + for (i = 0; i < [filterInfo.fileTypeNames count]; i++) { if (filterCompatible(extension, i)) { selectedFilterIndex = i; @@ -780,19 +865,17 @@ Tk_GetOpenFileObjCmd( } else { selectedFilter = @""; } - } } Tcl_ObjSetVar2(interp, typeVariablePtr, NULL, - Tcl_NewStringObj([selectedFilter UTF8String], -1), TCL_GLOBAL_ONLY); + Tcl_NewStringObj([selectedFilter UTF8String], -1), + TCL_GLOBAL_ONLY); } - end: return result; } - /* *---------------------------------------------------------------------- @@ -807,6 +890,7 @@ Tk_GetOpenFileObjCmd( * * Side effects: * See user documentation. + * *---------------------------------------------------------------------- */ @@ -828,7 +912,7 @@ Tk_GetSaveFileObjCmd( NSString *directory = nil, *filename = nil, *defaultType = nil; NSString *message = nil, *title = nil; NSWindow *parent; - savepanel = [NSSavePanel savePanel]; + savepanel = [NSSavePanel savePanel]; NSInteger modalReturnCode = modalError; BOOL parentIsKey = NO; @@ -906,13 +990,17 @@ Tk_GetSaveFileObjCmd( if (title) { [savepanel setTitle:title]; - /* From OSX 10.11, the title string is silently ignored, if the save panel is a sheet. - * Prepend the title to the message in this case - * NOTE should be conditional on OSX version, but - * -mmacosx-version-min does not revert this behaviour*/ + /* + * From OSX 10.11, the title string is silently ignored, if the save + * panel is a sheet. Prepend the title to the message in this case. + * NOTE: should be conditional on OSX version, but -mmacosx-version-min + * does not revert this behaviour. + */ + if (haveParentOption) { if (message) { - NSString *fullmessage = [[NSString alloc] initWithFormat:@"%@\n%@",title,message]; + NSString *fullmessage = + [[NSString alloc] initWithFormat:@"%@\n%@",title,message]; [message release]; [title release]; message = fullmessage; @@ -932,15 +1020,20 @@ Tk_GetSaveFileObjCmd( } if (filterInfo.doFileTypes) { - NSView *accessoryView = [[NSView alloc] initWithFrame:NSMakeRect(0.0, 0.0, 300, 32.0)]; - NSTextField *label = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 60, 22)]; + NSView *accessoryView = [[NSView alloc] + initWithFrame:NSMakeRect(0.0, 0.0, 300, 32.0)]; + NSTextField *label = [[NSTextField alloc] + initWithFrame:NSMakeRect(0, 0, 60, 22)]; + [label setEditable:NO]; [label setStringValue:NSLocalizedString(@"Format:", nil)]; [label setBordered:NO]; [label setBezeled:NO]; [label setDrawsBackground:NO]; - NSPopUpButton *popupButton = [[NSPopUpButton alloc] initWithFrame:NSMakeRect(50.0, 2, 340, 22.0) pullsDown:NO]; + NSPopUpButton *popupButton = [[NSPopUpButton alloc] + initWithFrame:NSMakeRect(50.0, 2, 340, 22.0) pullsDown:NO]; + [popupButton addItemsWithTitles:filterInfo.fileTypeLabels]; [popupButton selectItemAtIndex:filterInfo.fileTypeIndex]; [popupButton setAction:@selector(saveFormat:)]; @@ -953,10 +1046,14 @@ Tk_GetSaveFileObjCmd( [savepanel setAllowedFileTypes:[filterInfo.fileTypeExtensions objectAtIndex:filterInfo.fileTypeIndex]]; [savepanel setAllowsOtherFileTypes:filterInfo.allowedExtensionsAllowAll]; } else if (defaultType) { - /* If no filetypes are given, defaultextension is an alternative way - * to specify the attached extension. Just propose this extension, - * but don't display an accessory view */ + /* + * If no filetypes are given, defaultextension is an alternative way to + * specify the attached extension. Just propose this extension, but + * don't display an accessory view. + */ + NSMutableArray *AllowedFileTypes = [NSMutableArray array]; + [AllowedFileTypes addObject:defaultType]; [savepanel setAllowedFileTypes:AllowedFileTypes]; [savepanel setAllowsOtherFileTypes:YES]; @@ -978,27 +1075,39 @@ Tk_GetSaveFileObjCmd( parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window); if (haveParentOption && parent && ![parent attachedSheet]) { - parentIsKey = [parent isKeyWindow]; - if (directory) { + parentIsKey = [parent isKeyWindow]; + if (directory) { [savepanel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]]; } - /*check for file name, otherwise set to empty string; crashes with uncaught exception if set to nil*/ + + /* + * Check for file name, otherwise set to empty string; crashes with + * uncaught exception if set to nil. + */ + if (filename) { [savepanel setNameFieldStringValue:filename]; } else { [savepanel setNameFieldStringValue:@""]; } [savepanel beginSheetModalForWindow:parent - completionHandler:^(NSInteger returnCode) - { [NSApp tkFilePanelDidEnd:savepanel + completionHandler:^(NSInteger returnCode) { + [NSApp tkFilePanelDidEnd:savepanel returnCode:returnCode - contextInfo:callbackInfo ]; } ]; - modalReturnCode = cmdObj ? modalOther : [NSApp runModalForWindow:savepanel]; + contextInfo:callbackInfo]; + }]; + modalReturnCode = cmdObj ? modalOther : + [NSApp runModalForWindow:savepanel]; } else { if (directory) { [savepanel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]]; } - /*check for file name, otherwise set to empty string; crashes with uncaught exception if set to nil*/ + + /* + * Check for file name, otherwise set to empty string; crashes with + * uncaught exception if set to nil. + */ + if (filename) { [savepanel setNameFieldStringValue:filename]; } else { @@ -1013,16 +1122,20 @@ Tk_GetSaveFileObjCmd( [parent makeKeyWindow]; } - if ((typeVariablePtr && (modalReturnCode == NSOKButton)) && filterInfo.doFileTypes) { + if (typeVariablePtr && (modalReturnCode == NSOKButton) + && filterInfo.doFileTypes) { /* - * The -typevariable must be set to the selected file type, if the dialog was not cancelled + * The -typevariable must be set to the selected file type, if the + * dialog was not cancelled. */ - NSString * selectedFilter = [filterInfo.fileTypeNames objectAtIndex:filterInfo.fileTypeIndex]; + + NSString *selectedFilter = + [filterInfo.fileTypeNames objectAtIndex:filterInfo.fileTypeIndex]; Tcl_ObjSetVar2(interp, typeVariablePtr, NULL, - Tcl_NewStringObj([selectedFilter UTF8String], -1), TCL_GLOBAL_ONLY); + Tcl_NewStringObj([selectedFilter UTF8String], -1), + TCL_GLOBAL_ONLY); } - end: return result; } @@ -1130,7 +1243,12 @@ Tk_ChooseDirectoryObjCmd( callbackInfo->cmdObj = cmdObj; callbackInfo->interp = interp; callbackInfo->multiple = 0; - /*check for directory value, set to root if not specified; otherwise crashes with exception because of nil string parameter*/ + + /* + * Check for directory value, set to root if not specified; otherwise + * crashes with exception because of nil string parameter. + */ + if (!directory) { directory = @"/"; } @@ -1139,10 +1257,11 @@ Tk_ChooseDirectoryObjCmd( parentIsKey = [parent isKeyWindow]; [panel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]]; [panel beginSheetModalForWindow:parent - completionHandler:^(NSInteger returnCode) - { [NSApp tkFilePanelDidEnd:panel - returnCode:returnCode - contextInfo:callbackInfo ]; } ]; + completionHandler:^(NSInteger returnCode) { + [NSApp tkFilePanelDidEnd:panel + returnCode:returnCode + contextInfo:callbackInfo]; + }]; modalReturnCode = cmdObj ? modalOther : [NSApp runModalForWindow:panel]; } else { [panel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]]; @@ -1201,11 +1320,12 @@ TkAboutDlg(void) */ NSString *version = @"Tcl " TCL_PATCH_LEVEL " & Tk " TCL_PATCH_LEVEL; - NSString *url = @"www.tcl-lang.org"; + NSString *url = @"www.tcl-lang.org"; NSTextView *credits = [[NSTextView alloc] initWithFrame:NSMakeRect(0,0,300,300)]; NSFont *font = [NSFont systemFontOfSize:[NSFont systemFontSize]]; NSDictionary *textAttributes = [NSDictionary dictionaryWithObject:font forKey:NSFontAttributeName]; + [credits insertText: [[NSAttributedString alloc] initWithString:[NSString stringWithFormat: @"\n" "Tcl and Tk are distributed under a modified BSD license: " @@ -1219,11 +1339,13 @@ TkAboutDlg(void) "%1$C 1998-2000 Jim Ingham & Ray Johnson\n\n" "%1$C 1998-2000 Scriptics Inc.\n\n" "%1$C 1996-1997 Sun Microsystems Inc.", 0xA9, year] - attributes:textAttributes] - replacementRange:NSMakeRange(0,0)]; + attributes:textAttributes] + replacementRange:NSMakeRange(0,0)]; [credits setDrawsBackground:NO]; [credits setEditable:NO]; - NSAlert *about = [[NSAlert alloc] init]; + + NSAlert *about = [[NSAlert alloc] init]; + [[about window] setTitle:@"About Tcl & Tk"]; [about setMessageText: version]; [about setInformativeText:url]; @@ -1378,7 +1500,8 @@ Tk_MessageBoxObjCmd( */ if (Tcl_GetIndexFromObjStruct(interp, objv[indexDefaultOption + 1], - alertButtonStrings, sizeof(char *), "-default value", TCL_EXACT, &index) != TCL_OK) { + alertButtonStrings, sizeof(char *), "-default value", + TCL_EXACT, &index) != TCL_OK) { goto end; } @@ -1399,7 +1522,7 @@ Tk_MessageBoxObjCmd( [alert setAlertStyle:alertStyles[iconIndex]]; i = 0; while (i < 3 && alertButtonNames[typeIndex][i]) { - [alert addButtonWithTitle:(NSString*)alertButtonNames[typeIndex][i++]]; + [alert addButtonWithTitle:(NSString*) alertButtonNames[typeIndex][i++]]; } buttons = [alert buttons]; for (NSButton *b in buttons) { @@ -1428,10 +1551,11 @@ Tk_MessageBoxObjCmd( parentIsKey = [parent isKeyWindow]; #if MAC_OS_X_VERSION_MIN_REQUIRED > 1090 [alert beginSheetModalForWindow:parent - completionHandler:^(NSModalResponse returnCode) - { [NSApp tkAlertDidEnd:alert - returnCode:returnCode - contextInfo:callbackInfo ]; } ]; + completionHandler:^(NSModalResponse returnCode) { + [NSApp tkAlertDidEnd:alert + returnCode:returnCode + contextInfo:callbackInfo]; + }]; #else [alert beginSheetModalForWindow:parent modalDelegate:NSApp @@ -1471,7 +1595,10 @@ typedef struct FontchooserData { Tk_Window parent; } FontchooserData; -enum FontchooserEvent { FontchooserClosed, FontchooserSelection }; +enum FontchooserEvent { + FontchooserClosed, + FontchooserSelection +}; static void FontchooserEvent(int kind); static Tcl_Obj * FontchooserCget(FontchooserData *fcdPtr, @@ -1563,8 +1690,8 @@ enum FontchooserOption { * * FontchooserEvent -- * - * This processes events generated by user interaction with the - * font panel. + * This processes events generated by user interaction with the font + * panel. * * Results: * None. @@ -1623,9 +1750,8 @@ FontchooserEvent( * * FontchooserCget -- * - * Helper for the FontchooserConfigure command to return the - * current value of any of the options (which may be NULL in - * the structure) + * Helper for the FontchooserConfigure command to return the current value + * of any of the options (which may be NULL in the structure). * * Results: * Tcl object of option value. @@ -1688,8 +1814,8 @@ FontchooserCget( * * FontchooserConfigureCmd -- * - * Implementation of the 'tk fontchooser configure' ensemble command. - * See the user documentation for what it does. + * Implementation of the 'tk fontchooser configure' ensemble command. See + * the user documentation for what it does. * * Results: * See the user documentation. @@ -1822,7 +1948,8 @@ FontchooserConfigureCmd( [fm setSelectedAttributes:fontPanelFontAttributes isMultiple:NO]; if ([fp isVisible]) { - TkSendVirtualEvent(fcdPtr->parent, "TkFontchooserFontChanged", NULL); + TkSendVirtualEvent(fcdPtr->parent, + "TkFontchooserFontChanged", NULL); } break; case FontchooserCmd: @@ -1850,9 +1977,9 @@ FontchooserConfigureCmd( * * FontchooserShowCmd -- * - * Implements the 'tk fontchooser show' ensemble command. The - * per-interp configuration data for the dialog is held in an interp - * associated structure. + * Implements the 'tk fontchooser show' ensemble command. The per-interp + * configuration data for the dialog is held in an interp associated + * structure. * * Results: * See the user documentation. @@ -1878,8 +2005,10 @@ FontchooserShowCmd( Tk_CreateEventHandler(fcdPtr->parent, StructureNotifyMask, FontchooserParentEventHandler, fcdPtr); } + NSFontManager *fm = [NSFontManager sharedFontManager]; NSFontPanel *fp = [fm fontPanel:YES]; + if ([fp delegate] != NSApp) { [fp setDelegate:NSApp]; } @@ -1897,8 +2026,8 @@ FontchooserShowCmd( * * FontchooserHideCmd -- * - * Implementation of the 'tk fontchooser hide' ensemble. See the - * user documentation for details. + * Implementation of the 'tk fontchooser hide' ensemble. See the user + * documentation for details. * * Results: * See the user documentation. @@ -1917,6 +2046,7 @@ FontchooserHideCmd( Tcl_Obj *const objv[]) { NSFontPanel *fp = [[NSFontManager sharedFontManager] fontPanel:NO]; + if ([fp isVisible]) { [fp orderOut:NSApp]; } @@ -1997,8 +2127,8 @@ DeleteFontchooserData( * * TkInitFontchooser -- * - * Associate the font chooser configuration data with the Tcl - * interpreter. There is one font chooser per interp. + * Associate the font chooser configuration data with the Tcl interpreter. + * There is one font chooser per interp. * * Results: * None. diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c index faad137..dceb3a6 100644 --- a/macosx/tkMacOSXDraw.c +++ b/macosx/tkMacOSXDraw.c @@ -1,9 +1,8 @@ /* * tkMacOSXDraw.c -- * - * This file contains functions that perform drawing to - * Xlib windows. Most of the functions simple emulate - * Xlib functions. + * This file contains functions that perform drawing to Xlib windows. Most + * of the functions simple emulate Xlib functions. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * Copyright 2001-2009, Apple Inc. @@ -31,7 +30,7 @@ #endif */ -#define radians(d) ((d) * (M_PI/180.0)) +#define radians(d) ((d) * (M_PI/180.0)) /* * Non-antialiased CG drawing looks better and more like X11 drawing when using @@ -40,7 +39,7 @@ #define NON_AA_CG_OFFSET .999 static int cgAntiAliasLimit = 0; -#define notAA(w) ((w) < cgAntiAliasLimit) +#define notAA(w) ((w) < cgAntiAliasLimit) static int useThemedToplevel = 0; static int useThemedFrame = 0; @@ -119,24 +118,24 @@ TkMacOSXInitCGDrawing( * replacement is [NSView cacheDisplayInRect: toBitmapImageRep:] and that * is what is being used here. However, that method only works when the * view has a valid CGContext, and a view is only guaranteed to have a - * valid context during a call to [NSView drawRect]. To further - * complicate matters, cacheDisplayInRect calls [NSView drawRect]. - * Essentially it is asking the view to draw a subrectangle of itself into - * a special graphics context which is linked to the BitmapImageRep. But - * our implementation of [NSView drawRect] does not allow recursive calls. - * If called recursively it returns immediately without doing any drawing. + * valid context during a call to [NSView drawRect]. To further complicate + * matters, cacheDisplayInRect calls [NSView drawRect]. Essentially it is + * asking the view to draw a subrectangle of itself into a special + * graphics context which is linked to the BitmapImageRep. But our + * implementation of [NSView drawRect] does not allow recursive calls. If + * called recursively it returns immediately without doing any drawing. * So the bottom line is that this function either returns a NULL pointer - * or a black image. To make it useful would require a significant amount - * of rewriting of the drawRect method. Perhaps the next release of OSX + * or a black image. To make it useful would require a significant amount + * of rewriting of the drawRect method. Perhaps the next release of OSX * will include some more helpful ways of doing this. * * Results: - * Returns an NSBitmapRep representing the image of the given - * rectangle of the given drawable. This object is retained. - * The caller is responsible for releasing it. + * Returns an NSBitmapRep representing the image of the given rectangle of + * the given drawable. This object is retained. The caller is responsible + * for releasing it. * - * NOTE: The x,y coordinates should be relative to a coordinate system with - * origin at the top left, as used by XImage and CGImage, not bottom + * NOTE: The x,y coordinates should be relative to a coordinate system + * with origin at the top left, as used by XImage and CGImage, not bottom * left as used by NSView. * * Side effects: @@ -144,46 +143,46 @@ TkMacOSXInitCGDrawing( * *---------------------------------------------------------------------- */ -NSBitmapImageRep* + +NSBitmapImageRep * TkMacOSXBitmapRepFromDrawableRect( - Drawable drawable, - int x, - int y, - unsigned int width, - unsigned int height) + Drawable drawable, + int x, + int y, + unsigned int width, + unsigned int height) { MacDrawable *mac_drawable = (MacDrawable *) drawable; CGContextRef cg_context = NULL; - CGImageRef cg_image=NULL, sub_cg_image = NULL; + CGImageRef cg_image = NULL, sub_cg_image = NULL; NSBitmapImageRep *bitmap_rep = NULL; - NSView *view=NULL; - if ( mac_drawable->flags & TK_IS_PIXMAP ) { - + NSView *view = NULL; + if (mac_drawable->flags & TK_IS_PIXMAP) { /* * This MacDrawable is a bitmap, so its view is NULL. */ - cg_context = TkMacOSXGetCGContextForDrawable(drawable); CGRect image_rect = CGRectMake(x, y, width, height); - cg_image = CGBitmapContextCreateImage( (CGContextRef) cg_context); + + cg_context = TkMacOSXGetCGContextForDrawable(drawable); + cg_image = CGBitmapContextCreateImage((CGContextRef) cg_context); sub_cg_image = CGImageCreateWithImageInRect(cg_image, image_rect); - if ( sub_cg_image ) { + if (sub_cg_image) { bitmap_rep = [NSBitmapImageRep alloc]; [bitmap_rep initWithCGImage:sub_cg_image]; } - if ( cg_image ) { + if (cg_image) { CGImageRelease(cg_image); } - } else if ( (view = TkMacOSXDrawableView(mac_drawable)) ) { - + } else if ((view = TkMacOSXDrawableView(mac_drawable)) != NULL) { /* * Convert Tk top-left to NSView bottom-left coordinates. */ int view_height = [view bounds].size.height; NSRect view_rect = NSMakeRect(x + mac_drawable->xOff, - view_height - height - y - mac_drawable->yOff, - width, height); + view_height - height - y - mac_drawable->yOff, + width, height); /* * Attempt to copy from the view to a bitmapImageRep. If the view does @@ -218,8 +217,7 @@ TkMacOSXBitmapRepFromDrawableRect( * None. * * Side effects: - * Data is moved from a window or bitmap to a second window or - * bitmap. + * Data is moved from a window or bitmap to a second window or bitmap. * *---------------------------------------------------------------------- */ @@ -229,10 +227,10 @@ XCopyArea( Display *display, /* Display. */ Drawable src, /* Source drawable. */ Drawable dst, /* Destination drawable. */ - GC gc, /* GC to use. */ + GC gc, /* GC to use. */ int src_x, /* X & Y, width & height */ int src_y, /* define the source rectangle */ - unsigned int width, /* that will be copied. */ + unsigned int width, /* that will be copied. */ unsigned int height, int dest_x, /* Dest X & Y on dest rect. */ int dest_y) @@ -249,37 +247,36 @@ XCopyArea( } if (!TkMacOSXSetupDrawingContext(dst, gc, 1, &dc)) { - return; TkMacOSXDbgMsg("Failed to setup drawing context."); + return; } - if ( dc.context ) { - if (srcDraw->flags & TK_IS_PIXMAP) { - img = TkMacOSXCreateCGImageWithDrawable(src); - }else if (TkMacOSXDrawableWindow(src)) { - bitmap_rep = TkMacOSXBitmapRepFromDrawableRect(src, - src_x, src_y, width, height); - if ( bitmap_rep ) { - img = [bitmap_rep CGImage]; - } - } else { - TkMacOSXDbgMsg("Invalid source drawable - neither window nor pixmap."); - } + if (!dc.context) { + TkMacOSXDbgMsg("Invalid destination drawable - no context."); + return; + } - if (img) { - bounds = CGRectMake(0, 0, srcDraw->size.width, srcDraw->size.height); - srcRect = CGRectMake(src_x, src_y, width, height); - dstRect = CGRectMake(dest_x, dest_y, width, height); - TkMacOSXDrawCGImage(dst, gc, dc.context, img, - gc->foreground, gc->background, bounds, srcRect, dstRect); - CFRelease(img); - } else { - TkMacOSXDbgMsg("Failed to construct CGImage."); + if (srcDraw->flags & TK_IS_PIXMAP) { + img = TkMacOSXCreateCGImageWithDrawable(src); + } else if (TkMacOSXDrawableWindow(src)) { + bitmap_rep = TkMacOSXBitmapRepFromDrawableRect(src, + src_x, src_y, width, height); + if (bitmap_rep) { + img = [bitmap_rep CGImage]; } + } else { + TkMacOSXDbgMsg("Invalid source drawable - neither window nor pixmap."); + } + if (img) { + bounds = CGRectMake(0, 0, srcDraw->size.width, srcDraw->size.height); + srcRect = CGRectMake(src_x, src_y, width, height); + dstRect = CGRectMake(dest_x, dest_y, width, height); + TkMacOSXDrawCGImage(dst, gc, dc.context, img, + gc->foreground, gc->background, bounds, srcRect, dstRect); + CFRelease(img); } else { - TkMacOSXDbgMsg("Invalid destination drawable - no context."); - return; + TkMacOSXDbgMsg("Failed to construct CGImage."); } TkMacOSXRestoreDrawingContext(&dc); @@ -290,10 +287,9 @@ XCopyArea( * * XCopyPlane -- * - * Copies a bitmap from a source drawable to a destination - * drawable. The plane argument specifies which bit plane of - * the source contains the bitmap. Note that this implementation - * ignores the gc->function. + * Copies a bitmap from a source drawable to a destination drawable. The + * plane argument specifies which bit plane of the source contains the + * bitmap. Note that this implementation ignores the gc->function. * * Results: * None. @@ -334,29 +330,50 @@ XCopyPlane( if (!TkMacOSXSetupDrawingContext(dst, gc, 1, &dc)) { return; } + CGContextRef context = dc.context; + if (context) { CGImageRef img = TkMacOSXCreateCGImageWithDrawable(src); + if (img) { TkpClipMask *clipPtr = (TkpClipMask *) gc->clip_mask; unsigned long imageBackground = gc->background; - if (clipPtr && clipPtr->type == TKP_CLIP_PIXMAP){ + + if (clipPtr && clipPtr->type == TKP_CLIP_PIXMAP) { srcRect = CGRectMake(src_x, src_y, width, height); - CGImageRef mask = TkMacOSXCreateCGImageWithDrawable(clipPtr->value.pixmap); - CGImageRef submask = CGImageCreateWithImageInRect(img, srcRect); + CGImageRef mask = TkMacOSXCreateCGImageWithDrawable( + clipPtr->value.pixmap); + CGImageRef submask = CGImageCreateWithImageInRect( + img, srcRect); CGRect rect = CGRectMake(dest_x, dest_y, width, height); + rect = CGRectOffset(rect, dstDraw->xOff, dstDraw->yOff); CGContextSaveGState(context); - /* Move the origin of the destination to top left. */ - CGContextTranslateCTM(context, 0, rect.origin.y + CGRectGetMaxY(rect)); + + /* + * Move the origin of the destination to top left. + */ + + CGContextTranslateCTM(context, + 0, rect.origin.y + CGRectGetMaxY(rect)); CGContextScaleCTM(context, 1, -1); - /* Fill with the background color, clipping to the mask. */ + + /* + * Fill with the background color, clipping to the mask. + */ + CGContextClipToMask(context, rect, submask); TkMacOSXSetColorInContext(gc, gc->background, dc.context); CGContextFillRect(context, rect); - /* Fill with the foreground color, clipping to the - intersection of img and mask. */ - CGImageRef subimage = CGImageCreateWithImageInRect(img, srcRect); + + /* + * Fill with the foreground color, clipping to the + * intersection of img and mask. + */ + + CGImageRef subimage = CGImageCreateWithImageInRect( + img, srcRect); CGContextClipToMask(context, rect, subimage); TkMacOSXSetColorInContext(gc, gc->foreground, context); CGContextFillRect(context, rect); @@ -366,22 +383,31 @@ XCopyPlane( CGImageRelease(submask); CGImageRelease(subimage); } else { - bounds = CGRectMake(0, 0, srcDraw->size.width, srcDraw->size.height); + bounds = CGRectMake(0, 0, + srcDraw->size.width, srcDraw->size.height); srcRect = CGRectMake(src_x, src_y, width, height); dstRect = CGRectMake(dest_x, dest_y, width, height); - TkMacOSXDrawCGImage(dst, gc, dc.context, img, gc->foreground, - imageBackground, bounds, srcRect, dstRect); + TkMacOSXDrawCGImage(dst, gc, dc.context, img, + gc->foreground, imageBackground, bounds, + srcRect, dstRect); CGImageRelease(img); } - } else { /* no image */ + } else { + /* no image */ TkMacOSXDbgMsg("Invalid source drawable"); } } else { - TkMacOSXDbgMsg("Invalid destination drawable - could not get a bitmap context."); + TkMacOSXDbgMsg("Invalid destination drawable - " + "could not get a bitmap context."); } TkMacOSXRestoreDrawingContext(&dc); - } else { /* source drawable is a window, not a Pixmap */ - XCopyArea(display, src, dst, gc, src_x, src_y, width, height, dest_x, dest_y); + } else { + /* + * Source drawable is a Window, not a Pixmap. + */ + + XCopyArea(display, src, dst, gc, src_x, src_y, width, height, + dest_x, dest_y); } } @@ -430,7 +456,7 @@ TkMacOSXCreateCGImageWithDrawable( *---------------------------------------------------------------------- */ -static NSImage* +static NSImage * CreateNSImageWithPixmap( Pixmap pixmap, int width, @@ -466,7 +492,7 @@ CreateNSImageWithPixmap( *---------------------------------------------------------------------- */ -NSImage* +NSImage * TkMacOSXGetNSImageWithTkImage( Display *display, Tk_Image image, @@ -499,7 +525,7 @@ TkMacOSXGetNSImageWithTkImage( *---------------------------------------------------------------------- */ -NSImage* +NSImage * TkMacOSXGetNSImageWithBitmap( Display *display, Pixmap bitmap, @@ -550,23 +576,24 @@ TkMacOSXGetCGContextForDrawable( CGColorSpaceRef colorspace = NULL; CGBitmapInfo bitmapInfo = #ifdef __LITTLE_ENDIAN__ - kCGBitmapByteOrder32Host; + kCGBitmapByteOrder32Host; #else - kCGBitmapByteOrderDefault; + kCGBitmapByteOrderDefault; #endif char *data; - CGRect bounds = CGRectMake(0, 0, macDraw->size.width, macDraw->size.height); + CGRect bounds = CGRectMake(0, 0, + macDraw->size.width, macDraw->size.height); if (macDraw->flags & TK_IS_BW_PIXMAP) { bitsPerPixel = 8; - bitmapInfo = (CGBitmapInfo)kCGImageAlphaOnly; + bitmapInfo = (CGBitmapInfo) kCGImageAlphaOnly; } else { colorspace = CGColorSpaceCreateDeviceRGB(); bitsPerPixel = 32; bitmapInfo |= kCGImageAlphaPremultipliedFirst; } - bytesPerRow = ((size_t) macDraw->size.width * bitsPerPixel + 127) >> 3 - & ~15; + bytesPerRow = ((size_t) + macDraw->size.width * bitsPerPixel + 127) >> 3 & ~15; len = macDraw->size.height * bytesPerRow; data = ckalloc(len); bzero(data, len); @@ -630,8 +657,8 @@ TkMacOSXDrawCGImage( dstBounds = CGRectOffset(dstBounds, macDraw->xOff, macDraw->yOff); if (CGImageIsMask(image)) { if (macDraw->flags & TK_IS_BW_PIXMAP) { - - /* Set fill color to black; background comes from the context, + /* + * Set fill color to black; background comes from the context, * or is transparent. */ @@ -655,11 +682,13 @@ TkMacOSXDrawCGImage( CGContextSetRGBFillColor(context, 0, 1, 0, 0.1); CGContextFillRect(context, dstBounds); CGContextStrokeRect(context, dstBounds); + CGPoint p[4] = {dstBounds.origin, CGPointMake(CGRectGetMaxX(dstBounds), CGRectGetMaxY(dstBounds)), CGPointMake(CGRectGetMinX(dstBounds), CGRectGetMaxY(dstBounds)), CGPointMake(CGRectGetMaxX(dstBounds), CGRectGetMinY(dstBounds)) }; + CGContextStrokeLineSegments(context, p, 4); CGContextRestoreGState(context); TkMacOSXDbgMsg("Drawing CGImage at (x=%f, y=%f), (w=%f, h=%f)", @@ -736,12 +765,13 @@ XDrawLines( CGContextAddLineToPoint(dc.context, prevx, prevy); } } + /* - * In the case of closed polylines, the first and last points - * are the same. We want miter or bevel join be rendered also - * at this point, this needs telling CoreGraphics that the - * path is closed. + * In the case of closed polylines, the first and last points are the + * same. We want miter or bevel join be rendered also at this point, + * this needs telling CoreGraphics that the path is closed. */ + if ((points[0].x == points[npoints-1].x) && (points[0].y == points[npoints-1].y)) { CGContextClosePath(dc.context); @@ -820,10 +850,10 @@ XDrawSegments( void XFillPolygon( - Display* display, /* Display. */ + Display *display, /* Display. */ Drawable d, /* Draw on this. */ GC gc, /* Use this GC. */ - XPoint* points, /* Array of points. */ + XPoint *points, /* Array of points. */ int npoints, /* Number of points. */ int shape, /* Shape to draw. */ int mode) /* Drawing mode. */ @@ -902,8 +932,7 @@ XDrawRectangle( double o = (lw % 2) ? .5 : 0; rect = CGRectMake( - macWin->xOff + x + o, - macWin->yOff + y + o, + macWin->xOff + x + o, macWin->yOff + y + o, width, height); CGContextStrokeRect(dc.context, rect); } @@ -916,17 +945,15 @@ XDrawRectangle( * * XDrawRectangles -- * - * Draws the outlines of the specified rectangles as if a - * five-point PolyLine protocol request were specified for each - * rectangle: + * Draws the outlines of the specified rectangles as if a five-point + * PolyLine protocol request were specified for each rectangle: * * [x,y] [x+width,y] [x+width,y+height] [x,y+height] [x,y] * - * For the specified rectangles, these functions do not draw a - * pixel more than once. XDrawRectangles draws the rectangles in - * the order listed in the array. If rectangles intersect, the - * intersecting pixels are drawn multiple times. Draws a - * rectangle. + * For the specified rectangles, these functions do not draw a pixel more + * than once. XDrawRectangles draws the rectangles in the order listed in + * the array. If rectangles intersect, the intersecting pixels are drawn + * multiple times. Draws a rectangle. * * Results: * None. @@ -991,7 +1018,7 @@ XDrawRectangles( int XFillRectangles( - Display* display, /* Display. */ + Display *display, /* Display. */ Drawable d, /* Draw on this. */ GC gc, /* Use this GC. */ XRectangle *rectangles, /* Rectangle array. */ @@ -1042,7 +1069,7 @@ XFillRectangles( void XDrawArc( - Display* display, /* Display. */ + Display *display, /* Display. */ Drawable d, /* Draw on this. */ GC gc, /* Use this GC. */ int x, int y, /* Upper left of bounding rect. */ @@ -1099,14 +1126,13 @@ XDrawArc( * * XDrawArcs -- * - * Draws multiple circular or elliptical arcs. Each arc is - * specified by a rectangle and two angles. The center of the - * circle or ellipse is the center of the rect- angle, and the - * major and minor axes are specified by the width and height. - * Positive angles indicate counterclock- wise motion, and - * negative angles indicate clockwise motion. If the magnitude - * of angle2 is greater than 360 degrees, XDrawArcs truncates it - * to 360 degrees. + * Draws multiple circular or elliptical arcs. Each arc is specified by a + * rectangle and two angles. The center of the circle or ellipse is the + * center of the rect- angle, and the major and minor axes are specified + * by the width and height. Positive angles indicate counterclock- wise + * motion, and negative angles indicate clockwise motion. If the magnitude + * of angle2 is greater than 360 degrees, XDrawArcs truncates it to 360 + * degrees. * * Results: * None. @@ -1125,7 +1151,6 @@ XDrawArcs( XArc *arcArr, int nArcs) { - MacDrawable *macWin = (MacDrawable *) d; TkMacOSXDrawingContext dc; XArc *arcPtr; @@ -1195,7 +1220,7 @@ XDrawArcs( void XFillArc( - Display* display, /* Display. */ + Display *display, /* Display. */ Drawable d, /* Draw on this. */ GC gc, /* Use this GC. */ int x, int y, /* Upper left of bounding rect. */ @@ -1360,13 +1385,12 @@ XMaxRequestSize( * * TkScrollWindow -- * - * Scroll a rectangle of the specified window and accumulate - * a damage region. + * Scroll a rectangle of the specified window and accumulate a damage + * region. * * Results: - * Returns 0 if the scroll generated no additional damage. - * Otherwise, sets the region that needs to be repainted after - * scrolling and returns 1. + * Returns 0 if the scroll generated no additional damage. Otherwise, sets + * the region that needs to be repainted after scrolling and returns 1. * * Side effects: * Scrolls the bits in the window. @@ -1385,47 +1409,63 @@ TkScrollWindow( { Drawable drawable = Tk_WindowId(tkwin); MacDrawable *macDraw = (MacDrawable *) drawable; - TKContentView *view = (TKContentView *)TkMacOSXDrawableView(macDraw); + TKContentView *view = (TKContentView *) TkMacOSXDrawableView(macDraw); CGRect srcRect, dstRect; HIShapeRef dmgRgn = NULL, extraRgn = NULL; NSRect bounds, visRect, scrollSrc, scrollDst; int result = 0; - if ( view ) { - /* Get the scroll area in NSView coordinates (origin at bottom left). */ + if (view) { + /* + * Get the scroll area in NSView coordinates (origin at bottom left). + */ + bounds = [view bounds]; scrollSrc = NSMakeRect(macDraw->xOff + x, - bounds.size.height - height - (macDraw->yOff + y), - width, height); + bounds.size.height - height - (macDraw->yOff + y), + width, height); scrollDst = NSOffsetRect(scrollSrc, dx, -dy); - /* Limit scrolling to the window content area. */ + /* + * Limit scrolling to the window content area. + */ + visRect = [view visibleRect]; scrollSrc = NSIntersectionRect(scrollSrc, visRect); scrollDst = NSIntersectionRect(scrollDst, visRect); - if ( !NSIsEmptyRect(scrollSrc) && !NSIsEmptyRect(scrollDst) ) { + if (!NSIsEmptyRect(scrollSrc) && !NSIsEmptyRect(scrollDst)) { /* * Mark the difference between source and destination as damaged. - * This region is described in NSView coordinates (y=0 at the bottom) - * and converted to Tk coordinates later. + * This region is described in NSView coordinates (y=0 at the + * bottom) and converted to Tk coordinates later. */ srcRect = CGRectMake(x, y, width, height); dstRect = CGRectOffset(srcRect, dx, dy); - /* Compute the damage. */ + /* + * Compute the damage. + */ + dmgRgn = HIShapeCreateMutableWithRect(&srcRect); extraRgn = HIShapeCreateWithRect(&dstRect); - ChkErr(HIShapeDifference, dmgRgn, extraRgn, (HIMutableShapeRef) dmgRgn); + ChkErr(HIShapeDifference, dmgRgn, extraRgn, + (HIMutableShapeRef) dmgRgn); result = HIShapeIsEmpty(dmgRgn) ? 0 : 1; - /* Convert to Tk coordinates, offset by the window origin. */ + /* + * Convert to Tk coordinates, offset by the window origin. + */ + TkMacOSXSetWithNativeRegion(damageRgn, dmgRgn); if (extraRgn) { CFRelease(extraRgn); } - /* Scroll the rectangle. */ + /* + * Scroll the rectangle. + */ + [view scrollRect:scrollSrc by:NSMakeSize(dx, -dy)]; } } else { @@ -1472,8 +1512,8 @@ TkMacOSXSetUpGraphicsPort( * Set up a drawing context for the given drawable and GC. * * Results: - * Boolean indicating whether it is ok to draw; if false, drawing - * context was not setup, so do not attempt to draw and do not call + * Boolean indicating whether it is ok to draw; if false, drawing context + * was not setup, so do not attempt to draw and do not call * TkMacOSXRestoreDrawingContext(). * * Side effects: @@ -1486,18 +1526,18 @@ Bool TkMacOSXSetupDrawingContext( Drawable d, GC gc, - int useCG, /* advisory only ! */ + int useCG, /* advisory only ! */ TkMacOSXDrawingContext *dcPtr) { - MacDrawable *macDraw = ((MacDrawable*)d); + MacDrawable *macDraw = (MacDrawable *) d; Bool canDraw = true; NSWindow *win = NULL; TkMacOSXDrawingContext dc = {}; CGRect clipBounds; /* - * If the drawable is not a pixmap and it has an associated - * NSWindow then we know we are drawing to a window. + * If the drawable is not a pixmap and it has an associated NSWindow then + * we know we are drawing to a window. */ if (!(macDraw->flags & TK_IS_PIXMAP)) { @@ -1516,9 +1556,8 @@ TkMacOSXSetupDrawingContext( } /* - * If we already have a CGContext, use it. Otherwise, if we - * are drawing to a window then we can get one from the - * window. + * If we already have a CGContext, use it. Otherwise, if we are drawing to + * a window then we can get one from the window. */ dc.context = TkMacOSXGetCGContextForDrawable(d); @@ -1526,35 +1565,34 @@ TkMacOSXSetupDrawingContext( dc.portBounds = clipBounds = CGContextGetClipBoundingBox(dc.context); } else if (win) { NSView *view = TkMacOSXDrawableView(macDraw); - if (view) { - - /* - * We can only draw into the view when the current CGContext is - * valid and belongs to the view. Validity can only be guaranteed - * inside of a view's drawRect or setFrame methods. The isDrawing - * attribute tells us whether we are being called from one of those - * methods. - * - * If the CGContext is not valid, or belongs to a different View, - * then we mark our view as needing display and return failure. - * It should get drawn in a later call to drawRect. - */ - if (view != [NSView focusView]) { - [view setNeedsDisplay:YES]; - canDraw = false; - goto end; - } - dc.view = view; - dc.context = GET_CGCONTEXT; - dc.portBounds = NSRectToCGRect([view bounds]); - if (dc.clipRgn) { - clipBounds = CGContextGetClipBoundingBox(dc.context); - } - } else { + if (!view) { Tcl_Panic("TkMacOSXSetupDrawingContext(): " "no NSView to draw into !"); } + + /* + * We can only draw into the view when the current CGContext is valid + * and belongs to the view. Validity can only be guaranteed inside of + * a view's drawRect or setFrame methods. The isDrawing attribute + * tells us whether we are being called from one of those methods. + * + * If the CGContext is not valid, or belongs to a different View, then + * we mark our view as needing display and return failure. It should + * get drawn in a later call to drawRect. + */ + + if (view != [NSView focusView]) { + [view setNeedsDisplay:YES]; + canDraw = false; + goto end; + } + dc.view = view; + dc.context = GET_CGCONTEXT; + dc.portBounds = NSRectToCGRect([view bounds]); + if (dc.clipRgn) { + clipBounds = CGContextGetClipBoundingBox(dc.context); + } } else { Tcl_Panic("TkMacOSXSetupDrawingContext(): " "no context to draw into !"); @@ -1565,8 +1603,13 @@ TkMacOSXSetupDrawingContext( */ if (dc.context) { - CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1, .tx = 0, - .ty = dc.portBounds.size.height}; + CGAffineTransform t = { + .a = 1, .b = 0, + .c = 0, .d = -1, + .tx = 0, + .ty = dc.portBounds.size.height + }; + dc.portBounds.origin.x += macDraw->xOff; dc.portBounds.origin.y += macDraw->yOff; CGContextSaveGState(dc.context); @@ -1581,6 +1624,7 @@ TkMacOSXSetupDrawingContext( CGContextRestoreGState(dc.context); #endif /* TK_MAC_DEBUG_DRAWING */ CGRect r; + if (!HIShapeIsRectangular(dc.clipRgn) || !CGRectContainsRect( *HIShapeGetBounds(dc.clipRgn, &r), CGRectApplyAffineTransform(clipBounds, t))) { @@ -1608,21 +1652,28 @@ TkMacOSXSetupDrawingContext( CGContextSetPatternPhase(dc.context, CGSizeMake( dc.portBounds.size.width, dc.portBounds.size.height)); } - if(gc->function != GXcopy) { + if (gc->function != GXcopy) { TkMacOSXDbgMsg("Logical functions other than GXcopy are " "not supported for CG drawing!"); } - /* When should we antialias? */ + + /* + * When should we antialias? + */ + shouldAntialias = !notAA(gc->line_width); if (!shouldAntialias) { - /* Make non-antialiased CG drawing look more like X11 */ + /* + * Make non-antialiased CG drawing look more like X11. + */ + w -= (gc->line_width ? NON_AA_CG_OFFSET : 0); } CGContextSetShouldAntialias(dc.context, shouldAntialias); CGContextSetLineWidth(dc.context, w); if (gc->line_style != LineSolid) { int num = 0; - char *p = &(gc->dashes); + char *p = &gc->dashes; CGFloat dashOffset = gc->dash_offset; CGFloat lengths[10]; @@ -1632,13 +1683,13 @@ TkMacOSXSetupDrawingContext( } CGContextSetLineDash(dc.context, dashOffset, lengths, num); } - if ((unsigned)gc->cap_style < sizeof(cgCap)/sizeof(CGLineCap)) { + if ((unsigned) gc->cap_style < sizeof(cgCap)/sizeof(CGLineCap)) { CGContextSetLineCap(dc.context, - cgCap[(unsigned)gc->cap_style]); + cgCap[(unsigned) gc->cap_style]); } if ((unsigned)gc->join_style < sizeof(cgJoin)/sizeof(CGLineJoin)) { CGContextSetLineJoin(dc.context, - cgJoin[(unsigned)gc->join_style]); + cgJoin[(unsigned) gc->join_style]); } } } @@ -1647,8 +1698,11 @@ end: #ifdef TK_MAC_DEBUG_DRAWING if (!canDraw && win != NULL) { TkWindow *winPtr = TkMacOSXGetTkWindow(win); - if (winPtr) fprintf(stderr, "Cannot draw in %s - postponing.\n", - Tk_PathName(winPtr)); + + if (winPtr) { + fprintf(stderr, "Cannot draw in %s - postponing.\n", + Tk_PathName(winPtr)); + } } #endif if (!canDraw && dc.clipRgn) { @@ -1719,7 +1773,9 @@ TkMacOSXGetClipRgn( TkMacOSXUpdateClipRgn(macDraw->winPtr); #ifdef TK_MAC_DEBUG_DRAWING TkMacOSXDbgMsg("%s", macDraw->winPtr->pathName); + NSView *view = TkMacOSXDrawableView(macDraw); + CGContextSaveGState(context); CGContextConcatCTM(context, CGAffineTransformMake(1.0, 0.0, 0.0, -1.0, 0.0, [view bounds].size.height)); @@ -1743,8 +1799,8 @@ TkMacOSXGetClipRgn( * * TkMacOSXSetUpClippingRgn -- * - * Set up the clipping region so that drawing only occurs on the - * specified X subwindow. + * Set up the clipping region so that drawing only occurs on the specified + * X subwindow. * * Results: * None. @@ -1766,8 +1822,8 @@ TkMacOSXSetUpClippingRgn( * * TkpClipDrawableToRect -- * - * Clip all drawing into the drawable d to the given rectangle. - * If width or height are negative, reset to no clipping. + * Clip all drawing into the drawable d to the given rectangle. If width + * or height are negative, reset to no clipping. * * Results: * None. @@ -1832,8 +1888,8 @@ ClipToGC( HIShapeRef *clipRgnPtr) /* must point to initialized variable */ { if (gc && gc->clip_mask && - ((TkpClipMask*)gc->clip_mask)->type == TKP_CLIP_REGION) { - TkRegion gcClip = ((TkpClipMask*)gc->clip_mask)->value.region; + ((TkpClipMask *) gc->clip_mask)->type == TKP_CLIP_REGION) { + TkRegion gcClip = ((TkpClipMask *) gc->clip_mask)->value.region; int xOffset = ((MacDrawable *) d)->xOff + gc->clip_x_origin; int yOffset = ((MacDrawable *) d)->yOff + gc->clip_y_origin; HIShapeRef clipRgn = *clipRgnPtr, gcClipRgn; @@ -1856,10 +1912,9 @@ ClipToGC( * * TkMacOSXMakeStippleMap -- * - * Given a drawable and a stipple pattern this function draws the - * pattern repeatedly over the drawable. The drawable can then - * be used as a mask for bit-bliting a stipple pattern over an - * object. + * Given a drawable and a stipple pattern this function draws the pattern + * repeatedly over the drawable. The drawable can then be used as a mask + * for bit-bliting a stipple pattern over an object. * * Results: * A BitMap data structure. @@ -1883,12 +1938,12 @@ TkMacOSXMakeStippleMap( * * TkpDrawHighlightBorder -- * - * This procedure draws a rectangular ring around the outside of - * a widget to indicate that it has received the input focus. + * This procedure draws a rectangular ring around the outside of a widget + * to indicate that it has received the input focus. * - * On the Macintosh, this puts a 1 pixel border in the bgGC color - * between the widget and the focus ring, except in the case where - * highlightWidth is 1, in which case the border is left out. + * On the Macintosh, this puts a 1 pixel border in the bgGC color between + * the widget and the focus ring, except in the case where highlightWidth + * is 1, in which case the border is left out. * * For proper Mac L&F, use highlightWidth of 3. * @@ -1896,8 +1951,8 @@ TkMacOSXMakeStippleMap( * None. * * Side effects: - * A rectangle "width" pixels wide is drawn in "drawable", - * corresponding to the outer area of "tkwin". + * A rectangle "width" pixels wide is drawn in "drawable", corresponding + * to the outer area of "tkwin". * *---------------------------------------------------------------------- */ @@ -1926,8 +1981,8 @@ TkpDrawHighlightBorder ( * * TkpDrawFrame -- * - * This procedure draws the rectangular frame area. If the user - * has requested themeing, it draws with the background theme. + * This procedure draws the rectangular frame area. If the user has + * requested themeing, it draws with the background theme. * * Results: * None. diff --git a/macosx/tkMacOSXEmbed.c b/macosx/tkMacOSXEmbed.c index 932d4cb..79a2094 100644 --- a/macosx/tkMacOSXEmbed.c +++ b/macosx/tkMacOSXEmbed.c @@ -334,15 +334,15 @@ TkpUseWindow( macWin->flags |= TK_EMBEDDED; macWin->xOff = parent->winPtr->privatePtr->xOff + - parent->winPtr->changes.border_width + - winPtr->changes.x; + parent->winPtr->changes.border_width + + winPtr->changes.x; macWin->yOff = parent->winPtr->privatePtr->yOff + - parent->winPtr->changes.border_width + - winPtr->changes.y; + parent->winPtr->changes.border_width + + winPtr->changes.y; /* - * Finish filling up the container structure with the embedded - * window's information. + * Finish filling up the container structure with the embedded window's + * information. */ containerPtr->embedded = (Window) macWin; @@ -353,8 +353,8 @@ TkpUseWindow( * tkwin is eventually deleted. */ - Tk_CreateEventHandler(tkwin, StructureNotifyMask, EmbeddedEventProc, - winPtr); + Tk_CreateEventHandler(tkwin, StructureNotifyMask, + EmbeddedEventProc, winPtr); return TCL_OK; } @@ -588,7 +588,11 @@ TkpTestembedCmd( continue; } Tcl_DStringStartSublist(&dString); - /* Parent id */ + + /* + * Parent id + */ + if (containerPtr->parent == None) { Tcl_DStringAppendElement(&dString, ""); } else if (all) { @@ -597,7 +601,11 @@ TkpTestembedCmd( } else { Tcl_DStringAppendElement(&dString, "XXX"); } - /* Parent pathName */ + + /* + * Parent pathName + */ + if (containerPtr->parentPtr == NULL || parentInterp != interp) { Tcl_DStringAppendElement(&dString, ""); @@ -605,11 +613,17 @@ TkpTestembedCmd( Tcl_DStringAppendElement(&dString, containerPtr->parentPtr->pathName); } + /* * On X11 embedded is a wrapper, which does not exist on macOS. */ + Tcl_DStringAppendElement(&dString, ""); - /* Embedded window pathName */ + + /* + * Embedded window pathName + */ + if (containerPtr->embeddedPtr == NULL || embeddedInterp != interp) { Tcl_DStringAppendElement(&dString, ""); @@ -768,6 +782,7 @@ ContainerEventProc( /* * When the interpreter is being dismantled this can be nil. */ + return; } @@ -920,6 +935,7 @@ EmbedActivateProc( XEvent *eventPtr) /* ResizeRequest event. */ { Container *containerPtr = clientData; + if (containerPtr->embeddedPtr != NULL) { if (eventPtr->type == ActivateNotify) { TkGenerateActivateEvents(containerPtr->embeddedPtr,1); @@ -1024,11 +1040,10 @@ EmbedGeometryRequest( /* * Forward the requested size into our geometry management hierarchy via * the container window. We need to send a Configure event back to the - * embedded application if we decide not to honor its request; to make - * this happen, process all idle event handlers synchronously here (so - * that the geometry managers have had a chance to do whatever they want - * to do), and if the window's size didn't change then generate a - * configure event. + * embedded application if we decide not to honor its request; to make this + * happen, process all idle event handlers synchronously here (so that the + * geometry managers have had a chance to do whatever they want to do), and + * if the window's size didn't change then generate a configure event. */ Tk_GeometryRequest((Tk_Window) winPtr, width, height); @@ -1050,8 +1065,8 @@ EmbedGeometryRequest( * application of its current size and location. This procedure is called * when the embedded application made a geometry request that we did not * grant, so that the embedded application knows that its geometry didn't - * change after all. It is a response to ConfigureRequest events, which - * we do not currently synthesize on the Mac + * change after all. It is a response to ConfigureRequest events, which we + * do not currently synthesize on the Mac * * Results: * None. @@ -1111,8 +1126,8 @@ EmbedWindowDeleted( containerPtr->parentPtr->flags & TK_BOTH_HALVES) { XEvent event; - event.xany.serial = - LastKnownRequestProcessed(Tk_Display(containerPtr->parentPtr)); + event.xany.serial = LastKnownRequestProcessed( + Tk_Display(containerPtr->parentPtr)); event.xany.send_event = False; event.xany.display = Tk_Display(containerPtr->parentPtr); diff --git a/macosx/tkMacOSXFont.c b/macosx/tkMacOSXFont.c index 353ad6b..0e05ae5 100644 --- a/macosx/tkMacOSXFont.c +++ b/macosx/tkMacOSXFont.c @@ -1,8 +1,8 @@ /* * tkMacOSXFont.c -- * - * Contains the Macintosh implementation of the platform-independant - * font package interface. + * Contains the Macintosh implementation of the platform-independant font + * package interface. * * Copyright 2002-2004 Benjamin Riefenstahl, Benjamin.Riefenstahl@epost.de * Copyright (c) 2006-2009 Daniel A. Steffen @@ -32,9 +32,8 @@ */ typedef struct { - TkFont font; /* Stuff used by generic font package. Must - * be first in structure. */ - + TkFont font; /* Stuff used by generic font package. Must be + * first in structure. */ NSFont *nsFont; NSDictionary *nsAttributes; } MacFont; @@ -83,17 +82,21 @@ static int antialiasedTextEnabled = -1; static NSCharacterSet *whitespaceCharacterSet = nil; static NSCharacterSet *lineendingCharacterSet = nil; -static void GetTkFontAttributesForNSFont(NSFont *nsFont, - TkFontAttributes *faPtr); -static NSFont *FindNSFont(const char *familyName, NSFontTraitMask traits, - NSInteger weight, CGFloat size, int fallbackToDefault); -static void InitFont(NSFont *nsFont, const TkFontAttributes *reqFaPtr, - MacFont * fontPtr); -static int CreateNamedSystemFont(Tcl_Interp *interp, Tk_Window tkwin, - const char* name, TkFontAttributes *faPtr); -static void DrawCharsInContext(Display *display, Drawable drawable, GC gc, - Tk_Font tkfont, const char *source, int numBytes, int rangeStart, - int rangeLength, int x, int y, double angle); +static void GetTkFontAttributesForNSFont(NSFont *nsFont, + TkFontAttributes *faPtr); +static NSFont * FindNSFont(const char *familyName, + NSFontTraitMask traits, NSInteger weight, + CGFloat size, int fallbackToDefault); +static void InitFont(NSFont *nsFont, + const TkFontAttributes *reqFaPtr, + MacFont *fontPtr); +static int CreateNamedSystemFont(Tcl_Interp *interp, + Tk_Window tkwin, const char *name, + TkFontAttributes *faPtr); +static void DrawCharsInContext(Display *display, Drawable drawable, + GC gc, Tk_Font tkfont, const char *source, + int numBytes, int rangeStart, int rangeLength, + int x, int y, double angle); #pragma mark - #pragma mark Font Helpers: @@ -232,7 +235,7 @@ InitFont( int ascent, descent/*, dontAA*/; static const UniChar ch[] = {'.', 'W', ' ', 0xc4, 0xc1, 0xc2, 0xc3, 0xc7}; /* ., W, Space, Auml, Aacute, Acirc, Atilde, Ccedilla */ - #define nCh (sizeof(ch) / sizeof(UniChar)) +#define nCh (sizeof(ch) / sizeof(UniChar)) CGGlyph glyphs[nCh]; CGRect boundingRects[nCh]; @@ -244,7 +247,11 @@ InitFont( TkInitFontAttributes(faPtr); } fontPtr->nsFont = nsFont; - // some don't like antialiasing on fixed-width even if bigger than limit + + /* + * Some don't like antialiasing on fixed-width even if bigger than limit + */ + // dontAA = [nsFont isFixedPitch] && fontPtr->font.fa.size <= 10; if (antialiasedTextEnabled >= 0/* || dontAA*/) { renderingMode = (antialiasedTextEnabled == 0/* || dontAA*/) ? @@ -294,7 +301,7 @@ InitFont( NSLigatureAttributeName, [NSNumber numberWithDouble:kern], NSKernAttributeName, nil]; fontPtr->nsAttributes = [nsAttributes retain]; - #undef nCh +#undef nCh } /* @@ -358,10 +365,14 @@ TkpFontPkgInit( NSFont *nsFont; TkFontAttributes fa; NSMutableCharacterSet *cs; - /* Since we called before TkpInit, we need our own autorelease pool. */ + /* + * Since we called before TkpInit, we need our own autorelease pool. + */ NSAutoreleasePool *pool = [NSAutoreleasePool new]; - /* force this for now */ + /* + * Force this for now. + */ if (!mainPtr->winPtr->mainPtr) { mainPtr->winPtr->mainPtr = mainPtr; } @@ -413,17 +424,17 @@ TkpFontPkgInit( * Map a platform-specific native font name to a TkFont. * * Results: - * The return value is a pointer to a TkFont that represents the - * native font. If a native font by the given name could not be - * found, the return value is NULL. + * The return value is a pointer to a TkFont that represents the native + * font. If a native font by the given name could not be found, the return + * value is NULL. * - * Every call to this procedure returns a new TkFont structure, even - * if the name has already been seen before. The caller should call + * Every call to this procedure returns a new TkFont structure, even if + * the name has already been seen before. The caller should call * TkpDeleteFont() when the font is no longer needed. * - * The caller is responsible for initializing the memory associated - * with the generic TkFont when this function returns and releasing - * the contents of the generics TkFont before calling TkpDeleteFont(). + * The caller is responsible for initializing the memory associated with + * the generic TkFont when this function returns and releasing the + * contents of the generics TkFont before calling TkpDeleteFont(). * * Side effects: * None. @@ -449,8 +460,8 @@ TkpGetNativeFont( } else { return NULL; } - ctFont = CTFontCreateUIFontForLanguage(HIThemeGetUIFontType( - themeFontId), 0, NULL); + ctFont = CTFontCreateUIFontForLanguage( + HIThemeGetUIFontType(themeFontId), 0, NULL); if (ctFont) { fontPtr = ckalloc(sizeof(MacFont)); InitFont((NSFont*) ctFont, NULL, fontPtr); @@ -468,19 +479,18 @@ TkpGetNativeFont( * closest matching attributes. * * Results: - * The return value is a pointer to a TkFont that represents the font - * with the desired attributes. If a font with the desired attributes - * could not be constructed, some other font will be substituted - * automatically. + * The return value is a pointer to a TkFont that represents the font with + * the desired attributes. If a font with the desired attributes could not + * be constructed, some other font will be substituted automatically. * - * Every call to this procedure returns a new TkFont structure, even - * if the specified attributes have already been seen before. The - * caller should call TkpDeleteFont() to free the platform- specific - * data when the font is no longer needed. + * Every call to this procedure returns a new TkFont structure, even if + * the specified attributes have already been seen before. The caller + * should call TkpDeleteFont() to free the platform- specific data when + * the font is no longer needed. * - * The caller is responsible for initializing the memory associated - * with the generic TkFont when this function returns and releasing - * the contents of the generic TkFont before calling TkpDeleteFont(). + * The caller is responsible for initializing the memory associated with + * the generic TkFont when this function returns and releasing the + * contents of the generic TkFont before calling TkpDeleteFont(). * * Side effects: * None. @@ -492,16 +502,16 @@ TkFont * TkpGetFontFromAttributes( TkFont *tkFontPtr, /* If non-NULL, store the information in this * existing TkFont structure, rather than - * allocating a new structure to hold the - * font; the existing contents of the font - * will be released. If NULL, a new TkFont - * structure is allocated. */ + * allocating a new structure to hold the font; + * the existing contents of the font will be + * released. If NULL, a new TkFont structure is + * allocated. */ Tk_Window tkwin, /* For display where font will be used. */ const TkFontAttributes *faPtr) /* Set of attributes to match. */ { MacFont *fontPtr; - int points = (int)(TkFontGetPoints(tkwin, faPtr->size) + 0.5); + int points = (int) (TkFontGetPoints(tkwin, faPtr->size) + 0.5); NSFontTraitMask traits = GetNSFontTraitsFromTkFontAttributes(faPtr); NSInteger weight = (faPtr->weight == TK_FW_BOLD ? 9 : 5); NSFont *nsFont; @@ -538,9 +548,9 @@ TkpGetFontFromAttributes( * TkpDeleteFont -- * * Called to release a font allocated by TkpGetNativeFont() or - * TkpGetFontFromAttributes(). The caller should have already - * released the fields of the TkFont that are used exclusively by the - * generic TkFont code. + * TkpGetFontFromAttributes(). The caller should have already released the + * fields of the TkFont that are used exclusively by the generic TkFont + * code. * * Results: * TkFont is deallocated. @@ -567,8 +577,8 @@ TkpDeleteFont( * * TkpGetFontFamilies -- * - * Return information about the font families that are available on - * the display of the given window. + * Return information about the font families that are available on the + * display of the given window. * * Results: * Modifies interp's result object to hold a list of all the available @@ -600,12 +610,12 @@ TkpGetFontFamilies( * * TkpGetSubFonts -- * - * A function used by the testing package for querying the actual - * screen fonts that make up a font object. + * A function used by the testing package for querying the actual screen + * fonts that make up a font object. * * Results: - * Modifies interp's result object to hold a list containing the names - * of the screen fonts that make up the given font object. + * Modifies interp's result object to hold a list containing the names of + * the screen fonts that make up the given font object. * * Side effects: * None. @@ -642,8 +652,8 @@ TkpGetSubFonts( * * TkpGetFontAttrsForChar -- * - * Retrieve the font attributes of the actual font used to render a - * given character. + * Retrieve the font attributes of the actual font used to render a given + * character. * * Results: * None. @@ -745,10 +755,9 @@ Tk_MeasureChars( * all the characters on the line for context. * * Results: - * The return value is the number of bytes from source that - * fit into the span that extends from 0 to maxLength. *lengthPtr is - * filled with the x-coordinate of the right edge of the last - * character that did fit. + * The return value is the number of bytes from source that fit into the + * span that extends from 0 to maxLength. *lengthPtr is filled with the + * x-coordinate of the right edge of the last character that did fit. * * Side effects: * None. @@ -774,11 +783,11 @@ TkpMeasureCharsInContext( * TK_PARTIAL_OK means include the last char * which only partially fits on this line. * TK_WHOLE_WORDS means stop on a word - * boundary, if possible. TK_AT_LEAST_ONE - * means return at least one character even - * if no characters fit. If TK_WHOLE_WORDS - * and TK_AT_LEAST_ONE are set and the first - * word doesn't fit, we return at least one + * boundary, if possible. TK_AT_LEAST_ONE means + * return at least one character even if no + * characters fit. If TK_WHOLE_WORDS and + * TK_AT_LEAST_ONE are set and the first word + * doesn't fit, we return at least one * character or whatever characters fit into * maxLength. TK_ISOLATE_END means that the * last character should not be considered in @@ -864,14 +873,13 @@ TkpMeasureCharsInContext( } /* - * If there is no line breakpoint in the source string between - * its start and the index position that fits in maxWidth, then + * If there is no line breakpoint in the source string between its + * start and the index position that fits in maxWidth, then * CTTypesetterSuggestLineBreak() returns that very last index. - * However if the TK_WHOLE_WORDS flag is set, we want to break - * at a word boundary. In this situation, unless TK_AT_LEAST_ONE - * is set, we must report that zero chars actually fit (in other - * words the smallest word of the source string is still larger - * than maxWidth). + * However if the TK_WHOLE_WORDS flag is set, we want to break at a + * word boundary. In this situation, unless TK_AT_LEAST_ONE is set, we + * must report that zero chars actually fit (in other words the + * smallest word of the source string is still larger than maxWidth). */ if ((index >= start) && (index < len) && @@ -903,9 +911,12 @@ TkpMeasureCharsInContext( CFRelease(line); } - /* The call to CTTypesetterSuggestClusterBreak above will always - return at least one character regardless of whether it exceeded - it or not. Clean that up now. */ + /* + * The call to CTTypesetterSuggestClusterBreak above will always return + * at least one character regardless of whether it exceeded it or not. + * Clean that up now. + */ + while (width > maxWidth && !(flags & TK_PARTIAL_OK) && index > start+(flags & TK_AT_LEAST_ONE)) { range.length = --index; @@ -946,7 +957,7 @@ done: * actual implementation in TkpDrawCharsInContext(). * * Results: - * None. + * None. * * Side effects: * Information gets drawn on the screen. @@ -964,8 +975,8 @@ Tk_DrawChars( const char *source, /* UTF-8 string to be displayed. Need not be * '\0' terminated. All Tk meta-characters * (tabs, control characters, and newlines) - * should be stripped out of the string that - * is passed to this function. If they are not + * should be stripped out of the string that is + * passed to this function. If they are not * stripped out, they will be displayed as * regular printing characters. */ int numBytes, /* Number of bytes in string. */ @@ -986,8 +997,8 @@ TkDrawAngledChars( const char *source, /* UTF-8 string to be displayed. Need not be * '\0' terminated. All Tk meta-characters * (tabs, control characters, and newlines) - * should be stripped out of the string that - * is passed to this function. If they are not + * should be stripped out of the string that is + * passed to this function. If they are not * stripped out, they will be displayed as * regular printing characters. */ int numBytes, /* Number of bytes in string. */ @@ -1029,8 +1040,8 @@ TkpDrawCharsInContext( const char * source, /* UTF-8 string to be displayed. Need not be * '\0' terminated. All Tk meta-characters * (tabs, control characters, and newlines) - * should be stripped out of the string that - * is passed to this function. If they are not + * should be stripped out of the string that is + * passed to this function. If they are not * stripped out, they will be displayed as * regular printing characters. */ int numBytes, /* Number of bytes in string. */ @@ -1054,8 +1065,8 @@ DrawCharsInContext( const char * source, /* UTF-8 string to be displayed. Need not be * '\0' terminated. All Tk meta-characters * (tabs, control characters, and newlines) - * should be stripped out of the string that - * is passed to this function. If they are not + * should be stripped out of the string that is + * passed to this function. If they are not * stripped out, they will be displayed as * regular printing characters. */ int numBytes, /* Number of bytes in string. */ @@ -1091,6 +1102,7 @@ DrawCharsInContext( if (!string) { return; } + context = drawingContext.context; fg = TkMacOSXCreateCGColor(gc, gc->foreground); attributes = [fontPtr->nsAttributes mutableCopy]; @@ -1119,6 +1131,7 @@ DrawCharsInContext( len = Tcl_NumUtfChars(source, rangeStart + rangeLength); if (start > 0) { CGRect clipRect = CGRectInfinite, startBounds; + line = CTTypesetterCreateLine(typesetter, CFRangeMake(0, start)); startBounds = CTLineGetImageBounds(line, context); CFRelease(line); @@ -1241,9 +1254,10 @@ TkMacOSXFontDescriptionForNSFontAndNSFontAttributes( NSUnderlineStyleAttributeName]; id strikethrough = [nsAttributes objectForKey: NSStrikethroughStyleAttributeName]; + objv[i++] = Tcl_NewStringObj(familyName, -1); objv[i++] = Tcl_NewIntObj([nsFont pointSize]); -#define S(s) Tcl_NewStringObj(STRINGIFY(s),(int)(sizeof(STRINGIFY(s))-1)) +#define S(s) Tcl_NewStringObj(STRINGIFY(s),(int)(sizeof(STRINGIFY(s))-1)) objv[i++] = (traits & NSBoldFontMask) ? S(bold) : S(normal); objv[i++] = (traits & NSItalicFontMask) ? S(italic) : S(roman); if ([underline respondsToSelector:@selector(intValue)] && @@ -1267,8 +1281,9 @@ TkMacOSXFontDescriptionForNSFontAndNSFontAttributes( * TkMacOSXUseAntialiasedText -- * * Enables or disables application-wide use of antialiased text (where - * available). Sets up a linked Tcl global variable to allow - * disabling of antialiased text from tcl. + * available). Sets up a linked Tcl global variable to allow disabling of + * antialiased text from Tcl. + * * The possible values for this variable are: * * -1 - Use system default as configurable in "System Prefs" -> "General". diff --git a/macosx/tkMacOSXImage.c b/macosx/tkMacOSXImage.c index 38f4a70..36f1fc6 100644 --- a/macosx/tkMacOSXImage.c +++ b/macosx/tkMacOSXImage.c @@ -23,7 +23,7 @@ _XInitImageFuncPtrs( { return 0; } - + /* *---------------------------------------------------------------------- * @@ -81,14 +81,15 @@ TkMacOSXCreateCGImageWithXImage( data = memcpy(ckalloc(len), image->data + image->xoffset, len); } if (data) { - provider = CGDataProviderCreateWithData(data, data, len, releaseData); + provider = CGDataProviderCreateWithData(data, data, len, + releaseData); } if (provider) { - img = CGImageMaskCreate(image->width, image->height, bitsPerComponent, - bitsPerPixel, image->bytes_per_line, provider, decode, 0); + img = CGImageMaskCreate(image->width, image->height, + bitsPerComponent, bitsPerPixel, image->bytes_per_line, + provider, decode, 0); } - } else if (image->format == ZPixmap && image->bits_per_pixel == 32) { - + } else if ((image->format == ZPixmap) && (image->bits_per_pixel == 32)) { /* * Color image */ @@ -96,7 +97,6 @@ TkMacOSXCreateCGImageWithXImage( CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); if (image->width == 0 && image->height == 0) { - /* * CGCreateImage complains on early macOS releases. */ @@ -106,11 +106,12 @@ TkMacOSXCreateCGImageWithXImage( bitsPerComponent = 8; bitsPerPixel = 32; bitmapInfo = (image->byte_order == MSBFirst ? - kCGBitmapByteOrder32Little : kCGBitmapByteOrder32Big); + kCGBitmapByteOrder32Little : kCGBitmapByteOrder32Big); bitmapInfo |= kCGImageAlphaLast; data = memcpy(ckalloc(len), image->data + image->xoffset, len); if (data) { - provider = CGDataProviderCreateWithData(data, data, len, releaseData); + provider = CGDataProviderCreateWithData(data, data, len, + releaseData); } if (provider) { img = CGImageCreate(image->width, image->height, bitsPerComponent, @@ -127,7 +128,6 @@ TkMacOSXCreateCGImageWithXImage( return img; } - /* *---------------------------------------------------------------------- * @@ -179,15 +179,14 @@ XGetImage( if (win && has_retina == unknown) { #ifdef __clang__ - has_retina = [win respondsToSelector:@selector(backingScaleFactor)]? - yes : no; + has_retina = [win respondsToSelector:@selector(backingScaleFactor)] ? + yes : no; #else has_retina = no; #endif } if (has_retina == yes) { - /* * We only allow scale factors 1 or 2, as Apple currently does. */ @@ -205,7 +204,7 @@ XGetImage( } bitmap_rep = TkMacOSXBitmapRepFromDrawableRect(drawable, - x, y, width, height); + x, y, width, height); if (!bitmap_rep) { TkMacOSXDbgMsg("XGetImage: Failed to construct NSBitmapRep"); return NULL; @@ -214,12 +213,12 @@ XGetImage( size = [bitmap_rep bytesPerPlane]; bytes_per_row = [bitmap_rep bytesPerRow]; bitmap = ckalloc(size); - if (!bitmap || - (bitmap_fmt != 0 && bitmap_fmt != 1) || - [bitmap_rep samplesPerPixel] != 4 || - [bitmap_rep isPlanar] != 0 || - bytes_per_row < 4 * scaled_width || - size != bytes_per_row*scaled_height ) { + if (!bitmap + || (bitmap_fmt != 0 && bitmap_fmt != 1) + || [bitmap_rep samplesPerPixel] != 4 + || [bitmap_rep isPlanar] != 0 + || bytes_per_row < 4 * scaled_width + || size != bytes_per_row * scaled_height) { TkMacOSXDbgMsg("XGetImage: Unrecognized bitmap format"); CFRelease(bitmap_rep); return NULL; @@ -228,8 +227,8 @@ XGetImage( CFRelease(bitmap_rep); /* - * When Apple extracts a bitmap from an NSView, it may be in - * either BGRA or ABGR format. For an XImage we need RGBA. + * When Apple extracts a bitmap from an NSView, it may be in either + * BGRA or ABGR format. For an XImage we need RGBA. */ struct pixel_fmt pixel = bitmap_fmt == 0 ? bgra : abgr; @@ -248,16 +247,16 @@ XGetImage( } } imagePtr = XCreateImage(display, NULL, depth, format, offset, - (char*)bitmap, scaled_width, scaled_height, - bitmap_pad, bytes_per_row); + (char*) bitmap, scaled_width, scaled_height, + bitmap_pad, bytes_per_row); if (scalefactor == 2) { imagePtr->pixelpower = 1; } } else { /* - * There are some calls to XGetImage in the generic Tk - * code which pass an XYPixmap rather than a ZPixmap. - * XYPixmaps should be handled here. + * There are some calls to XGetImage in the generic Tk code which pass + * an XYPixmap rather than a ZPixmap. XYPixmaps should be handled + * here. */ TkMacOSXDbgMsg("XGetImage does not handle XYPixmaps at the moment."); } @@ -323,40 +322,40 @@ ImageGetPixel( + (((image->xoffset + x) * image->bits_per_pixel) / NBBY); switch (image->bits_per_pixel) { - case 32: { - r = (*((unsigned int*) srcPtr) >> 16) & 0xff; - g = (*((unsigned int*) srcPtr) >> 8) & 0xff; - b = (*((unsigned int*) srcPtr) ) & 0xff; - /*if (image->byte_order == LSBFirst) { - r = srcPtr[2]; g = srcPtr[1]; b = srcPtr[0]; - } else { - r = srcPtr[1]; g = srcPtr[2]; b = srcPtr[3]; - }*/ - break; - } - case 16: - r = (*((unsigned short*) srcPtr) >> 7) & 0xf8; - g = (*((unsigned short*) srcPtr) >> 2) & 0xf8; - b = (*((unsigned short*) srcPtr) << 3) & 0xf8; - break; - case 8: - r = (*srcPtr << 2) & 0xc0; - g = (*srcPtr << 4) & 0xc0; - b = (*srcPtr << 6) & 0xc0; - r |= r >> 2 | r >> 4 | r >> 6; - g |= g >> 2 | g >> 4 | g >> 6; - b |= b >> 2 | b >> 4 | b >> 6; - break; - case 4: { - unsigned char c = (x % 2) ? *srcPtr : (*srcPtr >> 4); - r = (c & 0x04) ? 0xff : 0; - g = (c & 0x02) ? 0xff : 0; - b = (c & 0x01) ? 0xff : 0; - break; - } - case 1: - r = g = b = ((*srcPtr) & (0x80 >> (x % 8))) ? 0xff : 0; - break; + case 32: + r = (*((unsigned int*) srcPtr) >> 16) & 0xff; + g = (*((unsigned int*) srcPtr) >> 8) & 0xff; + b = (*((unsigned int*) srcPtr) ) & 0xff; + /*if (image->byte_order == LSBFirst) { + r = srcPtr[2]; g = srcPtr[1]; b = srcPtr[0]; + } else { + r = srcPtr[1]; g = srcPtr[2]; b = srcPtr[3]; + }*/ + break; + case 16: + r = (*((unsigned short*) srcPtr) >> 7) & 0xf8; + g = (*((unsigned short*) srcPtr) >> 2) & 0xf8; + b = (*((unsigned short*) srcPtr) << 3) & 0xf8; + break; + case 8: + r = (*srcPtr << 2) & 0xc0; + g = (*srcPtr << 4) & 0xc0; + b = (*srcPtr << 6) & 0xc0; + r |= r >> 2 | r >> 4 | r >> 6; + g |= g >> 2 | g >> 4 | g >> 6; + b |= b >> 2 | b >> 4 | b >> 6; + break; + case 4: { + unsigned char c = (x % 2) ? *srcPtr : (*srcPtr >> 4); + + r = (c & 0x04) ? 0xff : 0; + g = (c & 0x02) ? 0xff : 0; + b = (c & 0x01) ? 0xff : 0; + break; + } + case 1: + r = g = b = ((*srcPtr) & (0x80 >> (x % 8))) ? 0xff : 0; + break; } } return (PIXEL_MAGIC << 24) | (r << 16) | (g << 8) | b; @@ -389,6 +388,7 @@ ImagePutPixel( unsigned char *dstPtr = ((unsigned char*) image->data) + (y * image->bytes_per_line) + (((image->xoffset + x) * image->bits_per_pixel) / NBBY); + if (image->bits_per_pixel == 32) { *((unsigned int*) dstPtr) = pixel; } else { @@ -420,7 +420,7 @@ ImagePutPixel( } return 0; } - + /* *---------------------------------------------------------------------- * @@ -451,6 +451,7 @@ XCreateImage( int bytes_per_line) { XImage *ximage; + display->request++; ximage = ckalloc(sizeof(XImage)); @@ -461,9 +462,12 @@ XCreateImage( ximage->format = format; ximage->data = data; ximage->obdata = NULL; - /* The default pixelpower is 0. This must be explicitly set to 1 in the + + /* + * The default pixelpower is 0. This must be explicitly set to 1 in the * case of an XImage extracted from a Retina display. */ + ximage->pixelpower = 0; if (format == ZPixmap) { @@ -476,7 +480,10 @@ XCreateImage( if (bitmap_pad) { ximage->bitmap_pad = bitmap_pad; } else { - /* Use 16 byte alignment for best Quartz perfomance */ + /* + * Use 16 byte alignment for best Quartz perfomance. + */ + ximage->bitmap_pad = 128; } if (bytes_per_line) { @@ -511,9 +518,9 @@ XCreateImage( * * TkPutImage -- * - * Copies a rectangular subimage of an XImage into a drawable. - * Currently this is only called by TkImgPhotoDisplay, using - * a Window as the drawable. + * Copies a rectangular subimage of an XImage into a drawable. Currently + * this is only called by TkImgPhotoDisplay, using a Window as the + * drawable. * * Results: * None. @@ -559,13 +566,15 @@ TkPutImage( } if (img) { - /* If the XImage has big pixels, the source is rescaled to reflect + /* + * If the XImage has big pixels, the source is rescaled to reflect * the actual pixel dimensions. This is not currently used, but * could arise if the image were copied from a retina monitor and * redrawn on an ordinary monitor. */ int pp = image->pixelpower; + bounds = CGRectMake(0, 0, image->width, image->height); srcRect = CGRectMake(src_x<dispPtr->grabWinPtr; - if (grabWinPtr && - grabWinPtr != winPtr && - !winPtr->dispPtr->grabFlags && /* this means the grab is local. */ - grabWinPtr->mainPtr == winPtr->mainPtr) { + + if (grabWinPtr + && grabWinPtr != winPtr + && !winPtr->dispPtr->grabFlags /* this means the grab is local. */ + && grabWinPtr->mainPtr == winPtr->mainPtr) { return theEvent; } } else { tkwin = (Tk_Window) winPtr->dispPtr->focusPtr; } if (!tkwin) { - TkMacOSXDbgMsg("tkwin == NULL"); - return theEvent; /* Give up. No window for this event. */ + TkMacOSXDbgMsg("tkwin == NULL"); + return theEvent; /* Give up. No window for this event. */ } /* - * If it's a function key, or we have modifiers other than Shift or Alt, - * pass it straight to Tk. Otherwise we'll send for input processing. + * If it's a function key, or we have modifiers other than Shift or + * Alt, pass it straight to Tk. Otherwise we'll send for input + * processing. */ - int code = (len == 0) ? - 0 : [charactersIgnoringModifiers characterAtIndex: 0]; + int code = (len == 0) ? 0 : + [charactersIgnoringModifiers characterAtIndex: 0]; if (type != NSKeyDown || isFunctionKey(code) - || (len > 0 && state & (ControlMask | Mod1Mask | Mod3Mask | Mod4Mask))) { - + || (len > 0 && state & (ControlMask | Mod1Mask | Mod3Mask | Mod4Mask))) { XEvent xEvent; - setupXEvent(&xEvent, w, state); + setupXEvent(&xEvent, w, state); if (type == NSFlagsChanged) { - if (savedModifiers > modifiers) { - xEvent.xany.type = KeyRelease; - } else { - xEvent.xany.type = KeyPress; - } + if (savedModifiers > modifiers) { + xEvent.xany.type = KeyRelease; + } else { + xEvent.xany.type = KeyPress; + } - /* - * Use special '-1' to signify a special keycode to our platform - * specific code in tkMacOSXKeyboard.c. This is rather like what - * happens on Windows. - */ + /* + * Use special '-1' to signify a special keycode to our + * platform specific code in tkMacOSXKeyboard.c. This is rather + * like what happens on Windows. + */ - xEvent.xany.send_event = -1; + xEvent.xany.send_event = -1; - /* - * Set keycode (which was zero) to the changed modifier - */ + /* + * Set keycode (which was zero) to the changed modifier + */ - xEvent.xkey.keycode = (modifiers ^ savedModifiers); + xEvent.xkey.keycode = (modifiers ^ savedModifiers); } else { - if (type == NSKeyUp || repeat) { - xEvent.xany.type = KeyRelease; - } else { - xEvent.xany.type = KeyPress; - } - - /* For command key, take input manager's word so things - like dvorak / qwerty layout work. */ - if ((modifiers & NSCommandKeyMask) == NSCommandKeyMask - && (modifiers & NSAlternateKeyMask) != NSAlternateKeyMask - && len > 0 && !isFunctionKey(code)) { - // head off keycode-based translation in tkMacOSXKeyboard.c - xEvent.xkey.nbytes = [characters length]; //len - } - - if ([characters length] > 0) { - xEvent.xkey.keycode = - (keyCode << 16) | (UInt16) [characters characterAtIndex:0]; - if (![characters getCString:xEvent.xkey.trans_chars - maxLength:XMaxTransChars encoding:NSUTF8StringEncoding]) { - /* prevent SF bug 2907388 (crash on some composite chars) */ - //PENDING: we might not need this anymore - TkMacOSXDbgMsg("characters too long"); - return theEvent; - } - } - - if (repeat) { - Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL); - xEvent.xany.type = KeyPress; - xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin)); - } + if (type == NSKeyUp || repeat) { + xEvent.xany.type = KeyRelease; + } else { + xEvent.xany.type = KeyPress; + } + + /* + * For command key, take input manager's word so things like + * dvorak / qwerty layout work. + */ + + if ((modifiers & NSCommandKeyMask) == NSCommandKeyMask + && (modifiers & NSAlternateKeyMask) != NSAlternateKeyMask + && len > 0 && !isFunctionKey(code)) { + // head off keycode-based translation in tkMacOSXKeyboard.c + xEvent.xkey.nbytes = [characters length]; //len + } + + if ([characters length] > 0) { + xEvent.xkey.keycode = (keyCode << 16) | + (UInt16) [characters characterAtIndex:0]; + if (![characters getCString:xEvent.xkey.trans_chars + maxLength:XMaxTransChars encoding:NSUTF8StringEncoding]) { + /* prevent SF bug 2907388 (crash on some composite chars) */ + //PENDING: we might not need this anymore + TkMacOSXDbgMsg("characters too long"); + return theEvent; + } + } + + if (repeat) { + Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL); + xEvent.xany.type = KeyPress; + xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin)); + } } Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL); savedModifiers = modifiers; return theEvent; - } /* if send straight to TK */ - - } /* if not processing compose */ + } /* if send straight to TK */ + } /* if not processing compose */ if (type == NSKeyDown) { - if (NS_KEYLOG) - fprintf (stderr, "keyDown: %s compose sequence.\n", - processingCompose == YES ? "Continue" : "Begin"); + if (NS_KEYLOG) { + TKLog(@"keyDown: %s compose sequence.\n", + processingCompose == YES ? "Continue" : "Begin"); + } processingCompose = YES; [nsEvArray addObject: theEvent]; [[w contentView] interpretKeyEvents: nsEvArray]; [nsEvArray removeObject: theEvent]; - } + } savedModifiers = modifiers; - return theEvent; } @end - @implementation TKContentView @@ -261,163 +264,189 @@ unsigned short releaseCode; by doCommandBySelector: deleteBackward: */ - (void)insertText: (id)aString { - int i, len = [(NSString *)aString length]; - XEvent xEvent; + int i, len = [(NSString *) aString length]; + XEvent xEvent; - if (NS_KEYLOG) - TKLog (@"insertText '%@'\tlen = %d", aString, len); - processingCompose = NO; - finishedCompose = YES; + if (NS_KEYLOG) { + TKLog(@"insertText '%@'\tlen = %d", aString, len); + } + processingCompose = NO; + finishedCompose = YES; - /* first, clear any working text */ - if (privateWorkingText != nil) - [self deleteWorkingText]; + /* + * First, clear any working text. + */ + + if (privateWorkingText != nil) { + [self deleteWorkingText]; + } - /* now insert the string as keystrokes */ - setupXEvent(&xEvent, [self window], 0); - xEvent.xany.type = KeyPress; + /* + * Now insert the string as keystrokes. + */ - for (i =0; i: inserts display of composing characters */ - (void)setMarkedText: (id)aString selectedRange: (NSRange)selRange { - NSString *str = [aString respondsToSelector: @selector (string)] ? - [aString string] : aString; - if (NS_KEYLOG) - TKLog (@"setMarkedText '%@' len =%lu range %lu from %lu", str, - (unsigned long) [str length], (unsigned long) selRange.length, - (unsigned long) selRange.location); - - if (privateWorkingText != nil) - [self deleteWorkingText]; - if ([str length] == 0) - return; + NSString *str = [aString respondsToSelector: @selector (string)] ? + [aString string] : aString; + if (NS_KEYLOG) { + TKLog(@"setMarkedText '%@' len =%lu range %lu from %lu", str, + (unsigned long) [str length], (unsigned long) selRange.length, + (unsigned long) selRange.location); + } - processingCompose = YES; - privateWorkingText = [str copy]; + if (privateWorkingText != nil) { + [self deleteWorkingText]; + } + if ([str length] == 0) { + return; + } - //PENDING: insert workingText underlined + processingCompose = YES; + privateWorkingText = [str copy]; + + //PENDING: insert workingText underlined } - (BOOL)hasMarkedText { - return privateWorkingText != nil; + return privateWorkingText != nil; } - (NSRange)markedRange { - NSRange rng = privateWorkingText != nil - ? NSMakeRange (0, [privateWorkingText length]) : NSMakeRange (NSNotFound, 0); - if (NS_KEYLOG) - TKLog (@"markedRange request"); - return rng; + NSRange rng = privateWorkingText != nil + ? NSMakeRange(0, [privateWorkingText length]) + : NSMakeRange(NSNotFound, 0); + + if (NS_KEYLOG) { + TKLog(@"markedRange request"); + } + return rng; } - (void)unmarkText { - if (NS_KEYLOG) - TKLog (@"unmark (accept) text"); - [self deleteWorkingText]; - processingCompose = NO; + if (NS_KEYLOG) { + TKLog(@"unmark (accept) text"); + } + [self deleteWorkingText]; + processingCompose = NO; } /* used to position char selection windows, etc. */ - (NSRect)firstRectForCharacterRange: (NSRange)theRange { - NSRect rect; - NSPoint pt; + NSRect rect; + NSPoint pt; - pt.x = caret_x; - pt.y = caret_y; + pt.x = caret_x; + pt.y = caret_y; - pt = [self convertPoint: pt toView: nil]; - pt = [[self window] tkConvertPointToScreen: pt]; - pt.y -= caret_height; + pt = [self convertPoint: pt toView: nil]; + pt = [[self window] tkConvertPointToScreen: pt]; + pt.y -= caret_height; - rect.origin = pt; - rect.size.width = caret_height; - rect.size.height = caret_height; - return rect; + rect.origin = pt; + rect.size.width = caret_height; + rect.size.height = caret_height; + return rect; } - (NSInteger)conversationIdentifier { - return (NSInteger)self; + return (NSInteger) self; } - (void)doCommandBySelector: (SEL)aSelector { - if (NS_KEYLOG) - TKLog (@"doCommandBySelector: %@", NSStringFromSelector (aSelector)); - processingCompose = NO; - if (aSelector == @selector (deleteBackward:)) - { - /* happens when user backspaces over an ongoing composition: - throw a 'delete' into the event queue */ - XEvent xEvent; - setupXEvent(&xEvent, [self window], 0); - xEvent.xany.type = KeyPress; - xEvent.xkey.nbytes = 1; - xEvent.xkey.keycode = (0x33 << 16) | 0x7F; - xEvent.xkey.trans_chars[0] = 0x7F; - xEvent.xkey.trans_chars[1] = 0x0; - Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL); + if (NS_KEYLOG) { + TKLog(@"doCommandBySelector: %@", NSStringFromSelector(aSelector)); + } + processingCompose = NO; + if (aSelector == @selector (deleteBackward:)) { + /* + * Happens when user backspaces over an ongoing composition: + * throw a 'delete' into the event queue. + */ + + XEvent xEvent; + + setupXEvent(&xEvent, [self window], 0); + xEvent.xany.type = KeyPress; + xEvent.xkey.nbytes = 1; + xEvent.xkey.keycode = (0x33 << 16) | 0x7F; + xEvent.xkey.trans_chars[0] = 0x7F; + xEvent.xkey.trans_chars[1] = 0x0; + Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL); } } - (NSArray *)validAttributesForMarkedText { - static NSArray *arr = nil; - if (arr == nil) arr = [NSArray new]; - /* [[NSArray arrayWithObject: NSUnderlineStyleAttributeName] retain]; */ - return arr; + static NSArray *arr = nil; + + if (arr == nil) { + arr = [NSArray new]; + } + /* [[NSArray arrayWithObject: NSUnderlineStyleAttributeName] retain]; */ + return arr; } - (NSRange)selectedRange { - if (NS_KEYLOG) - TKLog (@"selectedRange request"); - return NSMakeRange (NSNotFound, 0); + if (NS_KEYLOG) { + TKLog(@"selectedRange request"); + } + return NSMakeRange(NSNotFound, 0); } - (NSUInteger)characterIndexForPoint: (NSPoint)thePoint { - if (NS_KEYLOG) - TKLog (@"characterIndexForPoint request"); - return 0; + if (NS_KEYLOG) { + TKLog(@"characterIndexForPoint request"); + } + return 0; } - (NSAttributedString *)attributedSubstringFromRange: (NSRange)theRange { - static NSAttributedString *str = nil; - if (str == nil) str = [NSAttributedString new]; - if (NS_KEYLOG) - TKLog (@"attributedSubstringFromRange request"); - return str; + static NSAttributedString *str = nil; + if (str == nil) { + str = [NSAttributedString new]; + } + if (NS_KEYLOG) { + TKLog(@"attributedSubstringFromRange request"); + } + return str; } /* End impl. */ @end @@ -427,29 +456,30 @@ unsigned short releaseCode; /* delete display of composing characters [not in ] */ - (void)deleteWorkingText { - if (privateWorkingText == nil) - return; - if (NS_KEYLOG) - TKLog(@"deleteWorkingText len = %lu\n", - (unsigned long)[privateWorkingText length]); - [privateWorkingText release]; - privateWorkingText = nil; - processingCompose = NO; - - //PENDING: delete working text + if (privateWorkingText == nil) { + return; + } + if (NS_KEYLOG) { + TKLog(@"deleteWorkingText len = %lu\n", + (unsigned long)[privateWorkingText length]); + } + [privateWorkingText release]; + privateWorkingText = nil; + processingCompose = NO; + + //PENDING: delete working text } @end - - /* - * Set up basic fields in xevent for keyboard input. + * Set up basic fields in xevent for keyboard input. */ static void setupXEvent(XEvent *xEvent, NSWindow *w, unsigned int state) { TkWindow *winPtr = TkMacOSXGetTkWindow(w); Tk_Window tkwin = (Tk_Window) winPtr; + if (!winPtr) { return; } @@ -497,12 +527,13 @@ XGrabKeyboard( Time time) { keyboardGrabWinPtr = Tk_IdToWindow(display, grab_window); - TkWindow *captureWinPtr = (TkWindow *)TkMacOSXGetCapture(); + TkWindow *captureWinPtr = (TkWindow *) TkMacOSXGetCapture(); + if (keyboardGrabWinPtr && captureWinPtr) { NSWindow *w = TkMacOSXDrawableWindow(grab_window); MacDrawable *macWin = (MacDrawable *) grab_window; - if (w && macWin->toplevel->winPtr == (TkWindow*) captureWinPtr) { + if (w && macWin->toplevel->winPtr == (TkWindow *) captureWinPtr) { if (modalSession) { Tcl_Panic("XGrabKeyboard: already grabbed"); } @@ -621,7 +652,10 @@ Tk_SetCaretPos( } } - /* But adjust for fact that NS uses flipped view. */ + /* + * But adjust for fact that NS uses flipped view. + */ + y = Tk_Height(tkwin) - y; caret_x = x; @@ -632,75 +666,79 @@ Tk_SetCaretPos( static unsigned convert_ns_to_X_keysym[] = { - NSHomeFunctionKey, 0x50, - NSLeftArrowFunctionKey, 0x51, - NSUpArrowFunctionKey, 0x52, - NSRightArrowFunctionKey, 0x53, - NSDownArrowFunctionKey, 0x54, - NSPageUpFunctionKey, 0x55, - NSPageDownFunctionKey, 0x56, - NSEndFunctionKey, 0x57, - NSBeginFunctionKey, 0x58, - NSSelectFunctionKey, 0x60, - NSPrintFunctionKey, 0x61, - NSExecuteFunctionKey, 0x62, - NSInsertFunctionKey, 0x63, - NSUndoFunctionKey, 0x65, - NSRedoFunctionKey, 0x66, - NSMenuFunctionKey, 0x67, - NSFindFunctionKey, 0x68, - NSHelpFunctionKey, 0x6A, - NSBreakFunctionKey, 0x6B, - - NSF1FunctionKey, 0xBE, - NSF2FunctionKey, 0xBF, - NSF3FunctionKey, 0xC0, - NSF4FunctionKey, 0xC1, - NSF5FunctionKey, 0xC2, - NSF6FunctionKey, 0xC3, - NSF7FunctionKey, 0xC4, - NSF8FunctionKey, 0xC5, - NSF9FunctionKey, 0xC6, - NSF10FunctionKey, 0xC7, - NSF11FunctionKey, 0xC8, - NSF12FunctionKey, 0xC9, - NSF13FunctionKey, 0xCA, - NSF14FunctionKey, 0xCB, - NSF15FunctionKey, 0xCC, - NSF16FunctionKey, 0xCD, - NSF17FunctionKey, 0xCE, - NSF18FunctionKey, 0xCF, - NSF19FunctionKey, 0xD0, - NSF20FunctionKey, 0xD1, - NSF21FunctionKey, 0xD2, - NSF22FunctionKey, 0xD3, - NSF23FunctionKey, 0xD4, - NSF24FunctionKey, 0xD5, - - NSBackspaceCharacter, 0x08, /* 8: Not on some KBs. */ - NSDeleteCharacter, 0xFF, /* 127: Big 'delete' key upper right. */ - NSDeleteFunctionKey, 0x9F, /* 63272: Del forw key off main array. */ - - NSTabCharacter, 0x09, - 0x19, 0x09, /* left tab->regular since pass shift */ - NSCarriageReturnCharacter, 0x0D, - NSNewlineCharacter, 0x0D, - NSEnterCharacter, 0x8D, - - 0x1B, 0x1B /* escape */ + NSHomeFunctionKey, 0x50, + NSLeftArrowFunctionKey, 0x51, + NSUpArrowFunctionKey, 0x52, + NSRightArrowFunctionKey, 0x53, + NSDownArrowFunctionKey, 0x54, + NSPageUpFunctionKey, 0x55, + NSPageDownFunctionKey, 0x56, + NSEndFunctionKey, 0x57, + NSBeginFunctionKey, 0x58, + NSSelectFunctionKey, 0x60, + NSPrintFunctionKey, 0x61, + NSExecuteFunctionKey, 0x62, + NSInsertFunctionKey, 0x63, + NSUndoFunctionKey, 0x65, + NSRedoFunctionKey, 0x66, + NSMenuFunctionKey, 0x67, + NSFindFunctionKey, 0x68, + NSHelpFunctionKey, 0x6A, + NSBreakFunctionKey, 0x6B, + + NSF1FunctionKey, 0xBE, + NSF2FunctionKey, 0xBF, + NSF3FunctionKey, 0xC0, + NSF4FunctionKey, 0xC1, + NSF5FunctionKey, 0xC2, + NSF6FunctionKey, 0xC3, + NSF7FunctionKey, 0xC4, + NSF8FunctionKey, 0xC5, + NSF9FunctionKey, 0xC6, + NSF10FunctionKey, 0xC7, + NSF11FunctionKey, 0xC8, + NSF12FunctionKey, 0xC9, + NSF13FunctionKey, 0xCA, + NSF14FunctionKey, 0xCB, + NSF15FunctionKey, 0xCC, + NSF16FunctionKey, 0xCD, + NSF17FunctionKey, 0xCE, + NSF18FunctionKey, 0xCF, + NSF19FunctionKey, 0xD0, + NSF20FunctionKey, 0xD1, + NSF21FunctionKey, 0xD2, + NSF22FunctionKey, 0xD3, + NSF23FunctionKey, 0xD4, + NSF24FunctionKey, 0xD5, + + NSBackspaceCharacter, 0x08, /* 8: Not on some KBs. */ + NSDeleteCharacter, 0xFF, /* 127: Big 'delete' key upper right. */ + NSDeleteFunctionKey, 0x9F, /* 63272: Del forw key off main array. */ + + NSTabCharacter, 0x09, + 0x19, 0x09, /* left tab->regular since pass shift */ + NSCarriageReturnCharacter, 0x0D, + NSNewlineCharacter, 0x0D, + NSEnterCharacter, 0x8D, + + 0x1B, 0x1B /* escape */ }; -static unsigned isFunctionKey(unsigned code) +static unsigned +isFunctionKey( + unsigned code) { const unsigned last_keysym = (sizeof (convert_ns_to_X_keysym) / sizeof (convert_ns_to_X_keysym[0])); - unsigned keysym; - for (keysym = 0; keysym < last_keysym; keysym += 2) - if (code == convert_ns_to_X_keysym[keysym]) - return 0xFF00 | convert_ns_to_X_keysym[keysym+1]; - return 0; - } + unsigned keysym; + for (keysym = 0; keysym < last_keysym; keysym += 2) { + if (code == convert_ns_to_X_keysym[keysym]) { + return 0xFF00 | convert_ns_to_X_keysym[keysym+1]; + } + } + return 0; +} /* * Local Variables: diff --git a/macosx/tkMacOSXMenu.c b/macosx/tkMacOSXMenu.c index 227c379..fc1b7c4 100644 --- a/macosx/tkMacOSXMenu.c +++ b/macosx/tkMacOSXMenu.c @@ -193,10 +193,10 @@ static int ModifierCharWidth(Tk_Font tkfont); - (void) insertItem: (NSMenuItem *) newItem atIndex: (NSInteger) index { if (_tkMenu && index >= 0) { - if ((NSUInteger)index <= _tkOffset) { + if ((NSUInteger) index <= _tkOffset) { _tkOffset++; } else { - NSAssert((NSUInteger)index >= _tkItemCount + _tkOffset, + NSAssert((NSUInteger) index >= _tkItemCount + _tkOffset, @"Cannot insert in the middle of Tk menu"); } } @@ -206,9 +206,9 @@ static int ModifierCharWidth(Tk_Font tkfont); - (void) removeItemAtIndex: (NSInteger) index { if (_tkMenu && index >= 0) { - if ((NSUInteger)index < _tkOffset) { + if ((NSUInteger) index < _tkOffset) { _tkOffset--; - } else if ((NSUInteger)index < _tkItemCount + _tkOffset) { + } else if ((NSUInteger) index < _tkItemCount + _tkOffset) { _tkItemCount--; } } @@ -221,7 +221,7 @@ static int ModifierCharWidth(Tk_Font tkfont); action:@selector(tkMenuItemInvoke:) keyEquivalent:@""]; [menuItem setTarget:self]; - [menuItem setTag:(NSInteger)mePtr]; + [menuItem setTag:(NSInteger) mePtr]; return menuItem; } @end @@ -252,15 +252,16 @@ static int ModifierCharWidth(Tk_Font tkfont); */ if ([sender isKindOfClass:[NSMenuItem class]]) { - NSMenuItem *menuItem = (NSMenuItem *)sender; - TkMenu *menuPtr = (TkMenu *)_tkMenu; - TkMenuEntry *mePtr = (TkMenuEntry *)[menuItem tag]; + NSMenuItem *menuItem = (NSMenuItem *) sender; + TkMenu *menuPtr = (TkMenu *) _tkMenu; + TkMenuEntry *mePtr = (TkMenuEntry *) [menuItem tag]; if (menuPtr && mePtr) { Tcl_Interp *interp = menuPtr->interp; - /*Add time for errors to fire if necessary. This is sub-optimal - *but avoids issues with Tcl/Cocoa event loop integration. + /* + * Add time for errors to fire if necessary. This is sub-optimal + * but avoids issues with Tcl/Cocoa event loop integration. */ //Tcl_Sleep(100); @@ -305,8 +306,8 @@ static int ModifierCharWidth(Tk_Font tkfont); return NO; } else if (modifiers == (NSControlKeyMask | NSShiftKeyMask) && [event keyCode] == 48) { - - /* Starting with OSX 10.12 Control-Tab and Control-Shift-Tab are used + /* + * Starting with OSX 10.12 Control-Tab and Control-Shift-Tab are used * to select window tabs. But for some even more mysterious reason the * Control-Shift-Tab event has character 0x19 = NSBackTabCharacter * rather than 0x09 = NSTabCharacter. At the same time, the @@ -317,7 +318,6 @@ static int ModifierCharWidth(Tk_Font tkfont); key = @"\t"; } else if (([event modifierFlags] & NSCommandKeyMask) == NSCommandKeyMask) { - /* * If the command modifier is set, use the full character string so * things like the dvorak / qwerty layout will work. @@ -650,7 +650,7 @@ TkpConfigureMenuEntry( gc->foreground!=defaultFg? gc->foreground:gc->background); attributes = [[attributes mutableCopy] autorelease]; - [(NSMutableDictionary *)attributes setObject:color + [(NSMutableDictionary *) attributes setObject:color forKey:NSForegroundColorAttributeName]; } if (attributes) { @@ -690,21 +690,26 @@ TkpConfigureMenuEntry( [submenu setTitle:title]; if ([menuItem isEnabled]) { - /* This menuItem might have been previously disabled (XXX: - track this), which would have disabled entries; we must - re-enable the entries here. */ - int i = 0; - NSArray *itemArray = [submenu itemArray]; - for (NSMenuItem *item in itemArray) { - TkMenuEntry *submePtr = menuRefPtr->menuPtr->entries[i]; - /* Work around an apparent bug where itemArray can have - more items than the menu's entries[] array. */ - if (i >= menuRefPtr->menuPtr->numEntries) break; - [item setEnabled: !(submePtr->state == ENTRY_DISABLED)]; - i++; - } + + /* This menuItem might have been previously disabled (XXX: + * track this), which would have disabled entries; we must + * re-enable the entries here. + */ + + int i = 0; + NSArray *itemArray = [submenu itemArray]; + for (NSMenuItem *item in itemArray) { + TkMenuEntry *submePtr = menuRefPtr->menuPtr->entries[i]; + + /* Work around an apparent bug where itemArray can have + * more items than the menu's entries[] array. + */ + + if (i >= menuRefPtr->menuPtr->numEntries) break; + [item setEnabled: !(submePtr->state == ENTRY_DISABLED)]; + i++; + } } - } } } @@ -755,10 +760,10 @@ TkpDestroyMenuEntry( * * TkpPostMenu -- * - * Posts a menu on the screen. If entry is < 0 then the menu is - * drawn so its top left corner is located at the point with - * screen coordinates (x, y). Otherwise the top left corner of - * the specified entry is located at that point. + * Posts a menu on the screen. If entry is < 0 then the menu is drawn so + * its top left corner is located at the point with screen coordinates + * (x,y). Otherwise the top left corner of the specified entry is located + * at that point. * * Results: * Returns a standard Tcl result. @@ -828,13 +833,13 @@ TkpPostMenu( * * TkpPostTearoffMenu -- * - * Tearoff menus are not supported on the Mac. This placeholder - * function, which is simply a copy of the unix function, posts a - * completely useless window with a black background on the screen. If - * entry is < 0 then the window is positioned so that its top left corner - * is located at the point with screen coordinates (x, y). Otherwise the - * window position is offset so that top left corner of the specified - * entry would be located at that point, if there actually were a menu. + * Tearoff menus are not supported on the Mac. This placeholder function, + * which is simply a copy of the unix function, posts a completely useless + * window with a black background on the screen. If entry is < 0 then the + * window is positioned so that its top left corner is located at the + * point with screen coordinates (x, y). Otherwise the window position is + * offset so that top left corner of the specified entry would be located + * at that point, if there actually were a menu. * * Mac menus steal all mouse or keyboard input from the application until * the menu is dismissed, with or without a selection, by a mouse or key @@ -862,7 +867,7 @@ TkpPostTearoffMenu( int vRootX, vRootY, vRootWidth, vRootHeight; int result; - if (index >= menuPtr->numEntries) { + if (index >= (int) menuPtr->numEntries) { index = menuPtr->numEntries - 1; } if (index >= 0) { @@ -960,12 +965,12 @@ TkpSetWindowMenuBar( * * TkpSetMainMenubar -- * - * Puts the menu associated with a window into the menubar. Should only - * be called when the window is in front. + * Puts the menu associated with a window into the menubar. Should only be + * called when the window is in front. * * This is a no-op on all other platforms. On OS X it is a no-op when - * passed a NULL menuName or a nonexistent menuName, with an exception - * for the first call in a new interpreter. In that special case, passing a + * passed a NULL menuName or a nonexistent menuName, with an exception for + * the first call in a new interpreter. In that special case, passing a * NULL menuName installs the default menu. * * Results: @@ -993,11 +998,12 @@ TkpSetMainMenubar( */ if (Tk_IsEmbedded(winPtr)) { - return; - } + return; + } if (menuName) { Tk_Window menubar = NULL; + if (winPtr->wmInfoPtr && winPtr->wmInfoPtr->menuPtr && winPtr->wmInfoPtr->menuPtr->masterMenuPtr) { @@ -1005,7 +1011,8 @@ TkpSetMainMenubar( } /* - * Attempt to find the NSMenu directly. If that fails, ask Tk to find it. + * Attempt to find the NSMenu directly. If that fails, ask Tk to find + * it. */ if (menubar != NULL && strcmp(menuName, Tk_PathName(menubar)) == 0) { @@ -1013,6 +1020,7 @@ TkpSetMainMenubar( } else { TkMenuReferences *menuRefPtr = TkFindMenuReferences(interp, menuName); + if (menuRefPtr && menuRefPtr->menuPtr && menuRefPtr->menuPtr->platformData) { menu = (TKMenu *) menuRefPtr->menuPtr->platformData; @@ -1021,9 +1029,8 @@ TkpSetMainMenubar( } /* - * If we couldn't find a menu, do nothing unless the window belongs - * to a different application. In that case, install the default - * menubar. + * If we couldn't find a menu, do nothing unless the window belongs to a + * different application. In that case, install the default menubar. */ if (menu || interp != currentInterp) { @@ -1038,8 +1045,8 @@ TkpSetMainMenubar( * CheckForSpecialMenu -- * * Given a menu, check to see whether or not it is a cascade in a menubar - * with one of the special names ".apple", ".help" or ".window". If it - * is, the entry that points to this menu will be marked. + * with one of the special names ".apple", ".help" or ".window". If it is, + * the entry that points to this menu will be marked. * * Results: * None. @@ -1230,11 +1237,12 @@ TkpComputeStandardMenuGeometry( /* * Do nothing if this menu is a clone. */ + if (menuPtr->tkwin == NULL || menuPtr->masterMenuPtr != menuPtr) { return; } - menuSize = [(NSMenu *)menuPtr->platformData size]; + menuSize = [(NSMenu *) menuPtr->platformData size]; Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthPtr, &borderWidth); Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->activeBorderWidthPtr, @@ -1248,16 +1256,16 @@ TkpComputeStandardMenuGeometry( * want to do it intelligently. We are going to precalculate them and pass * them down to all of the measuring and drawing routines. We will measure * the font metrics of the menu once. If an entry does not have its own - * font set, then we give the geometry/drawing routines the menu's font - * and metrics. If an entry has its own font, we will measure that font - * and give all of the geometry/drawing the entry's font and metrics. + * font set, then we give the geometry/drawing routines the menu's font and + * metrics. If an entry has its own font, we will measure that font and + * give all of the geometry/drawing the entry's font and metrics. */ menuFont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr); Tk_GetFontMetrics(menuFont, &menuMetrics); menuModifierCharWidth = ModifierCharWidth(menuFont); - for (i = 0; i < menuPtr->numEntries; i++) { + for (i = 0; i < (int) menuPtr->numEntries; i++) { mePtr = menuPtr->entries[i]; if (mePtr->type == CASCADE_ENTRY || mePtr->accelLength > 0) { haveAccel = 1; @@ -1265,7 +1273,7 @@ TkpComputeStandardMenuGeometry( } } - for (i = 0; i < menuPtr->numEntries; i++) { + for (i = 0; i < (int) menuPtr->numEntries; i++) { mePtr = menuPtr->entries[i]; if (mePtr->type == TEAROFF_ENTRY) { continue; @@ -1295,6 +1303,7 @@ TkpComputeStandardMenuGeometry( NSMenuItem *menuItem = (NSMenuItem *) mePtr->platformEntryData; int haveImage = 0, width = 0, height = 0; + if (mePtr->image) { Tk_SizeOfImage(mePtr->image, &width, &height); haveImage = 1; @@ -1302,6 +1311,7 @@ TkpComputeStandardMenuGeometry( } else if (mePtr->bitmapPtr) { Pixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin, mePtr->bitmapPtr); + Tk_SizeOfBitmap(menuPtr->display, bitmap, &width, &height); haveImage = 1; height += 2; /* tweak */ @@ -1413,7 +1423,7 @@ GenerateMenuSelectEvent( if (menuPtr) { int index = [menu tkIndexOfItem:menuItem]; - if (index < 0 || index >= menuPtr->numEntries || + if (index < 0 || index >= (int) menuPtr->numEntries || (menuPtr->entries[index])->state == ENTRY_DISABLED) { TkActivateMenuEntry(menuPtr, -1); } else { @@ -1492,7 +1502,7 @@ RecursivelyClearActiveMenu( int i; TkActivateMenuEntry(menuPtr, -1); - for (i = 0; i < menuPtr->numEntries; i++) { + for (i = 0; i < (int) menuPtr->numEntries; i++) { TkMenuEntry *mePtr = menuPtr->entries[i]; if (mePtr->type == CASCADE_ENTRY @@ -1781,7 +1791,7 @@ TkMacOSXPreprocessMenu(void) * TkMacOSXUseID -- * * Take the ID out of the available list for new menus. Used by the - * default menu bar's menus so that they do not get created at the tk + * default menu bar's menus so that they do not get created at the Tk * level. See TkMacOSXGetNewMenuID for more information. * * Results: @@ -1806,8 +1816,7 @@ TkMacOSXUseMenuID( * * TkMacOSXDispatchMenuEvent -- * - * Given a menu id and an item, dispatches the command associated with - * it. + * Given a menu id and an item, dispatches the command associated with it. * * Results: * None. @@ -1857,9 +1866,10 @@ TkMacOSXHandleTearoffMenu(void) * * TkMacOSXSetHelpMenuItemCount -- * - * Has to be called after the first call to InsertMenu. Sets up the - * global variable for the number of items in the unmodified help menu. - * NB. Nobody uses this any more, since you can get the number of system + * Has to be called after the first call to InsertMenu. Sets up the global + * variable for the number of items in the unmodified help menu. + * + * NB: Nobody uses this any more, since you can get the number of system * help items from HMGetHelpMenu trivially. But it is in the stubs * table... * diff --git a/macosx/tkMacOSXMenubutton.c b/macosx/tkMacOSXMenubutton.c index b2b4b76..33ae213 100644 --- a/macosx/tkMacOSXMenubutton.c +++ b/macosx/tkMacOSXMenubutton.c @@ -1,8 +1,8 @@ /* * tkMacOSXMenubutton.c -- * - * This file implements the Macintosh specific portion of the - * menubutton widget. + * This file implements the Macintosh specific portion of the menubutton + * widget. * * Copyright (c) 1996 by Sun Microsystems, Inc. * Copyright 2001, Apple Computer, Inc. @@ -32,7 +32,6 @@ typedef struct { int hasImageOrBitmap; } DrawParams; - /* * Declaration of Mac specific button structure. */ @@ -50,21 +49,24 @@ typedef struct MacMenuButton { * Forward declarations for static functions defined later in this file: */ -static void MenuButtonEventProc(ClientData clientData, XEvent *eventPtr); -static void MenuButtonBackgroundDrawCB (MacMenuButton *ptr, SInt16 depth, - Boolean isColorDev); -static void MenuButtonContentDrawCB (ThemeButtonKind kind, - const HIThemeButtonDrawInfo * info, - MacMenuButton *ptr, SInt16 depth, - Boolean isColorDev); -static void MenuButtonEventProc ( ClientData clientData, XEvent *eventPtr); -static void TkMacOSXComputeMenuButtonParams (TkMenuButton * butPtr, - ThemeButtonKind* btnkind, - HIThemeButtonDrawInfo* drawinfo); -static void TkMacOSXComputeMenuButtonDrawParams (TkMenuButton * butPtr, - DrawParams * dpPtr); -static void TkMacOSXDrawMenuButton (MacMenuButton *butPtr, GC gc, Pixmap pixmap); -static void DrawMenuButtonImageAndText(TkMenuButton* butPtr); +static void MenuButtonEventProc(ClientData clientData, + XEvent *eventPtr); +static void MenuButtonBackgroundDrawCB(MacMenuButton *ptr, + SInt16 depth, Boolean isColorDev); +static void MenuButtonContentDrawCB(ThemeButtonKind kind, + const HIThemeButtonDrawInfo *info, + MacMenuButton *ptr, SInt16 depth, + Boolean isColorDev); +static void MenuButtonEventProc(ClientData clientData, + XEvent *eventPtr); +static void TkMacOSXComputeMenuButtonParams(TkMenuButton *butPtr, + ThemeButtonKind *btnkind, + HIThemeButtonDrawInfo *drawinfo); +static void TkMacOSXComputeMenuButtonDrawParams( + TkMenuButton *butPtr, DrawParams *dpPtr); +static void TkMacOSXDrawMenuButton(MacMenuButton *butPtr, GC gc, + Pixmap pixmap); +static void DrawMenuButtonImageAndText(TkMenuButton *butPtr); /* * The structure below defines menubutton class behavior by means of @@ -133,8 +135,7 @@ TkpCreateMenuButton( { MacMenuButton *mbPtr = (MacMenuButton *) ckalloc(sizeof(MacMenuButton)); - Tk_CreateEventHandler(tkwin, ActivateMask, MenuButtonEventProc, - (ClientData) mbPtr); + Tk_CreateEventHandler(tkwin, ActivateMask, MenuButtonEventProc, mbPtr); mbPtr->flags = FIRST_DRAW; mbPtr->btnkind = kThemePopupButton; bzero(&mbPtr->drawinfo, sizeof(mbPtr->drawinfo)); @@ -153,8 +154,7 @@ TkpCreateMenuButton( * None. * * Side effects: - * Commands are output to X to display the menubutton in its - * current mode. + * Commands are output to X to display the menubutton in its current mode. * *---------------------------------------------------------------------- */ @@ -163,11 +163,11 @@ void TkpDisplayMenuButton( ClientData clientData) /* Information about widget. */ { - MacMenuButton *mbPtr = (MacMenuButton *)clientData; - TkMenuButton *butPtr = (TkMenuButton *) clientData; - Tk_Window tkwin = butPtr->tkwin; + MacMenuButton *mbPtr = clientData; + TkMenuButton *butPtr = clientData; + Tk_Window tkwin = butPtr->tkwin; Pixmap pixmap; - DrawParams* dpPtr = &mbPtr->drawParams; + DrawParams *dpPtr = &mbPtr->drawParams; butPtr->flags &= ~REDRAW_PENDING; if ((butPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) { @@ -179,22 +179,26 @@ TkpDisplayMenuButton( TkMacOSXComputeMenuButtonDrawParams(butPtr, dpPtr); /* - * set up clipping region. Make sure the we are using the port - * for this button, or we will set the wrong window's clip. + * Set up clipping region. Make sure the we are using the port for this + * button, or we will set the wrong window's clip. */ TkMacOSXSetUpClippingRgn(pixmap); - /* Draw the native portion of the buttons. */ + /* + * Draw the native portion of the buttons. + */ + TkMacOSXDrawMenuButton(mbPtr, dpPtr->gc, pixmap); - /* Draw highlight border, if needed. */ - if (butPtr->highlightWidth < 3) { - if ((butPtr->flags & GOT_FOCUS)) { - Tk_Draw3DRectangle(tkwin, pixmap, butPtr->normalBorder, 0, 0, + /* + * Draw highlight border, if needed. + */ + + if ((butPtr->highlightWidth < 3) && (butPtr->flags & GOT_FOCUS)) { + Tk_Draw3DRectangle(tkwin, pixmap, butPtr->normalBorder, 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), butPtr->highlightWidth, TK_RELIEF_SOLID); - } } } @@ -203,8 +207,8 @@ TkpDisplayMenuButton( * * TkpDestroyMenuButton -- * - * Free data structures associated with the menubutton control. - * This is a no-op on the Mac. + * Free data structures associated with the menubutton control. This is a + * no-op on the Mac. * * Results: * None. @@ -279,44 +283,42 @@ TkpComputeMenuButtonGeometry(butPtr) } /* - * If the button is compound (ie, it shows both an image and text), - * the new geometry is a combination of the image and text geometry. - * We only honor the compound bit if the button has both text and an - * image, because otherwise it is not really a compound button. + * If the button is compound (ie, it shows both an image and text), the new + * geometry is a combination of the image and text geometry. We only honor + * the compound bit if the button has both text and an image, because + * otherwise it is not really a compound button. */ if (haveImage && haveText) { switch ((enum compound) butPtr->compound) { - case COMPOUND_TOP: - case COMPOUND_BOTTOM: { - /* - * Image is above or below text - */ - - height += txtHeight + butPtr->padY; - width = (width > txtWidth ? width : txtWidth); - break; - } - case COMPOUND_LEFT: - case COMPOUND_RIGHT: { - /* - * Image is left or right of text - */ - - width += txtWidth + butPtr->padX; - height = (height > txtHeight ? height : txtHeight); - break; - } - case COMPOUND_CENTER: { - /* - * Image and text are superimposed - */ - - width = (width > txtWidth ? width : txtWidth); - height = (height > txtHeight ? height : txtHeight); - break; - } - case COMPOUND_NONE: {break;} + case COMPOUND_TOP: + case COMPOUND_BOTTOM: + /* + * Image is above or below text + */ + + height += txtHeight + butPtr->padY; + width = (width > txtWidth ? width : txtWidth); + break; + case COMPOUND_LEFT: + case COMPOUND_RIGHT: + /* + * Image is left or right of text + */ + + width += txtWidth + butPtr->padX; + height = (height > txtHeight ? height : txtHeight); + break; + case COMPOUND_CENTER: + /* + * Image and text are superimposed + */ + + width = (width > txtWidth ? width : txtWidth); + height = (height > txtHeight ? height : txtHeight); + break; + case COMPOUND_NONE: + break; } if (butPtr->width > 0) { @@ -371,32 +373,24 @@ TkpComputeMenuButtonGeometry(butPtr) */ void DrawMenuButtonImageAndText( - TkMenuButton* butPtr) + TkMenuButton *butPtr) { - MacMenuButton *mbPtr = (MacMenuButton*)butPtr; - Tk_Window tkwin = butPtr->tkwin; - Pixmap pixmap; - int haveImage = 0; - int haveText = 0; - int imageWidth = 0; - int imageHeight = 0; - int imageXOffset = 0; - int imageYOffset = 0; - int textXOffset = 0; - int textYOffset = 0; - int width = 0; - int height = 0; - int fullWidth = 0; - int fullHeight = 0; - int pressed; + MacMenuButton *mbPtr = (MacMenuButton *) butPtr; + Tk_Window tkwin = butPtr->tkwin; + Pixmap pixmap; + int haveImage = 0, haveText = 0; + int imageWidth = 0, imageHeight = 0; + int imageXOffset = 0, imageYOffset = 0; + int textXOffset = 0, textYOffset = 0; + int width = 0, height = 0; + int fullWidth = 0, fullHeight = 0; if (tkwin == NULL || !Tk_IsMapped(tkwin)) { return; } - DrawParams* dpPtr = &mbPtr->drawParams; - pixmap = (Pixmap)Tk_WindowId(tkwin); - + DrawParams *dpPtr = &mbPtr->drawParams; + pixmap = (Pixmap) Tk_WindowId(tkwin); if (butPtr->image != None) { Tk_SizeOfImage(butPtr->image, &width, &height); @@ -406,86 +400,80 @@ DrawMenuButtonImageAndText( haveImage = 1; } - imageWidth = width; + imageWidth = width; imageHeight = height; - if (mbPtr->drawinfo.state == kThemeStatePressed) { - /* Offset bitmaps by a bit when the button is pressed. */ - pressed = 1; - } - haveText = (butPtr->textWidth != 0 && butPtr->textHeight != 0); if (butPtr->compound != COMPOUND_NONE && haveImage && haveText) { - int x = 0; - int y = 0; + int x = 0, y = 0; + textXOffset = 0; textYOffset = 0; fullWidth = 0; fullHeight = 0; switch ((enum compound) butPtr->compound) { - case COMPOUND_TOP: - case COMPOUND_BOTTOM: { - /* Image is above or below text */ - if (butPtr->compound == COMPOUND_TOP) { - textYOffset = height + butPtr->padY; - } else { - imageYOffset = butPtr->textHeight + butPtr->padY; - } - fullHeight = height + butPtr->textHeight + butPtr->padY; - fullWidth = (width > butPtr->textWidth ? - width : butPtr->textWidth); - textXOffset = (fullWidth - butPtr->textWidth)/2; - imageXOffset = (fullWidth - width)/2; - break; - } - case COMPOUND_LEFT: - case COMPOUND_RIGHT: { - /* - * Image is left or right of text - */ - - if (butPtr->compound == COMPOUND_LEFT) { - textXOffset = width + butPtr->padX - 2; - } else { - imageXOffset = butPtr->textWidth + butPtr->padX; - } - fullWidth = butPtr->textWidth + butPtr->padX + width; - fullHeight = (height > butPtr->textHeight ? height : - butPtr->textHeight); - textYOffset = (fullHeight - butPtr->textHeight)/2; - imageYOffset = (fullHeight - height)/2; - break; - } - case COMPOUND_CENTER: { - /* - * Image and text are superimposed - */ - - fullWidth = (width > butPtr->textWidth ? width : - butPtr->textWidth); - fullHeight = (height > butPtr->textHeight ? height : - butPtr->textHeight); - textXOffset = (fullWidth - butPtr->textWidth)/2; - imageXOffset = (fullWidth - width)/2; - textYOffset = (fullHeight - butPtr->textHeight)/2; - imageYOffset = (fullHeight - height)/2; - break; - } - case COMPOUND_NONE: {break;} + case COMPOUND_TOP: + case COMPOUND_BOTTOM: + /* + * Image is above or below text. + */ + + if (butPtr->compound == COMPOUND_TOP) { + textYOffset = height + butPtr->padY; + } else { + imageYOffset = butPtr->textHeight + butPtr->padY; + } + fullHeight = height + butPtr->textHeight + butPtr->padY; + fullWidth = (width > butPtr->textWidth ? + width : butPtr->textWidth); + textXOffset = (fullWidth - butPtr->textWidth)/2; + imageXOffset = (fullWidth - width)/2; + break; + case COMPOUND_LEFT: + case COMPOUND_RIGHT: + /* + * Image is left or right of text + */ + + if (butPtr->compound == COMPOUND_LEFT) { + textXOffset = width + butPtr->padX - 2; + } else { + imageXOffset = butPtr->textWidth + butPtr->padX; + } + fullWidth = butPtr->textWidth + butPtr->padX + width; + fullHeight = (height > butPtr->textHeight ? height : + butPtr->textHeight); + textYOffset = (fullHeight - butPtr->textHeight)/2; + imageYOffset = (fullHeight - height)/2; + break; + case COMPOUND_CENTER: + /* + * Image and text are superimposed + */ + + fullWidth = (width > butPtr->textWidth ? width : butPtr->textWidth); + fullHeight = (height > butPtr->textHeight ? height : + butPtr->textHeight); + textXOffset = (fullWidth - butPtr->textWidth) / 2; + imageXOffset = (fullWidth - width) / 2; + textYOffset = (fullHeight - butPtr->textHeight) / 2; + imageYOffset = (fullHeight - height) / 2; + break; + case COMPOUND_NONE: + break; } TkComputeAnchor(butPtr->anchor, tkwin, - butPtr->padX + butPtr->inset, - butPtr->padY + butPtr->inset, + butPtr->padX + butPtr->inset, butPtr->padY + butPtr->inset, fullWidth, fullHeight, &x, &y); imageXOffset = LEFT_INSET; imageYOffset += y; textYOffset -= 1; if (butPtr->image != NULL) { - Tk_RedrawImage(butPtr->image, 0, 0, width, - height, pixmap, imageXOffset, imageYOffset); + Tk_RedrawImage(butPtr->image, 0, 0, width, + height, pixmap, imageXOffset, imageYOffset); } else { XSetClipOrigin(butPtr->display, dpPtr->gc, imageXOffset, imageYOffset); @@ -499,12 +487,12 @@ DrawMenuButtonImageAndText( dpPtr->gc, butPtr->textLayout, x + textXOffset, y + textYOffset, 0, -1); Tk_UnderlineTextLayout(butPtr->display, pixmap, dpPtr->gc, - butPtr->textLayout, - x + textXOffset, y + textYOffset, + butPtr->textLayout, x + textXOffset, y + textYOffset, butPtr->underline); } else { + int x, y; + if (haveImage) { - int x, y; TkComputeAnchor(butPtr->anchor, tkwin, butPtr->padX + butPtr->borderWidth, butPtr->padY + butPtr->borderWidth, @@ -524,27 +512,24 @@ DrawMenuButtonImageAndText( XSetClipOrigin(butPtr->display, dpPtr->gc, 0, 0); } } else { - int x, y; textXOffset = LEFT_INSET; TkComputeAnchor(butPtr->anchor, tkwin, butPtr->padX, butPtr->padY, - butPtr->textWidth, butPtr->textHeight, &x, &y); + butPtr->textWidth, butPtr->textHeight, &x, &y); Tk_DrawTextLayout(butPtr->display, pixmap, dpPtr->gc, - butPtr->textLayout, textXOffset, y, 0, -1); + butPtr->textLayout, textXOffset, y, 0, -1); y += butPtr->textHeight/2; - } + } } } - - - + /* *-------------------------------------------------------------- * * TkMacOSXDrawMenuButton -- * - * This function draws the tk menubutton using Mac controls - * In addition, this code may apply custom colors passed - * in the TkMenubutton. + * This function draws the tk menubutton using Mac controls. In + * addition, this code may apply custom colors passed in the + * TkMenubutton. * * Results: * None. @@ -554,43 +539,39 @@ DrawMenuButtonImageAndText( * *-------------------------------------------------------------- */ + static void TkMacOSXDrawMenuButton( MacMenuButton *mbPtr, /* Mac menubutton. */ - GC gc, /* The GC we are drawing into - needed for - * the bevel button */ - Pixmap pixmap) /* The pixmap we are drawing into - needed - * for the bevel button */ + GC gc, /* The GC we are drawing into - needed for the bevel + * button */ + Pixmap pixmap) /* The pixmap we are drawing into - needed for the + * bevel button */ { - TkMenuButton * butPtr = ( TkMenuButton *)mbPtr; - TkWindow * winPtr; - HIRect cntrRect; + TkMenuButton *butPtr = (TkMenuButton *) mbPtr; + TkWindow *winPtr = (TkWindow *) butPtr->tkwin; + HIRect cntrRect; TkMacOSXDrawingContext dc; - DrawParams* dpPtr = &mbPtr->drawParams; + DrawParams *dpPtr = &mbPtr->drawParams; int useNewerHITools = 1; - winPtr = (TkWindow *)butPtr->tkwin; - TkMacOSXComputeMenuButtonParams(butPtr, &mbPtr->btnkind, &mbPtr->drawinfo); cntrRect = CGRectMake(winPtr->privatePtr->xOff, winPtr->privatePtr->yOff, - Tk_Width(butPtr->tkwin), - Tk_Height(butPtr->tkwin)); + Tk_Width(butPtr->tkwin), Tk_Height(butPtr->tkwin)); if (useNewerHITools == 1) { HIRect contHIRec; static HIThemeButtonDrawInfo hiinfo; - MenuButtonBackgroundDrawCB((MacMenuButton*) mbPtr, 32, true); - + MenuButtonBackgroundDrawCB(mbPtr, 32, true); if (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, 1, &dc)) { return; } - hiinfo.version = 0; hiinfo.state = mbPtr->drawinfo.state; - hiinfo.kind = mbPtr->btnkind; + hiinfo.kind = mbPtr->btnkind; hiinfo.value = mbPtr->drawinfo.value; hiinfo.adornment = mbPtr->drawinfo.adornment; hiinfo.animation.time.current = CFAbsoluteTimeGetCurrent(); @@ -599,10 +580,10 @@ TkMacOSXDrawMenuButton( } HIThemeDrawButton(&cntrRect, &hiinfo, dc.context, - kHIThemeOrientationNormal, &contHIRec); + kHIThemeOrientationNormal, &contHIRec); TkMacOSXRestoreDrawingContext(&dc); - MenuButtonContentDrawCB( mbPtr->btnkind, &mbPtr->drawinfo, - (MacMenuButton *)mbPtr, 32, true); + MenuButtonContentDrawCB(mbPtr->btnkind, &mbPtr->drawinfo, + mbPtr, 32, true); } else { if (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, 1, &dc)) { return; @@ -617,33 +598,34 @@ TkMacOSXDrawMenuButton( * * MenuButtonBackgroundDrawCB -- * - * This function draws the background that - * lies under checkboxes and radiobuttons. + * This function draws the background that lies under checkboxes and + * radiobuttons. * * Results: - * None. + * None. * * Side effects: - * The background gets updated to the current color. + * The background gets updated to the current color. * *-------------------------------------------------------------- */ + static void MenuButtonBackgroundDrawCB ( MacMenuButton *ptr, SInt16 depth, Boolean isColorDev) { - TkMenuButton* butPtr = (TkMenuButton*)ptr; - Tk_Window tkwin = butPtr->tkwin; + TkMenuButton* butPtr = (TkMenuButton *) ptr; + Tk_Window tkwin = butPtr->tkwin; Pixmap pixmap; + if (tkwin == NULL || !Tk_IsMapped(tkwin)) { return; } - pixmap = (Pixmap)Tk_WindowId(tkwin); - + pixmap = (Pixmap) Tk_WindowId(tkwin); Tk_Fill3DRectangle(tkwin, pixmap, butPtr->normalBorder, 0, 0, - Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT); + Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT); } /* @@ -651,16 +633,17 @@ MenuButtonBackgroundDrawCB ( * * MenuButtonContentDrawCB -- * - * This function draws the label and image for the button. + * This function draws the label and image for the button. * * Results: - * None. + * None. * * Side effects: - * The content of the button gets updated. + * The content of the button gets updated. * *-------------------------------------------------------------- */ + static void MenuButtonContentDrawCB ( ThemeButtonKind kind, @@ -669,8 +652,8 @@ MenuButtonContentDrawCB ( SInt16 depth, Boolean isColorDev) { - TkMenuButton *butPtr = (TkMenuButton *)ptr; - Tk_Window tkwin = butPtr->tkwin; + TkMenuButton *butPtr = (TkMenuButton *) ptr; + Tk_Window tkwin = butPtr->tkwin; if (tkwin == NULL || !Tk_IsMapped(tkwin)) { return; @@ -683,8 +666,8 @@ MenuButtonContentDrawCB ( * * MenuButtonEventProc -- * - * This procedure is invoked by the Tk dispatcher for various - * events on buttons. + * This procedure is invoked by the Tk dispatcher for various events on + * buttons. * * Results: * None. @@ -700,8 +683,8 @@ MenuButtonEventProc( ClientData clientData, /* Information about window. */ XEvent *eventPtr) /* Information about event. */ { - TkMenuButton *buttonPtr = (TkMenuButton *) clientData; - MacMenuButton *mbPtr = (MacMenuButton *) clientData; + TkMenuButton *buttonPtr = clientData; + MacMenuButton *mbPtr = clientData; if (eventPtr->type == ActivateNotify || eventPtr->type == DeactivateNotify) { @@ -725,9 +708,9 @@ MenuButtonEventProc( * * TkMacOSXComputeMenuButtonParams -- * - * This procedure computes the various parameters used - * when creating a Carbon Appearance control. - * These are determined by the various tk button parameters + * This procedure computes the various parameters used when creating a + * Carbon Appearance control. These are determined by the various Tk + * button parameters * * Results: * None. @@ -740,11 +723,11 @@ MenuButtonEventProc( static void TkMacOSXComputeMenuButtonParams( - TkMenuButton * butPtr, - ThemeButtonKind* btnkind, + TkMenuButton *butPtr, + ThemeButtonKind *btnkind, HIThemeButtonDrawInfo *drawinfo) { - MacMenuButton *mbPtr = (MacMenuButton *)butPtr; + MacMenuButton *mbPtr = (MacMenuButton *) butPtr; if (butPtr->image || butPtr->bitmap || butPtr->text) { /* TODO: allow for Small and Mini menubuttons. */ @@ -789,25 +772,25 @@ TkMacOSXComputeMenuButtonParams( * * TkMacOSXComputeMenuButtonDrawParams -- * - * This procedure selects an appropriate drawing context for - * drawing a menubutton. + * This procedure selects an appropriate drawing context for drawing a + * menubutton. * * Results: - * None. + * None. * * Side effects: - * Sets the button draw parameters. + * Sets the button draw parameters. * *---------------------------------------------------------------------- */ static void TkMacOSXComputeMenuButtonDrawParams( - TkMenuButton * butPtr, - DrawParams * dpPtr) + TkMenuButton *butPtr, + DrawParams *dpPtr) { - dpPtr->hasImageOrBitmap = ((butPtr->image != NULL) || - (butPtr->bitmap != None)); + dpPtr->hasImageOrBitmap = + ((butPtr->image != NULL) || (butPtr->bitmap != None)); dpPtr->border = butPtr->normalBorder; if ((butPtr->state == STATE_DISABLED) && (butPtr->disabledFg != NULL)) { dpPtr->gc = butPtr->disabledGC; @@ -818,7 +801,7 @@ TkMacOSXComputeMenuButtonDrawParams( dpPtr->gc = butPtr->normalTextGC; } } - + /* * Local Variables: * mode: objc diff --git a/macosx/tkMacOSXMenus.c b/macosx/tkMacOSXMenus.c index 7d77d23..5e6a37c 100644 --- a/macosx/tkMacOSXMenus.c +++ b/macosx/tkMacOSXMenus.c @@ -177,7 +177,6 @@ static Tcl_Obj * GetWidgetDemoPath(Tcl_Interp *interp); SEL action = [anItem action]; if (sel_isEqual(action, @selector(preferences:))) { - return (_eventInterp && Tcl_FindCommand(_eventInterp, "::tk::mac::ShowPreferences", NULL, 0)); } else if (sel_isEqual(action, @selector(tkDemo:))) { diff --git a/macosx/tkMacOSXNotify.c b/macosx/tkMacOSXNotify.c index 3a32527..7267b00 100644 --- a/macosx/tkMacOSXNotify.c +++ b/macosx/tkMacOSXNotify.c @@ -33,7 +33,7 @@ static void TkMacOSXEventsSetupProc(ClientData clientData, int flags); static void TkMacOSXEventsCheckProc(ClientData clientData, int flags); #ifdef TK_MAC_DEBUG_EVENTS -static char* Tk_EventName[39] = { +static const char *Tk_EventName[39] = { "", "", "KeyPress", /*2*/ @@ -136,8 +136,8 @@ void DebugPrintQueue(void) /* * Since the contentView is the first responder for a Tk Window, it is - * responsible for sending events up the responder chain. We also check - * the pasteboard here. + * responsible for sending events up the responder chain. We also check the + * pasteboard here. */ - (void) sendEvent: (NSEvent *) theEvent { @@ -190,8 +190,8 @@ GetRunLoopMode(NSModalSession modalSession) * * Tk_MacOSXSetupTkNotifier -- * - * This procedure is called during Tk initialization to create - * the event source for TkAqua events. + * This procedure is called during Tk initialization to create the event + * source for TkAqua events. * * Results: * None. @@ -224,8 +224,7 @@ Tk_MacOSXSetupTkNotifier(void) "first [load] of TkAqua has to occur in the main thread!"); } Tcl_CreateEventSource(TkMacOSXEventsSetupProc, - TkMacOSXEventsCheckProc, - NULL); + TkMacOSXEventsCheckProc, NULL); TkCreateExitHandler(TkMacOSXNotifyExitHandler, NULL); Tcl_SetServiceMode(TCL_SERVICE_ALL); TclMacOSXNotifierAddRunLoopMode(NSEventTrackingRunLoopMode); @@ -258,8 +257,7 @@ TkMacOSXNotifyExitHandler( TSD_INIT(); Tcl_DeleteEventSource(TkMacOSXEventsSetupProc, - TkMacOSXEventsCheckProc, - NULL); + TkMacOSXEventsCheckProc, NULL); tsdPtr->initialized = 0; } @@ -268,19 +266,19 @@ TkMacOSXNotifyExitHandler( * * TkMacOSXEventsSetupProc -- * - * This procedure implements the setup part of the MacOSX event - * source. It is invoked by Tcl_DoOneEvent before calling - * TkMacOSXEventsProc to process all queued NSEvents. In our - * case, all we need to do is to set the Tcl MaxBlockTime to - * 0 before starting the loop to process all queued NSEvents. + * This procedure implements the setup part of the MacOSX event source. It + * is invoked by Tcl_DoOneEvent before calling TkMacOSXEventsProc to + * process all queued NSEvents. In our case, all we need to do is to set + * the Tcl MaxBlockTime to 0 before starting the loop to process all + * queued NSEvents. * * Results: * None. * * Side effects: * - * If NSEvents are queued, then the maximum block time will be set - * to 0 to ensure that control returns immediately to Tcl. + * If NSEvents are queued, then the maximum block time will be set to 0 to + * ensure that control returns immediately to Tcl. * *---------------------------------------------------------------------- */ @@ -291,15 +289,24 @@ TkMacOSXEventsSetupProc( int flags) { NSString *runloopMode = [[NSRunLoop currentRunLoop] currentMode]; - /* runloopMode will be nil if we are in a Tcl event loop. */ + + /* + * runloopMode will be nil if we are in a Tcl event loop. + */ + if (flags & TCL_WINDOW_EVENTS && !runloopMode) { static const Tcl_Time zeroBlockTime = { 0, 0 }; [NSApp _resetAutoreleasePool]; - /* Call this with dequeue=NO -- just checking if the queue is empty. */ - NSEvent *currentEvent = [NSApp nextEventMatchingMask:NSAnyEventMask - untilDate:[NSDate distantPast] - inMode:GetRunLoopMode(TkMacOSXGetModalSession()) - dequeue:NO]; + + /* + * Call this with dequeue=NO -- just checking if the queue is empty. + */ + + NSEvent *currentEvent = + [NSApp nextEventMatchingMask:NSAnyEventMask + untilDate:[NSDate distantPast] + inMode:GetRunLoopMode(TkMacOSXGetModalSession()) + dequeue:NO]; if (currentEvent) { if (currentEvent.type > 0) { Tcl_SetMaxBlockTime(&zeroBlockTime); @@ -313,15 +320,15 @@ TkMacOSXEventsSetupProc( * * TkMacOSXEventsCheckProc -- * - * This procedure loops through all NSEvents waiting in the - * TKApplication event queue, generating X events from them. + * This procedure loops through all NSEvents waiting in the TKApplication + * event queue, generating X events from them. * * Results: * None. * * Side effects: - * NSevents are used to generate X events, which are added to the - * Tcl event queue. + * NSevents are used to generate X events, which are added to the Tcl + * event queue. * *---------------------------------------------------------------------- */ @@ -331,34 +338,48 @@ TkMacOSXEventsCheckProc( int flags) { NSString *runloopMode = [[NSRunLoop currentRunLoop] currentMode]; - /* runloopMode will be nil if we are in a Tcl event loop. */ + + /* + * runloopMode will be nil if we are in a Tcl event loop. + */ + if (flags & TCL_WINDOW_EVENTS && !runloopMode) { NSEvent *currentEvent = nil; NSEvent *testEvent = nil; NSModalSession modalSession; - /* It is possible for the SetupProc to be called before this function + + /* + * It is possible for the SetupProc to be called before this function * returns. This happens, for example, when we process an event which * opens a modal window. To prevent premature release of our * application-wide autorelease pool by a nested call to the SetupProc, * we must lock it here. */ + [NSApp _lockAutoreleasePool]; do { modalSession = TkMacOSXGetModalSession(); - testEvent = [NSApp nextEventMatchingMask:NSAnyEventMask - untilDate:[NSDate distantPast] - inMode:GetRunLoopMode(modalSession) - dequeue:NO]; - /* We must not steal any events during LiveResize. */ + testEvent = [NSApp nextEventMatchingMask:NSAnyEventMask + untilDate:[NSDate distantPast] + inMode:GetRunLoopMode(modalSession) + dequeue:NO]; + + /* + * We must not steal any events during LiveResize. + */ + if (testEvent && [[testEvent window] inLiveResize]) { break; } currentEvent = [NSApp nextEventMatchingMask:NSAnyEventMask - untilDate:[NSDate distantPast] - inMode:GetRunLoopMode(modalSession) - dequeue:YES]; + untilDate:[NSDate distantPast] + inMode:GetRunLoopMode(modalSession) + dequeue:YES]; if (currentEvent) { - /* Generate Xevents. */ + /* + * Generate Xevents. + */ + int oldServiceMode = Tcl_SetServiceMode(TCL_SERVICE_ALL); NSEvent *processedEvent = [NSApp tkProcessEvent:currentEvent]; Tcl_SetServiceMode(oldServiceMode); @@ -372,16 +393,18 @@ TkMacOSXEventsCheckProc( [NSApp sendEvent:currentEvent]; } } - } else { break; } } while (1); - /* Now we can unlock the pool. */ + + /* + * Now we can unlock the pool. + */ + [NSApp _unlockAutoreleasePool]; } } - /* * Local Variables: diff --git a/macosx/tkMacOSXRegion.c b/macosx/tkMacOSXRegion.c index 0f2a74a..323318c 100644 --- a/macosx/tkMacOSXRegion.c +++ b/macosx/tkMacOSXRegion.c @@ -187,8 +187,8 @@ TkMacOSXIsEmptyRegion( * Xwindow documentation for more details. * * Results: - * Returns RectanglePart or RectangleOut. Note that this is not a - * complete implementation since it doesn't test for RectangleIn. + * Returns RectanglePart or RectangleOut. Note that this is not a complete + * implementation since it doesn't test for RectangleIn. * * Side effects: * None. @@ -204,13 +204,13 @@ TkRectInRegion( unsigned int width, unsigned int height) { - if ( TkMacOSXIsEmptyRegion(region) ) { - return RectangleOut; - } - else { + if (TkMacOSXIsEmptyRegion(region)) { + return RectangleOut; + } else { const CGRect r = CGRectMake(x, y, width, height); + return HIShapeIntersectsRect((HIShapeRef) region, &r) ? - RectanglePart : RectangleOut; + RectanglePart : RectangleOut; } } @@ -234,7 +234,7 @@ TkRectInRegion( void TkClipBox( TkRegion r, - XRectangle* rect_return) + XRectangle *rect_return) { CGRect rect; diff --git a/macosx/tkMacOSXScale.c b/macosx/tkMacOSXScale.c index 8a6a96b..0195ffb 100644 --- a/macosx/tkMacOSXScale.c +++ b/macosx/tkMacOSXScale.c @@ -51,10 +51,10 @@ static ControlActionUPP scaleActionProc = NULL; /* Pointer to func. */ * Forward declarations for procedures defined later in this file: */ -static void MacScaleEventProc(ClientData clientData, XEvent *eventPtr); -static pascal void ScaleActionProc(ControlRef theControl, - ControlPartCode partCode); - +static void MacScaleEventProc(ClientData clientData, + XEvent *eventPtr); +static pascal void ScaleActionProc(ControlRef theControl, + ControlPartCode partCode); /* *---------------------------------------------------------------------- @@ -84,7 +84,7 @@ TkpCreateScale( } Tk_CreateEventHandler(tkwin, ButtonPressMask, - MacScaleEventProc, (ClientData) macScalePtr); + MacScaleEventProc, macScalePtr); return (TkScale *) macScalePtr; } @@ -125,8 +125,8 @@ TkpDestroyScale( * * TkpDisplayScale -- * - * This procedure is invoked as an idle handler to redisplay - * the contents of a scale widget. + * This procedure is invoked as an idle handler to redisplay the contents + * of a scale widget. * * Results: * None. @@ -141,12 +141,12 @@ void TkpDisplayScale( ClientData clientData) /* Widget record for scale. */ { - TkScale *scalePtr = (TkScale *) clientData; + TkScale *scalePtr = clientData; Tk_Window tkwin = scalePtr->tkwin; Tcl_Interp *interp = scalePtr->interp; int result; char string[TCL_DOUBLE_SPACE]; - MacScale *macScalePtr = (MacScale *) clientData; + MacScale *macScalePtr = clientData; Rect r; WindowRef windowRef; CGrafPtr destPort, savePort; @@ -168,9 +168,9 @@ TkpDisplayScale( * Invoke the scale's command if needed. */ - Tcl_Preserve((ClientData) scalePtr); + Tcl_Preserve(scalePtr); if ((scalePtr->flags & INVOKE_COMMAND) && (scalePtr->command != NULL)) { - Tcl_Preserve((ClientData) interp); + Tcl_Preserve(interp); if (snprintf(string, TCL_DOUBLE_SPACE, scalePtr->format, scalePtr->value) < 0) { string[TCL_DOUBLE_SPACE - 1] = '\0'; @@ -185,19 +185,18 @@ TkpDisplayScale( Tcl_AddErrorInfo(interp, "\n (command executed by scale)"); Tcl_BackgroundException(interp, result); } - Tcl_Release((ClientData) interp); + Tcl_Release(interp); } scalePtr->flags &= ~INVOKE_COMMAND; if (scalePtr->flags & SCALE_DELETED) { - Tcl_Release((ClientData) scalePtr); + Tcl_Release(scalePtr); return; } - Tcl_Release((ClientData) scalePtr); + Tcl_Release(scalePtr); /* - * Now handle the part of redisplay that is the same for - * horizontal and vertical scales: border and traversal - * highlight. + * Now handle the part of redisplay that is the same for horizontal and + * vertical scales: border and traversal highlight. */ if (scalePtr->highlightWidth != 0) { @@ -229,7 +228,7 @@ TkpDisplayScale( #define MAC_OSX_SCROLL_WIDTH 10 if (scalePtr->orient == ORIENT_HORIZONTAL) { - int offset = (Tk_Height(tkwin) - MAC_OSX_SCROLL_WIDTH)/2; + int offset = (Tk_Height(tkwin) - MAC_OSX_SCROLL_WIDTH) / 2; if (offset < 0) { offset = 0; @@ -240,7 +239,7 @@ TkpDisplayScale( r.right = macDraw->xOff+Tk_Width(tkwin) - scalePtr->inset; r.bottom = macDraw->yOff + offset + MAC_OSX_SCROLL_WIDTH/2; } else { - int offset = (Tk_Width(tkwin) - MAC_OSX_SCROLL_WIDTH)/2; + int offset = (Tk_Width(tkwin) - MAC_OSX_SCROLL_WIDTH) / 2; if (offset < 0) { offset = 0; @@ -249,7 +248,7 @@ TkpDisplayScale( r.left = macDraw->xOff + offset; r.top = macDraw->yOff + scalePtr->inset; r.right = macDraw->xOff + offset + MAC_OSX_SCROLL_WIDTH/2; - r.bottom = macDraw->yOff+Tk_Height(tkwin) - scalePtr->inset; + r.bottom = macDraw->yOff + Tk_Height(tkwin) - scalePtr->inset; } if (macScalePtr->scaleHandle == NULL) { @@ -273,7 +272,7 @@ TkpDisplayScale( CreateSliderControl(windowRef, &r, initialValue, minValue, maxValue, kControlSliderPointsDownOrRight, numTicks, 1, scaleActionProc, - &(macScalePtr->scaleHandle)); + &macScalePtr->scaleHandle); SetControlReference(macScalePtr->scaleHandle, (UInt32) scalePtr); if (IsWindowActive(windowRef)) { @@ -290,8 +289,8 @@ TkpDisplayScale( * Finally draw the control. */ - SetControlVisibility(macScalePtr->scaleHandle,true,true); - HiliteControl(macScalePtr->scaleHandle,0); + SetControlVisibility(macScalePtr->scaleHandle, true, true); + HiliteControl(macScalePtr->scaleHandle, 0); Draw1Control(macScalePtr->scaleHandle); if (portChanged) { @@ -306,13 +305,12 @@ done: * * TkpScaleElement -- * - * Determine which part of a scale widget lies under a given - * point. + * Determine which part of a scale widget lies under a given point. * * Results: - * The return value is either TROUGH1, SLIDER, TROUGH2, or - * OTHER, depending on which of the scale's active elements - * (if any) is under the point at (x,y). + * The return value is either TROUGH1, SLIDER, TROUGH2, or OTHER, + * depending on which of the scale's active elements (if any) is under the + * point at (x,y). * * Side effects: * None. @@ -357,22 +355,22 @@ TkpScaleElement( #endif switch (part) { - case inSlider: - return SLIDER; - case inInc: - if (scalePtr->orient == ORIENT_VERTICAL) { - return TROUGH1; - } else { - return TROUGH2; - } - case inDecr: - if (scalePtr->orient == ORIENT_VERTICAL) { - return TROUGH2; - } else { - return TROUGH1; - } - default: - return OTHER; + case inSlider: + return SLIDER; + case inInc: + if (scalePtr->orient == ORIENT_VERTICAL) { + return TROUGH1; + } else { + return TROUGH2; + } + case inDecr: + if (scalePtr->orient == ORIENT_VERTICAL) { + return TROUGH2; + } else { + return TROUGH1; + } + default: + return OTHER; } } @@ -381,15 +379,15 @@ TkpScaleElement( * * MacScaleEventProc -- * - * This procedure is invoked by the Tk dispatcher for - * ButtonPress events on scales. + * This procedure is invoked by the Tk dispatcher for ButtonPress events + * on scales. * * Results: * None. * * Side effects: - * When the window gets deleted, internal structures get - * cleaned up. When it gets exposed, it is redisplayed. + * When the window gets deleted, internal structures get cleaned up. When + * it gets exposed, it is redisplayed. * *-------------------------------------------------------------- */ @@ -411,9 +409,9 @@ MacScaleEventProc( #endif /* - * To call Macintosh control routines we must have the port - * set to the window containing the control. We will then test - * which part of the control was hit and act accordingly. + * To call Macintosh control routines we must have the port set to the + * window containing the control. We will then test which part of the + * control was hit and act accordingly. */ destPort = TkMacOSXGetDrawablePort(Tk_WindowId(macScalePtr->info.tkwin)); @@ -461,8 +459,8 @@ MacScaleEventProc( * ScaleActionProc -- * * Callback procedure used by the Macintosh toolbox call - * HandleControlClick. This call will update the display - * while the scrollbar is being manipulated by the user. + * HandleControlClick. This call will update the display while the + * scrollbar is being manipulated by the user. * * Results: * None. @@ -486,9 +484,9 @@ ScaleActionProc( #endif value = GetControlValue(theControl); TkScaleSetValue(scalePtr, value, 1, 1); - Tcl_Preserve((ClientData) scalePtr); + Tcl_Preserve(scalePtr); TkMacOSXRunTclEventLoop(); - Tcl_Release((ClientData) scalePtr); + Tcl_Release(scalePtr); } #endif diff --git a/macosx/tkMacOSXScrlbr.c b/macosx/tkMacOSXScrlbr.c index 4a108db..06e0a64 100644 --- a/macosx/tkMacOSXScrlbr.c +++ b/macosx/tkMacOSXScrlbr.c @@ -9,6 +9,7 @@ * Copyright (c) 2006-2009 Daniel A. Steffen * Copyright (c) 2015 Kevin Walzer/WordTech Commununications LLC. * Copyright (c) 2018 Marc Culler + * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -17,7 +18,6 @@ #include "tkScrollbar.h" #include "tkMacOSXPrivate.h" - #define MIN_SCROLLBAR_VALUE 0 /* @@ -27,18 +27,21 @@ #define MIN_SLIDER_LENGTH 5 -/*Borrowed from ttkMacOSXTheme.c to provide appropriate scaling.*/ +/* + * Borrowed from ttkMacOSXTheme.c to provide appropriate scaling. + */ + #ifdef __LP64__ -#define RangeToFactor(maximum) (((double) (INT_MAX >> 1)) / (maximum)) +#define RangeToFactor(maximum) (((double) (INT_MAX >> 1)) / (maximum)) #else -#define RangeToFactor(maximum) (((double) (LONG_MAX >> 1)) / (maximum)) +#define RangeToFactor(maximum) (((double) (LONG_MAX >> 1)) / (maximum)) #endif /* __LP64__ */ /* * Apple reversed the scroll direction with the release of OSX 10.7 Lion. */ -#define SNOW_LEOPARD_STYLE (NSAppKitVersionNumber < 1138) +#define SNOW_LEOPARD_STYLE (NSAppKitVersionNumber < 1138) /* * Declaration of an extended scrollbar structure with Mac specific additions. @@ -50,7 +53,7 @@ typedef struct MacScrollbar { GC copyGC; /* Used for copying from pixmap onto screen. */ Bool buttonDown; /* Is the mouse button down? */ Bool mouseOver; /* Is the pointer over the scrollbar. */ - HIThemeTrackDrawInfo info; /* Controls how the scrollbar is drawn. */ + HIThemeTrackDrawInfo info; /* Controls how the scrollbar is drawn. */ } MacScrollbar; /* Used to initialize a MacScrollbar's info field. */ @@ -69,33 +72,35 @@ HIThemeTrackDrawInfo defaultInfo = { const Tk_ClassProcs tkpScrollbarProcs = { sizeof(Tk_ClassProcs), /* size */ - NULL, /* worldChangedProc */ - NULL, /* createProc */ - NULL /* modalProc */ + NULL, /* worldChangedProc */ + NULL, /* createProc */ + NULL /* modalProc */ }; +/* + * Information on scrollbar layout, metrics, and draw info. + */ -/* Information on scrollbar layout, metrics, and draw info.*/ typedef struct ScrollbarMetrics { SInt32 width, minThumbHeight; int minHeight, topArrowHeight, bottomArrowHeight; NSControlSize controlSize; } ScrollbarMetrics; - static ScrollbarMetrics metrics = { - 15, 54, 26, 14, 14, kControlSizeNormal /* kThemeScrollBarMedium */ + 15, 54, 26, 14, 14, kControlSizeNormal /* kThemeScrollBarMedium */ }; - /* * Declarations of static functions defined later in this file: */ -static void ScrollbarEventProc(ClientData clientData, XEvent *eventPtr); -static int ScrollbarEvent(TkScrollbar *scrollPtr, XEvent *eventPtr); -static void UpdateControlValues(TkScrollbar *scrollPtr); - +static void ScrollbarEventProc(ClientData clientData, + XEvent *eventPtr); +static int ScrollbarEvent(TkScrollbar *scrollPtr, + XEvent *eventPtr); +static void UpdateControlValues(TkScrollbar *scrollPtr); + /* *---------------------------------------------------------------------- * @@ -114,10 +119,9 @@ static void UpdateControlValues(TkScrollbar *scrollPtr); TkScrollbar * TkpCreateScrollbar( - Tk_Window tkwin) + Tk_Window tkwin) { - - MacScrollbar *scrollPtr = (MacScrollbar *)ckalloc(sizeof(MacScrollbar)); + MacScrollbar *scrollPtr = ckalloc(sizeof(MacScrollbar)); scrollPtr->troughGC = NULL; scrollPtr->copyGC = NULL; @@ -125,15 +129,15 @@ TkpCreateScrollbar( scrollPtr->buttonDown = false; Tk_CreateEventHandler(tkwin, - ExposureMask | - StructureNotifyMask | - FocusChangeMask | - ButtonPressMask | - ButtonReleaseMask | - EnterWindowMask | - LeaveWindowMask | - VisibilityChangeMask, - ScrollbarEventProc, scrollPtr); + ExposureMask | + StructureNotifyMask | + FocusChangeMask | + ButtonPressMask | + ButtonReleaseMask | + EnterWindowMask | + LeaveWindowMask | + VisibilityChangeMask, + ScrollbarEventProc, scrollPtr); return (TkScrollbar *) scrollPtr; } @@ -144,8 +148,8 @@ TkpCreateScrollbar( * TkpDisplayScrollbar -- * * This procedure redraws the contents of a scrollbar window. It is - * invoked as a do-when-idle handler, so it only runs when there's - * nothing else for the application to do. + * invoked as a do-when-idle handler, so it only runs when there's nothing + * else for the application to do. * * Results: * None. @@ -158,9 +162,9 @@ TkpCreateScrollbar( void TkpDisplayScrollbar( - ClientData clientData) /* Information about window. */ + ClientData clientData) /* Information about window. */ { - register TkScrollbar *scrollPtr = (TkScrollbar *) clientData; + register TkScrollbar *scrollPtr = clientData; MacScrollbar *msPtr = (MacScrollbar *) scrollPtr; register Tk_Window tkwin = scrollPtr->tkwin; TkWindow *winPtr = (TkWindow *) tkwin; @@ -169,23 +173,31 @@ TkpDisplayScrollbar( scrollPtr->flags &= ~REDRAW_PENDING; if (tkwin == NULL || !Tk_IsMapped(tkwin)) { - return; + return; } - MacDrawable *macWin = (MacDrawable *) winPtr->window; + MacDrawable *macWin = (MacDrawable *) winPtr->window; NSView *view = TkMacOSXDrawableView(macWin); - if (!view || - macWin->flags & TK_DO_NOT_DRAW || - !TkMacOSXSetupDrawingContext((Drawable) macWin, NULL, 1, &dc)) { - return; + + if ((view == NULL) + || (macWin->flags & TK_DO_NOT_DRAW) + || !TkMacOSXSetupDrawingContext((Drawable) macWin, NULL, 1, &dc)) { + return; } CGFloat viewHeight = [view bounds].size.height; - CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1, .tx = 0, - .ty = viewHeight}; + CGAffineTransform t = { + .a = 1, .b = 0, + .c = 0, .d = -1, + .tx = 0, .ty = viewHeight + }; + CGContextConcatCTM(dc.context, t); - /*Draw a 3D rectangle to provide a base for the native scrollbar.*/ + /* + * Draw a 3D rectangle to provide a base for the native scrollbar. + */ + if (scrollPtr->highlightWidth != 0) { GC fgGC, bgGC; @@ -196,32 +208,37 @@ TkpDisplayScrollbar( fgGC = bgGC; } TkpDrawHighlightBorder(tkwin, fgGC, bgGC, scrollPtr->highlightWidth, - (Pixmap) macWin); + (Pixmap) macWin); } Tk_Draw3DRectangle(tkwin, (Pixmap) macWin, scrollPtr->bgBorder, - scrollPtr->highlightWidth, scrollPtr->highlightWidth, - Tk_Width(tkwin) - 2*scrollPtr->highlightWidth, - Tk_Height(tkwin) - 2*scrollPtr->highlightWidth, - scrollPtr->borderWidth, scrollPtr->relief); + scrollPtr->highlightWidth, scrollPtr->highlightWidth, + Tk_Width(tkwin) - 2*scrollPtr->highlightWidth, + Tk_Height(tkwin) - 2*scrollPtr->highlightWidth, + scrollPtr->borderWidth, scrollPtr->relief); Tk_Fill3DRectangle(tkwin, (Pixmap) macWin, scrollPtr->bgBorder, - scrollPtr->inset, scrollPtr->inset, - Tk_Width(tkwin) - 2*scrollPtr->inset, - Tk_Height(tkwin) - 2*scrollPtr->inset, 0, TK_RELIEF_FLAT); + scrollPtr->inset, scrollPtr->inset, + Tk_Width(tkwin) - 2*scrollPtr->inset, + Tk_Height(tkwin) - 2*scrollPtr->inset, 0, TK_RELIEF_FLAT); + + /* + * Update values and then draw the native scrollbar over the rectangle. + */ - /* Update values and then draw the native scrollbar over the rectangle.*/ UpdateControlValues(scrollPtr); if (SNOW_LEOPARD_STYLE) { - HIThemeDrawTrack (&(msPtr->info), 0, dc.context, kHIThemeOrientationInverted); + HIThemeDrawTrack(&msPtr->info, 0, dc.context, + kHIThemeOrientationInverted); } else { - HIThemeDrawTrack (&(msPtr->info), 0, dc.context, kHIThemeOrientationNormal); + HIThemeDrawTrack(&msPtr->info, 0, dc.context, + kHIThemeOrientationNormal); } TkMacOSXRestoreDrawingContext(&dc); scrollPtr->flags &= ~REDRAW_PENDING; } - + /* *---------------------------------------------------------------------- * @@ -240,44 +257,41 @@ TkpDisplayScrollbar( *---------------------------------------------------------------------- */ - - extern void TkpComputeScrollbarGeometry( register TkScrollbar *scrollPtr) - /* Scrollbar whose geometry may have - * changed. */ + /* Scrollbar whose geometry may have + * changed. */ { - - /* - * The code below is borrowed from tkUnixScrlbr.c but has been adjusted to - * account for some differences between macOS and X11. The Unix scrollbar - * has an arrow button on each end. On macOS 10.6 (Snow Leopard) the - * scrollbars by default have both arrow buttons at the bottom or right. - * (There is a preferences setting to use the Unix layout, but we are not - * supporting that!) On more recent versions of macOS there are no arrow - * buttons at all. The case of no arrow buttons can be handled as a special - * case of having both buttons at the end, but where scrollPtr->arrowLength - * happens to be zero. To adjust for having both arrows at the same end we - * shift the scrollbar up by the arrowLength. - */ + /* + * The code below is borrowed from tkUnixScrlbr.c but has been adjusted to + * account for some differences between macOS and X11. The Unix scrollbar + * has an arrow button on each end. On macOS 10.6 (Snow Leopard) the + * scrollbars by default have both arrow buttons at the bottom or right. + * (There is a preferences setting to use the Unix layout, but we are not + * supporting that!) On more recent versions of macOS there are no arrow + * buttons at all. The case of no arrow buttons can be handled as a special + * case of having both buttons at the end, but where scrollPtr->arrowLength + * happens to be zero. To adjust for having both arrows at the same end we + * shift the scrollbar up by the arrowLength. + */ int fieldLength; if (scrollPtr->highlightWidth < 0) { - scrollPtr->highlightWidth = 0; + scrollPtr->highlightWidth = 0; } scrollPtr->inset = scrollPtr->highlightWidth + scrollPtr->borderWidth; if ([NSApp macMinorVersion] == 6) { - scrollPtr->arrowLength = scrollPtr->width; + scrollPtr->arrowLength = scrollPtr->width; } else { - scrollPtr->arrowLength = 0; + scrollPtr->arrowLength = 0; } fieldLength = (scrollPtr->vertical ? Tk_Height(scrollPtr->tkwin) - : Tk_Width(scrollPtr->tkwin)) - - 2*(scrollPtr->arrowLength + scrollPtr->inset); + : Tk_Width(scrollPtr->tkwin)) + - 2*(scrollPtr->arrowLength + scrollPtr->inset); if (fieldLength < 0) { - fieldLength = 0; + fieldLength = 0; } scrollPtr->sliderFirst = fieldLength*scrollPtr->firstFraction; scrollPtr->sliderLast = fieldLength*scrollPtr->lastFraction; @@ -289,16 +303,16 @@ TkpComputeScrollbarGeometry( */ if (scrollPtr->sliderFirst > fieldLength - MIN_SLIDER_LENGTH) { - scrollPtr->sliderFirst = fieldLength - MIN_SLIDER_LENGTH; + scrollPtr->sliderFirst = fieldLength - MIN_SLIDER_LENGTH; } if (scrollPtr->sliderFirst < 0) { - scrollPtr->sliderFirst = 0; + scrollPtr->sliderFirst = 0; } if (scrollPtr->sliderLast < scrollPtr->sliderFirst + MIN_SLIDER_LENGTH) { - scrollPtr->sliderLast = scrollPtr->sliderFirst + MIN_SLIDER_LENGTH; + scrollPtr->sliderLast = scrollPtr->sliderFirst + MIN_SLIDER_LENGTH; } if (scrollPtr->sliderLast > fieldLength) { - scrollPtr->sliderLast = fieldLength; + scrollPtr->sliderLast = fieldLength; } scrollPtr->sliderFirst += -scrollPtr->arrowLength + scrollPtr->inset; scrollPtr->sliderLast += scrollPtr->inset; @@ -310,20 +324,20 @@ TkpComputeScrollbarGeometry( * be redisplayed. */ - if (scrollPtr->vertical) { - Tk_GeometryRequest(scrollPtr->tkwin, - scrollPtr->width + 2*scrollPtr->inset, - 2*(scrollPtr->arrowLength + scrollPtr->borderWidth - + scrollPtr->inset) + metrics.minThumbHeight); + if (scrollPtr->vertical) { + Tk_GeometryRequest(scrollPtr->tkwin, + scrollPtr->width + 2*scrollPtr->inset, + 2*(scrollPtr->arrowLength + scrollPtr->borderWidth + + scrollPtr->inset) + metrics.minThumbHeight); } else { - Tk_GeometryRequest(scrollPtr->tkwin, - 2*(scrollPtr->arrowLength + scrollPtr->borderWidth - + scrollPtr->inset) + metrics.minThumbHeight, - scrollPtr->width + 2*scrollPtr->inset); + Tk_GeometryRequest(scrollPtr->tkwin, + 2*(scrollPtr->arrowLength + scrollPtr->borderWidth + + scrollPtr->inset) + metrics.minThumbHeight, + scrollPtr->width + 2*scrollPtr->inset); } Tk_SetInternalBorder(scrollPtr->tkwin, scrollPtr->inset); } - + /* *---------------------------------------------------------------------- * @@ -342,9 +356,9 @@ TkpComputeScrollbarGeometry( void TkpDestroyScrollbar( - TkScrollbar *scrollPtr) + TkScrollbar *scrollPtr) { - MacScrollbar *macScrollPtr = (MacScrollbar *)scrollPtr; + MacScrollbar *macScrollPtr = (MacScrollbar *) scrollPtr; if (macScrollPtr->troughGC != None) { Tk_FreeGC(scrollPtr->display, macScrollPtr->troughGC); @@ -353,15 +367,15 @@ TkpDestroyScrollbar( Tk_FreeGC(scrollPtr->display, macScrollPtr->copyGC); } } - + /* *---------------------------------------------------------------------- * * TkpConfigureScrollbar -- * - * This procedure is called after the generic code has finished - * processing configuration options, in order to configure platform - * specific options. There are no such option on the Mac, however. + * This procedure is called after the generic code has finished processing + * configuration options, in order to configure platform specific options. + * There are no such option on the Mac, however. * * Results: * None. @@ -374,11 +388,11 @@ TkpDestroyScrollbar( void TkpConfigureScrollbar( - register TkScrollbar *scrollPtr) + register TkScrollbar *scrollPtr) { - + /* empty */ } - + /* *-------------------------------------------------------------- * @@ -403,29 +417,28 @@ TkpScrollbarPosition( /* Scrollbar widget record. */ int x, int y) /* Coordinates within scrollPtr's window. */ { - - /* - * The code below is borrowed from tkUnixScrlbr.c and needs no adjustment - * since it does not involve the arrow buttons. - */ + /* + * The code below is borrowed from tkUnixScrlbr.c and needs no adjustment + * since it does not involve the arrow buttons. + */ int length, width, tmp; register const int inset = scrollPtr->inset; if (scrollPtr->vertical) { - length = Tk_Height(scrollPtr->tkwin); - width = Tk_Width(scrollPtr->tkwin); + length = Tk_Height(scrollPtr->tkwin); + width = Tk_Width(scrollPtr->tkwin); } else { - tmp = x; - x = y; - y = tmp; - length = Tk_Width(scrollPtr->tkwin); - width = Tk_Height(scrollPtr->tkwin); + tmp = x; + x = y; + y = tmp; + length = Tk_Width(scrollPtr->tkwin); + width = Tk_Height(scrollPtr->tkwin); } if (x < inset || x >= width - inset || - y < inset || y >= length - inset) { - return OUTSIDE; + y < inset || y >= length - inset) { + return OUTSIDE; } /* @@ -436,31 +449,34 @@ TkpScrollbarPosition( */ if (y < scrollPtr->sliderFirst + scrollPtr->arrowLength) { - return TOP_GAP; - } - if (y < scrollPtr->sliderLast) { - return SLIDER; - } - if (y < length - (2*scrollPtr->arrowLength + inset)) { - return BOTTOM_GAP; - } - /* On systems newer than 10.6 we have already returned. */ - if (y < length - (scrollPtr->arrowLength + inset)) { - return TOP_ARROW; - } - return BOTTOM_ARROW; -} + return TOP_GAP; + } + if (y < scrollPtr->sliderLast) { + return SLIDER; + } + if (y < length - (2*scrollPtr->arrowLength + inset)) { + return BOTTOM_GAP; + } + /* + * On systems newer than 10.6 we have already returned. + */ + + if (y < length - (scrollPtr->arrowLength + inset)) { + return TOP_ARROW; + } + return BOTTOM_ARROW; +} + /* *-------------------------------------------------------------- * * UpdateControlValues -- * - * This procedure updates the Macintosh scrollbar control to - * display the values defined by the Tk scrollbar. This is the - * key interface to the Mac-native scrollbar; the Unix bindings - * drive scrolling in the Tk window and all the Mac scrollbar has - * to do is redraw itself. + * This procedure updates the Macintosh scrollbar control to display the + * values defined by the Tk scrollbar. This is the key interface to the + * Mac-native scrollbar; the Unix bindings drive scrolling in the Tk + * window and all the Mac scrollbar has to do is redraw itself. * * Results: * None. @@ -473,20 +489,21 @@ TkpScrollbarPosition( static void UpdateControlValues( - TkScrollbar *scrollPtr) /* Scrollbar data struct. */ + TkScrollbar *scrollPtr) /* Scrollbar data struct. */ { - MacScrollbar *msPtr = (MacScrollbar *)scrollPtr; + MacScrollbar *msPtr = (MacScrollbar *) scrollPtr; Tk_Window tkwin = scrollPtr->tkwin; MacDrawable *macWin = (MacDrawable *) Tk_WindowId(scrollPtr->tkwin); double dViewSize; - HIRect contrlRect; + HIRect contrlRect; short width, height; NSView *view = TkMacOSXDrawableView(macWin); CGFloat viewHeight = [view bounds].size.height; NSRect frame; + frame = NSMakeRect(macWin->xOff, macWin->yOff, Tk_Width(tkwin), - Tk_Height(tkwin)); + Tk_Height(tkwin)); frame = NSInsetRect(frame, scrollPtr->inset, scrollPtr->inset); frame.origin.y = viewHeight - (frame.origin.y + frame.size.height); @@ -503,9 +520,9 @@ UpdateControlValues( msPtr->info.bounds = contrlRect; if (scrollPtr->vertical) { - msPtr->info.attributes &= ~kThemeTrackHorizontal; + msPtr->info.attributes &= ~kThemeTrackHorizontal; } else { - msPtr->info.attributes |= kThemeTrackHorizontal; + msPtr->info.attributes |= kThemeTrackHorizontal; } /* @@ -518,69 +535,73 @@ UpdateControlValues( * the view area. */ - double maximum = 100, factor; - factor = RangeToFactor(maximum); - dViewSize = (scrollPtr->lastFraction - scrollPtr->firstFraction) - * factor; - msPtr->info.max = MIN_SCROLLBAR_VALUE + - factor - dViewSize; + double maximum = 100, factor = RangeToFactor(maximum); + + dViewSize = (scrollPtr->lastFraction - scrollPtr->firstFraction) * factor; + msPtr->info.max = MIN_SCROLLBAR_VALUE + factor - dViewSize; msPtr->info.trackInfo.scrollbar.viewsize = dViewSize; if (scrollPtr->vertical) { - if (SNOW_LEOPARD_STYLE) { - msPtr->info.value = factor * scrollPtr->firstFraction; - } else { - msPtr->info.value = msPtr->info.max - factor * scrollPtr->firstFraction; - } + if (SNOW_LEOPARD_STYLE) { + msPtr->info.value = factor * scrollPtr->firstFraction; + } else { + msPtr->info.value = msPtr->info.max - + factor * scrollPtr->firstFraction; + } } else { - msPtr->info.value = MIN_SCROLLBAR_VALUE + factor * scrollPtr->firstFraction; + msPtr->info.value = MIN_SCROLLBAR_VALUE + + factor * scrollPtr->firstFraction; } - if((scrollPtr->firstFraction <= 0.0 && scrollPtr->lastFraction >= 1.0) - || height <= metrics.minHeight) { + if ((scrollPtr->firstFraction <= 0.0 && scrollPtr->lastFraction >= 1.0) + || height <= metrics.minHeight) { msPtr->info.enableState = kThemeTrackHideTrack; } else { msPtr->info.enableState = kThemeTrackActive; - msPtr->info.attributes = kThemeTrackShowThumb | kThemeTrackThumbRgnIsNotGhost; + msPtr->info.attributes = + kThemeTrackShowThumb | kThemeTrackThumbRgnIsNotGhost; } - } - + /* *-------------------------------------------------------------- * * ScrollbarEvent -- * - * This procedure is invoked in response to , , - * , and events. The Scrollbar appearance is - * modified for each event. + * This procedure is invoked in response to , + * , , and events. The + * Scrollbar appearance is modified for each event. * *-------------------------------------------------------------- */ static int -ScrollbarEvent(TkScrollbar *scrollPtr, XEvent *eventPtr) +ScrollbarEvent( + TkScrollbar *scrollPtr, + XEvent *eventPtr) { - MacScrollbar *msPtr = (MacScrollbar *)scrollPtr; - - /* The pressState does not indicate whether the moused button was - * pressed at some location in the Scrollbar. Rather, it indicates - * that the scrollbar should appear as if it were pressed in that - * location. The standard Mac behavior is that once the button is - * pressed inside the Scrollbar the appearance should not change until - * the button is released, even if the mouse moves outside of the - * scrollbar. However, if the mouse lies over the scrollbar but the - * button is not pressed then the appearance should be the same as if - * the button had been pressed on the slider, i.e. kThemeThumbPressed. - * See the file Appearance.r, or HIToolbox.bridgesupport on 10.14. + MacScrollbar *msPtr = (MacScrollbar *) scrollPtr; + + /* + * The pressState does not indicate whether the moused button was pressed + * at some location in the Scrollbar. Rather, it indicates that the + * scrollbar should appear as if it were pressed in that location. The + * standard Mac behavior is that once the button is pressed inside the + * Scrollbar the appearance should not change until the button is released, + * even if the mouse moves outside of the scrollbar. However, if the mouse + * lies over the scrollbar but the button is not pressed then the + * appearance should be the same as if the button had been pressed on the + * slider, i.e. kThemeThumbPressed. See the file Appearance.r, or + * HIToolbox.bridgesupport on 10.14. */ if (eventPtr->type == ButtonPress) { msPtr->buttonDown = true; UpdateControlValues(scrollPtr); + int where = TkpScrollbarPosition(scrollPtr, - eventPtr->xbutton.x, - eventPtr->xbutton.y); - switch(where) { + eventPtr->xbutton.x, eventPtr->xbutton.y); + + switch (where) { case OUTSIDE: msPtr->info.trackInfo.scrollbar.pressState = 0; break; @@ -591,14 +612,20 @@ ScrollbarEvent(TkScrollbar *scrollPtr, XEvent *eventPtr) msPtr->info.trackInfo.scrollbar.pressState = kThemeThumbPressed; break; case BOTTOM_GAP: - msPtr->info.trackInfo.scrollbar.pressState = kThemeBottomTrackPressed; + msPtr->info.trackInfo.scrollbar.pressState = + kThemeBottomTrackPressed; break; case TOP_ARROW: - /* This looks wrong and the docs say it is wrong but it works. */ - msPtr->info.trackInfo.scrollbar.pressState = kThemeTopInsideArrowPressed; + /* + * This looks wrong and the docs say it is wrong but it works. + */ + + msPtr->info.trackInfo.scrollbar.pressState = + kThemeTopInsideArrowPressed; break; case BOTTOM_ARROW: - msPtr->info.trackInfo.scrollbar.pressState = kThemeBottomOutsideArrowPressed; + msPtr->info.trackInfo.scrollbar.pressState = + kThemeBottomOutsideArrowPressed; break; } } @@ -622,9 +649,7 @@ ScrollbarEvent(TkScrollbar *scrollPtr, XEvent *eventPtr) } return TCL_OK; } - - - + /* *-------------------------------------------------------------- * @@ -645,8 +670,8 @@ ScrollbarEvent(TkScrollbar *scrollPtr, XEvent *eventPtr) static void ScrollbarEventProc( - ClientData clientData, /* Information about window. */ - XEvent *eventPtr) /* Information about event. */ + ClientData clientData, /* Information about window. */ + XEvent *eventPtr) /* Information about event. */ { TkScrollbar *scrollPtr = clientData; @@ -668,7 +693,7 @@ ScrollbarEventProc( TkScrollbarEventProc(clientData, eventPtr); } } - + /* * Local Variables: * mode: objc diff --git a/macosx/tkMacOSXSend.c b/macosx/tkMacOSXSend.c index 1fdf048..8b65532 100644 --- a/macosx/tkMacOSXSend.c +++ b/macosx/tkMacOSXSend.c @@ -51,7 +51,7 @@ typedef struct RegisteredInterp { * A registry of all interpreters for a display is kept in a property * "InterpRegistry" on the root window of the display. It is organized as a * series of zero or more concatenated strings (in no particular order), each - * of the form + * of the form: * window space name '\0' * where "window" is the hex id of the comm. window to use to talk to an * interpreter named "name". @@ -78,7 +78,7 @@ typedef struct NameRegistry { * XFree; zero means use ckfree. */ } NameRegistry; -static int initialized = 0; /* A flag to denote if we have initialized +static int initialized = 0; /* A flag to denote if we have initialized * yet. */ static RegisteredInterp *interpListPtr = NULL; diff --git a/macosx/tkMacOSXSubwindows.c b/macosx/tkMacOSXSubwindows.c index 805d58f..06aaa9d 100644 --- a/macosx/tkMacOSXSubwindows.c +++ b/macosx/tkMacOSXSubwindows.c @@ -65,7 +65,7 @@ XDestroyWindow( TkMacOSXSelDeadWindow(macWin->winPtr); macWin->toplevel->referenceCount--; - if (!Tk_IsTopLevel(macWin->winPtr) ) { + if (!Tk_IsTopLevel(macWin->winPtr)) { TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW); if (macWin->winPtr->parentPtr != NULL) { TkMacOSXInvalClipRgns((Tk_Window) macWin->winPtr->parentPtr); @@ -151,19 +151,18 @@ XMapWindow( NSWindow *win = TkMacOSXDrawableWindow(window); /* - * We want to activate Tk when a toplevel is mapped - * but we must not supply YES here. This is because - * during Tk initialization the root window is mapped - * before applicationDidFinishLaunching returns. Forcing - * the app to activate too early can make the menu bar - * unresponsive. + * We want to activate Tk when a toplevel is mapped but we must not + * supply YES here. This is because during Tk initialization the + * root window is mapped before applicationDidFinishLaunching + * returns. Forcing the app to activate too early can make the menu + * bar unresponsive. */ TkMacOSXApplyWindowAttributes(macWin->winPtr, win); [win setExcludedFromWindowsMenu:NO]; [NSApp activateIgnoringOtherApps:NO]; [[win contentView] setNeedsDisplay:YES]; - if ( [win canBecomeKeyWindow] ) { + if ([win canBecomeKeyWindow]) { [win makeKeyAndOrderFront:NSApp]; } else { [win orderFrontRegardless]; @@ -185,7 +184,8 @@ XMapWindow( */ TkWindow *contWinPtr = TkpGetOtherWindow(macWin->winPtr); - TkMacOSXInvalClipRgns((Tk_Window)contWinPtr); + + TkMacOSXInvalClipRgns((Tk_Window) contWinPtr); TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW); } TkMacOSXInvalClipRgns((Tk_Window) macWin->winPtr); @@ -203,12 +203,9 @@ XMapWindow( event.xmap.event = window; event.xmap.override_redirect = macWin->winPtr->atts.override_redirect; Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); - } else { - /* * Rebuild the parent's clipping region and display the window. - * */ TkMacOSXInvalClipRgns((Tk_Window) macWin->winPtr->parentPtr); @@ -298,6 +295,7 @@ XUnmapWindow( if (!Tk_IsEmbedded(winPtr) && winPtr->wmInfoPtr->hints.initial_state!=IconicState) { NSWindow *win = TkMacOSXDrawableWindow(window); + [win orderOut:nil]; } TkMacOSXInvalClipRgns((Tk_Window) winPtr); @@ -316,15 +314,15 @@ XUnmapWindow( event.xunmap.from_configure = false; Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); } else { - /* * Rebuild the visRgn clip region for the parent so it will be allowed * to draw in the space from which this subwindow was removed. */ if (parentPtr && parentPtr->privatePtr->visRgn) { - TkMacOSXInvalidateViewRegion(TkMacOSXDrawableView(parentPtr->privatePtr), - parentPtr->privatePtr->visRgn); + TkMacOSXInvalidateViewRegion( + TkMacOSXDrawableView(parentPtr->privatePtr), + parentPtr->privatePtr->visRgn); } TkMacOSXInvalClipRgns((Tk_Window) parentPtr); TkMacOSXUpdateClipRgn(parentPtr); @@ -357,11 +355,14 @@ XResizeWindow( unsigned int height) { MacDrawable *macWin = (MacDrawable *) window; + display->request++; if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) { NSWindow *w = macWin->winPtr->wmInfoPtr->window; + if (w) { NSRect r = [w contentRectForFrameRect:[w frame]]; + r.origin.y += r.size.height - height; r.size.width = width; r.size.height = height; @@ -377,8 +378,8 @@ XResizeWindow( * * XMoveResizeWindow -- * - * Move or resize a given X window. See X windows documentation - * for further details. + * Move or resize a given X window. See X windows documentation for + * further details. * * Results: * None. @@ -402,22 +403,24 @@ XMoveResizeWindow( display->request++; if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) { NSWindow *w = macWin->winPtr->wmInfoPtr->window; - if (w) { - /* We explicitly convert everything to doubles so we don't get + if (w) { + /* + * We explicitly convert everything to doubles so we don't get * surprised (again) by what happens when you do arithmetic with * unsigned ints. */ - CGFloat X = (CGFloat)x; - CGFloat Y = (CGFloat)y; - CGFloat Width = (CGFloat)width; - CGFloat Height = (CGFloat)height; - CGFloat XOff = (CGFloat)macWin->winPtr->wmInfoPtr->xInParent; - CGFloat YOff = (CGFloat)macWin->winPtr->wmInfoPtr->yInParent; - NSRect r = NSMakeRect(X + XOff, - tkMacOSXZeroScreenHeight - Y - YOff - Height, - Width, Height); + CGFloat X = (CGFloat) x; + CGFloat Y = (CGFloat) y; + CGFloat Width = (CGFloat) width; + CGFloat Height = (CGFloat) height; + CGFloat XOff = (CGFloat) macWin->winPtr->wmInfoPtr->xInParent; + CGFloat YOff = (CGFloat) macWin->winPtr->wmInfoPtr->yInParent; + NSRect r = NSMakeRect( + X + XOff, tkMacOSXZeroScreenHeight - Y - YOff - Height, + Width, Height); + [w setFrame:[w frameRectForContentRect:r] display:YES]; } } else { @@ -430,8 +433,7 @@ XMoveResizeWindow( * * XMoveWindow -- * - * Move a given X window. See X windows documentation for further - * details. + * Move a given X window. See X windows documentation for further details. * * Results: * None. @@ -453,8 +455,10 @@ XMoveWindow( display->request++; if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) { NSWindow *w = macWin->winPtr->wmInfoPtr->window; + if (w) { - [w setFrameTopLeftPoint:NSMakePoint(x, tkMacOSXZeroScreenHeight - y)]; + [w setFrameTopLeftPoint: NSMakePoint( + x, tkMacOSXZeroScreenHeight - y)]; } } else { MoveResizeWindow(macWin); @@ -495,7 +499,6 @@ MoveResizeWindow( if (contWinPtr) { macParent = contWinPtr->privatePtr; } else { - /* * Here we should handle out of process embedding. At this point, * we are assuming that the changes.x,y is not maintained, if you @@ -504,7 +507,6 @@ MoveResizeWindow( */ } } else { - /* * TODO: update all xOff & yOffs */ @@ -596,7 +598,6 @@ XRaiseWindow( if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) { TkWmRestackToplevel(macWin->winPtr, Above, NULL); } else { - /* * TODO: this should generate damage */ @@ -631,7 +632,6 @@ XLowerWindow( if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) { TkWmRestackToplevel(macWin->winPtr, Below, NULL); } else { - /* * TODO: this should generate damage */ @@ -694,14 +694,16 @@ XConfigureWindow( TkMacOSXInvalClipRgns((Tk_Window) winPtr->parentPtr); TkMacOSXWinBounds(winPtr, &bounds); r = NSMakeRect(bounds.left, - [view bounds].size.height - bounds.bottom, - bounds.right - bounds.left, bounds.bottom - bounds.top); + [view bounds].size.height - bounds.bottom, + bounds.right - bounds.left, bounds.bottom - bounds.top); [view setNeedsDisplayInRect:r]; } } - /* TkGenWMMoveRequestEvent(macWin->winPtr, - macWin->winPtr->changes.x, macWin->winPtr->changes.y); */ +#if 0 + TkGenWMMoveRequestEvent(macWin->winPtr, + macWin->winPtr->changes.x, macWin->winPtr->changes.y); +#endif } /* @@ -723,14 +725,14 @@ XConfigureWindow( void TkMacOSXSetDrawingEnabled( - TkWindow *winPtr, - int flag) + TkWindow *winPtr, + int flag) { TkWindow *childPtr; MacDrawable *macWin = winPtr->privatePtr; if (macWin) { - if (flag ) { + if (flag) { macWin->flags &= ~TK_DO_NOT_DRAW; } else { macWin->flags |= TK_DO_NOT_DRAW; @@ -738,8 +740,8 @@ TkMacOSXSetDrawingEnabled( } /* - * Set the flag for all children & their descendants, excluding - * Toplevels. (??? Do we need to exclude Toplevels?) + * Set the flag for all children & their descendants, excluding Toplevels. + * (??? Do we need to exclude Toplevels?) */ childPtr = winPtr->childList; @@ -903,7 +905,6 @@ TkMacOSXUpdateClipRgn( } CFRelease(rgn); } else { - /* * An unmapped window has empty clip regions to prevent any * (erroneous) drawing into it or its children from becoming @@ -933,8 +934,8 @@ TkMacOSXUpdateClipRgn( * TkMacOSXVisableClipRgn -- * * This function returns the Macintosh clipping region for the given - * window. The caller is responsible for disposing of the returned - * region via TkDestroyRegion(). + * window. The caller is responsible for disposing of the returned region + * via TkDestroyRegion(). * * Results: * The region. @@ -952,7 +953,7 @@ TkMacOSXVisableClipRgn( if (winPtr->privatePtr->flags & TK_CLIP_INVALID) { TkMacOSXUpdateClipRgn(winPtr); } - return (TkRegion)HIShapeCreateMutableCopy(winPtr->privatePtr->visRgn); + return (TkRegion) HIShapeCreateMutableCopy(winPtr->privatePtr->visRgn); } /* @@ -972,7 +973,12 @@ TkMacOSXVisableClipRgn( */ static OSStatus -InvalViewRect(int msg, HIShapeRef rgn, const CGRect *rect, void *ref) { +InvalViewRect( + int msg, + HIShapeRef rgn, + const CGRect *rect, + void *ref) +{ static CGAffineTransform t; NSView *view = ref; @@ -1052,7 +1058,7 @@ TkMacOSXInvalidateWindow( *---------------------------------------------------------------------- */ -NSWindow* +NSWindow * TkMacOSXDrawableWindow( Drawable drawable) { @@ -1070,6 +1076,7 @@ TkMacOSXDrawableWindow( result = macWin->winPtr->wmInfoPtr->window; } else if (macWin->toplevel && (macWin->toplevel->flags & TK_EMBEDDED)) { TkWindow *contWinPtr = TkpGetOtherWindow(macWin->toplevel->winPtr); + if (contWinPtr) { result = TkMacOSXDrawableWindow((Drawable) contWinPtr->privatePtr); } @@ -1123,7 +1130,7 @@ TkMacOSXGetDrawablePort( *---------------------------------------------------------------------- */ -NSView* +NSView * TkMacOSXDrawableView( MacDrawable *macWin) { @@ -1137,6 +1144,7 @@ TkMacOSXDrawableView( result = macWin->toplevel->view; } else { TkWindow *contWinPtr = TkpGetOtherWindow(macWin->toplevel->winPtr); + if (contWinPtr) { result = TkMacOSXDrawableView(contWinPtr->privatePtr); } @@ -1164,7 +1172,6 @@ void * TkMacOSXGetRootControl( Drawable drawable) { - /* * will probably need to fix this up for embedding */ @@ -1281,7 +1288,8 @@ TkMacOSXWinBounds( TkWindow *winPtr, void *bounds) { - Rect *b = (Rect *)bounds; + Rect *b = (Rect *) bounds; + b->left = winPtr->privatePtr->xOff; b->top = winPtr->privatePtr->yOff; b->right = b->left + winPtr->changes.width; @@ -1345,7 +1353,6 @@ UpdateOffsets( TkWindow *childPtr; if (winPtr->privatePtr == NULL) { - /* * We haven't called Tk_MakeWindowExist for this window yet. The offset * information will be postponed and calulated at that time. (This will diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c index 54e1272..6b80761 100644 --- a/macosx/tkMacOSXWindowEvent.c +++ b/macosx/tkMacOSXWindowEvent.c @@ -68,7 +68,7 @@ extern NSString *NSWindowDidOrderOffScreenNotification; TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification); #endif BOOL movedOnly = [[notification name] - isEqualToString:NSWindowDidMoveNotification]; + isEqualToString:NSWindowDidMoveNotification]; NSWindow *w = [notification object]; TkWindow *winPtr = TkMacOSXGetTkWindow(w); @@ -91,7 +91,6 @@ extern NSString *NSWindowDidOrderOffScreenNotification; flags |= TK_SIZE_CHANGED; } if (Tcl_GetServiceMode() != TCL_SERVICE_NONE) { - /* * Propagate geometry changes immediately. */ @@ -140,11 +139,10 @@ extern NSString *NSWindowDidOrderOffScreenNotification; - (NSRect)windowWillUseStandardFrame:(NSWindow *)window defaultFrame:(NSRect)newFrame { - /* - * This method needs to be implemented in order for [NSWindow isZoomed] - * to give the correct answer. But it suffices to always validate - * every request. + * This method needs to be implemented in order for [NSWindow isZoomed] to + * give the correct answer. But it suffices to always validate every + * request. */ return newFrame; @@ -153,13 +151,12 @@ extern NSString *NSWindowDidOrderOffScreenNotification; - (NSSize)window:(NSWindow *)window willUseFullScreenContentSize:(NSSize)proposedSize { - /* - * We don't need to change the proposed size, but we do need to - * implement this method. Otherwise the full screen window will - * be sized to the screen's visibleFrame, leaving black bands at - * the top and bottom. + * We don't need to change the proposed size, but we do need to implement + * this method. Otherwise the full screen window will be sized to the + * screen's visibleFrame, leaving black bands at the top and bottom. */ + return proposedSize; } @@ -208,14 +205,13 @@ extern NSString *NSWindowDidOrderOffScreenNotification; } /* - * If necessary, TkGenWMDestroyEvent() handles [close]ing the window, - * so can always return NO from -windowShouldClose: for a Tk window. + * If necessary, TkGenWMDestroyEvent() handles [close]ing the window, so + * can always return NO from -windowShouldClose: for a Tk window. */ return (winPtr ? NO : YES); } - #ifdef TK_MAC_DEBUG_NOTIFICATIONS - (void) windowDragStart: (NSNotification *) notification @@ -256,7 +252,6 @@ extern NSString *NSWindowDidOrderOffScreenNotification; } } - #endif /* TK_MAC_DEBUG_NOTIFICATIONS */ - (void) _setupWindowNotifications @@ -363,11 +358,11 @@ extern NSString *NSWindowDidOrderOffScreenNotification; * * TkpAppIsDrawing -- * - * A widget display procedure can call this to determine whether it - * is being run inside of the drawRect method. This is needed for - * some tests, especially of the Text widget, which record data in - * a global Tcl variable and assume that display procedures will be - * run in a predictable sequence as Tcl idle tasks. + * A widget display procedure can call this to determine whether it is + * being run inside of the drawRect method. This is needed for some tests, + * especially of the Text widget, which record data in a global Tcl + * variable and assume that display procedures will be run in a + * predictable sequence as Tcl idle tasks. * * Results: * True only while running the drawRect method of a TKContentView; @@ -377,11 +372,11 @@ extern NSString *NSWindowDidOrderOffScreenNotification; * *---------------------------------------------------------------------- */ + MODULE_SCOPE Bool TkpAppIsDrawing(void) { return [NSApp isDrawing]; } - /* *---------------------------------------------------------------------- @@ -670,12 +665,10 @@ TkGenWMConfigureEvent( if ((flags & TK_SIZE_CHANGED) && !(wmPtr->flags & WM_SYNC_PENDING) && ((width != Tk_Width(tkwin)) || (height != Tk_Height(tkwin)))) { if ((wmPtr->width == -1) && (width == winPtr->reqWidth)) { - /* * Don't set external width, since the user didn't change it * from what the widgets asked for. */ - } else if (wmPtr->gridWin != NULL) { wmPtr->width = wmPtr->reqGridWidth + (width - winPtr->reqWidth)/wmPtr->widthInc; @@ -687,12 +680,10 @@ TkGenWMConfigureEvent( } if ((wmPtr->height == -1) && (height == winPtr->reqHeight)) { - /* * Don't set external height, since the user didn't change it * from what the widgets asked for. */ - } else if (wmPtr->gridWin != NULL) { wmPtr->height = wmPtr->reqGridHeight + (height - winPtr->reqHeight)/wmPtr->heightInc; @@ -708,7 +699,6 @@ TkGenWMConfigureEvent( } } - /* * Now set up the changes structure. Under X we wait for the * ConfigureNotify to set these values. On the Mac we know imediatly that @@ -899,8 +889,8 @@ ConfigureRestrictProc( #endif /* - * We do not allow recursive calls to drawRect, but we only log - * them on OSX > 10.13, where they should never happen. + * We do not allow recursive calls to drawRect, but we only log them on OSX + * > 10.13, where they should never happen. */ if ([NSApp isDrawing]) { @@ -955,9 +945,9 @@ ConfigureRestrictProc( Tk_RestrictProc *oldProc; /* - * This can be called from outside the Tk event loop. - * Since it calls Tcl_DoOneEvent, we need to make sure we - * don't clobber the AutoreleasePool set up by the caller. + * This can be called from outside the Tk event loop. Since it calls + * Tcl_DoOneEvent, we need to make sure we don't clobber the + * AutoreleasePool set up by the caller. */ [NSApp _lockAutoreleasePool]; @@ -973,7 +963,7 @@ ConfigureRestrictProc( */ TkGenWMConfigureEvent(tkwin, Tk_X(tkwin), Tk_Y(tkwin), width, height, - TK_SIZE_CHANGED | TK_MACOSX_HANDLE_EVENT_IMMEDIATELY); + TK_SIZE_CHANGED | TK_MACOSX_HANDLE_EVENT_IMMEDIATELY); oldProc = Tk_RestrictEvents(ConfigureRestrictProc, NULL, &oldArg); Tk_RestrictEvents(oldProc, oldArg, &oldArg); @@ -1061,9 +1051,9 @@ ConfigureRestrictProc( } /* - * This method is called when a user changes between light and dark mode. - * The implementation here generates a Tk virtual event which can be bound - * to a function that redraws the window in an appropriate style. + * This method is called when a user changes between light and dark mode. The + * implementation here generates a Tk virtual event which can be bound to a + * function that redraws the window in an appropriate style. */ - (void) viewDidChangeEffectiveAppearance @@ -1099,8 +1089,8 @@ ConfigureRestrictProc( } /* - * This is no-op on 10.7 and up because Apple has removed this widget, - * but we are leaving it here for backwards compatibility. + * This is no-op on 10.7 and up because Apple has removed this widget, but we + * are leaving it here for backwards compatibility. */ - (void) tkToolbarButton: (id) sender diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index 504c73f..d6456f2 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -3,8 +3,7 @@ * * This module takes care of the interactions between a Tk-based * application and the window manager. Among other things, it implements - * the "wm" command and passes geometry information to the window - * manager. + * the "wm" command and passes geometry information to the window manager. * * Copyright (c) 1994-1997 Sun Microsystems, Inc. * Copyright 2001-2009, Apple Inc. @@ -392,7 +391,7 @@ static void RemoveTransient(TkWindow *winPtr); if ([self styleMask] & NSFullScreenWindowMask) { frameRect = [NSWindow frameRectForContentRect:NSZeroRect - styleMask:[self styleMask]]; + styleMask:[self styleMask]]; } else { frameRect = [self frameRectForContentRect:NSZeroRect]; } @@ -454,7 +453,7 @@ static void RemoveTransient(TkWindow *winPtr); if (title == nil) { title = "unnamed window"; } - if (DEBUG_ZOMBIES > 1){ + if (DEBUG_ZOMBIES > 1) { fprintf(stderr, "Retained <%s>. Count is: %lu\n", title, [self retainCount]); } @@ -468,7 +467,7 @@ static void RemoveTransient(TkWindow *winPtr); if (title == nil) { title = "unnamed window"; } - if (DEBUG_ZOMBIES > 1){ + if (DEBUG_ZOMBIES > 1) { fprintf(stderr, "Autoreleased <%s>. Count is %lu\n", title, [self retainCount]); } @@ -480,7 +479,7 @@ static void RemoveTransient(TkWindow *winPtr); if (title == nil) { title = "unnamed window"; } - if (DEBUG_ZOMBIES > 1){ + if (DEBUG_ZOMBIES > 1) { fprintf(stderr, "Releasing <%s>. Count is %lu\n", title, [self retainCount]); } @@ -492,7 +491,7 @@ static void RemoveTransient(TkWindow *winPtr); if (title == nil) { title = "unnamed window"; } - if (DEBUG_ZOMBIES > 0){ + if (DEBUG_ZOMBIES > 0) { fprintf(stderr, ">>>> Freeing <%s>. Count is %lu\n", title, [self retainCount]); } @@ -998,25 +997,29 @@ TkWmDeadWindow( if (winPtr2 && nswindow != window) { WmInfo *wmPtr = winPtr2->wmInfoPtr; - BOOL minimized = (wmPtr->hints.initial_state == IconicState || - wmPtr->hints.initial_state == WithdrawnState); + BOOL minimized = (wmPtr->hints.initial_state == IconicState + || wmPtr->hints.initial_state == WithdrawnState); + /* * If no windows are left on the screen and the next window is * iconified or withdrawn, we don't want to make it be the * KeyWindow because that would cause it to be displayed on the * screen. */ + if ([nswindow canBecomeKeyWindow] && !minimized) { [nswindow makeKeyAndOrderFront:NSApp]; break; } } } + /* * Process all window events immediately to force the closed window to * be deallocated. But don't do this for the root window as that is * unnecessary and can lead to segfaults. */ + if (winPtr->parentPtr) { while (Tk_DoOneEvent(TK_WINDOW_EVENTS|TK_DONT_WAIT)) {} } @@ -2624,7 +2627,7 @@ WmIconpositionCmd( wmPtr->hints.flags &= ~IconPositionHint; } else { if ((Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK) - || (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK)){ + || (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK)) { return TCL_ERROR; } wmPtr->hints.icon_x = x; @@ -3453,14 +3456,17 @@ WmStateCmd( return TCL_ERROR; } - if (index == OPT_NORMAL) { + switch (index) { + case OPT_NORMAL: TkpWmSetState(winPtr, NormalState); /* * This varies from 'wm deiconify' because it does not force the * window to be raised and receive focus */ - } else if (index == OPT_ICONIC) { + + break; + case OPT_ICONIC: if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't iconify \"%s\": override-redirect flag is set", @@ -3478,10 +3484,13 @@ WmStateCmd( return TCL_ERROR; } TkpWmSetState(winPtr, IconicState); - } else if (index == OPT_WITHDRAWN) { + break; + case OPT_WITHDRAWN: TkpWmSetState(winPtr, WithdrawnState); - } else { /* OPT_ZOOMED */ + break; + default: /* OPT_ZOOMED */ TkpWmSetState(winPtr, ZoomState); + break; } } else if (wmPtr->iconFor != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj("icon", -1)); @@ -3601,14 +3610,12 @@ WmTransientCmd( } if (Tcl_GetString(objv[3])[0] == '\0') { RemoveTransient(winPtr); - } else { if (TkGetWindowFromObj(interp, tkwin, objv[3], &master) != TCL_OK) { return TCL_ERROR; } masterPtr = (TkWindow*) master; while (!Tk_TopWinHierarchy(masterPtr)) { - /* * Ensure that the master window is actually a Tk toplevel. */ @@ -3626,7 +3633,11 @@ WmTransientCmd( } wmPtr2 = masterPtr->wmInfoPtr; - /* Under some circumstances, wmPtr2 is NULL here. */ + + /* + * Under some circumstances, wmPtr2 is NULL here. + */ + if (wmPtr2 != NULL && wmPtr2->iconFor != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't make \"%s\" a master: it is an icon for %s", @@ -3677,7 +3688,7 @@ WmTransientCmd( ApplyMasterOverrideChanges(winPtr, NULL); return TCL_OK; } - + /* *---------------------------------------------------------------------- * @@ -3784,6 +3795,7 @@ WmWithdrawCmd( /* * If this window has a transient, the transient must also be withdrawn. */ + for (Transient *transientPtr = wmPtr->transientPtr; transientPtr != NULL; transientPtr = transientPtr->nextPtr) { TkWindow *winPtr2 = transientPtr->winPtr; @@ -3798,10 +3810,10 @@ WmWithdrawCmd( return TCL_OK; } - + /* - * Invoked by those wm subcommands that affect geometry. - * Schedules a geometry update. + * Invoked by those wm subcommands that affect geometry. Schedules a geometry + * update. */ static void @@ -4415,9 +4427,10 @@ ParseGeometry( if (flags & WM_NEGATIVE_X) { int borderwidth = wmPtr->parentWidth - winPtr->changes.width; int newWidth = width == -1 ? winPtr->changes.width : width; + x = (x == -1) ? - wmPtr->x + winPtr->changes.width - newWidth : - wmPtr->vRootWidth - x - newWidth - borderwidth; + wmPtr->x + winPtr->changes.width - newWidth : + wmPtr->vRootWidth - x - newWidth - borderwidth; } if (x == -1) { x = wmPtr->x; @@ -4425,9 +4438,10 @@ ParseGeometry( if (flags & WM_NEGATIVE_Y) { int borderheight = wmPtr->parentHeight - winPtr->changes.height; int newHeight = height == -1 ? winPtr->changes.height : height; + y = (y == -1) ? - wmPtr->y + winPtr->changes.height - newHeight : - wmPtr->vRootHeight - y - newHeight - borderheight; + wmPtr->y + winPtr->changes.height - newHeight : + wmPtr->vRootHeight - y - newHeight - borderheight; } if (y == -1) { y = wmPtr->y; @@ -4554,8 +4568,7 @@ Tk_GetRootCoords( * * Results: * The return result is either a token for the window corresponding to - * rootX and rootY, or else NULL to indicate that there is no such - * window. + * rootX and rootY, or else NULL to indicate that there is no such window. * * Side effects: * None. @@ -6144,9 +6157,9 @@ TkMacOSXMakeRealWindowExist( * * TkpDisplayWindow -- * - * Mark the contentView of this window as needing display so the - * window will be drawn by the window manager. If this is called - * within the drawRect method, do nothing. + * Mark the contentView of this window as needing display so the window + * will be drawn by the window manager. If this is called within the + * drawRect method, do nothing. * * Results: * None. @@ -6160,7 +6173,7 @@ TkMacOSXMakeRealWindowExist( MODULE_SCOPE void TkpDisplayWindow(Tk_Window tkwin) { if (![NSApp isDrawing]) { - TkWindow *winPtr = (TkWindow*)tkwin; + TkWindow *winPtr = (TkWindow *) tkwin; NSWindow *w = TkMacOSXDrawableWindow(winPtr->window); [[w contentView] setNeedsDisplay: YES]; @@ -6172,8 +6185,8 @@ TkpDisplayWindow(Tk_Window tkwin) { * * TkMacOSXRegisterOffScreenWindow -- * - * This function adds the passed in Off Screen Port to the hash table - * that maps Mac windows to root X windows. + * This function adds the passed in Off Screen Port to the hash table that + * maps Mac windows to root X windows. * * Results: * None. @@ -6981,7 +6994,7 @@ ApplyMasterOverrideChanges( } if (macWindow) { structureRect = [NSWindow frameRectForContentRect:NSZeroRect - styleMask:styleMask]; + styleMask:styleMask]; /* * Synchronize the wmInfoPtr to match the new window configuration @@ -7236,6 +7249,7 @@ RemapWindows( MacDrawable *parentWin) { TkWindow *childPtr; + /* * Remove the OS specific window. It will get rebuilt when the window gets * Mapped. diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index a890b63..0c474f0 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -60,10 +60,14 @@ /* * BoxToRect -- - * Convert a Ttk_Box in Tk coordinates relative to the given Drawable - * to a native Rect relative to the containing port. + * Convert a Ttk_Box in Tk coordinates relative to the given Drawable to a + * native Rect relative to the containing port. */ -static inline CGRect BoxToRect(Drawable d, Ttk_Box b) + +static inline CGRect +BoxToRect( + Drawable d, + Ttk_Box b) { MacDrawable *md = (MacDrawable*)d; CGRect rect; @@ -102,10 +106,10 @@ static Ttk_StateTable ThemeStateTable[] = { * * Apple's Human Interface Guidelines only allow three specific heights for * most buttons: Regular, small and mini. We always use the regular size. - * However, Ttk may provide an arbitrary bounding rectangle. We always draw - * the button centered vertically on the rectangle, and having the same width - * as the rectangle. This function returns the actual bounding rectangle that - * will be used in drawing the button. + * However, Ttk may provide an arbitrary bounding rectangle. We always draw the + * button centered vertically on the rectangle, and having the same width as + * the rectangle. This function returns the actual bounding rectangle that will + * be used in drawing the button. * * The BevelButton is allowed to have arbitrary size, and also has external * padding. This is handled separately here. @@ -115,8 +119,9 @@ static CGRect NormalizeButtonBounds( SInt32 heightMetric, CGRect bounds) { - SInt32 height; - if (heightMetric != NoThemeMetric) { + if (heightMetric != (SInt32) NoThemeMetric) { + SInt32 height; + ChkErr(GetThemeMetric, heightMetric, &height); bounds.origin.y += (bounds.size.height - height)/2; bounds.size.height = height; @@ -149,8 +154,8 @@ static CGFloat blackRGBA[4] = {0.0, 0.0, 0.0, 1.0}; * 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. + * lighter for the DarkAqua appearance. This is primarily used by the Fill + * and Background elements. */ static void GetBackgroundColor( @@ -161,11 +166,12 @@ static void GetBackgroundColor( { TkWindow *winPtr = (TkWindow *) tkwin; TkWindow *masterPtr = (TkWindow *) TkGetGeomMaster(tkwin); + while (masterPtr != NULL) { if (masterPtr->privatePtr->flags & TTK_HAS_CONTRASTING_BG) { break; } - masterPtr = (TkWindow *)TkGetGeomMaster(masterPtr); + masterPtr = (TkWindow *) TkGetGeomMaster(masterPtr); } if (masterPtr) { for (int i = 0; i < 4; i++) { @@ -176,6 +182,7 @@ static void GetBackgroundColor( NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; NSColor *windowColor = [[NSColor windowBackgroundColor] colorUsingColorSpace: deviceRGB]; + [windowColor getComponents: rgba]; } else { for (int i = 0; i < 4; i++) { @@ -219,6 +226,7 @@ static void DrawGroupBox( NSColor *borderColor, *bgColor; static CGFloat border[4] = {1.0, 1.0, 1.0, 0.25}; CGFloat fill[4]; + GetBackgroundColor(context, tkwin, 1, fill); bgColor = [NSColor colorWithColorSpace: deviceRGB components: fill count: 4]; @@ -255,6 +263,7 @@ static void SolidFillRoundedRectangle( NSColor *color) { CGPathRef path; + CGContextSetFillColorWithColor(context, color.CGColor); path = CGPathCreateWithRoundedRect(bounds, radius, radius, NULL); CGContextBeginPath(context); @@ -271,14 +280,17 @@ static void DrawDownArrow( CGFloat *rgba) { CGFloat x, y; + CGContextSetRGBStrokeColor(context, rgba[0], rgba[1], rgba[2], rgba[3]); CGContextSetLineWidth(context, 1.5); x = bounds.origin.x + inset; y = bounds.origin.y + trunc(bounds.size.height/2); - CGContextBeginPath(context); + CGPoint arrow[3] = { {x, y-size/4}, {x+size/2, y+size/4}, {x+size, y-size/4} }; + + CGContextBeginPath(context); CGContextAddLines(context, arrow, 3); CGContextStrokePath(context); } @@ -291,14 +303,17 @@ static void DrawUpArrow( CGFloat *rgba) { CGFloat x, y; + CGContextSetRGBStrokeColor(context, rgba[0], rgba[1], rgba[2], rgba[3]); CGContextSetLineWidth(context, 1.5); x = bounds.origin.x + inset; y = bounds.origin.y + trunc(bounds.size.height/2); - CGContextBeginPath(context); + CGPoint arrow[3] = { {x, y+size/4}, {x+size/2, y-size/4}, {x+size, y+size/4} }; + + CGContextBeginPath(context); CGContextAddLines(context, arrow, 3); CGContextStrokePath(context); } @@ -368,6 +383,7 @@ static void DrawListHeader( if (state & TTK_TREEVIEW_STATE_SORTARROW) { CGRect arrowBounds = bounds; + arrowBounds.origin.x = bounds.origin.x + bounds.size.width - 16; arrowBounds.size.width = 16; if (state & TTK_STATE_ALTERNATE) { @@ -413,7 +429,6 @@ static CGFloat darkInactiveGradient[8] = {89.0/255, 90.0/255, 93.0/255, 1.0, static CGFloat darkSelectedGradient[8] = {23.0/255, 111.0/255, 232.0/255, 1.0, 20.0/255, 94.0/255, 206.0/255, 1.0}; - /*---------------------------------------------------------------------- * GradientFillRoundedRectangle -- * @@ -424,7 +439,7 @@ static void GradientFillRoundedRectangle( CGContextRef context, CGRect bounds, CGFloat radius, - CGFloat* colors, + CGFloat *colors, int numColors) { NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; @@ -435,6 +450,7 @@ static void GradientFillRoundedRectangle( }; CGGradientRef gradient = CGGradientCreateWithColorComponents( deviceRGB.CGColorSpace, colors, NULL, numColors); + path = CGPathCreateWithRoundedRect(bounds, radius, radius, NULL); CGContextBeginPath(context); CGContextAddPath(context, path); @@ -452,14 +468,17 @@ static void DrawUpDownArrows( CGFloat *rgba) { CGFloat x, y; + CGContextSetRGBStrokeColor(context, rgba[0], rgba[1], rgba[2], rgba[3]); CGContextSetLineWidth(context, 1.5); x = bounds.origin.x + inset; y = bounds.origin.y + trunc(bounds.size.height/2); CGContextBeginPath(context); + CGPoint bottomArrow[3] = {{x, y+2}, {x+size/2, y+2+size/2}, {x+size, y+2}}; - CGContextAddLines(context, bottomArrow, 3); CGPoint topArrow[3] = {{x, y-2}, {x+size/2, y-2-size/2}, {x+size, y-2}}; + + CGContextAddLines(context, bottomArrow, 3); CGContextAddLines(context, topArrow, 3); CGContextStrokePath(context); } @@ -483,6 +502,7 @@ static void FillButtonBackground( bounds.origin.x, bounds.origin.y + bounds.size.height }; + CGContextBeginPath(context); path = CGPathCreateWithRoundedRect(bounds, radius, radius, NULL); CGContextAddPath(context, path); @@ -508,6 +528,7 @@ static void HighlightButtonBorder( CGPoint topEnd = {bounds.origin.x, bounds.origin.y + 3}; CGGradientRef topGradient = CGGradientCreateWithColorComponents( deviceRGB.CGColorSpace, darkTopGradient, NULL, 2); + CGContextSaveGState(context); CGContextBeginPath(context); CGContextAddArc(context, bounds.origin.x + 4, bounds.origin.y + 4, @@ -576,6 +597,7 @@ static void DrawDarkButton( if (kind == kThemePopupButton | kind == kThemeComboBox) { CGRect arrowBounds = bounds; + arrowBounds.size.width = 16; arrowBounds.origin.x += bounds.size.width - 16; @@ -584,9 +606,9 @@ static void DrawDarkButton( */ if (!(state & TTK_STATE_BACKGROUND) && - !(state & TTK_STATE_DISABLED)) { + !(state & TTK_STATE_DISABLED)) { GradientFillRoundedRectangle(context, arrowBounds, 4, - darkSelectedGradient, 2); + darkSelectedGradient, 2); } if (kind == kThemePopupButton) { DrawUpDownArrows(context, arrowBounds, 3, 7, whiteRGBA); @@ -601,8 +623,8 @@ static void DrawDarkButton( /*---------------------------------------------------------------------- * DrawDarkIncDecButton -- * - * This is a standalone drawing procedure which draws an IncDecButton - * (as used in a Spinbox) in the Dark Mode style. + * This is a standalone drawing procedure which draws an IncDecButton (as + * used in a Spinbox) in the Dark Mode style. */ static void DrawDarkIncDecButton( @@ -640,6 +662,7 @@ static void DrawDarkIncDecButton( if (state & TTK_STATE_PRESSED) { CGRect clip = bounds; + clip.size.height /= 2; CGContextSaveGState(context); if (drawState == kThemeStatePressedDown) { @@ -647,7 +670,7 @@ static void DrawDarkIncDecButton( } CGContextClipToRect(context, clip); GradientFillRoundedRectangle(context, bounds, 5, - darkSelectedGradient, 2); + darkSelectedGradient, 2); CGContextRestoreGState(context); } DrawUpDownArrows(context, bounds, 3, 5, whiteRGBA); @@ -714,6 +737,7 @@ static void DrawDarkCheckBox( NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; NSColor *stroke; CGFloat x, y; + bounds = CGRectOffset(checkbounds, bounds.origin.x, bounds.origin.y); x = bounds.origin.x; y = bounds.origin.y; @@ -741,15 +765,17 @@ static void DrawDarkCheckBox( CGContextSetStrokeColorWithColor(context, stroke.CGColor); } if (state & TTK_STATE_SELECTED) { + CGPoint check[3] = {{x+4, y+8}, {x+7, y+11}, {x+11, y+4}}; + CGContextSetLineWidth(context, 1.5); CGContextBeginPath(context); - CGPoint check[3] = {{x+4, y+8}, {x+7, y+11}, {x+11, y+4}}; CGContextAddLines(context, check, 3); CGContextStrokePath(context); } else if (state & TTK_STATE_ALTERNATE) { + CGPoint bar[2] = {{x+4, y+8}, {x+12, y+8}}; + CGContextSetLineWidth(context, 2.0); CGContextBeginPath(context); - CGPoint bar[2] = {{x+4, y+8}, {x+12, y+8}}; CGContextAddLines(context, bar, 2); CGContextStrokePath(context); } @@ -758,8 +784,8 @@ static void DrawDarkCheckBox( /*---------------------------------------------------------------------- * DrawDarkRadioButton -- * - * This is a standalone drawing procedure which draws RadioButtons - * in the Dark Mode style. + * This is a standalone drawing procedure which draws RadioButtons in the + * Dark Mode style. */ static void DrawDarkRadioButton( @@ -771,6 +797,7 @@ static void DrawDarkRadioButton( NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; NSColor *fill; CGFloat x, y; + bounds = CGRectOffset(checkbounds, bounds.origin.x, bounds.origin.y); x = bounds.origin.x; y = bounds.origin.y; @@ -798,12 +825,14 @@ static void DrawDarkRadioButton( CGContextSetFillColorWithColor(context, fill.CGColor); } if (state & TTK_STATE_SELECTED) { - CGContextBeginPath(context); CGRect dot = {{x + 6, y + 6}, {6, 6}}; + + CGContextBeginPath(context); CGContextAddEllipseInRect(context, dot); CGContextFillPath(context); } else if (state & TTK_STATE_ALTERNATE) { CGRect bar = {{x + 5, y + 8}, {8, 2}}; + CGContextFillRect(context, bar); } } @@ -873,9 +902,9 @@ static void DrawDarkTab( CGContextSetStrokeColorWithColor(context, stroke.CGColor); CGContextBeginPath(context); CGContextMoveToPoint(context, originalBounds.origin.x, - originalBounds.origin.y + 1); + originalBounds.origin.y + 1); CGContextAddLineToPoint(context, originalBounds.origin.x, - originalBounds.origin.y + originalBounds.size.height - 1); + originalBounds.origin.y + originalBounds.size.height - 1); CGContextStrokePath(context); CGContextRestoreGState(context); } @@ -891,7 +920,7 @@ static void DrawDarkTab( } if (!(state & TTK_STATE_BACKGROUND)) { GradientFillRoundedRectangle(context, bounds, 4, - darkSelectedGradient, 2); + darkSelectedGradient, 2); } else { faceColor = [NSColor colorWithColorSpace: deviceRGB components: darkInactiveSelectedTab @@ -901,12 +930,12 @@ static void DrawDarkTab( HighlightButtonBorder(context, bounds); } } - + /*---------------------------------------------------------------------- * DrawDarkSeparator -- * - * This is a standalone drawing procedure which draws a separator widget - * in Dark Mode. + * This is a standalone drawing procedure which draws a separator widget in + * Dark Mode. */ static void DrawDarkSeparator( @@ -919,15 +948,16 @@ static void DrawDarkSeparator( NSColor *fillColor = [NSColor colorWithColorSpace: deviceRGB components: fill count:4]; + CGContextSetFillColorWithColor(context, fillColor.CGColor); CGContextFillRect(context, bounds); } - + /*---------------------------------------------------------------------- * DrawDarkFrame -- * - * This is a standalone drawing procedure which draws various - * types of borders in Dark Mode. + * This is a standalone drawing procedure which draws various types of + * borders in Dark Mode. */ static void DrawDarkFrame( @@ -937,7 +967,6 @@ static void DrawDarkFrame( { NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; NSColor *stroke; - CGContextSetStrokeColorSpace(context, deviceRGB.CGColorSpace); CGFloat x = bounds.origin.x, y = bounds.origin.y; CGFloat w = bounds.size.width, h = bounds.size.height; CGPoint topPart[4] = { @@ -945,7 +974,9 @@ static void DrawDarkFrame( }; CGPoint bottom[2] = {{x, y + h}, {x + w, y + h}}; CGPoint accent[2] = {{x, y + 1}, {x + w, y + 1}}; - switch(kind) { + + CGContextSetStrokeColorSpace(context, deviceRGB.CGColorSpace); + switch (kind) { case kHIThemeFrameTextFieldSquare: CGContextSaveGState(context); CGContextSetShouldAntialias(context, false); @@ -978,8 +1009,8 @@ static void DrawDarkFrame( /*---------------------------------------------------------------------- * DrawListHeader -- * - * This is a standalone drawing procedure which draws column - * headers for a Treeview in the Dark Mode. + * This is a standalone drawing procedure which draws column headers for a + * Treeview in the Dark Mode. */ static void DrawDarkListHeader( @@ -990,13 +1021,13 @@ static void DrawDarkListHeader( { NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; NSColor *stroke; - CGContextSetStrokeColorSpace(context, deviceRGB.CGColorSpace); CGFloat x = bounds.origin.x, y = bounds.origin.y; CGFloat w = bounds.size.width, h = bounds.size.height; CGPoint top[2] = {{x, y}, {x + w, y}}; CGPoint bottom[2] = {{x, y + h}, {x + w, y + h}}; CGPoint separator[2] = {{x + w, y + 3}, {x + w, y + h - 3}}; + CGContextSetStrokeColorSpace(context, deviceRGB.CGColorSpace); CGContextSaveGState(context); CGContextSetShouldAntialias(context, false); stroke = [NSColor colorWithColorSpace: deviceRGB @@ -1032,8 +1063,8 @@ static void DrawDarkListHeader( */ /* - * When Ttk draws the various types of buttons, a pointer to one of these - * is passed as the clientData. + * When Ttk draws the various types of buttons, a pointer to one of these is + * passed as the clientData. */ typedef struct { @@ -1082,6 +1113,7 @@ static inline HIThemeButtonDrawInfo computeButtonDrawInfo( */ SInt32 HIThemeState; + switch (params->kind) { case kThemePushButton: HIThemeState = kThemeStateActive; @@ -1101,9 +1133,13 @@ static inline HIThemeButtonDrawInfo computeButtonDrawInfo( return info; } -static void ButtonElementMinSize( - void *clientData, void *elementRecord, Tk_Window tkwin, - int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) +static void +ButtonElementMinSize( + void *clientData, + void *elementRecord, + Tk_Window tkwin, + int *minWidth, int *minHeight, + Ttk_Padding *paddingPtr) { ThemeButtonParams *params = clientData; @@ -1111,9 +1147,8 @@ static void ButtonElementMinSize( ChkErr(GetThemeMetric, params->heightMetric, minHeight); /* - * The theme height does not include the 1-pixel border around - * the button, although it does include the 1-pixel shadow at - * the bottom. + * The theme height does not include the 1-pixel border around the + * button, although it does include the 1-pixel shadow at the bottom. */ *minHeight += 2; @@ -1129,9 +1164,13 @@ static void ButtonElementMinSize( } } -static void ButtonElementSize( - void *clientData, void *elementRecord, Tk_Window tkwin, - int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) +static void +ButtonElementSize( + void *clientData, + void *elementRecord, + Tk_Window tkwin, + int *minWidth, int *minHeight, + Ttk_Padding *paddingPtr) { ThemeButtonParams *params = clientData; const HIThemeButtonDrawInfo info = computeButtonDrawInfo(params, 0, tkwin); @@ -1153,10 +1192,10 @@ static void ButtonElementSize( * to draw a button with a certain bounding rectangle it draws the button * centered within the rectangle. * - * To compute the effective padding around a button we request the - * content and bounding rectangles for a 100x100 button and use the - * padding between those. However, we symmetrize the padding on the - * top and bottom, because that is how the button will be drawn. + * To compute the effective padding around a button we request the content + * and bounding rectangles for a 100x100 button and use the padding between + * those. However, we symmetrize the padding on the top and bottom, because + * that is how the button will be drawn. */ ChkErr(HIThemeGetButtonContentBounds, @@ -1170,16 +1209,21 @@ static void ButtonElementSize( paddingPtr->top = paddingPtr->bottom = verticalPad / 2; } -static void ButtonElementDraw( - void *clientData, void *elementRecord, Tk_Window tkwin, - Drawable d, Ttk_Box b, Ttk_State state) +static void +ButtonElementDraw( + void *clientData, + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + Ttk_State state) { ThemeButtonParams *params = clientData; CGRect bounds = BoxToRect(d, b); HIThemeButtonDrawInfo info = computeButtonDrawInfo(params, state, tkwin); bounds = NormalizeButtonBounds(params->heightMetric, bounds); - BEGIN_DRAWING(d) + BEGIN_DRAWING(d); if (TkMacOSXInDarkMode(tkwin)) { #if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 switch (info.kind) { @@ -1235,7 +1279,7 @@ static void ButtonElementDraw( ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); } - END_DRAWING + END_DRAWING; } static Ttk_ElementSpec ButtonElementSpec = { @@ -1315,18 +1359,26 @@ static Ttk_StateTable TabPositionTable[] = { * TP30000359-TPXREF116> */ -static void TabElementSize( - void *clientData, void *elementRecord, Tk_Window tkwin, - int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) +static void +TabElementSize( + void *clientData, + void *elementRecord, + Tk_Window tkwin, + int *minWidth, int *minHeight, + Ttk_Padding *paddingPtr) { - GetThemeMetric(kThemeMetricLargeTabHeight, (SInt32 *)minHeight); + GetThemeMetric(kThemeMetricLargeTabHeight, (SInt32 *) minHeight); *paddingPtr = Ttk_MakePadding(0, 0, 0, 2); - } -static void TabElementDraw( - void *clientData, void *elementRecord, Tk_Window tkwin, - Drawable d, Ttk_Box b, Ttk_State state) +static void +TabElementDraw( + void *clientData, + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + Ttk_State state) { CGRect bounds = BoxToRect(d, b); HIThemeTabDrawInfo info = { @@ -1338,7 +1390,8 @@ static void TabElementDraw( .kind = kHIThemeTabKindNormal, .position = Ttk_StateTableLookup(TabPositionTable, state), }; - BEGIN_DRAWING(d) + + BEGIN_DRAWING(d); #if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 if (TkMacOSXInDarkMode(tkwin)) { DrawDarkTab(bounds, state, dc.context); @@ -1348,7 +1401,7 @@ static void TabElementDraw( #else ChkErr(HIThemeDrawTab, &bounds, &info, dc.context, HIOrientation, NULL); #endif - END_DRAWING + END_DRAWING; } static Ttk_ElementSpec TabElementSpec = { @@ -1375,27 +1428,28 @@ static void PaneElementDraw( Drawable d, Ttk_Box b, Ttk_State state) { CGRect bounds = BoxToRect(d, b); + bounds.origin.y -= kThemeMetricTabFrameOverlap; bounds.size.height += kThemeMetricTabFrameOverlap; - BEGIN_DRAWING(d) + BEGIN_DRAWING(d); if ([NSApp macMinorVersion] > 9) { #if MAC_OS_X_VERSION_MAX_ALLOWED > 1080 - DrawGroupBox(bounds, dc.context, tkwin); + DrawGroupBox(bounds, dc.context, tkwin); #endif } else { - HIThemeTabPaneDrawInfo info = { - .version = 1, - .state = Ttk_StateTableLookup(ThemeStateTable, state), - .direction = kThemeTabNorth, - .size = kHIThemeTabSizeNormal, - .kind = kHIThemeTabKindNormal, - .adornment = kHIThemeTabPaneAdornmentNormal, - }; - bounds.origin.y -= kThemeMetricTabFrameOverlap; - bounds.size.height += kThemeMetricTabFrameOverlap; - ChkErr(HIThemeDrawTabPane, &bounds, &info, dc.context, HIOrientation); + HIThemeTabPaneDrawInfo info = { + .version = 1, + .state = Ttk_StateTableLookup(ThemeStateTable, state), + .direction = kThemeTabNorth, + .size = kHIThemeTabSizeNormal, + .kind = kHIThemeTabKindNormal, + .adornment = kHIThemeTabPaneAdornmentNormal, + }; + bounds.origin.y -= kThemeMetricTabFrameOverlap; + bounds.size.height += kThemeMetricTabFrameOverlap; + ChkErr(HIThemeDrawTabPane, &bounds, &info, dc.context, HIOrientation); } - END_DRAWING + END_DRAWING; } static Ttk_ElementSpec PaneElementSpec = { @@ -1418,32 +1472,39 @@ static Ttk_ElementSpec PaneElementSpec = { */ static void GroupElementSize( - void *clientData, void *elementRecord, Tk_Window tkwin, - int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + int *minWidth, int *minHeight, + Ttk_Padding *paddingPtr) { *paddingPtr = Ttk_UniformPadding(4); } static void GroupElementDraw( - void *clientData, void *elementRecord, Tk_Window tkwin, - Drawable d, Ttk_Box b, Ttk_State state) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + Ttk_State state) { CGRect bounds = BoxToRect(d, b); - BEGIN_DRAWING(d) + BEGIN_DRAWING(d); if ([NSApp macMinorVersion] > 9) { #if MAC_OS_X_VERSION_MAX_ALLOWED > 1080 - DrawGroupBox(bounds, dc.context, tkwin); + DrawGroupBox(bounds, dc.context, tkwin); #endif } else { - const HIThemeGroupBoxDrawInfo info = { - .version = 0, - .state = Ttk_StateTableLookup(ThemeStateTable, state), - .kind = kHIThemeGroupBoxKindPrimaryOpaque, - }; - ChkErr(HIThemeDrawGroupBox, &bounds, &info, dc.context, HIOrientation); + const HIThemeGroupBoxDrawInfo info = { + .version = 0, + .state = Ttk_StateTableLookup(ThemeStateTable, state), + .kind = kHIThemeGroupBoxKindPrimaryOpaque, + }; + ChkErr(HIThemeDrawGroupBox, &bounds, &info, dc.context, HIOrientation); } - END_DRAWING + END_DRAWING; } static Ttk_ElementSpec GroupElementSpec = { @@ -1469,9 +1530,9 @@ typedef struct { static Ttk_ElementOptionSpec EntryElementOptions[] = { { "-background", TK_OPTION_BORDER, - Tk_Offset(EntryElement,backgroundObj), ENTRY_DEFAULT_BACKGROUND }, + Tk_Offset(EntryElement,backgroundObj), ENTRY_DEFAULT_BACKGROUND }, { "-fieldbackground", TK_OPTION_BORDER, - Tk_Offset(EntryElement,fieldbackgroundObj), ENTRY_DEFAULT_BACKGROUND }, + Tk_Offset(EntryElement,fieldbackgroundObj), ENTRY_DEFAULT_BACKGROUND }, {0} }; @@ -1495,9 +1556,10 @@ static void EntryElementDraw( if (TkMacOSXInDarkMode(tkwin)) { #if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 - BEGIN_DRAWING(d) + BEGIN_DRAWING(d); NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; CGFloat fill[4]; + GetBackgroundColor(dc.context, tkwin, 1, fill); background = [NSColor colorWithColorSpace: deviceRGB components: fill @@ -1505,7 +1567,7 @@ static void EntryElementDraw( CGContextSetFillColorWithColor(dc.context, background.CGColor); CGContextFillRect(dc.context, bounds); DrawDarkFrame(bounds, dc.context, kHIThemeFrameTextFieldSquare); - END_DRAWING + END_DRAWING; #endif } else { const HIThemeFrameDrawInfo info = { @@ -1534,7 +1596,7 @@ static void EntryElementDraw( Tk_3DBorderGC(tkwin, backgroundPtr, TK_3D_FLAT_GC), inner.x, inner.y, inner.width, inner.height); } - BEGIN_DRAWING(d) + BEGIN_DRAWING(d); if (backgroundPtr == NULL) { background = [NSColor textBackgroundColor]; #if MAC_OS_X_VERSION_MIN_REQUIRED > 1080 @@ -1545,7 +1607,7 @@ static void EntryElementDraw( CGContextFillRect(dc.context, bounds); } ChkErr(HIThemeDrawFrame, &bounds, &info, dc.context, HIOrientation); - END_DRAWING + END_DRAWING; } /*if (state & TTK_STATE_FOCUS) { ChkErr(DrawThemeFocusRect, &bounds, 1); @@ -1604,26 +1666,26 @@ static void ComboboxElementDraw( .adornment = Ttk_StateTableLookup(ButtonAdornmentTable, state), }; - BEGIN_DRAWING(d) + BEGIN_DRAWING(d); bounds.origin.y += 1; if (TkMacOSXInDarkMode(tkwin)) { #if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 bounds.size.height += 1; DrawDarkButton(bounds, info.kind, state, dc.context); #endif - } else - { + } else { #if MAC_OS_X_VERSION_MIN_REQUIRED > 1080 if ((state & TTK_STATE_BACKGROUND) && - !(state & TTK_STATE_DISABLED)) { + !(state & TTK_STATE_DISABLED)) { NSColor *background = [NSColor textBackgroundColor]; CGRect innerBounds = CGRectInset(bounds, 1, 2); + SolidFillRoundedRectangle(dc.context, innerBounds, 4, background); } #endif ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); } - END_DRAWING + END_DRAWING; } static Ttk_ElementSpec ComboboxElementSpec = { @@ -1674,12 +1736,14 @@ static void SpinButtonUpElementDraw( { CGRect bounds = BoxToRect(d, Ttk_PadBox(b, SpinbuttonMargins)); int infoState; + bounds.size.height *= 2; if (state & TTK_STATE_PRESSED) { infoState = kThemeStatePressedUp; } else { infoState = Ttk_StateTableLookup(ThemeStateTable, state); } + const HIThemeButtonDrawInfo info = { .version = 0, .state = infoState, @@ -1687,7 +1751,8 @@ static void SpinButtonUpElementDraw( .value = Ttk_StateTableLookup(ButtonValueTable, state), .adornment = kThemeAdornmentNone, }; - BEGIN_DRAWING(d) + + BEGIN_DRAWING(d); #if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 if (TkMacOSXInDarkMode(tkwin)) { DrawDarkIncDecButton(bounds, infoState, state, dc.context); @@ -1696,7 +1761,7 @@ static void SpinButtonUpElementDraw( { ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); } - END_DRAWING + END_DRAWING; } static Ttk_ElementSpec SpinButtonUpElementSpec = { @@ -1725,12 +1790,13 @@ static void SpinButtonDownElementDraw( { CGRect bounds = BoxToRect(d, Ttk_PadBox(b, SpinbuttonMargins)); int infoState = 0; + bounds.origin.y -= bounds.size.height; bounds.size.height *= 2; if (state & TTK_STATE_PRESSED) { infoState = kThemeStatePressedDown; } else { - return; + return; // ??? } const HIThemeButtonDrawInfo info = { .version = 0, @@ -1740,16 +1806,17 @@ static void SpinButtonDownElementDraw( .adornment = kThemeAdornmentNone, }; - BEGIN_DRAWING(d) + BEGIN_DRAWING(d); #if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 if (TkMacOSXInDarkMode(tkwin)) { DrawDarkIncDecButton(bounds, infoState, state, dc.context); } else #endif { - ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); + ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, + NULL); } - END_DRAWING + END_DRAWING; } static Ttk_ElementSpec SpinButtonDownElementSpec = { @@ -1850,7 +1917,7 @@ static void TrackElementDraw( info.trackInfo.slider.thumbDir = kThemeThumbPlain; } } - BEGIN_DRAWING(d) + BEGIN_DRAWING(d); #if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 if (TkMacOSXInDarkMode(tkwin)) { CGRect bounds = BoxToRect(d, b); @@ -1858,6 +1925,7 @@ static void TrackElementDraw( NSColor *trackColor = [NSColor colorWithColorSpace: deviceRGB components: darkTrack count: 4]; + if (orientation == TTK_ORIENT_HORIZONTAL) { bounds = CGRectInset(bounds, 1, bounds.size.height/2 - 2); } else { @@ -1867,7 +1935,7 @@ static void TrackElementDraw( } #endif ChkErr(HIThemeDrawTrack, &info, NULL, dc.context, HIOrientation); - END_DRAWING + END_DRAWING; } static Ttk_ElementSpec TrackElementSpec = { @@ -1887,6 +1955,7 @@ static Ttk_ElementSpec TrackElementSpec = { * Also buggy: The geometry here is a Wild-Assed-Guess; I can't figure out how * to get the Appearance Manager to tell me the slider size. */ + static void SliderElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) @@ -1971,7 +2040,7 @@ static void PbarElementDraw( .trackInfo.progress.phase = phase, }; - BEGIN_DRAWING(d) + BEGIN_DRAWING(d); #if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 if (TkMacOSXInDarkMode(tkwin)) { CGRect bounds = BoxToRect(d, b); @@ -1988,7 +2057,7 @@ static void PbarElementDraw( } #endif ChkErr(HIThemeDrawTrack, &info, NULL, dc.context, HIOrientation); - END_DRAWING + END_DRAWING; } static Ttk_ElementSpec PbarElementSpec = { @@ -2054,6 +2123,7 @@ static void TroughElementDraw( NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; NSColor *troughColor; CGFloat *rgba = TkMacOSXInDarkMode(tkwin) ? darkTrough : lightTrough; + Ttk_GetOrientFromObj(NULL, scrollbar->orientObj, &orientation); if (orientation == TTK_ORIENT_HORIZONTAL) { bounds = CGRectInset(bounds, 0, 1); @@ -2063,7 +2133,7 @@ static void TroughElementDraw( troughColor = [NSColor colorWithColorSpace: deviceRGB components: rgba count: 4]; - BEGIN_DRAWING(d) + BEGIN_DRAWING(d); if ([NSApp macMinorVersion] > 8) { #if MAC_OS_X_VERSION_MIN_REQUIRED > 1080 CGContextSetFillColorWithColor(dc.context, troughColor.CGColor); @@ -2073,7 +2143,7 @@ static void TroughElementDraw( dc.context, HIOrientation); } CGContextFillRect(dc.context, bounds); - END_DRAWING + END_DRAWING; } static Ttk_ElementSpec TroughElementSpec = { @@ -2105,6 +2175,7 @@ static void ThumbElementDraw( { ScrollbarElement *scrollbar = elementRecord; int orientation = TTK_ORIENT_HORIZONTAL; + Ttk_GetOrientFromObj(NULL, scrollbar->orientObj, &orientation); /* @@ -2129,15 +2200,18 @@ static void ThumbElementDraw( NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; NSColor *thumbColor; CGFloat *rgba; - if ((orientation == TTK_ORIENT_HORIZONTAL && - thumbBounds.size.width >= Tk_Width(tkwin) - 8) || - (orientation == TTK_ORIENT_VERTICAL && - thumbBounds.size.height >= Tk_Height(tkwin) - 8)) { + + if ((orientation == TTK_ORIENT_HORIZONTAL + && thumbBounds.size.width >= Tk_Width(tkwin) - 8) + || (orientation == TTK_ORIENT_VERTICAL + && thumbBounds.size.height >= Tk_Height(tkwin) - 8)) { return; } + int isDark = TkMacOSXInDarkMode(tkwin); + if ((state & TTK_STATE_PRESSED) || - (state & TTK_STATE_HOVER) ) { + (state & TTK_STATE_HOVER)) { rgba = isDark ? darkActiveThumb : lightActiveThumb; } else { rgba = isDark ? darkInactiveThumb : lightInactiveThumb; @@ -2145,9 +2219,9 @@ static void ThumbElementDraw( thumbColor = [NSColor colorWithColorSpace: deviceRGB components: rgba count: 4]; - BEGIN_DRAWING(d) - SolidFillRoundedRectangle(dc.context, thumbBounds, 4, thumbColor); - END_DRAWING + BEGIN_DRAWING(d); + SolidFillRoundedRectangle(dc.context, thumbBounds, 4, thumbColor); + END_DRAWING; #endif } else { double thumbSize, trackSize, visibleSize, viewSize; @@ -2164,6 +2238,7 @@ static void ThumbElementDraw( */ viewSize = RangeToFactor(100.0); + HIThemeTrackDrawInfo info = { .version = 0, .bounds = troughBounds, @@ -2171,6 +2246,7 @@ static void ThumbElementDraw( .attributes = kThemeTrackShowThumb | kThemeTrackThumbRgnIsNotGhost, .enableState = kThemeTrackActive }; + info.trackInfo.scrollbar.viewsize = viewSize*.8; if (orientation == TTK_ORIENT_HORIZONTAL) { trackSize = troughBounds.size.width; @@ -2186,7 +2262,7 @@ static void ThumbElementDraw( info.value = info.max * (b.y / (trackSize - thumbSize)); } if ((state & TTK_STATE_PRESSED) || - (state & TTK_STATE_HOVER) ) { + (state & TTK_STATE_HOVER)) { info.trackInfo.scrollbar.pressState = kThemeThumbPressed; } else { info.trackInfo.scrollbar.pressState = 0; @@ -2196,10 +2272,10 @@ static void ThumbElementDraw( } else { info.attributes &= ~kThemeTrackHorizontal; } - BEGIN_DRAWING(d) - HIThemeDrawTrack (&info, 0, dc.context, kHIThemeOrientationNormal); - END_DRAWING - } + BEGIN_DRAWING(d); + HIThemeDrawTrack(&info, 0, dc.context, kHIThemeOrientationNormal); + END_DRAWING; + } } static Ttk_ElementSpec ThumbElementSpec = { @@ -2255,7 +2331,7 @@ static void SeparatorElementDraw( .state = Ttk_StateTableLookup(ThemeStateTable, state & TTK_STATE_BACKGROUND), }; - BEGIN_DRAWING(d) + BEGIN_DRAWING(d); #if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 if (TkMacOSXInDarkMode(tkwin)) { DrawDarkSeparator(bounds, dc.context, tkwin); @@ -2265,7 +2341,7 @@ static void SeparatorElementDraw( #else ChkErr(HIThemeDrawSeparator, &bounds, &info, dc.context, HIOrientation); #endif - END_DRAWING + END_DRAWING; } static Ttk_ElementSpec SeparatorElementSpec = { @@ -2316,9 +2392,9 @@ static void SizegripElementDraw( .size = kHIThemeGrowBoxSizeNormal, }; - BEGIN_DRAWING(d) + BEGIN_DRAWING(d); ChkErr(HIThemeDrawGrowBox, &bounds.origin, &info, dc.context, HIOrientation); - END_DRAWING + END_DRAWING; } static Ttk_ElementSpec SizegripElementSpec = { @@ -2381,23 +2457,25 @@ static void FillElementDraw( NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; NSColor *bgColor; CGFloat fill[4]; - BEGIN_DRAWING(d) + + BEGIN_DRAWING(d); GetBackgroundColor(dc.context, tkwin, 0, fill); bgColor = [NSColor colorWithColorSpace: deviceRGB components: fill count: 4]; CGContextSetFillColorSpace(dc.context, deviceRGB.CGColorSpace); CGContextSetFillColorWithColor(dc.context, bgColor.CGColor); CGContextFillRect(dc.context, bounds); - END_DRAWING + END_DRAWING; #else ThemeBrush brush = (state & TTK_STATE_BACKGROUND) ? kThemeBrushModelessDialogBackgroundInactive : kThemeBrushModelessDialogBackgroundActive; - BEGIN_DRAWING(d) + + BEGIN_DRAWING(d); ChkErr(HIThemeSetFill, brush, NULL, dc.context, HIOrientation); //QDSetPatternOrigin(PatternOrigin(tkwin, d)); CGContextFillRect(dc.context, bounds); - END_DRAWING + END_DRAWING; #endif } @@ -2406,7 +2484,7 @@ static void BackgroundElementDraw( Drawable d, Ttk_Box b, unsigned int state) { FillElementDraw(clientData, elementRecord, tkwin, d, Ttk_WinBox(tkwin), - state); + state); } static Ttk_ElementSpec FillElementSpec = { @@ -2429,9 +2507,9 @@ static Ttk_ElementSpec BackgroundElementSpec = { * +++ ToolbarBackground element -- toolbar style for frames. * * This is very similar to the normal background element, but uses a - * different ThemeBrush in order to get the lighter pinstripe effect - * used in toolbars. We use SetThemeBackground() rather than - * ApplyThemeBackground() in order to get the right style. + * different ThemeBrush in order to get the lighter pinstripe effect used in + * toolbars. We use SetThemeBackground() rather than ApplyThemeBackground() + * in order to get the right style. * * 8) { #if MAC_OS_X_VERSION_MIN_REQUIRED > 1080 - /* - * Compensate for the padding added in TreeHeaderElementSize, so - * the larger heading will be drawn at the top of the widget. + * Compensate for the padding added in TreeHeaderElementSize, so the + * larger heading will be drawn at the top of the widget. */ bounds.origin.y -= 4; @@ -2586,7 +2663,7 @@ static void TreeHeaderElementDraw( } else { ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); } - END_DRAWING + END_DRAWING; } static Ttk_ElementSpec TreeHeaderElementSpec = { @@ -2636,9 +2713,9 @@ static void DisclosureElementDraw( .adornment = kThemeAdornmentDrawIndicatorOnly, }; - BEGIN_DRAWING(d) + BEGIN_DRAWING(d); ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); - END_DRAWING + END_DRAWING; } } @@ -2735,13 +2812,15 @@ TTK_LAYOUT("Horizontal.TScrollbar", TTK_NODE("Horizontal.Scrollbar.rightarrow", TTK_PACK_RIGHT) TTK_NODE("Horizontal.Scrollbar.leftarrow", TTK_PACK_RIGHT))) -TTK_END_LAYOUT_TABLE +TTK_END_LAYOUT_TABLE; /*---------------------------------------------------------------------- * +++ Initialization. */ -static int AquaTheme_Init(Tcl_Interp *interp) +static int +AquaTheme_Init( + Tcl_Interp *interp) { Ttk_Theme themePtr = Ttk_CreateTheme(interp, "aqua", NULL); @@ -2752,38 +2831,41 @@ static int AquaTheme_Init(Tcl_Interp *interp) /* * Elements: */ + Ttk_RegisterElementSpec(themePtr, "background", &BackgroundElementSpec, 0); Ttk_RegisterElementSpec(themePtr, "fill", &FillElementSpec, 0); Ttk_RegisterElementSpec(themePtr, "field", &FieldElementSpec, 0); Ttk_RegisterElementSpec(themePtr, "Toolbar.background", - &ToolbarBackgroundElementSpec, 0); + &ToolbarBackgroundElementSpec, 0); Ttk_RegisterElementSpec(themePtr, "Button.button", - &ButtonElementSpec, &PushButtonParams); + &ButtonElementSpec, &PushButtonParams); Ttk_RegisterElementSpec(themePtr, "Checkbutton.button", - &ButtonElementSpec, &CheckBoxParams); + &ButtonElementSpec, &CheckBoxParams); Ttk_RegisterElementSpec(themePtr, "Radiobutton.button", - &ButtonElementSpec, &RadioButtonParams); + &ButtonElementSpec, &RadioButtonParams); Ttk_RegisterElementSpec(themePtr, "Toolbutton.border", - &ButtonElementSpec, &BevelButtonParams); + &ButtonElementSpec, &BevelButtonParams); Ttk_RegisterElementSpec(themePtr, "Menubutton.button", - &ButtonElementSpec, &PopupButtonParams); + &ButtonElementSpec, &PopupButtonParams); Ttk_RegisterElementSpec(themePtr, "Spinbox.uparrow", - &SpinButtonUpElementSpec, 0); + &SpinButtonUpElementSpec, 0); Ttk_RegisterElementSpec(themePtr, "Spinbox.downarrow", - &SpinButtonDownElementSpec, 0); + &SpinButtonDownElementSpec, 0); Ttk_RegisterElementSpec(themePtr, "Combobox.button", - &ComboboxElementSpec, 0); + &ComboboxElementSpec, 0); Ttk_RegisterElementSpec(themePtr, "Treeitem.indicator", - &DisclosureElementSpec, &DisclosureParams); + &DisclosureElementSpec, &DisclosureParams); Ttk_RegisterElementSpec(themePtr, "Treeheading.cell", - &TreeHeaderElementSpec, &ListHeaderParams); + &TreeHeaderElementSpec, &ListHeaderParams); - Ttk_RegisterElementSpec(themePtr, "Treeview.treearea", &TreeAreaElementSpec, 0); + Ttk_RegisterElementSpec(themePtr, "Treeview.treearea", + &TreeAreaElementSpec, 0); Ttk_RegisterElementSpec(themePtr, "Notebook.tab", &TabElementSpec, 0); Ttk_RegisterElementSpec(themePtr, "Notebook.client", &PaneElementSpec, 0); - Ttk_RegisterElementSpec(themePtr, "Labelframe.border", &GroupElementSpec, 0); + Ttk_RegisterElementSpec(themePtr, "Labelframe.border", + &GroupElementSpec, 0); Ttk_RegisterElementSpec(themePtr, "Entry.field", &EntryElementSpec, 0); Ttk_RegisterElementSpec(themePtr, "Spinbox.field", &EntryElementSpec, 0); @@ -2803,23 +2885,31 @@ static int AquaTheme_Init(Tcl_Interp *interp) Ttk_RegisterElementSpec(themePtr,"Progressbar.track", &PbarElementSpec, 0); Ttk_RegisterElementSpec(themePtr,"Scale.trough", &TrackElementSpec, - &ScaleData); + &ScaleData); Ttk_RegisterElementSpec(themePtr,"Scale.slider", &SliderElementSpec, 0); - Ttk_RegisterElementSpec(themePtr,"Vertical.Scrollbar.trough", &TroughElementSpec, 0); - Ttk_RegisterElementSpec(themePtr,"Vertical.Scrollbar.thumb", &ThumbElementSpec, 0); - Ttk_RegisterElementSpec(themePtr,"Horizontal.Scrollbar.trough", &TroughElementSpec, 0); - Ttk_RegisterElementSpec(themePtr,"Horizontal.Scrollbar.thumb", &ThumbElementSpec, 0); + Ttk_RegisterElementSpec(themePtr,"Vertical.Scrollbar.trough", + &TroughElementSpec, 0); + Ttk_RegisterElementSpec(themePtr,"Vertical.Scrollbar.thumb", + &ThumbElementSpec, 0); + Ttk_RegisterElementSpec(themePtr,"Horizontal.Scrollbar.trough", + &TroughElementSpec, 0); + Ttk_RegisterElementSpec(themePtr,"Horizontal.Scrollbar.thumb", + &ThumbElementSpec, 0); /* * If we are not in Snow Leopard or Lion the arrows won't actually be * displayed. */ - Ttk_RegisterElementSpec(themePtr,"Vertical.Scrollbar.uparrow", &ArrowElementSpec, 0); - Ttk_RegisterElementSpec(themePtr,"Vertical.Scrollbar.downarrow", &ArrowElementSpec, 0); - Ttk_RegisterElementSpec(themePtr,"Horizontal.Scrollbar.leftarrow", &ArrowElementSpec, 0); - Ttk_RegisterElementSpec(themePtr,"Horizontal.Scrollbar.rightarrow", &ArrowElementSpec, 0); + Ttk_RegisterElementSpec(themePtr,"Vertical.Scrollbar.uparrow", + &ArrowElementSpec, 0); + Ttk_RegisterElementSpec(themePtr,"Vertical.Scrollbar.downarrow", + &ArrowElementSpec, 0); + Ttk_RegisterElementSpec(themePtr,"Horizontal.Scrollbar.leftarrow", + &ArrowElementSpec, 0); + Ttk_RegisterElementSpec(themePtr,"Horizontal.Scrollbar.rightarrow", + &ArrowElementSpec, 0); /* * Layouts: -- cgit v0.12 From fe47ed884e4c078ce819858ea94ef4319721dd04 Mon Sep 17 00:00:00 2001 From: culler Date: Wed, 17 Apr 2019 14:30:50 +0000 Subject: Add a couple of blank lines. --- macosx/tkMacOSXKeyEvent.c | 1 + macosx/tkMacOSXMenu.c | 1 + 2 files changed, 2 insertions(+) diff --git a/macosx/tkMacOSXKeyEvent.c b/macosx/tkMacOSXKeyEvent.c index 7ff1184..d578c36 100644 --- a/macosx/tkMacOSXKeyEvent.c +++ b/macosx/tkMacOSXKeyEvent.c @@ -732,6 +732,7 @@ isFunctionKey( const unsigned last_keysym = (sizeof (convert_ns_to_X_keysym) / sizeof (convert_ns_to_X_keysym[0])); unsigned keysym; + for (keysym = 0; keysym < last_keysym; keysym += 2) { if (code == convert_ns_to_X_keysym[keysym]) { return 0xFF00 | convert_ns_to_X_keysym[keysym+1]; diff --git a/macosx/tkMacOSXMenu.c b/macosx/tkMacOSXMenu.c index fc1b7c4..e04b413 100644 --- a/macosx/tkMacOSXMenu.c +++ b/macosx/tkMacOSXMenu.c @@ -698,6 +698,7 @@ TkpConfigureMenuEntry( int i = 0; NSArray *itemArray = [submenu itemArray]; + for (NSMenuItem *item in itemArray) { TkMenuEntry *submePtr = menuRefPtr->menuPtr->entries[i]; -- cgit v0.12 From 7d6fc907cfaf28414508b5d86fe39cee99b6168a Mon Sep 17 00:00:00 2001 From: culler Date: Wed, 17 Apr 2019 15:02:23 +0000 Subject: Adjust some whitespace. --- macosx/tkMacOSXKeyEvent.c | 102 +++++++++++++++++++++++----------------------- macosx/tkMacOSXMenu.c | 10 +++-- 2 files changed, 58 insertions(+), 54 deletions(-) diff --git a/macosx/tkMacOSXKeyEvent.c b/macosx/tkMacOSXKeyEvent.c index d578c36..6cf3783 100644 --- a/macosx/tkMacOSXKeyEvent.c +++ b/macosx/tkMacOSXKeyEvent.c @@ -666,54 +666,54 @@ Tk_SetCaretPos( static unsigned convert_ns_to_X_keysym[] = { - NSHomeFunctionKey, 0x50, - NSLeftArrowFunctionKey, 0x51, - NSUpArrowFunctionKey, 0x52, - NSRightArrowFunctionKey, 0x53, - NSDownArrowFunctionKey, 0x54, - NSPageUpFunctionKey, 0x55, - NSPageDownFunctionKey, 0x56, - NSEndFunctionKey, 0x57, - NSBeginFunctionKey, 0x58, - NSSelectFunctionKey, 0x60, - NSPrintFunctionKey, 0x61, - NSExecuteFunctionKey, 0x62, - NSInsertFunctionKey, 0x63, - NSUndoFunctionKey, 0x65, - NSRedoFunctionKey, 0x66, - NSMenuFunctionKey, 0x67, - NSFindFunctionKey, 0x68, - NSHelpFunctionKey, 0x6A, - NSBreakFunctionKey, 0x6B, - - NSF1FunctionKey, 0xBE, - NSF2FunctionKey, 0xBF, - NSF3FunctionKey, 0xC0, - NSF4FunctionKey, 0xC1, - NSF5FunctionKey, 0xC2, - NSF6FunctionKey, 0xC3, - NSF7FunctionKey, 0xC4, - NSF8FunctionKey, 0xC5, - NSF9FunctionKey, 0xC6, - NSF10FunctionKey, 0xC7, - NSF11FunctionKey, 0xC8, - NSF12FunctionKey, 0xC9, - NSF13FunctionKey, 0xCA, - NSF14FunctionKey, 0xCB, - NSF15FunctionKey, 0xCC, - NSF16FunctionKey, 0xCD, - NSF17FunctionKey, 0xCE, - NSF18FunctionKey, 0xCF, - NSF19FunctionKey, 0xD0, - NSF20FunctionKey, 0xD1, - NSF21FunctionKey, 0xD2, - NSF22FunctionKey, 0xD3, - NSF23FunctionKey, 0xD4, - NSF24FunctionKey, 0xD5, - - NSBackspaceCharacter, 0x08, /* 8: Not on some KBs. */ - NSDeleteCharacter, 0xFF, /* 127: Big 'delete' key upper right. */ - NSDeleteFunctionKey, 0x9F, /* 63272: Del forw key off main array. */ + NSHomeFunctionKey, 0x50, + NSLeftArrowFunctionKey, 0x51, + NSUpArrowFunctionKey, 0x52, + NSRightArrowFunctionKey, 0x53, + NSDownArrowFunctionKey, 0x54, + NSPageUpFunctionKey, 0x55, + NSPageDownFunctionKey, 0x56, + NSEndFunctionKey, 0x57, + NSBeginFunctionKey, 0x58, + NSSelectFunctionKey, 0x60, + NSPrintFunctionKey, 0x61, + NSExecuteFunctionKey, 0x62, + NSInsertFunctionKey, 0x63, + NSUndoFunctionKey, 0x65, + NSRedoFunctionKey, 0x66, + NSMenuFunctionKey, 0x67, + NSFindFunctionKey, 0x68, + NSHelpFunctionKey, 0x6A, + NSBreakFunctionKey, 0x6B, + + NSF1FunctionKey, 0xBE, + NSF2FunctionKey, 0xBF, + NSF3FunctionKey, 0xC0, + NSF4FunctionKey, 0xC1, + NSF5FunctionKey, 0xC2, + NSF6FunctionKey, 0xC3, + NSF7FunctionKey, 0xC4, + NSF8FunctionKey, 0xC5, + NSF9FunctionKey, 0xC6, + NSF10FunctionKey, 0xC7, + NSF11FunctionKey, 0xC8, + NSF12FunctionKey, 0xC9, + NSF13FunctionKey, 0xCA, + NSF14FunctionKey, 0xCB, + NSF15FunctionKey, 0xCC, + NSF16FunctionKey, 0xCD, + NSF17FunctionKey, 0xCE, + NSF18FunctionKey, 0xCF, + NSF19FunctionKey, 0xD0, + NSF20FunctionKey, 0xD1, + NSF21FunctionKey, 0xD2, + NSF22FunctionKey, 0xD3, + NSF23FunctionKey, 0xD4, + NSF24FunctionKey, 0xD5, + + NSBackspaceCharacter, 0x08, /* 8: Not on some KBs. */ + NSDeleteCharacter, 0xFF, /* 127: Big 'delete' key upper right. */ + NSDeleteFunctionKey, 0x9F, /* 63272: Del forw key off main array. */ NSTabCharacter, 0x09, 0x19, 0x09, /* left tab->regular since pass shift */ @@ -729,13 +729,13 @@ static unsigned isFunctionKey( unsigned code) { - const unsigned last_keysym = (sizeof (convert_ns_to_X_keysym) - / sizeof (convert_ns_to_X_keysym[0])); + const unsigned last_keysym = (sizeof(convert_ns_to_X_keysym) + / sizeof(convert_ns_to_X_keysym[0])); unsigned keysym; for (keysym = 0; keysym < last_keysym; keysym += 2) { if (code == convert_ns_to_X_keysym[keysym]) { - return 0xFF00 | convert_ns_to_X_keysym[keysym+1]; + return 0xFF00 | convert_ns_to_X_keysym[keysym + 1]; } } return 0; diff --git a/macosx/tkMacOSXMenu.c b/macosx/tkMacOSXMenu.c index e04b413..053b374 100644 --- a/macosx/tkMacOSXMenu.c +++ b/macosx/tkMacOSXMenu.c @@ -691,7 +691,8 @@ TkpConfigureMenuEntry( if ([menuItem isEnabled]) { - /* This menuItem might have been previously disabled (XXX: + /* + * This menuItem might have been previously disabled (XXX: * track this), which would have disabled entries; we must * re-enable the entries here. */ @@ -702,11 +703,14 @@ TkpConfigureMenuEntry( for (NSMenuItem *item in itemArray) { TkMenuEntry *submePtr = menuRefPtr->menuPtr->entries[i]; - /* Work around an apparent bug where itemArray can have + /* + * Work around an apparent bug where itemArray can have * more items than the menu's entries[] array. */ - if (i >= menuRefPtr->menuPtr->numEntries) break; + if (i >= (int) menuRefPtr->menuPtr->numEntries) { + break; + } [item setEnabled: !(submePtr->state == ENTRY_DISABLED)]; i++; } -- cgit v0.12 From 3379fb3b181b00a1d943eb3a009f97437fcce779 Mon Sep 17 00:00:00 2001 From: culler Date: Wed, 17 Apr 2019 20:41:37 +0000 Subject: Clean up formatting in ttkMacOSXTheme.c. --- macosx/ttkMacOSXTheme.c | 1939 ++++++++++++++++++++++++++--------------------- 1 file changed, 1062 insertions(+), 877 deletions(-) diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index 0c474f0..1f231a9 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -1,7 +1,7 @@ /* * ttkMacOSXTheme.c -- * - * Tk theme engine for Mac OSX, using the Appearance Manager API. + * Tk theme engine for Mac OSX, using the Appearance Manager API. * * Copyright (c) 2004 Joe English * Copyright (c) 2005 Neil Madden @@ -16,30 +16,32 @@ * See also: * * + * Appearance_Manager/appearance_manager/APIIndex.html > * * Notes: - * "Active" means different things in Mac and Tk terminology -- - * On Aqua, widgets are "Active" if they belong to the foreground window, - * "Inactive" if they are in a background window. Tk uses the term - * "active" to mean that the mouse cursor is over a widget; aka "hover", - * "prelight", or "hot-tracked". Aqua doesn't use this kind of feedback. + * "Active" means different things in Mac and Tk terminology -- + * On Aqua, widgets are "Active" if they belong to the foreground window, + * "Inactive" if they are in a background window. Tk uses the term + * "active" to mean that the mouse cursor is over a widget; aka "hover", + * "prelight", or "hot-tracked". Aqua doesn't use this kind of feedback. * - * The QuickDraw/Carbon coordinate system is relative to the top-level - * window, not to the Tk_Window. BoxToRect() accounts for this. + * The QuickDraw/Carbon coordinate system is relative to the top-level + * window, not to the Tk_Window. BoxToRect() accounts for this. */ #include "tkMacOSXPrivate.h" #include "ttk/ttkTheme.h" #include + /* * Macros for handling drawing contexts. */ -#define BEGIN_DRAWING(d) { \ - TkMacOSXDrawingContext dc; \ - if (!TkMacOSXSetupDrawingContext((d), NULL, 1, &dc)) {return;} + +#define BEGIN_DRAWING(d) { \ + TkMacOSXDrawingContext dc; \ + if (!TkMacOSXSetupDrawingContext((d), NULL, 1, &dc)) {return;} #define END_DRAWING \ - TkMacOSXRestoreDrawingContext(&dc); } + TkMacOSXRestoreDrawingContext(&dc);} #define HIOrientation kHIThemeOrientationNormal #define NoThemeMetric 0xFFFFFFFF @@ -50,9 +52,9 @@ #define RangeToFactor(maximum) (((double) (LONG_MAX >> 1)) / (maximum)) #endif /* __LP64__ */ -#define TTK_STATE_FIRST_TAB TTK_STATE_USER1 -#define TTK_STATE_LAST_TAB TTK_STATE_USER2 -#define TTK_TREEVIEW_STATE_SORTARROW TTK_STATE_USER1 +#define TTK_STATE_FIRST_TAB TTK_STATE_USER1 +#define TTK_STATE_LAST_TAB TTK_STATE_USER2 +#define TTK_TREEVIEW_STATE_SORTARROW TTK_STATE_USER1 /*---------------------------------------------------------------------- * +++ Utilities. @@ -60,22 +62,21 @@ /* * BoxToRect -- - * Convert a Ttk_Box in Tk coordinates relative to the given Drawable to a - * native Rect relative to the containing port. + * Convert a Ttk_Box in Tk coordinates relative to the given Drawable + * to a native Rect relative to the containing port. */ -static inline CGRect -BoxToRect( +static inline CGRect BoxToRect( Drawable d, Ttk_Box b) { - MacDrawable *md = (MacDrawable*)d; + MacDrawable *md = (MacDrawable *) d; CGRect rect; - rect.origin.y = b.y + md->yOff; - rect.origin.x = b.x + md->xOff; - rect.size.height = b.height; - rect.size.width = b.width; + rect.origin.y = b.y + md->yOff; + rect.origin.x = b.x + md->xOff; + rect.size.height = b.height; + rect.size.width = b.width; return rect; } @@ -89,49 +90,53 @@ static Ttk_StateTable ThemeStateTable[] = { {kThemeStatePressed, TTK_STATE_PRESSED, 0}, {kThemeStateInactive, TTK_STATE_BACKGROUND, 0}, {kThemeStateActive, 0, 0} -/* Others: Not sure what these are supposed to mean. - Up/Down have something to do with "little arrow" increment controls... - Dunno what a "Rollover" is. - NEM: Rollover is TTK_STATE_ACTIVE... but we don't handle that yet, by the - looks of things - {kThemeStateRollover, 0, 0}, - {kThemeStateUnavailableInactive, 0, 0} - {kThemeStatePressedUp, 0, 0}, - {kThemeStatePressedDown, 0, 0} -*/ + + /* Others: Not sure what these are supposed to mean. Up/Down have + * something to do with "little arrow" increment controls... Dunno what + * a "Rollover" is. + * NEM: Rollover is TTK_STATE_ACTIVE... but we don't handle that yet, by + * the looks of things + * + * {kThemeStateRollover, 0, 0}, + * {kThemeStateUnavailableInactive, 0, 0} + * {kThemeStatePressedUp, 0, 0}, + * {kThemeStatePressedDown, 0, 0} + */ }; -/* +/*---------------------------------------------------------------------- * NormalizeButtonBounds -- * - * Apple's Human Interface Guidelines only allow three specific heights for - * most buttons: Regular, small and mini. We always use the regular size. - * However, Ttk may provide an arbitrary bounding rectangle. We always draw the - * button centered vertically on the rectangle, and having the same width as - * the rectangle. This function returns the actual bounding rectangle that will - * be used in drawing the button. + * Apple's Human Interface Guidelines only allow three specific heights + * for most buttons: Regular, small and mini. We always use the regular + * size. However, Ttk may provide an arbitrary bounding rectangle. We + * always draw the button centered vertically on the rectangle, and + * having the same width as the rectangle. This function returns the + * actual bounding rectangle that will be used in drawing the button. * - * The BevelButton is allowed to have arbitrary size, and also has external - * padding. This is handled separately here. + * The BevelButton is allowed to have arbitrary size, and also has + * external padding. This is handled separately here. */ static CGRect NormalizeButtonBounds( SInt32 heightMetric, CGRect bounds) { - if (heightMetric != (SInt32) NoThemeMetric) { - SInt32 height; + SInt32 height; + if (heightMetric != (SInt32) NoThemeMetric) { ChkErr(GetThemeMetric, heightMetric, &height); - bounds.origin.y += (bounds.size.height - height)/2; + bounds.origin.y += (bounds.size.height - height) / 2; bounds.size.height = height; } return bounds; } -#if MAC_OS_X_VERSION_MAX_ALLOWED > 1080 +#if MAC_OS_X_VERSION_MIN_REQUIRED > 1080 /*---------------------------------------------------------------------- - * +++ Support for contrasting background colors when GroupBoxes or Tabbed + * +++ Backgrounds + * + * Support for contrasting background colors when GroupBoxes or Tabbed * panes are nested inside each other. Early versions of macOS used ridged * borders, so do not need contrasting backgrounds. */ @@ -144,18 +149,21 @@ static CGRect NormalizeButtonBounds( * support Dark Mode anyway. */ -static CGFloat windowBackground[4] = {236.0/255, 236.0/255, 236.0/255, 1.0}; +static CGFloat windowBackground[4] = { + 235.0 / 255, 235.0 / 255, 235.0 / 255, 1.0 +}; +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. + * 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( @@ -181,8 +189,7 @@ static void GetBackgroundColor( if ([NSApp macMinorVersion] > 13) { NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; NSColor *windowColor = [[NSColor windowBackgroundColor] - colorUsingColorSpace: deviceRGB]; - + colorUsingColorSpace: deviceRGB]; [windowColor getComponents: rgba]; } else { for (int i = 0; i < 4; i++) { @@ -194,12 +201,12 @@ static void GetBackgroundColor( int isDark = (rgba[0] + rgba[1] + rgba[2] < 1.5); if (isDark) { - for (int i=0; i<3; i++) { - rgba[i] += 8.0/255.0; + for (int i = 0; i < 3; i++) { + rgba[i] += 8.0 / 255.0; } } else { - for (int i=0; i<3; i++) { - rgba[i] -= 8.0/255.0; + for (int i = 0; i < 3; i++) { + rgba[i] -= 8.0 / 255.0; } } winPtr->privatePtr->flags |= TTK_HAS_CONTRASTING_BG; @@ -212,8 +219,8 @@ static void GetBackgroundColor( /*---------------------------------------------------------------------- * DrawGroupBox -- * - * This is a standalone drawing procedure which draws the contrasting - * rounded rectangular box for LabelFrames and Notebook panes. + * This is a standalone drawing procedure which draws the contrasting + * rounded rectangular box for LabelFrames and Notebook panes. */ static void DrawGroupBox( @@ -229,7 +236,7 @@ static void DrawGroupBox( GetBackgroundColor(context, tkwin, 1, fill); bgColor = [NSColor colorWithColorSpace: deviceRGB components: fill - count: 4]; + count: 4]; CGContextSetFillColorSpace(context, deviceRGB.CGColorSpace); CGContextSetFillColorWithColor(context, bgColor.CGColor); path = CGPathCreateWithRoundedRect(bounds, 4, 4, NULL); @@ -238,7 +245,7 @@ static void DrawGroupBox( CGContextAddPath(context, path); CGContextFillPath(context); borderColor = [NSColor colorWithColorSpace: deviceRGB components: border - count: 4]; + count: 4]; CGContextSetFillColorWithColor(context, borderColor.CGColor); [borderColor getComponents: fill]; CGContextSetRGBFillColor(context, fill[0], fill[1], fill[2], fill[3]); @@ -253,7 +260,7 @@ static void DrawGroupBox( /*---------------------------------------------------------------------- * SolidFillRoundedRectangle -- * - * Fill a rounded rectangle with a specified solid color. + * Fill a rounded rectangle with a specified solid color. */ static void SolidFillRoundedRectangle( @@ -272,7 +279,44 @@ static void SolidFillRoundedRectangle( CFRelease(path); } -static void DrawDownArrow( +/*---------------------------------------------------------------------- + * GradientFillRoundedRectangle -- + * + * Fill a rounded rectangle with a specified gradient. + */ + +static void GradientFillRoundedRectangle( + CGContextRef context, + CGRect bounds, + CGFloat radius, + CGFloat *colors, + int numColors) +{ + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + CGPathRef path; + CGPoint end = { + bounds.origin.x, + bounds.origin.y + bounds.size.height + }; + CGGradientRef gradient = CGGradientCreateWithColorComponents( + deviceRGB.CGColorSpace, colors, NULL, numColors); + + path = CGPathCreateWithRoundedRect(bounds, radius, radius, NULL); + CGContextBeginPath(context); + CGContextAddPath(context, path); + CGContextClip(context); + CGContextDrawLinearGradient(context, gradient, bounds.origin, end, 0); + CFRelease(path); + CFRelease(gradient); +} + +/*---------------------------------------------------------------------- + * +++ Arrow Buttons -- + * + * Used in MenuButtons, SpinButtons, ComboBoxes, ListHeaders. + */ + +static void DrawUpDownArrows( CGContextRef context, CGRect bounds, CGFloat inset, @@ -284,13 +328,35 @@ static void DrawDownArrow( CGContextSetRGBStrokeColor(context, rgba[0], rgba[1], rgba[2], rgba[3]); CGContextSetLineWidth(context, 1.5); x = bounds.origin.x + inset; - y = bounds.origin.y + trunc(bounds.size.height/2); + y = bounds.origin.y + trunc(bounds.size.height / 2); + CGContextBeginPath(context); + CGPoint bottomArrow[3] = + {{x, y + 2}, {x + size / 2, y + 2 + size / 2}, {x + size, y + 2}}; + CGContextAddLines(context, bottomArrow, 3); + CGPoint topArrow[3] = + {{x, y - 2}, {x + size / 2, y - 2 - size / 2}, {x + size, y - 2}}; + CGContextAddLines(context, topArrow, 3); + CGContextStrokePath(context); +} - CGPoint arrow[3] = { - {x, y-size/4}, {x+size/2, y+size/4}, {x+size, y-size/4} - }; +static void DrawDownArrow( + CGContextRef context, + CGRect bounds, + CGFloat inset, + CGFloat size, + CGFloat *rgba) +{ + CGFloat x, y; + CGContextSetRGBStrokeColor(context, rgba[0], rgba[1], rgba[2], rgba[3]); + CGContextSetLineWidth(context, 1.5); + x = bounds.origin.x + inset; + y = bounds.origin.y + trunc(bounds.size.height / 2); CGContextBeginPath(context); + CGPoint arrow[3] = { + {x, y - size / 4}, {x + size / 2, y + size / 4}, + {x + size, y - size / 4} + }; CGContextAddLines(context, arrow, 3); CGContextStrokePath(context); } @@ -307,24 +373,23 @@ static void DrawUpArrow( CGContextSetRGBStrokeColor(context, rgba[0], rgba[1], rgba[2], rgba[3]); CGContextSetLineWidth(context, 1.5); x = bounds.origin.x + inset; - y = bounds.origin.y + trunc(bounds.size.height/2); - + y = bounds.origin.y + trunc(bounds.size.height / 2); + CGContextBeginPath(context); CGPoint arrow[3] = { - {x, y+size/4}, {x+size/2, y-size/4}, {x+size, y+size/4} + {x, y + size / 4}, {x + size / 2, y - size / 4}, + {x + size, y + size / 4} }; - - CGContextBeginPath(context); CGContextAddLines(context, arrow, 3); CGContextStrokePath(context); } /*---------------------------------------------------------------------- - * DrawListHeader -- + * +++ DrawListHeader -- * - * This is a standalone drawing procedure which draws column headers for a - * Treeview in the Aqua appearance. The HITheme headers have not matched - * the native ones since OSX 10.8. Note that the header image is ignored, - * but we draw arrows according to the state. + * This is a standalone drawing procedure which draws column headers for + * a Treeview in the Aqua appearance. The HITheme headers have not + * matched the native ones since OSX 10.8. Note that the header image is + * ignored, but we draw arrows according to the state. */ static void DrawListHeader( @@ -335,10 +400,18 @@ static void DrawListHeader( { NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; NSColor *strokeColor, *bgColor; - static CGFloat borderRGBA[4] = {200.0/255, 200.0/255, 200.0/255, 1.0}; - static CGFloat separatorRGBA[4] = {220.0/255, 220.0/255, 220.0/255, 1.0}; - static CGFloat activeBgRGBA[4] = {238.0/255, 238.0/255, 238.0/255, 1.0}; - static CGFloat inactiveBgRGBA[4] = {246.0/255, 246.0/255, 246.0/255, 1.0}; + static CGFloat borderRGBA[4] = { + 200.0 / 255, 200.0 / 255, 200.0 / 255, 1.0 + }; + static CGFloat separatorRGBA[4] = { + 220.0 / 255, 220.0 / 255, 220.0 / 255, 1.0 + }; + static CGFloat activeBgRGBA[4] = { + 238.0 / 255, 238.0 / 255, 238.0 / 255, 1.0 + }; + static CGFloat inactiveBgRGBA[4] = { + 246.0 / 255, 246.0 / 255, 246.0 / 255, 1.0 + }; /* * Apple changes the background of a list header when the window is not @@ -351,12 +424,12 @@ static void DrawListHeader( CGFloat x = bounds.origin.x, y = bounds.origin.y; CGFloat w = bounds.size.width, h = bounds.size.height; CGPoint top[2] = {{x, y + 1}, {x + w, y + 1}}; - CGPoint bottom[2] = {{x, y + h}, {x + w, y + h}}; + CGPoint bottom[2] = {{x, y + h}, {x + w, y + h}}; CGPoint separator[2] = {{x + w - 1, y + 3}, {x + w - 1, y + h - 3}}; - + bgColor = [NSColor colorWithColorSpace: deviceRGB - components: bgRGBA - count: 4]; + components: bgRGBA + count: 4]; CGContextSaveGState(context); CGContextSetShouldAntialias(context, false); CGContextSetFillColorSpace(context, deviceRGB.CGColorSpace); @@ -366,14 +439,14 @@ static void DrawListHeader( CGContextAddRect(context, bounds); CGContextFillPath(context); strokeColor = [NSColor colorWithColorSpace: deviceRGB - components: separatorRGBA - count: 4]; + components: separatorRGBA + count: 4]; CGContextSetStrokeColorWithColor(context, strokeColor.CGColor); CGContextAddLines(context, separator, 2); CGContextStrokePath(context); strokeColor = [NSColor colorWithColorSpace: deviceRGB - components: borderRGBA - count: 4]; + components: borderRGBA + count: 4]; CGContextSetStrokeColorWithColor(context, strokeColor.CGColor); CGContextAddLines(context, top, 2); CGContextStrokePath(context); @@ -383,7 +456,6 @@ static void DrawListHeader( if (state & TTK_TREEVIEW_STATE_SORTARROW) { CGRect arrowBounds = bounds; - arrowBounds.origin.x = bounds.origin.x + bounds.size.width - 16; arrowBounds.size.width = 16; if (state & TTK_STATE_ALTERNATE) { @@ -394,99 +466,63 @@ static void DrawListHeader( } } -#endif /* MAC_OS_X_VERSION_MAX_ALLOWED > 1080 */ +#endif /* MAC_OS_X_VERSION_MIN_REQUIRED > 1080 */ -#if MAC_OS_X_VERSION_MAX_ALLOWED > 101300 +#if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 /*---------------------------------------------------------------------- * +++ Drawing procedures for widgets in Apple's "Dark Mode" (10.14 and up). * - * The HIToolbox does not support Dark Mode, and apparently never will, - * so to make widgets look "native" we have to provide analogues of the - * HITheme drawing functions to be used in DarkAqua. We continue to use - * HITheme in Aqua, since it understands earlier versions of the OS. + * The HIToolbox does not support Dark Mode, and apparently never will, + * so to make widgets look "native" we have to provide analogues of the + * HITheme drawing functions to be used in DarkAqua. We continue to use + * HITheme in Aqua, since it understands earlier versions of the OS. */ /* * Colors and gradients used in Dark Mode. */ -static CGFloat darkButtonFace[4] = {112.0/255, 113.0/255, 115.0/255, 1.0}; -static CGFloat darkPressedBevelFace[4] = {135.0/255, 136.0/255, 138.0/255, 1.0}; -static CGFloat darkSelectedBevelFace[4] = {162.0/255, 163.0/255, 165.0/255, 1.0}; -static CGFloat darkDisabledButtonFace[4] = {86.0/255, 87.0/255, 89.0/255, 1.0}; -static CGFloat darkInactiveSelectedTab[4] = {159.0/255, 160.0/255, 161.0/255, 1.0}; +static CGFloat darkButtonFace[4] = { + 112.0 / 255, 113.0 / 255, 115.0 / 255, 1.0 +}; +static CGFloat darkPressedBevelFace[4] = { + 135.0 / 255, 136.0 / 255, 138.0 / 255, 1.0 +}; +static CGFloat darkSelectedBevelFace[4] = { + 162.0 / 255, 163.0 / 255, 165.0 / 255, 1.0 +}; +static CGFloat darkDisabledButtonFace[4] = { + 86.0 / 255, 87.0 / 255, 89.0 / 255, 1.0 +}; +static CGFloat darkInactiveSelectedTab[4] = { + 159.0 / 255, 160.0 / 255, 161.0 / 255, 1.0 +}; static CGFloat darkTabSeparator[4] = {0.0, 0.0, 0.0, 0.25}; static CGFloat darkTrack[4] = {1.0, 1.0, 1.0, 0.25}; static CGFloat darkFrameTop[4] = {1.0, 1.0, 1.0, 0.0625}; static CGFloat darkFrameBottom[4] = {1.0, 1.0, 1.0, 0.125}; static CGFloat darkFrameAccent[4] = {0.0, 0.0, 0.0, 0.0625}; -static CGFloat darkTopGradient[8] = {1.0, 1.0, 1.0, 0.3, - 1.0, 1.0, 1.0, 0.0}; -static CGFloat darkBackgroundGradient[8] = {0.0, 0.0, 0.0, 0.1, - 0.0, 0.0, 0.0, 0.25}; -static CGFloat darkInactiveGradient[8] = {89.0/255, 90.0/255, 93.0/255, 1.0, - 119.0/255, 120.0/255, 122.0/255, 1.0}; -static CGFloat darkSelectedGradient[8] = {23.0/255, 111.0/255, 232.0/255, 1.0, - 20.0/255, 94.0/255, 206.0/255, 1.0}; - -/*---------------------------------------------------------------------- - * GradientFillRoundedRectangle -- - * - * Fill a rounded rectangle with a specified gradient. - */ - -static void GradientFillRoundedRectangle( - CGContextRef context, - CGRect bounds, - CGFloat radius, - CGFloat *colors, - int numColors) -{ - NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; - CGPathRef path; - CGPoint end = { - bounds.origin.x, - bounds.origin.y + bounds.size.height - }; - CGGradientRef gradient = CGGradientCreateWithColorComponents( - deviceRGB.CGColorSpace, colors, NULL, numColors); - - path = CGPathCreateWithRoundedRect(bounds, radius, radius, NULL); - CGContextBeginPath(context); - CGContextAddPath(context, path); - CGContextClip(context); - CGContextDrawLinearGradient(context, gradient, bounds.origin, end, 0); - CFRelease(path); - CFRelease(gradient); -} - -static void DrawUpDownArrows( - CGContextRef context, - CGRect bounds, - CGFloat inset, - CGFloat size, - CGFloat *rgba) -{ - CGFloat x, y; - - CGContextSetRGBStrokeColor(context, rgba[0], rgba[1], rgba[2], rgba[3]); - CGContextSetLineWidth(context, 1.5); - x = bounds.origin.x + inset; - y = bounds.origin.y + trunc(bounds.size.height/2); - CGContextBeginPath(context); - - CGPoint bottomArrow[3] = {{x, y+2}, {x+size/2, y+2+size/2}, {x+size, y+2}}; - CGPoint topArrow[3] = {{x, y-2}, {x+size/2, y-2-size/2}, {x+size, y-2}}; - - CGContextAddLines(context, bottomArrow, 3); - CGContextAddLines(context, topArrow, 3); - CGContextStrokePath(context); -} +static CGFloat darkTopGradient[8] = { + 1.0, 1.0, 1.0, 0.3, + 1.0, 1.0, 1.0, 0.0 +}; +static CGFloat darkBackgroundGradient[8] = { + 0.0, 0.0, 0.0, 0.1, + 0.0, 0.0, 0.0, 0.25 +}; +static CGFloat darkInactiveGradient[8] = { + 89.0 / 255, 90.0 / 255, 93.0 / 255, 1.0, + 119.0 / 255, 120.0 / 255, 122.0 / 255, 1.0 +}; +static CGFloat darkSelectedGradient[8] = { + 23.0 / 255, 111.0 / 255, 232.0 / 255, 1.0, + 20.0 / 255, 94.0 / 255, 206.0 / 255, 1.0 +}; /*---------------------------------------------------------------------- - * FillButtonBackground -- + * +++ FillButtonBackground -- * - * Fills a rounded rectangle with a transparent black gradient. + * Fills a rounded rectangle with a transparent black gradient. */ static void FillButtonBackground( @@ -497,7 +533,7 @@ static void FillButtonBackground( CGPathRef path; NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; CGGradientRef backgroundGradient = CGGradientCreateWithColorComponents( - deviceRGB.CGColorSpace, darkBackgroundGradient, NULL, 2); + deviceRGB.CGColorSpace, darkBackgroundGradient, NULL, 2); CGPoint backgroundEnd = { bounds.origin.x, bounds.origin.y + bounds.size.height @@ -508,13 +544,13 @@ static void FillButtonBackground( CGContextAddPath(context, path); CGContextClip(context); CGContextDrawLinearGradient(context, backgroundGradient, - bounds.origin, backgroundEnd, 0); + bounds.origin, backgroundEnd, 0); CFRelease(path); CFRelease(backgroundGradient); } /*---------------------------------------------------------------------- - * HighlightButtonBorder -- + * +++ HighlightButtonBorder -- * * Accent the top border of a rounded rectangle with a transparent * white gradient. @@ -527,30 +563,29 @@ static void HighlightButtonBorder( NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; CGPoint topEnd = {bounds.origin.x, bounds.origin.y + 3}; CGGradientRef topGradient = CGGradientCreateWithColorComponents( - deviceRGB.CGColorSpace, darkTopGradient, NULL, 2); + deviceRGB.CGColorSpace, darkTopGradient, NULL, 2); CGContextSaveGState(context); CGContextBeginPath(context); CGContextAddArc(context, bounds.origin.x + 4, bounds.origin.y + 4, - 4, PI, 3*PI/2, 0); + 4, PI, 3 * PI / 2, 0); CGContextAddArc(context, bounds.origin.x + bounds.size.width - 4, - bounds.origin.y + 4, 4, 3*PI/2, 0, 0); + bounds.origin.y + 4, 4, 3 * PI / 2, 0, 0); CGContextReplacePathWithStrokedPath(context); CGContextClip(context); - CGContextDrawLinearGradient(context, topGradient, bounds.origin, topEnd, 0.0); + CGContextDrawLinearGradient(context, topGradient, bounds.origin, topEnd, + 0.0); CGContextRestoreGState(context); CFRelease(topGradient); } /*---------------------------------------------------------------------- - * DrawDarkButton -- + * +++ DrawDarkButton -- * - * This is a standalone drawing procedure which draws PushButtons and - * PopupButtons in the Dark Mode style. + * This is a standalone drawing procedure which draws PushButtons and + * PopupButtons in the Dark Mode style. */ -static CGFloat whiteRGBA[4] = {1.0, 1.0, 1.0, 1.0}; - static void DrawDarkButton( CGRect bounds, ThemeButtonKind kind, @@ -577,16 +612,16 @@ static void DrawDarkButton( bounds = CGRectInset(bounds, 1, 1); if (kind == kThemePushButton && (state & TTK_STATE_PRESSED)) { GradientFillRoundedRectangle(context, bounds, 4, - darkSelectedGradient, 2); + darkSelectedGradient, 2); } else { if (state & TTK_STATE_DISABLED) { faceColor = [NSColor colorWithColorSpace: deviceRGB - components: darkDisabledButtonFace - count: 4]; + components: darkDisabledButtonFace + count: 4]; } else { faceColor = [NSColor colorWithColorSpace: deviceRGB - components: darkButtonFace - count: 4]; + components: darkButtonFace + count: 4]; } SolidFillRoundedRectangle(context, bounds, 4, faceColor); } @@ -597,18 +632,17 @@ static void DrawDarkButton( if (kind == kThemePopupButton | kind == kThemeComboBox) { CGRect arrowBounds = bounds; - arrowBounds.size.width = 16; arrowBounds.origin.x += bounds.size.width - 16; - /* - * If the toplevel is front, paint the button blue. - */ + /* + * If the toplevel is front, paint the button blue. + */ if (!(state & TTK_STATE_BACKGROUND) && - !(state & TTK_STATE_DISABLED)) { + !(state & TTK_STATE_DISABLED)) { GradientFillRoundedRectangle(context, arrowBounds, 4, - darkSelectedGradient, 2); + darkSelectedGradient, 2); } if (kind == kThemePopupButton) { DrawUpDownArrows(context, arrowBounds, 3, 7, whiteRGBA); @@ -621,10 +655,10 @@ static void DrawDarkButton( } /*---------------------------------------------------------------------- - * DrawDarkIncDecButton -- + * +++ DrawDarkIncDecButton -- * - * This is a standalone drawing procedure which draws an IncDecButton (as - * used in a Spinbox) in the Dark Mode style. + * This is a standalone drawing procedure which draws an IncDecButton + * (as used in a Spinbox) in the Dark Mode style. */ static void DrawDarkIncDecButton( @@ -647,22 +681,21 @@ static void DrawDarkIncDecButton( bounds = CGRectInset(bounds, 1, 1); if (state & TTK_STATE_DISABLED) { faceColor = [NSColor colorWithColorSpace: deviceRGB - components: darkDisabledButtonFace - count: 4]; + components: darkDisabledButtonFace + count: 4]; } else { faceColor = [NSColor colorWithColorSpace: deviceRGB - components: darkButtonFace - count: 4]; + components: darkButtonFace + count: 4]; } SolidFillRoundedRectangle(context, bounds, 4, faceColor); /* * If pressed, paint the appropriate half blue. */ - + if (state & TTK_STATE_PRESSED) { CGRect clip = bounds; - clip.size.height /= 2; CGContextSaveGState(context); if (drawState == kThemeStatePressedDown) { @@ -670,7 +703,7 @@ static void DrawDarkIncDecButton( } CGContextClipToRect(context, clip); GradientFillRoundedRectangle(context, bounds, 5, - darkSelectedGradient, 2); + darkSelectedGradient, 2); CGContextRestoreGState(context); } DrawUpDownArrows(context, bounds, 3, 5, whiteRGBA); @@ -678,10 +711,10 @@ static void DrawDarkIncDecButton( } /*---------------------------------------------------------------------- - * DrawDarkBevelButton -- + * +++ DrawDarkBevelButton -- * - * This is a standalone drawing procedure which draws RoundedBevelButtons - * in the Dark Mode style. + * This is a standalone drawing procedure which draws RoundedBevelButtons + * in the Dark Mode style. */ static void DrawDarkBevelButton( @@ -691,6 +724,7 @@ static void DrawDarkBevelButton( { NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; NSColor *faceColor; + CGContextClipToRect(context, bounds); FillButtonBackground(context, bounds, 5); @@ -701,31 +735,31 @@ static void DrawDarkBevelButton( bounds = CGRectInset(bounds, 1, 1); if (state & TTK_STATE_PRESSED) { faceColor = [NSColor colorWithColorSpace: deviceRGB - components: darkPressedBevelFace - count: 4]; + components: darkPressedBevelFace + count: 4]; } else if ((state & TTK_STATE_DISABLED) || - (state & TTK_STATE_ALTERNATE)) { + (state & TTK_STATE_ALTERNATE)) { faceColor = [NSColor colorWithColorSpace: deviceRGB - components: darkDisabledButtonFace - count: 4]; + components: darkDisabledButtonFace + count: 4]; } else if (state & TTK_STATE_SELECTED) { faceColor = [NSColor colorWithColorSpace: deviceRGB - components: darkSelectedBevelFace - count: 4]; + components: darkSelectedBevelFace + count: 4]; } else { faceColor = [NSColor colorWithColorSpace: deviceRGB - components: darkButtonFace - count: 4]; + components: darkButtonFace + count: 4]; } SolidFillRoundedRectangle(context, bounds, 4, faceColor); HighlightButtonBorder(context, bounds); } /*---------------------------------------------------------------------- - * DrawDarkCheckBox -- + * +++ DrawDarkCheckBox -- * - * This is a standalone drawing procedure which draws Checkboxes in the - * Dark Mode style. + * This is a standalone drawing procedure which draws Checkboxes in the + * Dark Mode style. */ static void DrawDarkCheckBox( @@ -733,7 +767,7 @@ static void DrawDarkCheckBox( Ttk_State state, CGContextRef context) { - CGRect checkbounds = {{0, bounds.size.height/2 - 8},{16, 16}}; + CGRect checkbounds = {{0, bounds.size.height / 2 - 8}, {16, 16}}; NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; NSColor *stroke; CGFloat x, y; @@ -746,13 +780,13 @@ static void DrawDarkCheckBox( FillButtonBackground(context, bounds, 4); bounds = CGRectInset(bounds, 1, 1); if (!(state & TTK_STATE_BACKGROUND) && - !(state & TTK_STATE_DISABLED) && - ((state & TTK_STATE_SELECTED) || (state & TTK_STATE_ALTERNATE))) { + !(state & TTK_STATE_DISABLED) && + ((state & TTK_STATE_SELECTED) || (state & TTK_STATE_ALTERNATE))) { GradientFillRoundedRectangle(context, bounds, 3, - darkSelectedGradient, 2); + darkSelectedGradient, 2); } else { GradientFillRoundedRectangle(context, bounds, 3, - darkInactiveGradient, 2); + darkInactiveGradient, 2); } HighlightButtonBorder(context, bounds); if ((state & TTK_STATE_SELECTED) || (state & TTK_STATE_ALTERNATE)) { @@ -765,27 +799,25 @@ static void DrawDarkCheckBox( CGContextSetStrokeColorWithColor(context, stroke.CGColor); } if (state & TTK_STATE_SELECTED) { - CGPoint check[3] = {{x+4, y+8}, {x+7, y+11}, {x+11, y+4}}; - CGContextSetLineWidth(context, 1.5); CGContextBeginPath(context); + CGPoint check[3] = {{x + 4, y + 8}, {x + 7, y + 11}, {x + 11, y + 4}}; CGContextAddLines(context, check, 3); CGContextStrokePath(context); } else if (state & TTK_STATE_ALTERNATE) { - CGPoint bar[2] = {{x+4, y+8}, {x+12, y+8}}; - CGContextSetLineWidth(context, 2.0); CGContextBeginPath(context); + CGPoint bar[2] = {{x + 4, y + 8}, {x + 12, y + 8}}; CGContextAddLines(context, bar, 2); CGContextStrokePath(context); } } /*---------------------------------------------------------------------- - * DrawDarkRadioButton -- + * +++ DrawDarkRadioButton -- * - * This is a standalone drawing procedure which draws RadioButtons in the - * Dark Mode style. + * This is a standalone drawing procedure which draws RadioButtons + * in the Dark Mode style. */ static void DrawDarkRadioButton( @@ -793,7 +825,7 @@ static void DrawDarkRadioButton( Ttk_State state, CGContextRef context) { - CGRect checkbounds = {{0, bounds.size.height/2 - 9},{18, 18}}; + CGRect checkbounds = {{0, bounds.size.height / 2 - 9}, {18, 18}}; NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; NSColor *fill; CGFloat x, y; @@ -806,13 +838,13 @@ static void DrawDarkRadioButton( FillButtonBackground(context, bounds, 9); bounds = CGRectInset(bounds, 1, 1); if (!(state & TTK_STATE_BACKGROUND) && - !(state & TTK_STATE_DISABLED) && - ((state & TTK_STATE_SELECTED) || (state & TTK_STATE_ALTERNATE))) { + !(state & TTK_STATE_DISABLED) && + ((state & TTK_STATE_SELECTED) || (state & TTK_STATE_ALTERNATE))) { GradientFillRoundedRectangle(context, bounds, 8, - darkSelectedGradient, 2); + darkSelectedGradient, 2); } else { GradientFillRoundedRectangle(context, bounds, 8, - darkInactiveGradient, 2); + darkInactiveGradient, 2); } HighlightButtonBorder(context, bounds); if ((state & TTK_STATE_SELECTED) || (state & TTK_STATE_ALTERNATE)) { @@ -825,23 +857,21 @@ static void DrawDarkRadioButton( CGContextSetFillColorWithColor(context, fill.CGColor); } if (state & TTK_STATE_SELECTED) { - CGRect dot = {{x + 6, y + 6}, {6, 6}}; - CGContextBeginPath(context); + CGRect dot = {{x + 6, y + 6}, {6, 6}}; CGContextAddEllipseInRect(context, dot); CGContextFillPath(context); } else if (state & TTK_STATE_ALTERNATE) { CGRect bar = {{x + 5, y + 8}, {8, 2}}; - CGContextFillRect(context, bar); } } /*---------------------------------------------------------------------- - * DrawDarkTab -- + * +++ DrawDarkTab -- * - * This is a standalone drawing procedure which draws Tabbed Pane - * Tabs in the Dark Mode style. + * This is a standalone drawing procedure which draws Tabbed Pane + * Tabs in the Dark Mode style. */ static void DrawDarkTab( @@ -851,7 +881,7 @@ static void DrawDarkTab( { NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; NSColor *faceColor, *stroke; - CGRect originalBounds= bounds; + CGRect originalBounds = bounds; CGContextSetLineWidth(context, 1.0); CGContextClipToRect(context, bounds); @@ -872,70 +902,72 @@ static void DrawDarkTab( /* * Fill the tab face with the appropriate color or gradient. Use a solid - * color if the tab is not selected, otherwise use a blue or gray gradient. + * color if the tab is not selected, otherwise use a blue or gray + * gradient. */ bounds = CGRectInset(bounds, 1, 1); if (!(state & TTK_STATE_SELECTED)) { if (state & TTK_STATE_DISABLED) { faceColor = [NSColor colorWithColorSpace: deviceRGB - components: darkDisabledButtonFace - count: 4]; + components: darkDisabledButtonFace + count: 4]; } else { faceColor = [NSColor colorWithColorSpace: deviceRGB - components: darkButtonFace - count: 4]; + components: darkButtonFace + count: 4]; } SolidFillRoundedRectangle(context, bounds, 4, faceColor); - /* - * Draw a separator line on the left side of the tab if it - * not first. - */ + /* + * Draw a separator line on the left side of the tab if it + * not first. + */ if (!(state & TTK_STATE_FIRST_TAB)) { CGContextSaveGState(context); CGContextSetShouldAntialias(context, false); stroke = [NSColor colorWithColorSpace: deviceRGB - components: darkTabSeparator - count: 4]; + components: darkTabSeparator + count: 4]; CGContextSetStrokeColorWithColor(context, stroke.CGColor); CGContextBeginPath(context); CGContextMoveToPoint(context, originalBounds.origin.x, - originalBounds.origin.y + 1); + originalBounds.origin.y + 1); CGContextAddLineToPoint(context, originalBounds.origin.x, - originalBounds.origin.y + originalBounds.size.height - 1); + originalBounds.origin.y + originalBounds.size.height - 1); CGContextStrokePath(context); CGContextRestoreGState(context); } } else { - /* - * This is the selected tab; paint it blue. If it is first, cover up - * the separator line drawn by the second one. (The selected tab is - * always drawn last.) - */ + + /* + * This is the selected tab; paint it blue. If it is first, cover up + * the separator line drawn by the second one. (The selected tab is + * always drawn last.) + */ if ((state & TTK_STATE_FIRST_TAB) && !(state & TTK_STATE_LAST_TAB)) { bounds.size.width += 1; } if (!(state & TTK_STATE_BACKGROUND)) { GradientFillRoundedRectangle(context, bounds, 4, - darkSelectedGradient, 2); + darkSelectedGradient, 2); } else { faceColor = [NSColor colorWithColorSpace: deviceRGB - components: darkInactiveSelectedTab - count: 4]; + components: darkInactiveSelectedTab + count: 4]; SolidFillRoundedRectangle(context, bounds, 4, faceColor); } HighlightButtonBorder(context, bounds); } } - + /*---------------------------------------------------------------------- - * DrawDarkSeparator -- + * +++ DrawDarkSeparator -- * - * This is a standalone drawing procedure which draws a separator widget in - * Dark Mode. + * This is a standalone drawing procedure which draws a separator widget + * in Dark Mode. */ static void DrawDarkSeparator( @@ -946,18 +978,18 @@ static void DrawDarkSeparator( static CGFloat fill[4] = {1.0, 1.0, 1.0, 0.3}; NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; NSColor *fillColor = [NSColor colorWithColorSpace: deviceRGB - components: fill - count:4]; + components: fill + count:4]; CGContextSetFillColorWithColor(context, fillColor.CGColor); CGContextFillRect(context, bounds); } - + /*---------------------------------------------------------------------- - * DrawDarkFrame -- + * +++ DrawDarkFrame -- * - * This is a standalone drawing procedure which draws various types of - * borders in Dark Mode. + * This is a standalone drawing procedure which draws various + * types of borders in Dark Mode. */ static void DrawDarkFrame( @@ -967,35 +999,35 @@ static void DrawDarkFrame( { NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; NSColor *stroke; + + CGContextSetStrokeColorSpace(context, deviceRGB.CGColorSpace); CGFloat x = bounds.origin.x, y = bounds.origin.y; CGFloat w = bounds.size.width, h = bounds.size.height; CGPoint topPart[4] = { {x, y + h - 1}, {x, y}, {x + w, y}, {x + w, y + h - 1} }; - CGPoint bottom[2] = {{x, y + h}, {x + w, y + h}}; + CGPoint bottom[2] = {{x, y + h}, {x + w, y + h}}; CGPoint accent[2] = {{x, y + 1}, {x + w, y + 1}}; - - CGContextSetStrokeColorSpace(context, deviceRGB.CGColorSpace); switch (kind) { case kHIThemeFrameTextFieldSquare: CGContextSaveGState(context); CGContextSetShouldAntialias(context, false); CGContextBeginPath(context); stroke = [NSColor colorWithColorSpace: deviceRGB - components: darkFrameTop - count: 4]; + components: darkFrameTop + count: 4]; CGContextSetStrokeColorWithColor(context, stroke.CGColor); CGContextAddLines(context, topPart, 4); CGContextStrokePath(context); stroke = [NSColor colorWithColorSpace: deviceRGB - components: darkFrameBottom - count: 4]; + components: darkFrameBottom + count: 4]; CGContextSetStrokeColorWithColor(context, stroke.CGColor); CGContextAddLines(context, bottom, 2); CGContextStrokePath(context); stroke = [NSColor colorWithColorSpace: deviceRGB - components: darkFrameAccent - count: 4]; + components: darkFrameAccent + count: 4]; CGContextSetStrokeColorWithColor(context, stroke.CGColor); CGContextAddLines(context, accent, 2); CGContextStrokePath(context); @@ -1007,10 +1039,10 @@ static void DrawDarkFrame( } /*---------------------------------------------------------------------- - * DrawListHeader -- + * +++ DrawListHeader -- * - * This is a standalone drawing procedure which draws column headers for a - * Treeview in the Dark Mode. + * This is a standalone drawing procedure which draws column + * headers for a Treeview in the Dark Mode. */ static void DrawDarkListHeader( @@ -1021,18 +1053,19 @@ static void DrawDarkListHeader( { NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; NSColor *stroke; + + CGContextSetStrokeColorSpace(context, deviceRGB.CGColorSpace); CGFloat x = bounds.origin.x, y = bounds.origin.y; CGFloat w = bounds.size.width, h = bounds.size.height; CGPoint top[2] = {{x, y}, {x + w, y}}; - CGPoint bottom[2] = {{x, y + h}, {x + w, y + h}}; + CGPoint bottom[2] = {{x, y + h}, {x + w, y + h}}; CGPoint separator[2] = {{x + w, y + 3}, {x + w, y + h - 3}}; - CGContextSetStrokeColorSpace(context, deviceRGB.CGColorSpace); CGContextSaveGState(context); CGContextSetShouldAntialias(context, false); stroke = [NSColor colorWithColorSpace: deviceRGB - components: darkFrameBottom - count: 4]; + components: darkFrameBottom + count: 4]; CGContextSetStrokeColorWithColor(context, stroke.CGColor); CGContextBeginPath(context); CGContextAddLines(context, top, 2); @@ -1063,43 +1096,49 @@ static void DrawDarkListHeader( */ /* - * When Ttk draws the various types of buttons, a pointer to one of these is - * passed as the clientData. + * When Ttk draws the various types of buttons, a pointer to one of these + * is passed as the clientData. */ typedef struct { ThemeButtonKind kind; ThemeMetric heightMetric; } ThemeButtonParams; - static ThemeButtonParams - PushButtonParams = { kThemePushButton, kThemeMetricPushButtonHeight }, - CheckBoxParams = { kThemeCheckBox, kThemeMetricCheckBoxHeight }, - RadioButtonParams = { kThemeRadioButton, kThemeMetricRadioButtonHeight }, - BevelButtonParams = { kThemeRoundedBevelButton, NoThemeMetric }, - PopupButtonParams = { kThemePopupButton, kThemeMetricPopupButtonHeight }, - DisclosureParams = { kThemeDisclosureButton, kThemeMetricDisclosureTriangleHeight }, - ListHeaderParams = { kThemeListHeaderButton, kThemeMetricListHeaderHeight }; - + PushButtonParams = {kThemePushButton, kThemeMetricPushButtonHeight}, + CheckBoxParams = {kThemeCheckBox, kThemeMetricCheckBoxHeight}, + RadioButtonParams = {kThemeRadioButton, kThemeMetricRadioButtonHeight}, + BevelButtonParams = {kThemeRoundedBevelButton, NoThemeMetric}, + PopupButtonParams = {kThemePopupButton, kThemeMetricPopupButtonHeight}, + DisclosureParams = { + kThemeDisclosureButton, kThemeMetricDisclosureTriangleHeight +}, + ListHeaderParams = +{kThemeListHeaderButton, kThemeMetricListHeaderHeight}; static Ttk_StateTable ButtonValueTable[] = { - { kThemeButtonMixed, TTK_STATE_ALTERNATE, 0 }, - { kThemeButtonOn, TTK_STATE_SELECTED, 0 }, - { kThemeButtonOff, 0, 0 } -/* Others: kThemeDisclosureRight, kThemeDisclosureDown, kThemeDisclosureLeft */ -}; + {kThemeButtonMixed, TTK_STATE_ALTERNATE, 0}, + {kThemeButtonOn, TTK_STATE_SELECTED, 0}, + {kThemeButtonOff, 0, 0} + /* + * Others: kThemeDisclosureRight, kThemeDisclosureDown, + * kThemeDisclosureLeft + */ + +}; static Ttk_StateTable ButtonAdornmentTable[] = { - { kThemeAdornmentDefault | kThemeAdornmentFocus, - TTK_STATE_ALTERNATE | TTK_STATE_FOCUS, 0 }, - { kThemeAdornmentDefault, TTK_STATE_ALTERNATE, 0 }, - { kThemeAdornmentNone, TTK_STATE_ALTERNATE, 0 }, - { kThemeAdornmentFocus, TTK_STATE_FOCUS, 0 }, - { kThemeAdornmentNone, 0, 0 } + {kThemeAdornmentDefault | kThemeAdornmentFocus, + TTK_STATE_ALTERNATE | TTK_STATE_FOCUS, 0}, + {kThemeAdornmentDefault, TTK_STATE_ALTERNATE, 0}, + {kThemeAdornmentNone, TTK_STATE_ALTERNATE, 0}, + {kThemeAdornmentFocus, TTK_STATE_FOCUS, 0}, + {kThemeAdornmentNone, 0, 0} }; /*---------------------------------------------------------------------- - * computeButtonDrawInfo -- - * Fill in an appearance manager HIThemeButtonDrawInfo record. + * +++ computeButtonDrawInfo -- + * + * Fill in an appearance manager HIThemeButtonDrawInfo record. */ static inline HIThemeButtonDrawInfo computeButtonDrawInfo( @@ -1107,6 +1146,7 @@ static inline HIThemeButtonDrawInfo computeButtonDrawInfo( Ttk_State state, Tk_Window tkwin) { + /* * See ButtonElementDraw for the explanation of why we always draw * PushButtons in the active state. @@ -1133,12 +1173,16 @@ static inline HIThemeButtonDrawInfo computeButtonDrawInfo( return info; } -static void -ButtonElementMinSize( +/*---------------------------------------------------------------------- + * +++ Button elements. + */ + +static void ButtonElementMinSize( void *clientData, void *elementRecord, Tk_Window tkwin, - int *minWidth, int *minHeight, + int *minWidth, + int *minHeight, Ttk_Padding *paddingPtr) { ThemeButtonParams *params = clientData; @@ -1146,40 +1190,43 @@ ButtonElementMinSize( if (params->heightMetric != NoThemeMetric) { ChkErr(GetThemeMetric, params->heightMetric, minHeight); - /* - * The theme height does not include the 1-pixel border around the - * button, although it does include the 1-pixel shadow at the bottom. - */ + /* + * The theme height does not include the 1-pixel border around + * the button, although it does include the 1-pixel shadow at + * the bottom. + */ *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. - */ + /* + * 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; } } -static void -ButtonElementSize( +static void ButtonElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, - int *minWidth, int *minHeight, + int *minWidth, + int *minHeight, Ttk_Padding *paddingPtr) { ThemeButtonParams *params = clientData; - const HIThemeButtonDrawInfo info = computeButtonDrawInfo(params, 0, tkwin); + const HIThemeButtonDrawInfo info = + computeButtonDrawInfo(params, 0, tkwin); static const CGRect scratchBounds = {{0, 0}, {100, 100}}; CGRect contentBounds, backgroundBounds; int verticalPad; ButtonElementMinSize(clientData, elementRecord, tkwin, - minWidth, minHeight, paddingPtr); + minWidth, minHeight, paddingPtr); /* * Given a hypothetical bounding rectangle for a button, HIToolbox will @@ -1192,25 +1239,24 @@ ButtonElementSize( * to draw a button with a certain bounding rectangle it draws the button * centered within the rectangle. * - * To compute the effective padding around a button we request the content - * and bounding rectangles for a 100x100 button and use the padding between - * those. However, we symmetrize the padding on the top and bottom, because - * that is how the button will be drawn. + * To compute the effective padding around a button we request the + * content and bounding rectangles for a 100x100 button and use the + * padding between those. However, we symmetrize the padding on the + * top and bottom, because that is how the button will be drawn. */ ChkErr(HIThemeGetButtonContentBounds, - &scratchBounds, &info, &contentBounds); + &scratchBounds, &info, &contentBounds); ChkErr(HIThemeGetButtonBackgroundBounds, - &scratchBounds, &info, &backgroundBounds); + &scratchBounds, &info, &backgroundBounds); paddingPtr->left = contentBounds.origin.x - backgroundBounds.origin.x; paddingPtr->right = - CGRectGetMaxX(backgroundBounds) - CGRectGetMaxX(contentBounds); + CGRectGetMaxX(backgroundBounds) - CGRectGetMaxX(contentBounds); verticalPad = backgroundBounds.size.height - contentBounds.size.height; paddingPtr->top = paddingPtr->bottom = verticalPad / 2; } -static void -ButtonElementDraw( +static void ButtonElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, @@ -1221,9 +1267,10 @@ ButtonElementDraw( ThemeButtonParams *params = clientData; CGRect bounds = BoxToRect(d, b); HIThemeButtonDrawInfo info = computeButtonDrawInfo(params, state, tkwin); + bounds = NormalizeButtonBounds(params->heightMetric, bounds); - - BEGIN_DRAWING(d); + + BEGIN_DRAWING(d) if (TkMacOSXInDarkMode(tkwin)) { #if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 switch (info.kind) { @@ -1242,34 +1289,36 @@ ButtonElementDraw( break; default: ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, - HIOrientation, NULL); + HIOrientation, NULL); } -#endif +#endif /* if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 */ } else { - /* - * Apple's PushButton and PopupButton do not change their fill color - * when the window is inactive. However, except in 10.7 (Lion), the - * color of the arrow button on a PopupButton does change. For some - * reason HITheme fills inactive buttons with a transparent color that - * allows the window background to show through, leading to - * inconsistent behavior. We work around this by filling behind an - * inactive PopupButton with a text background color before asking - * HIToolbox to draw it. For PushButtons, we simply draw them in the - * active state. - */ + + /* + * Apple's PushButton and PopupButton do not change their fill color + * when the window is inactive. However, except in 10.7 (Lion), the + * color of the arrow button on a PopupButton does change. For some + * reason HITheme fills inactive buttons with a transparent color that + * allows the window background to show through, leading to + * inconsistent behavior. We work around this by filling behind an + * inactive PopupButton with a text background color before asking + * HIToolbox to draw it. For PushButtons, we simply draw them in the + * active state. + */ #if MAC_OS_X_VERSION_MIN_REQUIRED > 1080 - if (info.kind == kThemePopupButton && (state & TTK_STATE_BACKGROUND)) { + if (info.kind == kThemePopupButton && + (state & TTK_STATE_BACKGROUND)) { CGRect innerBounds = CGRectInset(bounds, 1, 1); NSColor *whiteRGBA = [NSColor whiteColor]; SolidFillRoundedRectangle(dc.context, innerBounds, 4, whiteRGBA); } #endif - /* - * A BevelButton with mixed value is drawn borderless, which does make - * much sense for us. - */ + /* + * A BevelButton with mixed value is drawn borderless, which does make + * much sense for us. + */ if (info.kind == kThemeRoundedBevelButton && info.value == kThemeButtonMixed) { @@ -1277,9 +1326,9 @@ ButtonElementDraw( info.state = kThemeStateInactive; } ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, - NULL); + NULL); } - END_DRAWING; + END_DRAWING } static Ttk_ElementSpec ButtonElementSpec = { @@ -1295,29 +1344,26 @@ static Ttk_ElementSpec ButtonElementSpec = { */ /* Tab position logic, c.f. ttkNotebook.c TabState() */ - static Ttk_StateTable TabStyleTable[] = { - { kThemeTabFrontInactive, TTK_STATE_SELECTED | TTK_STATE_BACKGROUND}, - { kThemeTabNonFrontInactive, TTK_STATE_BACKGROUND}, - { kThemeTabFrontUnavailable, TTK_STATE_DISABLED | TTK_STATE_SELECTED}, - { kThemeTabNonFrontUnavailable, TTK_STATE_DISABLED}, - { kThemeTabFront, TTK_STATE_SELECTED}, - { kThemeTabNonFrontPressed, TTK_STATE_PRESSED}, - { kThemeTabNonFront, 0} + {kThemeTabFrontInactive, TTK_STATE_SELECTED | TTK_STATE_BACKGROUND}, + {kThemeTabNonFrontInactive, TTK_STATE_BACKGROUND}, + {kThemeTabFrontUnavailable, TTK_STATE_DISABLED | TTK_STATE_SELECTED}, + {kThemeTabNonFrontUnavailable, TTK_STATE_DISABLED}, + {kThemeTabFront, TTK_STATE_SELECTED}, + {kThemeTabNonFrontPressed, TTK_STATE_PRESSED}, + {kThemeTabNonFront, 0} }; - static Ttk_StateTable TabAdornmentTable[] = { - { kHIThemeTabAdornmentNone, TTK_STATE_FIRST_TAB | TTK_STATE_LAST_TAB}, - { kHIThemeTabAdornmentTrailingSeparator, TTK_STATE_FIRST_TAB}, - { kHIThemeTabAdornmentNone, TTK_STATE_LAST_TAB}, - { kHIThemeTabAdornmentTrailingSeparator, 0 }, + {kHIThemeTabAdornmentNone, TTK_STATE_FIRST_TAB | TTK_STATE_LAST_TAB}, + {kHIThemeTabAdornmentTrailingSeparator, TTK_STATE_FIRST_TAB}, + {kHIThemeTabAdornmentNone, TTK_STATE_LAST_TAB}, + {kHIThemeTabAdornmentTrailingSeparator, 0}, }; - static Ttk_StateTable TabPositionTable[] = { - { kHIThemeTabPositionOnly, TTK_STATE_FIRST_TAB | TTK_STATE_LAST_TAB}, - { kHIThemeTabPositionFirst, TTK_STATE_FIRST_TAB}, - { kHIThemeTabPositionLast, TTK_STATE_LAST_TAB}, - { kHIThemeTabPositionMiddle, 0 }, + {kHIThemeTabPositionOnly, TTK_STATE_FIRST_TAB | TTK_STATE_LAST_TAB}, + {kHIThemeTabPositionFirst, TTK_STATE_FIRST_TAB}, + {kHIThemeTabPositionLast, TTK_STATE_LAST_TAB}, + {kHIThemeTabPositionMiddle, 0}, }; /* @@ -1335,7 +1381,8 @@ static Ttk_StateTable TabPositionTable[] = { * should be placed so that there are equal margins of space before and after * it. The guidelines below provide the specifications you should use for tab * labels: - * - Regular size: System font. Center in tab, leaving 12 pixels on each side. + * - Regular size: System font. Center in tab, leaving 12 pixels on each + *side. * - Small: Small system font. Center in tab, leaving 10 pixels on each side. * - Mini: Mini system font. Center in tab, leaving 8 pixels on each side. * @@ -1359,20 +1406,20 @@ static Ttk_StateTable TabPositionTable[] = { * TP30000359-TPXREF116> */ -static void -TabElementSize( +static void TabElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, - int *minWidth, int *minHeight, + int *minWidth, + int *minHeight, Ttk_Padding *paddingPtr) { GetThemeMetric(kThemeMetricLargeTabHeight, (SInt32 *) minHeight); *paddingPtr = Ttk_MakePadding(0, 0, 0, 2); + } -static void -TabElementDraw( +static void TabElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, @@ -1391,17 +1438,18 @@ TabElementDraw( .position = Ttk_StateTableLookup(TabPositionTable, state), }; - BEGIN_DRAWING(d); + BEGIN_DRAWING(d) #if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 if (TkMacOSXInDarkMode(tkwin)) { DrawDarkTab(bounds, state, dc.context); } else { - ChkErr(HIThemeDrawTab, &bounds, &info, dc.context, HIOrientation, NULL); + ChkErr(HIThemeDrawTab, &bounds, &info, dc.context, HIOrientation, + NULL); } #else ChkErr(HIThemeDrawTab, &bounds, &info, dc.context, HIOrientation, NULL); #endif - END_DRAWING; + END_DRAWING } static Ttk_ElementSpec TabElementSpec = { @@ -1417,39 +1465,45 @@ static Ttk_ElementSpec TabElementSpec = { */ static void PaneElementSize( - void *clientData, void *elementRecord, Tk_Window tkwin, - int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + int *minWidth, + int *minHeight, + Ttk_Padding *paddingPtr) { *paddingPtr = Ttk_MakePadding(9, 5, 9, 9); } static void PaneElementDraw( - void *clientData, void *elementRecord, Tk_Window tkwin, - Drawable d, Ttk_Box b, Ttk_State state) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + Ttk_State state) { CGRect bounds = BoxToRect(d, b); bounds.origin.y -= kThemeMetricTabFrameOverlap; bounds.size.height += kThemeMetricTabFrameOverlap; - BEGIN_DRAWING(d); - if ([NSApp macMinorVersion] > 9) { -#if MAC_OS_X_VERSION_MAX_ALLOWED > 1080 - DrawGroupBox(bounds, dc.context, tkwin); -#endif - } else { - HIThemeTabPaneDrawInfo info = { - .version = 1, - .state = Ttk_StateTableLookup(ThemeStateTable, state), - .direction = kThemeTabNorth, - .size = kHIThemeTabSizeNormal, - .kind = kHIThemeTabKindNormal, - .adornment = kHIThemeTabPaneAdornmentNormal, - }; - bounds.origin.y -= kThemeMetricTabFrameOverlap; - bounds.size.height += kThemeMetricTabFrameOverlap; - ChkErr(HIThemeDrawTabPane, &bounds, &info, dc.context, HIOrientation); - } - END_DRAWING; + BEGIN_DRAWING(d) +#if MAC_OS_X_VERSION_MIN_REQUIRED > 10800 + DrawGroupBox(bounds, dc.context, tkwin); +#else + HIThemeTabPaneDrawInfo info = { + .version = 1, + .state = Ttk_StateTableLookup(ThemeStateTable, state), + .direction = kThemeTabNorth, + .size = kHIThemeTabSizeNormal, + .kind = kHIThemeTabKindNormal, + .adornment = kHIThemeTabPaneAdornmentNormal, + }; + bounds.origin.y -= kThemeMetricTabFrameOverlap; + bounds.size.height += kThemeMetricTabFrameOverlap; + ChkErr(HIThemeDrawTabPane, &bounds, &info, dc.context, HIOrientation); +#endif /* if MAC_OS_X_VERSION_MIN_REQUIRED > 10800 */ + END_DRAWING } static Ttk_ElementSpec PaneElementSpec = { @@ -1460,12 +1514,12 @@ static Ttk_ElementSpec PaneElementSpec = { PaneElementDraw }; -/* - * Labelframe borders: - * Use "primary group box ..." - * Quoth DrawThemePrimaryGroup reference: - * "The primary group box frame is drawn inside the specified rectangle and is - * a maximum of 2 pixels thick." +/*---------------------------------------------------------------------- + * +++ Labelframe elements -- + * + * Labelframe borders: Use "primary group box ..." Quoth + * DrawThemePrimaryGroup reference: "The primary group box frame is drawn + * inside the specified rectangle and is a maximum of 2 pixels thick." * * "Maximum of 2 pixels thick" is apparently a lie; looks more like 4 to me * with shading. @@ -1475,7 +1529,8 @@ static void GroupElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, - int *minWidth, int *minHeight, + int *minWidth, + int *minHeight, Ttk_Padding *paddingPtr) { *paddingPtr = Ttk_UniformPadding(4); @@ -1491,20 +1546,18 @@ static void GroupElementDraw( { CGRect bounds = BoxToRect(d, b); - BEGIN_DRAWING(d); - if ([NSApp macMinorVersion] > 9) { -#if MAC_OS_X_VERSION_MAX_ALLOWED > 1080 - DrawGroupBox(bounds, dc.context, tkwin); + BEGIN_DRAWING(d) +#if MAC_OS_X_VERSION_MIN_REQUIRED > 10800 + DrawGroupBox(bounds, dc.context, tkwin); +#else + const HIThemeGroupBoxDrawInfo info = { + .version = 0, + .state = Ttk_StateTableLookup(ThemeStateTable, state), + .kind = kHIThemeGroupBoxKindPrimaryOpaque, + }; + ChkErr(HIThemeDrawGroupBox, &bounds, &info, dc.context, HIOrientation); #endif - } else { - const HIThemeGroupBoxDrawInfo info = { - .version = 0, - .state = Ttk_StateTableLookup(ThemeStateTable, state), - .kind = kHIThemeGroupBoxKindPrimaryOpaque, - }; - ChkErr(HIThemeDrawGroupBox, &bounds, &info, dc.context, HIOrientation); - } - END_DRAWING; + END_DRAWING } static Ttk_ElementSpec GroupElementSpec = { @@ -1516,36 +1569,45 @@ static Ttk_ElementSpec GroupElementSpec = { }; /*---------------------------------------------------------------------- - * +++ Entry element -- + * +++ Entry elements -- + * * 3 pixels padding for focus rectangle * 2 pixels padding for EditTextFrame */ typedef struct { - Tcl_Obj *backgroundObj; - Tcl_Obj *fieldbackgroundObj; + Tcl_Obj *backgroundObj; + Tcl_Obj *fieldbackgroundObj; } EntryElement; #define ENTRY_DEFAULT_BACKGROUND "systemTextBackgroundColor" static Ttk_ElementOptionSpec EntryElementOptions[] = { - { "-background", TK_OPTION_BORDER, - Tk_Offset(EntryElement,backgroundObj), ENTRY_DEFAULT_BACKGROUND }, - { "-fieldbackground", TK_OPTION_BORDER, - Tk_Offset(EntryElement,fieldbackgroundObj), ENTRY_DEFAULT_BACKGROUND }, + {"-background", TK_OPTION_BORDER, + Tk_Offset(EntryElement, backgroundObj), ENTRY_DEFAULT_BACKGROUND}, + {"-fieldbackground", TK_OPTION_BORDER, + Tk_Offset(EntryElement, fieldbackgroundObj), ENTRY_DEFAULT_BACKGROUND}, {0} }; static void EntryElementSize( - void *clientData, void *elementRecord, Tk_Window tkwin, - int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + int *minWidth, + int *minHeight, + Ttk_Padding *paddingPtr) { *paddingPtr = Ttk_UniformPadding(5); } static void EntryElementDraw( - void *clientData, void *elementRecord, Tk_Window tkwin, - Drawable d, Ttk_Box b, Ttk_State state) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + Ttk_State state) { EntryElement *e = elementRecord; Ttk_Box inner = Ttk_PadBox(b, Ttk_UniformPadding(3)); @@ -1556,19 +1618,18 @@ static void EntryElementDraw( if (TkMacOSXInDarkMode(tkwin)) { #if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 - BEGIN_DRAWING(d); + BEGIN_DRAWING(d) NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; CGFloat fill[4]; - GetBackgroundColor(dc.context, tkwin, 1, fill); background = [NSColor colorWithColorSpace: deviceRGB - components: fill - count: 4]; + components: fill + count: 4]; CGContextSetFillColorWithColor(dc.context, background.CGColor); CGContextFillRect(dc.context, bounds); DrawDarkFrame(bounds, dc.context, kHIThemeFrameTextFieldSquare); - END_DRAWING; -#endif + END_DRAWING +#endif /* if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 */ } else { const HIThemeFrameDrawInfo info = { .version = 0, @@ -1577,26 +1638,27 @@ static void EntryElementDraw( .isFocused = state & TTK_STATE_FOCUS, }; - /* - * Earlier versions of the Aqua theme ignored the -fieldbackground - * option and used the -background as if it were -fieldbackground. - * Here we are enabling -fieldbackground. For backwards compatibility, - * if -fieldbackground is set to the default color and -background is - * set to a different color then we use -background as - * -fieldbackground. - */ + /* + * Earlier versions of the Aqua theme ignored the -fieldbackground + * option and used the -background as if it were -fieldbackground. + * Here we are enabling -fieldbackground. For backwards + * compatibility, if -fieldbackground is set to the default color and + * -background is set to a different color then we use -background as + * -fieldbackground. + */ if (0 != strcmp(Tcl_GetString(e->fieldbackgroundObj), defaultBG)) { - backgroundPtr = Tk_Get3DBorderFromObj(tkwin,e->fieldbackgroundObj); + backgroundPtr = + Tk_Get3DBorderFromObj(tkwin, e->fieldbackgroundObj); } else if (0 != strcmp(Tcl_GetString(e->backgroundObj), defaultBG)) { - backgroundPtr = Tk_Get3DBorderFromObj(tkwin,e->backgroundObj); + backgroundPtr = Tk_Get3DBorderFromObj(tkwin, e->backgroundObj); } if (backgroundPtr != NULL) { XFillRectangle(Tk_Display(tkwin), d, - Tk_3DBorderGC(tkwin, backgroundPtr, TK_3D_FLAT_GC), - inner.x, inner.y, inner.width, inner.height); + Tk_3DBorderGC(tkwin, backgroundPtr, TK_3D_FLAT_GC), + inner.x, inner.y, inner.width, inner.height); } - BEGIN_DRAWING(d); + BEGIN_DRAWING(d) if (backgroundPtr == NULL) { background = [NSColor textBackgroundColor]; #if MAC_OS_X_VERSION_MIN_REQUIRED > 1080 @@ -1607,11 +1669,8 @@ static void EntryElementDraw( CGContextFillRect(dc.context, bounds); } ChkErr(HIThemeDrawFrame, &bounds, &info, dc.context, HIOrientation); - END_DRAWING; + END_DRAWING } - /*if (state & TTK_STATE_FOCUS) { - ChkErr(DrawThemeFocusRect, &bounds, 1); - }*/ } static Ttk_ElementSpec EntryElementSpec = { @@ -1623,30 +1682,34 @@ static Ttk_ElementSpec EntryElementSpec = { }; /*---------------------------------------------------------------------- - * +++ Combobox: + * +++ Combobox elements -- * * NOTES: - * The HIToolbox has incomplete and inconsistent support for ComboBoxes. - * There is no constant available to get the height of a ComboBox with - * GetThemeMetric. In fact, ComboBoxes are the same (fixed) height as - * PopupButtons and PushButtons, but they have no shadow at the bottom. - * As a result, they are drawn 1 pixel above the center of the bounds - * rectangle rather than being centered like the other buttons. One can - * request background bounds for a ComboBox, and it is reported with - * height 23, while the actual button face, including its 1-pixel border - * has height 21. Attempting to request the content bounds returns a 0x0 - * rectangle. Measurement indicates that the arrow button has width 18. + * The HIToolbox has incomplete and inconsistent support for ComboBoxes. + * There is no constant available to get the height of a ComboBox with + * GetThemeMetric. In fact, ComboBoxes are the same (fixed) height as + * PopupButtons and PushButtons, but they have no shadow at the bottom. + * As a result, they are drawn 1 pixel above the center of the bounds + * rectangle rather than being centered like the other buttons. One can + * request background bounds for a ComboBox, and it is reported with + * height 23, while the actual button face, including its 1-pixel border + * has height 21. Attempting to request the content bounds returns a 0x0 + * rectangle. Measurement indicates that the arrow button has width 18. * - * With no help available from HIToolbox, we have to use hard-wired - * constants for the padding. We shift the bounding rectangle downward by - * 1 pixel to account for the fact that the button is not centered. + * With no help available from HIToolbox, we have to use hard-wired + * constants for the padding. We shift the bounding rectangle downward by + * 1 pixel to account for the fact that the button is not centered. */ -static Ttk_Padding ComboboxPadding = {4, 2, 20, 2 }; +static Ttk_Padding ComboboxPadding = {4, 2, 20, 2}; static void ComboboxElementSize( - void *clientData, void *elementRecord, Tk_Window tkwin, - int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + int *minWidth, + int *minHeight, + Ttk_Padding *paddingPtr) { *minWidth = 24; *minHeight = 23; @@ -1654,8 +1717,12 @@ static void ComboboxElementSize( } static void ComboboxElementDraw( - void *clientData, void *elementRecord, Tk_Window tkwin, - Drawable d, Ttk_Box b, Ttk_State state) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + Ttk_State state) { CGRect bounds = BoxToRect(d, b); const HIThemeButtonDrawInfo info = { @@ -1666,26 +1733,26 @@ static void ComboboxElementDraw( .adornment = Ttk_StateTableLookup(ButtonAdornmentTable, state), }; - BEGIN_DRAWING(d); + BEGIN_DRAWING(d) bounds.origin.y += 1; if (TkMacOSXInDarkMode(tkwin)) { #if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 bounds.size.height += 1; DrawDarkButton(bounds, info.kind, state, dc.context); #endif - } else { + } else{ #if MAC_OS_X_VERSION_MIN_REQUIRED > 1080 if ((state & TTK_STATE_BACKGROUND) && - !(state & TTK_STATE_DISABLED)) { + !(state & TTK_STATE_DISABLED)) { NSColor *background = [NSColor textBackgroundColor]; CGRect innerBounds = CGRectInset(bounds, 1, 2); - SolidFillRoundedRectangle(dc.context, innerBounds, 4, background); } #endif - ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); + ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, + NULL); } - END_DRAWING; + END_DRAWING } static Ttk_ElementSpec ComboboxElementSpec = { @@ -1697,42 +1764,51 @@ static Ttk_ElementSpec ComboboxElementSpec = { }; /*---------------------------------------------------------------------- - * +++ Spinbuttons. + * +++ Spinbutton elements -- * - * From Apple HIG, part III, section "Controls", "The Stepper Control": - * there should be 2 pixels of space between the stepper control (AKA - * IncDecButton, AKA "little arrows") and the text field it modifies. + * From Apple HIG, part III, section "Controls", "The Stepper Control": + * there should be 2 pixels of space between the stepper control (AKA + * IncDecButton, AKA "little arrows") and the text field it modifies. * - * Ttk expects the up and down arrows to be distinct elements but - * HIToolbox draws them as one widget with two different pressed states. - * We work around this by defining them as separate elements in the - * layout, but making each one have a drawing method which also draws the - * other one. The down button does no drawing when not pressed, and when - * pressed draws the entire IncDecButton in its "pressed down" state. The - * up button draws the entire IncDecButton when not pressed and when - * pressed draws the IncDecButton in its "pressed up" state. NOTE: This - * means that when the down button is pressed the IncDecButton will be - * drawn twice, first in unpressed state by the up arrow and then in - * "pressed down" state by the down button. The drawing must be done in - * that order. So the up button must be listed first in the layout. + * Ttk expects the up and down arrows to be distinct elements but + * HIToolbox draws them as one widget with two different pressed states. + * We work around this by defining them as separate elements in the + * layout, but making each one have a drawing method which also draws the + * other one. The down button does no drawing when not pressed, and when + * pressed draws the entire IncDecButton in its "pressed down" state. + * The up button draws the entire IncDecButton when not pressed and when + * pressed draws the IncDecButton in its "pressed up" state. NOTE: This + * means that when the down button is pressed the IncDecButton will be + * drawn twice, first in unpressed state by the up arrow and then in + * "pressed down" state by the down button. The drawing must be done in + * that order. So the up button must be listed first in the layout. */ static Ttk_Padding SpinbuttonMargins = {0, 0, 2, 0}; + static void SpinButtonUpElementSize( - void *clientData, void *elementRecord, Tk_Window tkwin, - int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + int *minWidth, + int *minHeight, + Ttk_Padding *paddingPtr) { SInt32 s; ChkErr(GetThemeMetric, kThemeMetricLittleArrowsWidth, &s); *minWidth = s + Ttk_PaddingWidth(SpinbuttonMargins); ChkErr(GetThemeMetric, kThemeMetricLittleArrowsHeight, &s); - *minHeight = (s + Ttk_PaddingHeight(SpinbuttonMargins)) / 2; + *minHeight = (s + Ttk_PaddingHeight(SpinbuttonMargins)) / 2; } static void SpinButtonUpElementDraw( - void *clientData, void *elementRecord, Tk_Window tkwin, - Drawable d, Ttk_Box b, Ttk_State state) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + Ttk_State state) { CGRect bounds = BoxToRect(d, Ttk_PadBox(b, SpinbuttonMargins)); int infoState; @@ -1743,7 +1819,6 @@ static void SpinButtonUpElementDraw( } else { infoState = Ttk_StateTableLookup(ThemeStateTable, state); } - const HIThemeButtonDrawInfo info = { .version = 0, .state = infoState, @@ -1751,17 +1826,17 @@ static void SpinButtonUpElementDraw( .value = Ttk_StateTableLookup(ButtonValueTable, state), .adornment = kThemeAdornmentNone, }; - - BEGIN_DRAWING(d); + BEGIN_DRAWING(d) #if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 if (TkMacOSXInDarkMode(tkwin)) { DrawDarkIncDecButton(bounds, infoState, state, dc.context); } else #endif { - ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); + ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, + NULL); } - END_DRAWING; + END_DRAWING } static Ttk_ElementSpec SpinButtonUpElementSpec = { @@ -1771,10 +1846,13 @@ static Ttk_ElementSpec SpinButtonUpElementSpec = { SpinButtonUpElementSize, SpinButtonUpElementDraw }; - static void SpinButtonDownElementSize( - void *clientData, void *elementRecord, Tk_Window tkwin, - int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + int *minWidth, + int *minHeight, + Ttk_Padding *paddingPtr) { SInt32 s; @@ -1785,8 +1863,12 @@ static void SpinButtonDownElementSize( } static void SpinButtonDownElementDraw( - void *clientData, void *elementRecord, Tk_Window tkwin, - Drawable d, Ttk_Box b, Ttk_State state) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + Ttk_State state) { CGRect bounds = BoxToRect(d, Ttk_PadBox(b, SpinbuttonMargins)); int infoState = 0; @@ -1796,7 +1878,7 @@ static void SpinButtonDownElementDraw( if (state & TTK_STATE_PRESSED) { infoState = kThemeStatePressedDown; } else { - return; // ??? + return; } const HIThemeButtonDrawInfo info = { .version = 0, @@ -1806,7 +1888,7 @@ static void SpinButtonDownElementDraw( .adornment = kThemeAdornmentNone, }; - BEGIN_DRAWING(d); + BEGIN_DRAWING(d) #if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 if (TkMacOSXInDarkMode(tkwin)) { DrawDarkIncDecButton(bounds, infoState, state, dc.context); @@ -1814,9 +1896,9 @@ static void SpinButtonDownElementDraw( #endif { ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, - NULL); + NULL); } - END_DRAWING; + END_DRAWING } static Ttk_ElementSpec SpinButtonDownElementSpec = { @@ -1829,6 +1911,7 @@ static Ttk_ElementSpec SpinButtonDownElementSpec = { /*---------------------------------------------------------------------- * +++ DrawThemeTrack-based elements -- + * * Progress bars and scales. (See also: <>) */ @@ -1838,15 +1921,15 @@ static Ttk_ElementSpec SpinButtonDownElementSpec = { */ static Ttk_StateTable ThemeTrackEnableTable[] = { - { kThemeTrackDisabled, TTK_STATE_DISABLED, 0 }, - { kThemeTrackActive, TTK_STATE_BACKGROUND, 0 }, - { kThemeTrackActive, 0, 0 } + {kThemeTrackDisabled, TTK_STATE_DISABLED, 0}, + {kThemeTrackActive, TTK_STATE_BACKGROUND, 0}, + {kThemeTrackActive, 0, 0} /* { kThemeTrackNothingToScroll, ?, ? }, */ }; -typedef struct { /* TrackElement client data */ - ThemeTrackKind kind; - SInt32 thicknessMetric; +typedef struct { /* TrackElement client data */ + ThemeTrackKind kind; + SInt32 thicknessMetric; } TrackElementData; static TrackElementData ScaleData = { @@ -1854,34 +1937,41 @@ static TrackElementData ScaleData = { }; typedef struct { - Tcl_Obj *fromObj; /* minimum value */ - Tcl_Obj *toObj; /* maximum value */ - Tcl_Obj *valueObj; /* current value */ - Tcl_Obj *orientObj; /* horizontal / vertical */ + Tcl_Obj *fromObj; /* minimum value */ + Tcl_Obj *toObj; /* maximum value */ + Tcl_Obj *valueObj; /* current value */ + Tcl_Obj *orientObj; /* horizontal / vertical */ } TrackElement; static Ttk_ElementOptionSpec TrackElementOptions[] = { - { "-from", TK_OPTION_DOUBLE, Tk_Offset(TrackElement,fromObj) }, - { "-to", TK_OPTION_DOUBLE, Tk_Offset(TrackElement,toObj) }, - { "-value", TK_OPTION_DOUBLE, Tk_Offset(TrackElement,valueObj) }, - { "-orient", TK_OPTION_STRING, Tk_Offset(TrackElement,orientObj) }, - {0,0,0} + {"-from", TK_OPTION_DOUBLE, Tk_Offset(TrackElement, fromObj)}, + {"-to", TK_OPTION_DOUBLE, Tk_Offset(TrackElement, toObj)}, + {"-value", TK_OPTION_DOUBLE, Tk_Offset(TrackElement, valueObj)}, + {"-orient", TK_OPTION_STRING, Tk_Offset(TrackElement, orientObj)}, + {0, 0, 0} }; - static void TrackElementSize( - void *clientData, void *elementRecord, Tk_Window tkwin, - int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + int *minWidth, + int *minHeight, + Ttk_Padding *paddingPtr) { TrackElementData *data = clientData; - SInt32 size = 24; /* reasonable default ... */ + SInt32 size = 24; /* reasonable default ... */ ChkErr(GetThemeMetric, data->thicknessMetric, &size); *minWidth = *minHeight = size; } static void TrackElementDraw( - void *clientData, void *elementRecord, Tk_Window tkwin, - Drawable d, Ttk_Box b, Ttk_State state) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + Ttk_State state) { TrackElementData *data = clientData; TrackElement *elem = elementRecord; @@ -1902,40 +1992,39 @@ static void TrackElementDraw( .max = to * factor, .value = value * factor, .attributes = kThemeTrackShowThumb | - (orientation == TTK_ORIENT_HORIZONTAL ? - kThemeTrackHorizontal : 0), + (orientation == TTK_ORIENT_HORIZONTAL ? + kThemeTrackHorizontal : 0), .enableState = Ttk_StateTableLookup(ThemeTrackEnableTable, state), .trackInfo.progress.phase = 0, }; if (info.kind == kThemeSlider) { info.trackInfo.slider.pressState = state & TTK_STATE_PRESSED ? - kThemeThumbPressed : 0; + kThemeThumbPressed : 0; if (state & TTK_STATE_ALTERNATE) { info.trackInfo.slider.thumbDir = kThemeThumbDownward; } else { info.trackInfo.slider.thumbDir = kThemeThumbPlain; } } - BEGIN_DRAWING(d); + BEGIN_DRAWING(d) #if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 if (TkMacOSXInDarkMode(tkwin)) { CGRect bounds = BoxToRect(d, b); NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; NSColor *trackColor = [NSColor colorWithColorSpace: deviceRGB - components: darkTrack - count: 4]; - + components: darkTrack + count: 4]; if (orientation == TTK_ORIENT_HORIZONTAL) { - bounds = CGRectInset(bounds, 1, bounds.size.height/2 - 2); + bounds = CGRectInset(bounds, 1, bounds.size.height / 2 - 2); } else { - bounds = CGRectInset(bounds, bounds.size.width/2 - 3, 2); + bounds = CGRectInset(bounds, bounds.size.width / 2 - 3, 2); } SolidFillRoundedRectangle(dc.context, bounds, 2, trackColor); } -#endif +#endif /* if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 */ ChkErr(HIThemeDrawTrack, &info, NULL, dc.context, HIOrientation); - END_DRAWING; + END_DRAWING } static Ttk_ElementSpec TrackElementSpec = { @@ -1946,19 +2035,22 @@ static Ttk_ElementSpec TrackElementSpec = { TrackElementDraw }; -/* - * Slider element -- <> +/*---------------------------------------------------------------------- + * Slider elements -- <> + * * Has geometry only. The Scale widget adjusts the position of this element, * and uses it for hit detection. In the Aqua theme, the slider is actually * drawn as part of the trough element. * - * Also buggy: The geometry here is a Wild-Assed-Guess; I can't figure out how - * to get the Appearance Manager to tell me the slider size. */ static void SliderElementSize( - void *clientData, void *elementRecord, Tk_Window tkwin, - int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + int *minWidth, + int *minHeight, + Ttk_Padding *paddingPtr) { *minWidth = *minHeight = 24; } @@ -1972,7 +2064,7 @@ static Ttk_ElementSpec SliderElementSpec = { }; /*---------------------------------------------------------------------- - * +++ Progress bar element: + * +++ Progress bar elements -- * * @@@ NOTE: According to an older revision of the Aqua reference docs, * @@@ the 'phase' field is between 0 and 4. Newer revisions say @@ -1980,40 +2072,47 @@ static Ttk_ElementSpec SliderElementSpec = { */ typedef struct { - Tcl_Obj *orientObj; /* horizontal / vertical */ - Tcl_Obj *valueObj; /* current value */ - Tcl_Obj *maximumObj; /* maximum value */ - Tcl_Obj *phaseObj; /* animation phase */ - Tcl_Obj *modeObj; /* progress bar mode */ + Tcl_Obj *orientObj; /* horizontal / vertical */ + Tcl_Obj *valueObj; /* current value */ + Tcl_Obj *maximumObj; /* maximum value */ + Tcl_Obj *phaseObj; /* animation phase */ + Tcl_Obj *modeObj; /* progress bar mode */ } PbarElement; static Ttk_ElementOptionSpec PbarElementOptions[] = { - { "-orient", TK_OPTION_STRING, - Tk_Offset(PbarElement,orientObj), "horizontal" }, - { "-value", TK_OPTION_DOUBLE, - Tk_Offset(PbarElement,valueObj), "0" }, - { "-maximum", TK_OPTION_DOUBLE, - Tk_Offset(PbarElement,maximumObj), "100" }, - { "-phase", TK_OPTION_INT, - Tk_Offset(PbarElement,phaseObj), "0" }, - { "-mode", TK_OPTION_STRING, - Tk_Offset(PbarElement,modeObj), "determinate" }, - {0,0,0,0} + {"-orient", TK_OPTION_STRING, + Tk_Offset(PbarElement, orientObj), "horizontal"}, + {"-value", TK_OPTION_DOUBLE, + Tk_Offset(PbarElement, valueObj), "0"}, + {"-maximum", TK_OPTION_DOUBLE, + Tk_Offset(PbarElement, maximumObj), "100"}, + {"-phase", TK_OPTION_INT, + Tk_Offset(PbarElement, phaseObj), "0"}, + {"-mode", TK_OPTION_STRING, + Tk_Offset(PbarElement, modeObj), "determinate"}, + {0, 0, 0, 0} }; - static void PbarElementSize( - void *clientData, void *elementRecord, Tk_Window tkwin, - int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + int *minWidth, + int *minHeight, + Ttk_Padding *paddingPtr) { - SInt32 size = 24; /* @@@ Check HIG for correct default */ + SInt32 size = 24; /* @@@ Check HIG for correct default */ ChkErr(GetThemeMetric, kThemeMetricLargeProgressBarThickness, &size); *minWidth = *minHeight = size; } static void PbarElementDraw( - void *clientData, void *elementRecord, Tk_Window tkwin, - Drawable d, Ttk_Box b, Ttk_State state) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + Ttk_State state) { PbarElement *pbar = elementRecord; int orientation = TTK_ORIENT_HORIZONTAL, phase = 0; @@ -2027,37 +2126,39 @@ static void PbarElementDraw( HIThemeTrackDrawInfo info = { .version = 0, - .kind = (!strcmp("indeterminate", Tcl_GetString(pbar->modeObj)) && value) ? - kThemeIndeterminateBar : kThemeProgressBar, + .kind = + (!strcmp("indeterminate", + Tcl_GetString(pbar->modeObj)) && value) ? + kThemeIndeterminateBar : kThemeProgressBar, .bounds = BoxToRect(d, b), .min = 0, .max = maximum * factor, .value = value * factor, .attributes = kThemeTrackShowThumb | - (orientation == TTK_ORIENT_HORIZONTAL ? - kThemeTrackHorizontal : 0), + (orientation == TTK_ORIENT_HORIZONTAL ? + kThemeTrackHorizontal : 0), .enableState = Ttk_StateTableLookup(ThemeTrackEnableTable, state), .trackInfo.progress.phase = phase, }; - BEGIN_DRAWING(d); + BEGIN_DRAWING(d) #if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 if (TkMacOSXInDarkMode(tkwin)) { CGRect bounds = BoxToRect(d, b); NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; NSColor *trackColor = [NSColor colorWithColorSpace: deviceRGB - components: darkTrack - count: 4]; + components: darkTrack + count: 4]; if (orientation == TTK_ORIENT_HORIZONTAL) { - bounds = CGRectInset(bounds, 1, bounds.size.height/2 - 3); + bounds = CGRectInset(bounds, 1, bounds.size.height / 2 - 3); } else { - bounds = CGRectInset(bounds, bounds.size.width/2 - 3, 1); + bounds = CGRectInset(bounds, bounds.size.width / 2 - 3, 1); } SolidFillRoundedRectangle(dc.context, bounds, 3, trackColor); } -#endif +#endif /* if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 */ ChkErr(HIThemeDrawTrack, &info, NULL, dc.context, HIOrientation); - END_DRAWING; + END_DRAWING } static Ttk_ElementSpec PbarElementSpec = { @@ -2069,7 +2170,7 @@ static Ttk_ElementSpec PbarElementSpec = { }; /*---------------------------------------------------------------------- - * +++ Scrollbar element + * +++ Scrollbar elements */ typedef struct @@ -2078,14 +2179,17 @@ typedef struct } ScrollbarElement; static Ttk_ElementOptionSpec ScrollbarElementOptions[] = { - { "-orient", TK_OPTION_STRING, - Tk_Offset(ScrollbarElement,orientObj), "horizontal" }, - {0,0,0,0} + {"-orient", TK_OPTION_STRING, + Tk_Offset(ScrollbarElement, orientObj), "horizontal"}, + {0, 0, 0, 0} }; - static void TroughElementSize( - void *clientData, void *elementRecord, Tk_Window tkwin, - int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + int *minWidth, + int *minHeight, + Ttk_Padding *paddingPtr) { ScrollbarElement *scrollbar = elementRecord; int orientation = TTK_ORIENT_HORIZONTAL; @@ -2094,28 +2198,39 @@ static void TroughElementSize( Ttk_GetOrientFromObj(NULL, scrollbar->orientObj, &orientation); ChkErr(GetThemeMetric, kThemeMetricScrollBarWidth, &thickness); if (orientation == TTK_ORIENT_HORIZONTAL) { - *minHeight = thickness; + *minHeight = thickness; if ([NSApp macMinorVersion] > 7) { *paddingPtr = Ttk_MakePadding(4, 4, 4, 3); } } else { - *minWidth = thickness; + *minWidth = thickness; if ([NSApp macMinorVersion] > 7) { *paddingPtr = Ttk_MakePadding(4, 4, 3, 4); } } } -static CGFloat lightTrough[4] = {250.0/255, 250.0/255, 250.0/255, 1.0}; -static CGFloat darkTrough[4] = {45.0/255, 46.0/255, 49.0/255, 1.0}; -static CGFloat lightInactiveThumb[4] = {200.0/255, 200.0/255, 200.0/255, 1.0}; -static CGFloat lightActiveThumb[4] = {133.0/255, 133.0/255, 133.0/255, 1.0}; -static CGFloat darkInactiveThumb[4] = {116.0/255, 117.0/255, 118.0/255, 1.0}; -static CGFloat darkActiveThumb[4] = {158.0/255, 158.0/255, 159.0/255, 1.0}; - +static CGFloat lightTrough[4] = {250.0 / 255, 250.0 / 255, 250.0 / 255, 1.0}; +static CGFloat darkTrough[4] = {45.0 / 255, 46.0 / 255, 49.0 / 255, 1.0}; +static CGFloat lightInactiveThumb[4] = { + 200.0 / 255, 200.0 / 255, 200.0 / 255, 1.0 +}; +static CGFloat lightActiveThumb[4] = { + 133.0 / 255, 133.0 / 255, 133.0 / 255, 1.0 +}; +static CGFloat darkInactiveThumb[4] = { + 116.0 / 255, 117.0 / 255, 118.0 / 255, 1.0 +}; +static CGFloat darkActiveThumb[4] = { + 158.0 / 255, 158.0 / 255, 159.0 / 255, 1.0 +}; static void TroughElementDraw( - void *clientData, void *elementRecord, Tk_Window tkwin, - Drawable d, Ttk_Box b, Ttk_State state) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + Ttk_State state) { ScrollbarElement *scrollbar = elementRecord; int orientation = TTK_ORIENT_HORIZONTAL; @@ -2131,19 +2246,19 @@ static void TroughElementDraw( bounds = CGRectInset(bounds, 1, 0); } troughColor = [NSColor colorWithColorSpace: deviceRGB - components: rgba - count: 4]; - BEGIN_DRAWING(d); + components: rgba + count: 4]; + BEGIN_DRAWING(d) if ([NSApp macMinorVersion] > 8) { #if MAC_OS_X_VERSION_MIN_REQUIRED > 1080 CGContextSetFillColorWithColor(dc.context, troughColor.CGColor); #endif } else { ChkErr(HIThemeSetFill, kThemeBrushDocumentWindowBackground, NULL, - dc.context, HIOrientation); + dc.context, HIOrientation); } CGContextFillRect(dc.context, bounds); - END_DRAWING; + END_DRAWING } static Ttk_ElementSpec TroughElementSpec = { @@ -2153,10 +2268,13 @@ static Ttk_ElementSpec TroughElementSpec = { TroughElementSize, TroughElementDraw }; - static void ThumbElementSize( - void *clientData, void *elementRecord, Tk_Window tkwin, - int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + int *minWidth, + int *minHeight, + Ttk_Padding *paddingPtr) { ScrollbarElement *scrollbar = elementRecord; int orientation = TTK_ORIENT_HORIZONTAL; @@ -2165,13 +2283,17 @@ static void ThumbElementSize( if (orientation == TTK_ORIENT_HORIZONTAL) { *minHeight = 8; } else { - *minWidth = 8; + *minWidth = 8; } } static void ThumbElementDraw( - void *clientData, void *elementRecord, Tk_Window tkwin, - Drawable d, Ttk_Box b, Ttk_State state) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + Ttk_State state) { ScrollbarElement *scrollbar = elementRecord; int orientation = TTK_ORIENT_HORIZONTAL; @@ -2180,18 +2302,18 @@ static void ThumbElementDraw( /* * 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 + * 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. + * 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) { @@ -2200,69 +2322,66 @@ static void ThumbElementDraw( NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; NSColor *thumbColor; CGFloat *rgba; - - if ((orientation == TTK_ORIENT_HORIZONTAL - && thumbBounds.size.width >= Tk_Width(tkwin) - 8) - || (orientation == TTK_ORIENT_VERTICAL - && thumbBounds.size.height >= Tk_Height(tkwin) - 8)) { + if ((orientation == TTK_ORIENT_HORIZONTAL && + thumbBounds.size.width >= Tk_Width(tkwin) - 8) || + (orientation == TTK_ORIENT_VERTICAL && + thumbBounds.size.height >= Tk_Height(tkwin) - 8)) { return; } - int isDark = TkMacOSXInDarkMode(tkwin); - if ((state & TTK_STATE_PRESSED) || - (state & TTK_STATE_HOVER)) { + (state & TTK_STATE_HOVER)) { rgba = isDark ? darkActiveThumb : lightActiveThumb; } else { rgba = isDark ? darkInactiveThumb : lightInactiveThumb; } thumbColor = [NSColor colorWithColorSpace: deviceRGB - components: rgba - count: 4]; - BEGIN_DRAWING(d); + components: rgba + count: 4]; + BEGIN_DRAWING(d) SolidFillRoundedRectangle(dc.context, thumbBounds, 4, thumbColor); - END_DRAWING; -#endif + END_DRAWING +#endif /* if MAC_OS_X_VERSION_MIN_REQUIRED > 1080 */ } else { double thumbSize, trackSize, visibleSize, viewSize; MacDrawable *macWin = (MacDrawable *) Tk_WindowId(tkwin); CGRect troughBounds = {{macWin->xOff, macWin->yOff}, {Tk_Width(tkwin), Tk_Height(tkwin)}}; - /* - * The info struct has integer fields, which will be converted to - * floats in the drawing routine. All of values provided in the info - * struct, namely min, max, value, and viewSize are only defined up to - * an arbitrary scale factor. To avoid roundoff error we scale so that - * the viewSize is a large float which is smaller than the largest int. - */ - - viewSize = RangeToFactor(100.0); + /* + * The info struct has integer fields, which will be converted to + * floats in the drawing routine. All of values provided in the info + * struct, namely min, max, value, and viewSize are only defined up to + * an arbitrary scale factor. To avoid roundoff error we scale so + * that the viewSize is a large float which is smaller than the + * largest int. + */ + viewSize = RangeToFactor(100.0); HIThemeTrackDrawInfo info = { .version = 0, .bounds = troughBounds, .min = 0, - .attributes = kThemeTrackShowThumb | kThemeTrackThumbRgnIsNotGhost, + .attributes = kThemeTrackShowThumb | + kThemeTrackThumbRgnIsNotGhost, .enableState = kThemeTrackActive }; - - info.trackInfo.scrollbar.viewsize = viewSize*.8; + info.trackInfo.scrollbar.viewsize = viewSize * .8; 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)); + info.value = info.max * (b.x / (trackSize - thumbSize)); } else { thumbSize = b.height; trackSize = troughBounds.size.height; visibleSize = (thumbSize / trackSize) * viewSize; info.max = viewSize - visibleSize; - info.value = info.max * (b.y / (trackSize - thumbSize)); + info.value = info.max * (b.y / (trackSize - thumbSize)); } if ((state & TTK_STATE_PRESSED) || - (state & TTK_STATE_HOVER)) { + (state & TTK_STATE_HOVER)) { info.trackInfo.scrollbar.pressState = kThemeThumbPressed; } else { info.trackInfo.scrollbar.pressState = 0; @@ -2272,9 +2391,9 @@ static void ThumbElementDraw( } else { info.attributes &= ~kThemeTrackHorizontal; } - BEGIN_DRAWING(d); + BEGIN_DRAWING(d) HIThemeDrawTrack(&info, 0, dc.context, kHIThemeOrientationNormal); - END_DRAWING; + END_DRAWING } } @@ -2285,10 +2404,13 @@ static Ttk_ElementSpec ThumbElementSpec = { ThumbElementSize, ThumbElementDraw }; - static void ArrowElementSize( - void *clientData, void *elementRecord, Tk_Window tkwin, - int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + int *minWidth, + int *minHeight, + Ttk_Padding *paddingPtr) { if ([NSApp macMinorVersion] < 8) { *minHeight = *minWidth = 14; @@ -2314,34 +2436,44 @@ static Ttk_ElementSpec ArrowElementSpec = { */ static void SeparatorElementSize( - void *clientData, void *elementRecord, Tk_Window tkwin, - int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + int *minWidth, + int *minHeight, + Ttk_Padding *paddingPtr) { *minWidth = *minHeight = 1; } static void SeparatorElementDraw( - void *clientData, void *elementRecord, Tk_Window tkwin, - Drawable d, Ttk_Box b, unsigned int state) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + unsigned int state) { CGRect bounds = BoxToRect(d, b); const HIThemeSeparatorDrawInfo info = { .version = 0, - /* Separator only supports kThemeStateActive, kThemeStateInactive */ - .state = Ttk_StateTableLookup(ThemeStateTable, state & TTK_STATE_BACKGROUND), + /* Separator only supports kThemeStateActive, kThemeStateInactive */ + .state = Ttk_StateTableLookup(ThemeStateTable, + state & TTK_STATE_BACKGROUND), }; - BEGIN_DRAWING(d); + BEGIN_DRAWING(d) #if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 if (TkMacOSXInDarkMode(tkwin)) { DrawDarkSeparator(bounds, dc.context, tkwin); } else { - ChkErr(HIThemeDrawSeparator, &bounds, &info, dc.context, HIOrientation); + ChkErr(HIThemeDrawSeparator, &bounds, &info, dc.context, + HIOrientation); } #else ChkErr(HIThemeDrawSeparator, &bounds, &info, dc.context, HIOrientation); #endif - END_DRAWING; + END_DRAWING } static Ttk_ElementSpec SeparatorElementSpec = { @@ -2353,15 +2485,19 @@ static Ttk_ElementSpec SeparatorElementSpec = { }; /*---------------------------------------------------------------------- - * +++ Size grip element. + * +++ Size grip elements -- (obsolete) */ static const ThemeGrowDirection sizegripGrowDirection - = kThemeGrowRight|kThemeGrowDown; + = kThemeGrowRight | kThemeGrowDown; static void SizegripElementSize( - void *clientData, void *elementRecord, Tk_Window tkwin, - int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + int *minWidth, + int *minHeight, + Ttk_Padding *paddingPtr) { HIThemeGrowBoxDrawInfo info = { .version = 0, @@ -2378,23 +2514,28 @@ static void SizegripElementSize( } static void SizegripElementDraw( - void *clientData, void *elementRecord, Tk_Window tkwin, - Drawable d, Ttk_Box b, unsigned int state) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + unsigned int state) { CGRect bounds = BoxToRect(d, b); HIThemeGrowBoxDrawInfo info = { .version = 0, - /* Grow box only supports kThemeStateActive, kThemeStateInactive */ + /* Grow box only supports kThemeStateActive, kThemeStateInactive */ .state = Ttk_StateTableLookup(ThemeStateTable, - state & TTK_STATE_BACKGROUND), + state & TTK_STATE_BACKGROUND), .kind = kHIThemeGrowBoxKindNormal, .direction = sizegripGrowDirection, .size = kHIThemeGrowBoxSizeNormal, }; - BEGIN_DRAWING(d); - ChkErr(HIThemeDrawGrowBox, &bounds.origin, &info, dc.context, HIOrientation); - END_DRAWING; + BEGIN_DRAWING(d) + ChkErr(HIThemeDrawGrowBox, &bounds.origin, &info, dc.context, + HIOrientation); + END_DRAWING } static Ttk_ElementSpec SizegripElementSpec = { @@ -2406,85 +2547,93 @@ static Ttk_ElementSpec SizegripElementSpec = { }; /*---------------------------------------------------------------------- - * +++ Background and fill elements. + * +++ Background and fill elements -- * - * Before drawing any ttk widget, its bounding rectangle is filled with a - * background color. This color must match the background color of the - * containing widget to avoid looking ugly. The need for care when doing - * this is exacerbated by the fact that ttk enforces its "native look" by - * not allowing user control of the background or highlight colors of ttk - * widgets. + * Before drawing any ttk widget, its bounding rectangle is filled with a + * background color. This color must match the background color of the + * containing widget to avoid looking ugly. The need for care when doing + * this is exacerbated by the fact that ttk enforces its "native look" by + * not allowing user control of the background or highlight colors of ttk + * widgets. * - * 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. + * 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 - * system background color. If widgets inside the box were drawn with the - * system background color the backgrounds would match. But this produces - * a GroupBox with no contrast, the only visual clue being a faint - * highlighting around the top of the GroupBox. Moreover, the TabbedPane - * does not have an Opaque version, so while it is drawn inside a - * contrasting rounded rectangle, the widgets inside the pane needed to be - * enclosed in a frame with the system background color. This added a - * visual artifact since the frame's background color does not match the - * Pane's background color. That code has now been replaced with the - * standalone drawing procedure macOSXDrawGroupBox, which draws a rounded - * rectangle with an appropriate contrasting background 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 + * system background color. If widgets inside the box were drawn with + * the system background color the backgrounds would match. But this + * produces a GroupBox with no contrast, the only visual clue being a + * faint highlighting around the top of the GroupBox. Moreover, the + * TabbedPane does not have an Opaque version, so while it is drawn + * inside a contrasting rounded rectangle, the widgets inside the pane + * needed to be enclosed in a frame with the system background + * color. This added a visual artifact since the frame's background color + * does not match the Pane's background color. That code has now been + * replaced with the standalone drawing procedure macOSXDrawGroupBox, + * which draws a rounded rectangle with an appropriate contrasting + * background color. * - * Patterned backgrounds, which are now obsolete, should be aligned with - * the coordinate system of the top-level window. Apparently failing to - * do this used to cause graphics anomalies when drawing into an - * off-screen graphics port. The code for handling this is currently - * commented out. + * Patterned backgrounds, which are now obsolete, should be aligned with + * the coordinate system of the top-level window. Apparently failing to + * do this used to cause graphics anomalies when drawing into an + * off-screen graphics port. The code for handling this is currently + * commented out. */ static void FillElementDraw( - void *clientData, void *elementRecord, Tk_Window tkwin, - Drawable d, Ttk_Box b, Ttk_State state) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + Ttk_State state) { CGRect bounds = BoxToRect(d, b); + #if MAC_OS_X_VERSION_MIN_REQUIRED > 1080 NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; NSColor *bgColor; CGFloat fill[4]; - - BEGIN_DRAWING(d); + BEGIN_DRAWING(d) GetBackgroundColor(dc.context, tkwin, 0, fill); bgColor = [NSColor colorWithColorSpace: deviceRGB components: fill - count: 4]; + count: 4]; CGContextSetFillColorSpace(dc.context, deviceRGB.CGColorSpace); CGContextSetFillColorWithColor(dc.context, bgColor.CGColor); CGContextFillRect(dc.context, bounds); - END_DRAWING; -#else + END_DRAWING +#else /* if MAC_OS_X_VERSION_MIN_REQUIRED > 1080 */ ThemeBrush brush = (state & TTK_STATE_BACKGROUND) - ? kThemeBrushModelessDialogBackgroundInactive - : kThemeBrushModelessDialogBackgroundActive; - - BEGIN_DRAWING(d); + ? kThemeBrushModelessDialogBackgroundInactive + : kThemeBrushModelessDialogBackgroundActive; + BEGIN_DRAWING(d) ChkErr(HIThemeSetFill, brush, NULL, dc.context, HIOrientation); //QDSetPatternOrigin(PatternOrigin(tkwin, d)); CGContextFillRect(dc.context, bounds); - END_DRAWING; -#endif + END_DRAWING +#endif /* if MAC_OS_X_VERSION_MIN_REQUIRED > 1080 */ } static void BackgroundElementDraw( - void *clientData, void *elementRecord, Tk_Window tkwin, - Drawable d, Ttk_Box b, unsigned int state) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + unsigned int state) { FillElementDraw(clientData, elementRecord, tkwin, d, Ttk_WinBox(tkwin), - state); + state); } static Ttk_ElementSpec FillElementSpec = { @@ -2494,7 +2643,6 @@ static Ttk_ElementSpec FillElementSpec = { TtkNullElementSize, FillElementDraw }; - static Ttk_ElementSpec BackgroundElementSpec = { TK_STYLE_VERSION_2, sizeof(NullElement), @@ -2507,28 +2655,32 @@ static Ttk_ElementSpec BackgroundElementSpec = { * +++ ToolbarBackground element -- toolbar style for frames. * * This is very similar to the normal background element, but uses a - * different ThemeBrush in order to get the lighter pinstripe effect used in - * toolbars. We use SetThemeBackground() rather than ApplyThemeBackground() - * in order to get the right style. + * different ThemeBrush in order to get the lighter pinstripe effect + * used in toolbars. We use SetThemeBackground() rather than + * ApplyThemeBackground() in order to get the right style. * - * * */ static void ToolbarBackgroundElementDraw( - void *clientData, void *elementRecord, Tk_Window tkwin, - Drawable d, Ttk_Box b, Ttk_State state) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + Ttk_State state) { ThemeBrush brush = kThemeBrushToolbarBackground; CGRect bounds = BoxToRect(d, Ttk_WinBox(tkwin)); - BEGIN_DRAWING(d); + BEGIN_DRAWING(d) ChkErr(HIThemeSetFill, brush, NULL, dc.context, HIOrientation); //QDSetPatternOrigin(PatternOrigin(tkwin, d)); CGContextFillRect(dc.context, bounds); - END_DRAWING; + END_DRAWING } static Ttk_ElementSpec ToolbarBackgroundElementSpec = { @@ -2540,30 +2692,36 @@ static Ttk_ElementSpec ToolbarBackgroundElementSpec = { }; /*---------------------------------------------------------------------- - * +++ Field element: - * Used for the Treeview widget. This is like the BackgroundElement + * +++ Field elements -- + * + * Used for the Treeview widget. This is like the BackgroundElement * except that the fieldbackground color is configureable. */ typedef struct { - Tcl_Obj *backgroundObj; + Tcl_Obj *backgroundObj; } FieldElement; static Ttk_ElementOptionSpec FieldElementOptions[] = { - { "-fieldbackground", TK_OPTION_BORDER, - Tk_Offset(FieldElement, backgroundObj), "white" }, - { NULL, 0, 0, NULL } + {"-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) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + Ttk_State state) { FieldElement *e = elementRecord; - Tk_3DBorder backgroundPtr = Tk_Get3DBorderFromObj(tkwin,e->backgroundObj); + Tk_3DBorder backgroundPtr = + Tk_Get3DBorderFromObj(tkwin, e->backgroundObj); + XFillRectangle(Tk_Display(tkwin), d, - Tk_3DBorderGC(tkwin, backgroundPtr, TK_3D_FLAT_GC), - b.x, b.y, b.width, b.height); + Tk_3DBorderGC(tkwin, backgroundPtr, TK_3D_FLAT_GC), + b.x, b.y, b.width, b.height); } static Ttk_ElementSpec FieldElementSpec = { @@ -2575,30 +2733,35 @@ static Ttk_ElementSpec FieldElementSpec = { }; /*---------------------------------------------------------------------- - * +++ Treeview header + * +++ Treeview headers -- + * * Redefine the header to use a kThemeListHeaderButton. */ static Ttk_StateTable TreeHeaderValueTable[] = { - { kThemeButtonOn, TTK_STATE_ALTERNATE}, - { kThemeButtonOn, TTK_STATE_SELECTED}, - { kThemeButtonOff, 0} + {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} + {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) +{ -static void TreeAreaElementSize( - void *clientData, void *elementRecord, Tk_Window tkwin, - int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) -{ /* * Padding is needed to get the heading text to align correctly, since the * widget expects the heading to be the same height as a row. @@ -2616,22 +2779,29 @@ static Ttk_ElementSpec TreeAreaElementSpec = { TreeAreaElementSize, TtkNullElementDraw }; - static void TreeHeaderElementSize( - void *clientData, void *elementRecord, Tk_Window tkwin, - int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + int *minWidth, + int *minHeight, + Ttk_Padding *paddingPtr) { if ([NSApp macMinorVersion] > 8) { *minHeight = 24; } else { ButtonElementSize(clientData, elementRecord, tkwin, minWidth, - minHeight, paddingPtr); + minHeight, paddingPtr); } } static void TreeHeaderElementDraw( - void *clientData, void *elementRecord, Tk_Window tkwin, - Drawable d, Ttk_Box b, Ttk_State state) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + Ttk_State state) { ThemeButtonParams *params = clientData; CGRect bounds = BoxToRect(d, b); @@ -2643,14 +2813,15 @@ static void TreeHeaderElementDraw( .adornment = Ttk_StateTableLookup(TreeHeaderAdornmentTable, state), }; - BEGIN_DRAWING(d); + BEGIN_DRAWING(d) if ([NSApp macMinorVersion] > 8) { #if MAC_OS_X_VERSION_MIN_REQUIRED > 1080 - /* - * Compensate for the padding added in TreeHeaderElementSize, so the - * larger heading will be drawn at the top of the widget. - */ - + + /* + * Compensate for the padding added in TreeHeaderElementSize, so + * the larger heading will be drawn at the top of the widget. + */ + bounds.origin.y -= 4; if (TkMacOSXInDarkMode(tkwin)) { #if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 @@ -2661,9 +2832,10 @@ static void TreeHeaderElementDraw( } #endif /* MAC_OS_X_VERSION_MIN_REQUIRED > 1080 */ } else { - ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); + ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, + NULL); } - END_DRAWING; + END_DRAWING } static Ttk_ElementSpec TreeHeaderElementSpec = { @@ -2674,20 +2846,23 @@ static Ttk_ElementSpec TreeHeaderElementSpec = { TreeHeaderElementDraw }; -/* - * Disclosure triangle: +/*---------------------------------------------------------------------- + * +++ Disclosure triangles -- */ -#define TTK_TREEVIEW_STATE_OPEN TTK_STATE_USER1 -#define TTK_TREEVIEW_STATE_LEAF TTK_STATE_USER2 +#define TTK_TREEVIEW_STATE_OPEN TTK_STATE_USER1 +#define TTK_TREEVIEW_STATE_LEAF TTK_STATE_USER2 static Ttk_StateTable DisclosureValueTable[] = { - { kThemeDisclosureDown, TTK_TREEVIEW_STATE_OPEN, 0 }, - { kThemeDisclosureRight, 0, 0 }, + {kThemeDisclosureDown, TTK_TREEVIEW_STATE_OPEN, 0}, + {kThemeDisclosureRight, 0, 0}, }; - static void DisclosureElementSize( - void *clientData, void *elementRecord, Tk_Window tkwin, - int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + int *minWidth, + int *minHeight, + Ttk_Padding *paddingPtr) { SInt32 s; @@ -2698,8 +2873,12 @@ static void DisclosureElementSize( } static void DisclosureElementDraw( - void *clientData, void *elementRecord, Tk_Window tkwin, - Drawable d, Ttk_Box b, Ttk_State state) + void *clientData, + void *elementRecord, + Tk_Window tkwin, + Drawable d, + Ttk_Box b, + Ttk_State state) { if (!(state & TTK_TREEVIEW_STATE_LEAF)) { int triangleState = TkMacOSXInDarkMode(tkwin) ? @@ -2713,9 +2892,10 @@ static void DisclosureElementDraw( .adornment = kThemeAdornmentDrawIndicatorOnly, }; - BEGIN_DRAWING(d); - ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); - END_DRAWING; + BEGIN_DRAWING(d) + ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, + NULL); + END_DRAWING } } @@ -2728,7 +2908,7 @@ static Ttk_ElementSpec DisclosureElementSpec = { }; /*---------------------------------------------------------------------- - * +++ Widget layouts. + * +++ Widget layouts -- */ TTK_BEGIN_LAYOUT_TABLE(LayoutTable) @@ -2738,52 +2918,52 @@ TTK_LAYOUT("Toolbar", TTK_LAYOUT("TButton", TTK_GROUP("Button.button", TTK_FILL_BOTH, - TTK_GROUP("Button.padding", TTK_FILL_BOTH, - TTK_NODE("Button.label", TTK_FILL_BOTH)))) + TTK_GROUP("Button.padding", TTK_FILL_BOTH, + TTK_NODE("Button.label", TTK_FILL_BOTH)))) TTK_LAYOUT("TRadiobutton", TTK_GROUP("Radiobutton.button", TTK_FILL_BOTH, - TTK_GROUP("Radiobutton.padding", TTK_FILL_BOTH, - TTK_NODE("Radiobutton.label", TTK_PACK_LEFT)))) + TTK_GROUP("Radiobutton.padding", TTK_FILL_BOTH, + TTK_NODE("Radiobutton.label", TTK_PACK_LEFT)))) TTK_LAYOUT("TCheckbutton", TTK_GROUP("Checkbutton.button", TTK_FILL_BOTH, - TTK_GROUP("Checkbutton.padding", TTK_FILL_BOTH, - TTK_NODE("Checkbutton.label", TTK_PACK_LEFT)))) + TTK_GROUP("Checkbutton.padding", TTK_FILL_BOTH, + TTK_NODE("Checkbutton.label", TTK_PACK_LEFT)))) TTK_LAYOUT("TMenubutton", TTK_GROUP("Menubutton.button", TTK_FILL_BOTH, - TTK_GROUP("Menubutton.padding", TTK_FILL_BOTH, - TTK_NODE("Menubutton.label", TTK_PACK_LEFT)))) + TTK_GROUP("Menubutton.padding", TTK_FILL_BOTH, + TTK_NODE("Menubutton.label", TTK_PACK_LEFT)))) TTK_LAYOUT("TCombobox", - TTK_GROUP("Combobox.button", TTK_FILL_BOTH, - TTK_GROUP("Combobox.padding", TTK_FILL_BOTH, - TTK_NODE("Combobox.textarea", TTK_FILL_BOTH)))) + TTK_GROUP("Combobox.button", TTK_FILL_BOTH, + TTK_GROUP("Combobox.padding", TTK_FILL_BOTH, + TTK_NODE("Combobox.textarea", TTK_FILL_BOTH)))) /* Notebook tabs -- no focus ring */ TTK_LAYOUT("Tab", TTK_GROUP("Notebook.tab", TTK_FILL_BOTH, - TTK_GROUP("Notebook.padding", TTK_EXPAND|TTK_FILL_BOTH, - TTK_NODE("Notebook.label", TTK_EXPAND|TTK_FILL_BOTH)))) + TTK_GROUP("Notebook.padding", TTK_EXPAND | TTK_FILL_BOTH, + TTK_NODE("Notebook.label", TTK_EXPAND | TTK_FILL_BOTH)))) /* Spinbox -- buttons 2px to the right of the field. */ - TTK_LAYOUT("TSpinbox", - TTK_GROUP("Spinbox.buttons", TTK_PACK_RIGHT, - TTK_NODE("Spinbox.uparrow", TTK_PACK_TOP|TTK_STICK_E) - TTK_NODE("Spinbox.downarrow", TTK_PACK_BOTTOM|TTK_STICK_E)) - TTK_GROUP("Spinbox.field", TTK_EXPAND|TTK_FILL_X, - TTK_NODE("Spinbox.textarea", TTK_EXPAND|TTK_FILL_X))) +TTK_LAYOUT("TSpinbox", + TTK_GROUP("Spinbox.buttons", TTK_PACK_RIGHT, + TTK_NODE("Spinbox.uparrow", TTK_PACK_TOP | TTK_STICK_E) + TTK_NODE("Spinbox.downarrow", TTK_PACK_BOTTOM | TTK_STICK_E)) + TTK_GROUP("Spinbox.field", TTK_EXPAND | TTK_FILL_X, + TTK_NODE("Spinbox.textarea", TTK_EXPAND | TTK_FILL_X))) /* Progress bars -- track only */ TTK_LAYOUT("TProgressbar", - TTK_NODE("Progressbar.track", TTK_EXPAND|TTK_FILL_BOTH)) + TTK_NODE("Progressbar.track", TTK_EXPAND | TTK_FILL_BOTH)) /* Treeview -- no border. */ TTK_LAYOUT("Treeview", TTK_GROUP("Treeview.field", TTK_FILL_BOTH, - TTK_GROUP("Treeview.padding", TTK_FILL_BOTH, - TTK_NODE("Treeview.treearea", TTK_FILL_BOTH)))) + TTK_GROUP("Treeview.padding", TTK_FILL_BOTH, + TTK_NODE("Treeview.treearea", TTK_FILL_BOTH)))) /* Tree heading -- no border, fixed height */ TTK_LAYOUT("Heading", @@ -2794,32 +2974,33 @@ TTK_LAYOUT("Heading", /* Tree items -- omit focus ring */ TTK_LAYOUT("Item", TTK_GROUP("Treeitem.padding", TTK_FILL_BOTH, - TTK_NODE("Treeitem.indicator", TTK_PACK_LEFT) - TTK_NODE("Treeitem.image", TTK_PACK_LEFT) - TTK_NODE("Treeitem.text", TTK_PACK_LEFT))) + TTK_NODE("Treeitem.indicator", TTK_PACK_LEFT) + TTK_NODE("Treeitem.image", TTK_PACK_LEFT) + TTK_NODE("Treeitem.text", TTK_PACK_LEFT))) /* Scrollbar Layout -- Buttons at the bottom (Snow Leopard and Lion only) */ TTK_LAYOUT("Vertical.TScrollbar", TTK_GROUP("Vertical.Scrollbar.trough", TTK_FILL_Y, - TTK_NODE("Vertical.Scrollbar.thumb", TTK_PACK_TOP|TTK_EXPAND|TTK_FILL_BOTH) - TTK_NODE("Vertical.Scrollbar.downarrow", TTK_PACK_BOTTOM) - TTK_NODE("Vertical.Scrollbar.uparrow", TTK_PACK_BOTTOM))) + TTK_NODE("Vertical.Scrollbar.thumb", + TTK_PACK_TOP | TTK_EXPAND | TTK_FILL_BOTH) + TTK_NODE("Vertical.Scrollbar.downarrow", TTK_PACK_BOTTOM) + TTK_NODE("Vertical.Scrollbar.uparrow", TTK_PACK_BOTTOM))) TTK_LAYOUT("Horizontal.TScrollbar", TTK_GROUP("Horizontal.Scrollbar.trough", TTK_FILL_X, - TTK_NODE("Horizontal.Scrollbar.thumb", TTK_PACK_LEFT|TTK_EXPAND|TTK_FILL_BOTH) - TTK_NODE("Horizontal.Scrollbar.rightarrow", TTK_PACK_RIGHT) - TTK_NODE("Horizontal.Scrollbar.leftarrow", TTK_PACK_RIGHT))) + TTK_NODE("Horizontal.Scrollbar.thumb", + TTK_PACK_LEFT | TTK_EXPAND | TTK_FILL_BOTH) + TTK_NODE("Horizontal.Scrollbar.rightarrow", TTK_PACK_RIGHT) + TTK_NODE("Horizontal.Scrollbar.leftarrow", TTK_PACK_RIGHT))) -TTK_END_LAYOUT_TABLE; +TTK_END_LAYOUT_TABLE /*---------------------------------------------------------------------- - * +++ Initialization. + * +++ Initialization -- */ -static int -AquaTheme_Init( +static int AquaTheme_Init( Tcl_Interp *interp) { Ttk_Theme themePtr = Ttk_CreateTheme(interp, "aqua", NULL); @@ -2832,40 +3013,41 @@ AquaTheme_Init( * Elements: */ - Ttk_RegisterElementSpec(themePtr, "background", &BackgroundElementSpec, 0); + Ttk_RegisterElementSpec(themePtr, "background", &BackgroundElementSpec, + 0); Ttk_RegisterElementSpec(themePtr, "fill", &FillElementSpec, 0); Ttk_RegisterElementSpec(themePtr, "field", &FieldElementSpec, 0); Ttk_RegisterElementSpec(themePtr, "Toolbar.background", - &ToolbarBackgroundElementSpec, 0); + &ToolbarBackgroundElementSpec, 0); Ttk_RegisterElementSpec(themePtr, "Button.button", - &ButtonElementSpec, &PushButtonParams); + &ButtonElementSpec, &PushButtonParams); Ttk_RegisterElementSpec(themePtr, "Checkbutton.button", - &ButtonElementSpec, &CheckBoxParams); + &ButtonElementSpec, &CheckBoxParams); Ttk_RegisterElementSpec(themePtr, "Radiobutton.button", - &ButtonElementSpec, &RadioButtonParams); + &ButtonElementSpec, &RadioButtonParams); Ttk_RegisterElementSpec(themePtr, "Toolbutton.border", - &ButtonElementSpec, &BevelButtonParams); + &ButtonElementSpec, &BevelButtonParams); Ttk_RegisterElementSpec(themePtr, "Menubutton.button", - &ButtonElementSpec, &PopupButtonParams); + &ButtonElementSpec, &PopupButtonParams); Ttk_RegisterElementSpec(themePtr, "Spinbox.uparrow", - &SpinButtonUpElementSpec, 0); + &SpinButtonUpElementSpec, 0); Ttk_RegisterElementSpec(themePtr, "Spinbox.downarrow", - &SpinButtonDownElementSpec, 0); + &SpinButtonDownElementSpec, 0); Ttk_RegisterElementSpec(themePtr, "Combobox.button", - &ComboboxElementSpec, 0); + &ComboboxElementSpec, 0); Ttk_RegisterElementSpec(themePtr, "Treeitem.indicator", - &DisclosureElementSpec, &DisclosureParams); + &DisclosureElementSpec, &DisclosureParams); Ttk_RegisterElementSpec(themePtr, "Treeheading.cell", - &TreeHeaderElementSpec, &ListHeaderParams); + &TreeHeaderElementSpec, &ListHeaderParams); Ttk_RegisterElementSpec(themePtr, "Treeview.treearea", - &TreeAreaElementSpec, 0); + &TreeAreaElementSpec, 0); Ttk_RegisterElementSpec(themePtr, "Notebook.tab", &TabElementSpec, 0); Ttk_RegisterElementSpec(themePtr, "Notebook.client", &PaneElementSpec, 0); - Ttk_RegisterElementSpec(themePtr, "Labelframe.border", - &GroupElementSpec, 0); + Ttk_RegisterElementSpec(themePtr, "Labelframe.border", &GroupElementSpec, + 0); Ttk_RegisterElementSpec(themePtr, "Entry.field", &EntryElementSpec, 0); Ttk_RegisterElementSpec(themePtr, "Spinbox.field", &EntryElementSpec, 0); @@ -2877,39 +3059,41 @@ AquaTheme_Init( /* * <> - * 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". */ - Ttk_RegisterElementSpec(themePtr,"Progressbar.track", &PbarElementSpec, 0); + Ttk_RegisterElementSpec(themePtr, "Progressbar.track", &PbarElementSpec, + 0); - Ttk_RegisterElementSpec(themePtr,"Scale.trough", &TrackElementSpec, - &ScaleData); - Ttk_RegisterElementSpec(themePtr,"Scale.slider", &SliderElementSpec, 0); + Ttk_RegisterElementSpec(themePtr, "Scale.trough", &TrackElementSpec, + &ScaleData); + Ttk_RegisterElementSpec(themePtr, "Scale.slider", &SliderElementSpec, 0); - Ttk_RegisterElementSpec(themePtr,"Vertical.Scrollbar.trough", - &TroughElementSpec, 0); - Ttk_RegisterElementSpec(themePtr,"Vertical.Scrollbar.thumb", - &ThumbElementSpec, 0); - Ttk_RegisterElementSpec(themePtr,"Horizontal.Scrollbar.trough", - &TroughElementSpec, 0); - Ttk_RegisterElementSpec(themePtr,"Horizontal.Scrollbar.thumb", - &ThumbElementSpec, 0); + Ttk_RegisterElementSpec(themePtr, "Vertical.Scrollbar.trough", + &TroughElementSpec, 0); + Ttk_RegisterElementSpec(themePtr, "Vertical.Scrollbar.thumb", + &ThumbElementSpec, 0); + Ttk_RegisterElementSpec(themePtr, "Horizontal.Scrollbar.trough", + &TroughElementSpec, 0); + Ttk_RegisterElementSpec(themePtr, "Horizontal.Scrollbar.thumb", + &ThumbElementSpec, 0); /* * If we are not in Snow Leopard or Lion the arrows won't actually be * displayed. */ - Ttk_RegisterElementSpec(themePtr,"Vertical.Scrollbar.uparrow", - &ArrowElementSpec, 0); - Ttk_RegisterElementSpec(themePtr,"Vertical.Scrollbar.downarrow", - &ArrowElementSpec, 0); - Ttk_RegisterElementSpec(themePtr,"Horizontal.Scrollbar.leftarrow", - &ArrowElementSpec, 0); - Ttk_RegisterElementSpec(themePtr,"Horizontal.Scrollbar.rightarrow", - &ArrowElementSpec, 0); + Ttk_RegisterElementSpec(themePtr, "Vertical.Scrollbar.uparrow", + &ArrowElementSpec, 0); + Ttk_RegisterElementSpec(themePtr, "Vertical.Scrollbar.downarrow", + &ArrowElementSpec, 0); + Ttk_RegisterElementSpec(themePtr, "Horizontal.Scrollbar.leftarrow", + &ArrowElementSpec, 0); + Ttk_RegisterElementSpec(themePtr, "Horizontal.Scrollbar.rightarrow", + &ArrowElementSpec, 0); /* * Layouts: @@ -2922,11 +3106,12 @@ AquaTheme_Init( } MODULE_SCOPE -int Ttk_MacOSXPlatformInit(Tcl_Interp *interp) +int Ttk_MacOSXPlatformInit( + Tcl_Interp *interp) { return AquaTheme_Init(interp); } - + /* * Local Variables: * mode: objc -- cgit v0.12 From 23928a5f10c089cf05427e29d77b268e60ab7fc6 Mon Sep 17 00:00:00 2001 From: culler Date: Wed, 17 Apr 2019 21:06:14 +0000 Subject: Restore code ordering which avoids unused function warnings in old systems. --- macosx/ttkMacOSXTheme.c | 118 +++++++++++++++++++++++++----------------------- 1 file changed, 62 insertions(+), 56 deletions(-) diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index 1f231a9..49082b3 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -280,65 +280,11 @@ static void SolidFillRoundedRectangle( } /*---------------------------------------------------------------------- - * GradientFillRoundedRectangle -- - * - * Fill a rounded rectangle with a specified gradient. - */ - -static void GradientFillRoundedRectangle( - CGContextRef context, - CGRect bounds, - CGFloat radius, - CGFloat *colors, - int numColors) -{ - NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; - CGPathRef path; - CGPoint end = { - bounds.origin.x, - bounds.origin.y + bounds.size.height - }; - CGGradientRef gradient = CGGradientCreateWithColorComponents( - deviceRGB.CGColorSpace, colors, NULL, numColors); - - path = CGPathCreateWithRoundedRect(bounds, radius, radius, NULL); - CGContextBeginPath(context); - CGContextAddPath(context, path); - CGContextClip(context); - CGContextDrawLinearGradient(context, gradient, bounds.origin, end, 0); - CFRelease(path); - CFRelease(gradient); -} - -/*---------------------------------------------------------------------- - * +++ Arrow Buttons -- + * +++ Single Arrow Buttons -- * - * Used in MenuButtons, SpinButtons, ComboBoxes, ListHeaders. + * Used in ListHeaders and Comboboxes. */ -static void DrawUpDownArrows( - CGContextRef context, - CGRect bounds, - CGFloat inset, - CGFloat size, - CGFloat *rgba) -{ - CGFloat x, y; - - CGContextSetRGBStrokeColor(context, rgba[0], rgba[1], rgba[2], rgba[3]); - CGContextSetLineWidth(context, 1.5); - x = bounds.origin.x + inset; - y = bounds.origin.y + trunc(bounds.size.height / 2); - CGContextBeginPath(context); - CGPoint bottomArrow[3] = - {{x, y + 2}, {x + size / 2, y + 2 + size / 2}, {x + size, y + 2}}; - CGContextAddLines(context, bottomArrow, 3); - CGPoint topArrow[3] = - {{x, y - 2}, {x + size / 2, y - 2 - size / 2}, {x + size, y - 2}}; - CGContextAddLines(context, topArrow, 3); - CGContextStrokePath(context); -} - static void DrawDownArrow( CGContextRef context, CGRect bounds, @@ -520,6 +466,66 @@ static CGFloat darkSelectedGradient[8] = { }; /*---------------------------------------------------------------------- + * GradientFillRoundedRectangle -- + * + * Fill a rounded rectangle with a specified gradient. + */ + +static void GradientFillRoundedRectangle( + CGContextRef context, + CGRect bounds, + CGFloat radius, + CGFloat *colors, + int numColors) +{ + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + CGPathRef path; + CGPoint end = { + bounds.origin.x, + bounds.origin.y + bounds.size.height + }; + CGGradientRef gradient = CGGradientCreateWithColorComponents( + deviceRGB.CGColorSpace, colors, NULL, numColors); + + path = CGPathCreateWithRoundedRect(bounds, radius, radius, NULL); + CGContextBeginPath(context); + CGContextAddPath(context, path); + CGContextClip(context); + CGContextDrawLinearGradient(context, gradient, bounds.origin, end, 0); + CFRelease(path); + CFRelease(gradient); +} + +/*---------------------------------------------------------------------- + * +++ Double Arrow Buttons -- + * + * Used in MenuButtons and SpinButtons. + */ + +static void DrawUpDownArrows( + CGContextRef context, + CGRect bounds, + CGFloat inset, + CGFloat size, + CGFloat *rgba) +{ + CGFloat x, y; + + CGContextSetRGBStrokeColor(context, rgba[0], rgba[1], rgba[2], rgba[3]); + CGContextSetLineWidth(context, 1.5); + x = bounds.origin.x + inset; + y = bounds.origin.y + trunc(bounds.size.height / 2); + CGContextBeginPath(context); + CGPoint bottomArrow[3] = + {{x, y + 2}, {x + size / 2, y + 2 + size / 2}, {x + size, y + 2}}; + CGContextAddLines(context, bottomArrow, 3); + CGPoint topArrow[3] = + {{x, y - 2}, {x + size / 2, y - 2 - size / 2}, {x + size, y - 2}}; + CGContextAddLines(context, topArrow, 3); + CGContextStrokePath(context); +} + +/*---------------------------------------------------------------------- * +++ FillButtonBackground -- * * Fills a rounded rectangle with a transparent black gradient. -- cgit v0.12 From 2922de7aa8539798cbae60aefd0d7a9cfe35283d Mon Sep 17 00:00:00 2001 From: culler Date: Thu, 18 Apr 2019 16:13:18 +0000 Subject: Eliminate the confusing conditional code from ttkMacOSXTheme.c. --- library/ttk/aquaTheme.tcl | 2 +- macosx/tkMacOSXWm.c | 18 +- macosx/ttkMacOSXTheme.c | 586 ++++++++++++++++++++++------------------------ 3 files changed, 295 insertions(+), 311 deletions(-) diff --git a/library/ttk/aquaTheme.tcl b/library/ttk/aquaTheme.tcl index 4b0740f..ffcad2c 100644 --- a/library/ttk/aquaTheme.tcl +++ b/library/ttk/aquaTheme.tcl @@ -62,7 +62,7 @@ namespace eval ttk::theme::aqua { ttk::style configure TNotebook -tabmargins {10 0} -tabposition n ttk::style configure TNotebook -padding {18 8 18 17} ttk::style configure TNotebook.Tab -padding {12 3 12 2} - ttk::style configure TNotebook.Tab -foreground white + ttk::style configure TNotebook.Tab -foreground systemControlTextColor ttk::style map TNotebook.Tab \ -foreground { {background !disabled !selected} systemControlTextColor diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index d6456f2..07230bd 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -5927,15 +5927,15 @@ WmWinAppearance( resultString = appearanceStrings[APPEARANCE_AUTO]; } else if (appearance == NSAppearanceNameAqua) { resultString = appearanceStrings[APPEARANCE_AQUA]; -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 - } else if (appearance == NSAppearanceNameDarkAqua) { - resultString = appearanceStrings[APPEARANCE_DARKAQUA]; -#endif + } else if (@available(macOS 10.14, *)) { + if (appearance == NSAppearanceNameDarkAqua) { + resultString = appearanceStrings[APPEARANCE_DARKAQUA]; + } } else { resultString = "unrecognized"; } #else - resultString = appearanceStrings[APPEARANCE_AQUA]; + resultString = appearanceStrings[APPEARANCE_AQUA]; #endif result = Tcl_NewStringObj(resultString, strlen(resultString)); } @@ -5952,11 +5952,13 @@ WmWinAppearance( switch ((enum appearances) index) { case APPEARANCE_AQUA: win.appearance = [NSAppearance appearanceNamed: - NSAppearanceNameAqua]; + NSAppearanceNameAqua]; break; case APPEARANCE_DARKAQUA: - win.appearance = [NSAppearance appearanceNamed: - NSAppearanceNameDarkAqua]; + if (@available(macOS 10.14, *)) { + win.appearance = [NSAppearance appearanceNamed: + NSAppearanceNameDarkAqua]; + } break; default: win.appearance = nil; diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index 49082b3..ec606ac 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -56,6 +56,64 @@ #define TTK_STATE_LAST_TAB TTK_STATE_USER2 #define TTK_TREEVIEW_STATE_SORTARROW TTK_STATE_USER1 +/* + * Colors and gradients used in Dark Mode. + */ + +static CGFloat darkButtonFace[4] = { + 112.0 / 255, 113.0 / 255, 115.0 / 255, 1.0 +}; +static CGFloat darkPressedBevelFace[4] = { + 135.0 / 255, 136.0 / 255, 138.0 / 255, 1.0 +}; +static CGFloat darkSelectedBevelFace[4] = { + 162.0 / 255, 163.0 / 255, 165.0 / 255, 1.0 +}; +static CGFloat darkDisabledButtonFace[4] = { + 86.0 / 255, 87.0 / 255, 89.0 / 255, 1.0 +}; +static CGFloat darkInactiveSelectedTab[4] = { + 159.0 / 255, 160.0 / 255, 161.0 / 255, 1.0 +}; +static CGFloat darkTabSeparator[4] = {0.0, 0.0, 0.0, 0.25}; +static CGFloat darkTrack[4] = {1.0, 1.0, 1.0, 0.25}; +static CGFloat darkFrameTop[4] = {1.0, 1.0, 1.0, 0.0625}; +static CGFloat darkFrameBottom[4] = {1.0, 1.0, 1.0, 0.125}; +static CGFloat darkFrameAccent[4] = {0.0, 0.0, 0.0, 0.0625}; +static CGFloat darkTopGradient[8] = { + 1.0, 1.0, 1.0, 0.3, + 1.0, 1.0, 1.0, 0.0 +}; +static CGFloat darkBackgroundGradient[8] = { + 0.0, 0.0, 0.0, 0.1, + 0.0, 0.0, 0.0, 0.25 +}; +static CGFloat darkInactiveGradient[8] = { + 89.0 / 255, 90.0 / 255, 93.0 / 255, 1.0, + 119.0 / 255, 120.0 / 255, 122.0 / 255, 1.0 +}; +static CGFloat darkSelectedGradient[8] = { + 23.0 / 255, 111.0 / 255, 232.0 / 255, 1.0, + 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 +#endif + /*---------------------------------------------------------------------- * +++ Utilities. */ @@ -132,7 +190,6 @@ static CGRect NormalizeButtonBounds( return bounds; } -#if MAC_OS_X_VERSION_MIN_REQUIRED > 1080 /*---------------------------------------------------------------------- * +++ Backgrounds * @@ -216,6 +273,148 @@ static void GetBackgroundColor( } } + +/*---------------------------------------------------------------------- + * +++ Single Arrow Buttons -- + * + * Used in ListHeaders and Comboboxes. + */ + +static void DrawDownArrow( + CGContextRef context, + CGRect bounds, + CGFloat inset, + CGFloat size, + CGFloat *rgba) +{ + CGFloat x, y; + + CGContextSetRGBStrokeColor(context, rgba[0], rgba[1], rgba[2], rgba[3]); + CGContextSetLineWidth(context, 1.5); + x = bounds.origin.x + inset; + y = bounds.origin.y + trunc(bounds.size.height / 2); + CGContextBeginPath(context); + CGPoint arrow[3] = { + {x, y - size / 4}, {x + size / 2, y + size / 4}, + {x + size, y - size / 4} + }; + CGContextAddLines(context, arrow, 3); + CGContextStrokePath(context); +} + +static void DrawUpArrow( + CGContextRef context, + CGRect bounds, + CGFloat inset, + CGFloat size, + CGFloat *rgba) +{ + CGFloat x, y; + + CGContextSetRGBStrokeColor(context, rgba[0], rgba[1], rgba[2], rgba[3]); + CGContextSetLineWidth(context, 1.5); + x = bounds.origin.x + inset; + y = bounds.origin.y + trunc(bounds.size.height / 2); + CGContextBeginPath(context); + CGPoint arrow[3] = { + {x, y + size / 4}, {x + size / 2, y - size / 4}, + {x + size, y + size / 4} + }; + CGContextAddLines(context, arrow, 3); + CGContextStrokePath(context); +} + +/*---------------------------------------------------------------------- + * +++ Double Arrow Buttons -- + * + * Used in MenuButtons and SpinButtons. + */ + +static void DrawUpDownArrows( + CGContextRef context, + CGRect bounds, + CGFloat inset, + CGFloat size, + CGFloat *rgba) +{ + CGFloat x, y; + + CGContextSetRGBStrokeColor(context, rgba[0], rgba[1], rgba[2], rgba[3]); + CGContextSetLineWidth(context, 1.5); + x = bounds.origin.x + inset; + y = bounds.origin.y + trunc(bounds.size.height / 2); + CGContextBeginPath(context); + CGPoint bottomArrow[3] = + {{x, y + 2}, {x + size / 2, y + 2 + size / 2}, {x + size, y + 2}}; + CGContextAddLines(context, bottomArrow, 3); + CGPoint topArrow[3] = + {{x, y - 2}, {x + size / 2, y - 2 - size / 2}, {x + size, y - 2}}; + CGContextAddLines(context, topArrow, 3); + CGContextStrokePath(context); +} + + +/*---------------------------------------------------------------------- + * +++ 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) +{ + CGPathRef path; + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + CGGradientRef backgroundGradient = CGGradientCreateWithColorComponents( + deviceRGB.CGColorSpace, darkBackgroundGradient, NULL, 2); + CGPoint backgroundEnd = { + bounds.origin.x, + bounds.origin.y + bounds.size.height + }; + + CGContextBeginPath(context); + path = CGPathCreateWithRoundedRect(bounds, radius, radius, NULL); + CGContextAddPath(context, path); + CGContextClip(context); + CGContextDrawLinearGradient(context, backgroundGradient, + bounds.origin, backgroundEnd, 0); + CFRelease(path); + CFRelease(backgroundGradient); +} + +/*---------------------------------------------------------------------- + * +++ HighlightButtonBorder -- + * + * Accent the top border of a rounded rectangle with a transparent + * white gradient. + */ + +static void HighlightButtonBorder( + CGContextRef context, + CGRect bounds) +{ + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + CGPoint topEnd = {bounds.origin.x, bounds.origin.y + 3}; + CGGradientRef topGradient = CGGradientCreateWithColorComponents( + deviceRGB.CGColorSpace, darkTopGradient, NULL, 2); + + CGContextSaveGState(context); + CGContextBeginPath(context); + CGContextAddArc(context, bounds.origin.x + 4, bounds.origin.y + 4, + 4, PI, 3 * PI / 2, 0); + CGContextAddArc(context, bounds.origin.x + bounds.size.width - 4, + bounds.origin.y + 4, 4, 3 * PI / 2, 0, 0); + CGContextReplacePathWithStrokedPath(context); + CGContextClip(context); + CGContextDrawLinearGradient(context, topGradient, bounds.origin, topEnd, + 0.0); + CGContextRestoreGState(context); + CFRelease(topGradient); +} + /*---------------------------------------------------------------------- * DrawGroupBox -- * @@ -238,7 +437,7 @@ static void DrawGroupBox( bgColor = [NSColor colorWithColorSpace: deviceRGB components: fill count: 4]; CGContextSetFillColorSpace(context, deviceRGB.CGColorSpace); - CGContextSetFillColorWithColor(context, bgColor.CGColor); + CGContextSetFillColorWithColor(context, CGCOLOR(bgColor)); path = CGPathCreateWithRoundedRect(bounds, 4, 4, NULL); CGContextClipToRect(context, bounds); CGContextBeginPath(context); @@ -246,7 +445,7 @@ static void DrawGroupBox( CGContextFillPath(context); borderColor = [NSColor colorWithColorSpace: deviceRGB components: border count: 4]; - CGContextSetFillColorWithColor(context, borderColor.CGColor); + CGContextSetFillColorWithColor(context, CGCOLOR(borderColor)); [borderColor getComponents: fill]; CGContextSetRGBFillColor(context, fill[0], fill[1], fill[2], fill[3]); @@ -271,7 +470,7 @@ static void SolidFillRoundedRectangle( { CGPathRef path; - CGContextSetFillColorWithColor(context, color.CGColor); + CGContextSetFillColorWithColor(context, CGCOLOR(color)); path = CGPathCreateWithRoundedRect(bounds, radius, radius, NULL); CGContextBeginPath(context); CGContextAddPath(context, path); @@ -280,56 +479,6 @@ static void SolidFillRoundedRectangle( } /*---------------------------------------------------------------------- - * +++ Single Arrow Buttons -- - * - * Used in ListHeaders and Comboboxes. - */ - -static void DrawDownArrow( - CGContextRef context, - CGRect bounds, - CGFloat inset, - CGFloat size, - CGFloat *rgba) -{ - CGFloat x, y; - - CGContextSetRGBStrokeColor(context, rgba[0], rgba[1], rgba[2], rgba[3]); - CGContextSetLineWidth(context, 1.5); - x = bounds.origin.x + inset; - y = bounds.origin.y + trunc(bounds.size.height / 2); - CGContextBeginPath(context); - CGPoint arrow[3] = { - {x, y - size / 4}, {x + size / 2, y + size / 4}, - {x + size, y - size / 4} - }; - CGContextAddLines(context, arrow, 3); - CGContextStrokePath(context); -} - -static void DrawUpArrow( - CGContextRef context, - CGRect bounds, - CGFloat inset, - CGFloat size, - CGFloat *rgba) -{ - CGFloat x, y; - - CGContextSetRGBStrokeColor(context, rgba[0], rgba[1], rgba[2], rgba[3]); - CGContextSetLineWidth(context, 1.5); - x = bounds.origin.x + inset; - y = bounds.origin.y + trunc(bounds.size.height / 2); - CGContextBeginPath(context); - CGPoint arrow[3] = { - {x, y + size / 4}, {x + size / 2, y - size / 4}, - {x + size, y + size / 4} - }; - CGContextAddLines(context, arrow, 3); - CGContextStrokePath(context); -} - -/*---------------------------------------------------------------------- * +++ DrawListHeader -- * * This is a standalone drawing procedure which draws column headers for @@ -381,19 +530,19 @@ static void DrawListHeader( CGContextSetFillColorSpace(context, deviceRGB.CGColorSpace); CGContextSetStrokeColorSpace(context, deviceRGB.CGColorSpace); CGContextBeginPath(context); - CGContextSetFillColorWithColor(context, bgColor.CGColor); + CGContextSetFillColorWithColor(context, CGCOLOR(bgColor)); CGContextAddRect(context, bounds); CGContextFillPath(context); strokeColor = [NSColor colorWithColorSpace: deviceRGB components: separatorRGBA count: 4]; - CGContextSetStrokeColorWithColor(context, strokeColor.CGColor); + CGContextSetStrokeColorWithColor(context, CGCOLOR(strokeColor)); CGContextAddLines(context, separator, 2); CGContextStrokePath(context); strokeColor = [NSColor colorWithColorSpace: deviceRGB components: borderRGBA count: 4]; - CGContextSetStrokeColorWithColor(context, strokeColor.CGColor); + CGContextSetStrokeColorWithColor(context, CGCOLOR(strokeColor)); CGContextAddLines(context, top, 2); CGContextStrokePath(context); CGContextAddLines(context, bottom, 2); @@ -412,9 +561,6 @@ static void DrawListHeader( } } -#endif /* MAC_OS_X_VERSION_MIN_REQUIRED > 1080 */ - -#if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 /*---------------------------------------------------------------------- * +++ Drawing procedures for widgets in Apple's "Dark Mode" (10.14 and up). * @@ -422,49 +568,12 @@ static void DrawListHeader( * so to make widgets look "native" we have to provide analogues of the * HITheme drawing functions to be used in DarkAqua. We continue to use * HITheme in Aqua, since it understands earlier versions of the OS. + * + * Drawing the dark widgets requires NSColors that were introduced in OSX + * 10.14, so we make some of these functions be no-ops when building on + * systems older than 10.14. */ -/* - * Colors and gradients used in Dark Mode. - */ - -static CGFloat darkButtonFace[4] = { - 112.0 / 255, 113.0 / 255, 115.0 / 255, 1.0 -}; -static CGFloat darkPressedBevelFace[4] = { - 135.0 / 255, 136.0 / 255, 138.0 / 255, 1.0 -}; -static CGFloat darkSelectedBevelFace[4] = { - 162.0 / 255, 163.0 / 255, 165.0 / 255, 1.0 -}; -static CGFloat darkDisabledButtonFace[4] = { - 86.0 / 255, 87.0 / 255, 89.0 / 255, 1.0 -}; -static CGFloat darkInactiveSelectedTab[4] = { - 159.0 / 255, 160.0 / 255, 161.0 / 255, 1.0 -}; -static CGFloat darkTabSeparator[4] = {0.0, 0.0, 0.0, 0.25}; -static CGFloat darkTrack[4] = {1.0, 1.0, 1.0, 0.25}; -static CGFloat darkFrameTop[4] = {1.0, 1.0, 1.0, 0.0625}; -static CGFloat darkFrameBottom[4] = {1.0, 1.0, 1.0, 0.125}; -static CGFloat darkFrameAccent[4] = {0.0, 0.0, 0.0, 0.0625}; -static CGFloat darkTopGradient[8] = { - 1.0, 1.0, 1.0, 0.3, - 1.0, 1.0, 1.0, 0.0 -}; -static CGFloat darkBackgroundGradient[8] = { - 0.0, 0.0, 0.0, 0.1, - 0.0, 0.0, 0.0, 0.25 -}; -static CGFloat darkInactiveGradient[8] = { - 89.0 / 255, 90.0 / 255, 93.0 / 255, 1.0, - 119.0 / 255, 120.0 / 255, 122.0 / 255, 1.0 -}; -static CGFloat darkSelectedGradient[8] = { - 23.0 / 255, 111.0 / 255, 232.0 / 255, 1.0, - 20.0 / 255, 94.0 / 255, 206.0 / 255, 1.0 -}; - /*---------------------------------------------------------------------- * GradientFillRoundedRectangle -- * @@ -497,95 +606,6 @@ static void GradientFillRoundedRectangle( } /*---------------------------------------------------------------------- - * +++ Double Arrow Buttons -- - * - * Used in MenuButtons and SpinButtons. - */ - -static void DrawUpDownArrows( - CGContextRef context, - CGRect bounds, - CGFloat inset, - CGFloat size, - CGFloat *rgba) -{ - CGFloat x, y; - - CGContextSetRGBStrokeColor(context, rgba[0], rgba[1], rgba[2], rgba[3]); - CGContextSetLineWidth(context, 1.5); - x = bounds.origin.x + inset; - y = bounds.origin.y + trunc(bounds.size.height / 2); - CGContextBeginPath(context); - CGPoint bottomArrow[3] = - {{x, y + 2}, {x + size / 2, y + 2 + size / 2}, {x + size, y + 2}}; - CGContextAddLines(context, bottomArrow, 3); - CGPoint topArrow[3] = - {{x, y - 2}, {x + size / 2, y - 2 - size / 2}, {x + size, y - 2}}; - CGContextAddLines(context, topArrow, 3); - CGContextStrokePath(context); -} - -/*---------------------------------------------------------------------- - * +++ FillButtonBackground -- - * - * Fills a rounded rectangle with a transparent black gradient. - */ - -static void FillButtonBackground( - CGContextRef context, - CGRect bounds, - CGFloat radius) -{ - CGPathRef path; - NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; - CGGradientRef backgroundGradient = CGGradientCreateWithColorComponents( - deviceRGB.CGColorSpace, darkBackgroundGradient, NULL, 2); - CGPoint backgroundEnd = { - bounds.origin.x, - bounds.origin.y + bounds.size.height - }; - - CGContextBeginPath(context); - path = CGPathCreateWithRoundedRect(bounds, radius, radius, NULL); - CGContextAddPath(context, path); - CGContextClip(context); - CGContextDrawLinearGradient(context, backgroundGradient, - bounds.origin, backgroundEnd, 0); - CFRelease(path); - CFRelease(backgroundGradient); -} - -/*---------------------------------------------------------------------- - * +++ HighlightButtonBorder -- - * - * Accent the top border of a rounded rectangle with a transparent - * white gradient. - */ - -static void HighlightButtonBorder( - CGContextRef context, - CGRect bounds) -{ - NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; - CGPoint topEnd = {bounds.origin.x, bounds.origin.y + 3}; - CGGradientRef topGradient = CGGradientCreateWithColorComponents( - deviceRGB.CGColorSpace, darkTopGradient, NULL, 2); - - CGContextSaveGState(context); - CGContextBeginPath(context); - CGContextAddArc(context, bounds.origin.x + 4, bounds.origin.y + 4, - 4, PI, 3 * PI / 2, 0); - CGContextAddArc(context, bounds.origin.x + bounds.size.width - 4, - bounds.origin.y + 4, 4, 3 * PI / 2, 0, 0); - CGContextReplacePathWithStrokedPath(context); - CGContextClip(context); - CGContextDrawLinearGradient(context, topGradient, bounds.origin, topEnd, - 0.0); - CGContextRestoreGState(context); - CFRelease(topGradient); -} - -/*---------------------------------------------------------------------- * +++ DrawDarkButton -- * * This is a standalone drawing procedure which draws PushButtons and @@ -636,7 +656,7 @@ static void DrawDarkButton( * If this is a popup, draw the arrow button. */ - if (kind == kThemePopupButton | kind == kThemeComboBox) { + if ((kind == kThemePopupButton) | (kind == kThemeComboBox)) { CGRect arrowBounds = bounds; arrowBounds.size.width = 16; arrowBounds.origin.x += bounds.size.width - 16; @@ -802,7 +822,7 @@ static void DrawDarkCheckBox( } else { stroke = [NSColor controlTextColor]; } - CGContextSetStrokeColorWithColor(context, stroke.CGColor); + CGContextSetStrokeColorWithColor(context, CGCOLOR(stroke)); } if (state & TTK_STATE_SELECTED) { CGContextSetLineWidth(context, 1.5); @@ -860,7 +880,7 @@ static void DrawDarkRadioButton( } else { fill = [NSColor controlTextColor]; } - CGContextSetFillColorWithColor(context, fill.CGColor); + CGContextSetFillColorWithColor(context, CGCOLOR(fill)); } if (state & TTK_STATE_SELECTED) { CGContextBeginPath(context); @@ -936,7 +956,7 @@ static void DrawDarkTab( stroke = [NSColor colorWithColorSpace: deviceRGB components: darkTabSeparator count: 4]; - CGContextSetStrokeColorWithColor(context, stroke.CGColor); + CGContextSetStrokeColorWithColor(context, CGCOLOR(stroke)); CGContextBeginPath(context); CGContextMoveToPoint(context, originalBounds.origin.x, originalBounds.origin.y + 1); @@ -987,7 +1007,7 @@ static void DrawDarkSeparator( components: fill count:4]; - CGContextSetFillColorWithColor(context, fillColor.CGColor); + CGContextSetFillColorWithColor(context, CGCOLOR(fillColor)); CGContextFillRect(context, bounds); } @@ -1022,19 +1042,19 @@ static void DrawDarkFrame( stroke = [NSColor colorWithColorSpace: deviceRGB components: darkFrameTop count: 4]; - CGContextSetStrokeColorWithColor(context, stroke.CGColor); + CGContextSetStrokeColorWithColor(context, CGCOLOR(stroke)); CGContextAddLines(context, topPart, 4); CGContextStrokePath(context); stroke = [NSColor colorWithColorSpace: deviceRGB components: darkFrameBottom count: 4]; - CGContextSetStrokeColorWithColor(context, stroke.CGColor); + CGContextSetStrokeColorWithColor(context, CGCOLOR(stroke)); CGContextAddLines(context, bottom, 2); CGContextStrokePath(context); stroke = [NSColor colorWithColorSpace: deviceRGB components: darkFrameAccent count: 4]; - CGContextSetStrokeColorWithColor(context, stroke.CGColor); + CGContextSetStrokeColorWithColor(context, CGCOLOR(stroke)); CGContextAddLines(context, accent, 2); CGContextStrokePath(context); CGContextRestoreGState(context); @@ -1072,7 +1092,7 @@ static void DrawDarkListHeader( stroke = [NSColor colorWithColorSpace: deviceRGB components: darkFrameBottom count: 4]; - CGContextSetStrokeColorWithColor(context, stroke.CGColor); + CGContextSetStrokeColorWithColor(context, CGCOLOR(stroke)); CGContextBeginPath(context); CGContextAddLines(context, top, 2); CGContextStrokePath(context); @@ -1095,8 +1115,6 @@ static void DrawDarkListHeader( } } -#endif /* MAC_OS_X_VERSION_MIN_REQUIRED >101300 */ - /*---------------------------------------------------------------------- * +++ Button element: Used for elements drawn with DrawThemeButton. */ @@ -1278,7 +1296,6 @@ static void ButtonElementDraw( BEGIN_DRAWING(d) if (TkMacOSXInDarkMode(tkwin)) { -#if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 switch (info.kind) { case kThemePushButton: case kThemePopupButton: @@ -1297,7 +1314,6 @@ static void ButtonElementDraw( ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); } -#endif /* if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 */ } else { /* @@ -1312,14 +1328,12 @@ static void ButtonElementDraw( * active state. */ -#if MAC_OS_X_VERSION_MIN_REQUIRED > 1080 if (info.kind == kThemePopupButton && (state & TTK_STATE_BACKGROUND)) { CGRect innerBounds = CGRectInset(bounds, 1, 1); NSColor *whiteRGBA = [NSColor whiteColor]; SolidFillRoundedRectangle(dc.context, innerBounds, 4, whiteRGBA); } -#endif /* * A BevelButton with mixed value is drawn borderless, which does make @@ -1445,16 +1459,12 @@ static void TabElementDraw( }; BEGIN_DRAWING(d) -#if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 if (TkMacOSXInDarkMode(tkwin)) { DrawDarkTab(bounds, state, dc.context); } else { ChkErr(HIThemeDrawTab, &bounds, &info, dc.context, HIOrientation, NULL); } -#else - ChkErr(HIThemeDrawTab, &bounds, &info, dc.context, HIOrientation, NULL); -#endif END_DRAWING } @@ -1494,21 +1504,21 @@ static void PaneElementDraw( bounds.origin.y -= kThemeMetricTabFrameOverlap; bounds.size.height += kThemeMetricTabFrameOverlap; BEGIN_DRAWING(d) -#if MAC_OS_X_VERSION_MIN_REQUIRED > 10800 - DrawGroupBox(bounds, dc.context, tkwin); -#else - HIThemeTabPaneDrawInfo info = { - .version = 1, - .state = Ttk_StateTableLookup(ThemeStateTable, state), - .direction = kThemeTabNorth, - .size = kHIThemeTabSizeNormal, - .kind = kHIThemeTabKindNormal, - .adornment = kHIThemeTabPaneAdornmentNormal, - }; - bounds.origin.y -= kThemeMetricTabFrameOverlap; - bounds.size.height += kThemeMetricTabFrameOverlap; - ChkErr(HIThemeDrawTabPane, &bounds, &info, dc.context, HIOrientation); -#endif /* if MAC_OS_X_VERSION_MIN_REQUIRED > 10800 */ + if ([NSApp macMinorVersion] > 8) { + DrawGroupBox(bounds, dc.context, tkwin); + } else { + HIThemeTabPaneDrawInfo info = { + .version = 1, + .state = Ttk_StateTableLookup(ThemeStateTable, state), + .direction = kThemeTabNorth, + .size = kHIThemeTabSizeNormal, + .kind = kHIThemeTabKindNormal, + .adornment = kHIThemeTabPaneAdornmentNormal, + }; + bounds.origin.y -= kThemeMetricTabFrameOverlap; + bounds.size.height += kThemeMetricTabFrameOverlap; + ChkErr(HIThemeDrawTabPane, &bounds, &info, dc.context, HIOrientation); + } END_DRAWING } @@ -1553,16 +1563,16 @@ static void GroupElementDraw( CGRect bounds = BoxToRect(d, b); BEGIN_DRAWING(d) -#if MAC_OS_X_VERSION_MIN_REQUIRED > 10800 - DrawGroupBox(bounds, dc.context, tkwin); -#else - const HIThemeGroupBoxDrawInfo info = { - .version = 0, - .state = Ttk_StateTableLookup(ThemeStateTable, state), - .kind = kHIThemeGroupBoxKindPrimaryOpaque, - }; - ChkErr(HIThemeDrawGroupBox, &bounds, &info, dc.context, HIOrientation); -#endif + if ([NSApp macMinorVersion] > 8) { + DrawGroupBox(bounds, dc.context, tkwin); + } else { + const HIThemeGroupBoxDrawInfo info = { + .version = 0, + .state = Ttk_StateTableLookup(ThemeStateTable, state), + .kind = kHIThemeGroupBoxKindPrimaryOpaque, + }; + ChkErr(HIThemeDrawGroupBox, &bounds, &info, dc.context, HIOrientation); + } END_DRAWING } @@ -1623,7 +1633,6 @@ static void EntryElementDraw( static const char *defaultBG = ENTRY_DEFAULT_BACKGROUND; if (TkMacOSXInDarkMode(tkwin)) { -#if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 BEGIN_DRAWING(d) NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; CGFloat fill[4]; @@ -1631,11 +1640,10 @@ static void EntryElementDraw( background = [NSColor colorWithColorSpace: deviceRGB components: fill count: 4]; - CGContextSetFillColorWithColor(dc.context, background.CGColor); + CGContextSetFillColorWithColor(dc.context, CGCOLOR(background)); CGContextFillRect(dc.context, bounds); DrawDarkFrame(bounds, dc.context, kHIThemeFrameTextFieldSquare); END_DRAWING -#endif /* if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 */ } else { const HIThemeFrameDrawInfo info = { .version = 0, @@ -1666,12 +1674,12 @@ static void EntryElementDraw( } BEGIN_DRAWING(d) if (backgroundPtr == NULL) { - background = [NSColor textBackgroundColor]; -#if MAC_OS_X_VERSION_MIN_REQUIRED > 1080 - CGContextSetFillColorWithColor(dc.context, background.CGColor); -#else - CGContextSetRGBFillColor(dc.context, 1.0, 1.0, 1.0, 1.0); -#endif + if ([NSApp macMinorVersion] > 8) { + background = [NSColor textBackgroundColor]; + CGContextSetFillColorWithColor(dc.context, CGCOLOR(background)); + } else { + CGContextSetRGBFillColor(dc.context, 1.0, 1.0, 1.0, 1.0); + } CGContextFillRect(dc.context, bounds); } ChkErr(HIThemeDrawFrame, &bounds, &info, dc.context, HIOrientation); @@ -1742,21 +1750,17 @@ static void ComboboxElementDraw( BEGIN_DRAWING(d) bounds.origin.y += 1; if (TkMacOSXInDarkMode(tkwin)) { -#if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 - bounds.size.height += 1; + bounds.size.height += 1; DrawDarkButton(bounds, info.kind, state, dc.context); -#endif - } else{ -#if MAC_OS_X_VERSION_MIN_REQUIRED > 1080 - if ((state & TTK_STATE_BACKGROUND) && - !(state & TTK_STATE_DISABLED)) { + } else if ([NSApp macMinorVersion] > 8) { + if ((state & TTK_STATE_BACKGROUND) && + !(state & TTK_STATE_DISABLED)) { NSColor *background = [NSColor textBackgroundColor]; CGRect innerBounds = CGRectInset(bounds, 1, 2); SolidFillRoundedRectangle(dc.context, innerBounds, 4, background); } -#endif - ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, - NULL); + ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, + NULL); } END_DRAWING } @@ -1833,14 +1837,11 @@ static void SpinButtonUpElementDraw( .adornment = kThemeAdornmentNone, }; BEGIN_DRAWING(d) -#if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 if (TkMacOSXInDarkMode(tkwin)) { DrawDarkIncDecButton(bounds, infoState, state, dc.context); - } else -#endif - { + } else { ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, - NULL); + NULL); } END_DRAWING } @@ -1895,14 +1896,11 @@ static void SpinButtonDownElementDraw( }; BEGIN_DRAWING(d) -#if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 if (TkMacOSXInDarkMode(tkwin)) { DrawDarkIncDecButton(bounds, infoState, state, dc.context); - } else -#endif - { + } else { ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, - NULL); + NULL); } END_DRAWING } @@ -2014,7 +2012,6 @@ static void TrackElementDraw( } } BEGIN_DRAWING(d) -#if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 if (TkMacOSXInDarkMode(tkwin)) { CGRect bounds = BoxToRect(d, b); NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; @@ -2028,7 +2025,6 @@ static void TrackElementDraw( } SolidFillRoundedRectangle(dc.context, bounds, 2, trackColor); } -#endif /* if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 */ ChkErr(HIThemeDrawTrack, &info, NULL, dc.context, HIOrientation); END_DRAWING } @@ -2148,7 +2144,6 @@ static void PbarElementDraw( }; BEGIN_DRAWING(d) -#if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 if (TkMacOSXInDarkMode(tkwin)) { CGRect bounds = BoxToRect(d, b); NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; @@ -2162,7 +2157,6 @@ static void PbarElementDraw( } SolidFillRoundedRectangle(dc.context, bounds, 3, trackColor); } -#endif /* if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 */ ChkErr(HIThemeDrawTrack, &info, NULL, dc.context, HIOrientation); END_DRAWING } @@ -2256,9 +2250,7 @@ static void TroughElementDraw( count: 4]; BEGIN_DRAWING(d) if ([NSApp macMinorVersion] > 8) { -#if MAC_OS_X_VERSION_MIN_REQUIRED > 1080 - CGContextSetFillColorWithColor(dc.context, troughColor.CGColor); -#endif + CGContextSetFillColorWithColor(dc.context, CGCOLOR(troughColor)); } else { ChkErr(HIThemeSetFill, kThemeBrushDocumentWindowBackground, NULL, dc.context, HIOrientation); @@ -2323,7 +2315,6 @@ static void ThumbElementDraw( */ if ([NSApp macMinorVersion] > 8) { -#if MAC_OS_X_VERSION_MIN_REQUIRED > 1080 CGRect thumbBounds = BoxToRect(d, b); NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; NSColor *thumbColor; @@ -2347,7 +2338,6 @@ static void ThumbElementDraw( BEGIN_DRAWING(d) SolidFillRoundedRectangle(dc.context, thumbBounds, 4, thumbColor); END_DRAWING -#endif /* if MAC_OS_X_VERSION_MIN_REQUIRED > 1080 */ } else { double thumbSize, trackSize, visibleSize, viewSize; MacDrawable *macWin = (MacDrawable *) Tk_WindowId(tkwin); @@ -2469,16 +2459,12 @@ static void SeparatorElementDraw( }; BEGIN_DRAWING(d) -#if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 if (TkMacOSXInDarkMode(tkwin)) { DrawDarkSeparator(bounds, dc.context, tkwin); } else { ChkErr(HIThemeDrawSeparator, &bounds, &info, dc.context, HIOrientation); } -#else - ChkErr(HIThemeDrawSeparator, &bounds, &info, dc.context, HIOrientation); -#endif END_DRAWING } @@ -2606,28 +2592,28 @@ static void FillElementDraw( { CGRect bounds = BoxToRect(d, b); -#if MAC_OS_X_VERSION_MIN_REQUIRED > 1080 - NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; - NSColor *bgColor; - CGFloat fill[4]; - BEGIN_DRAWING(d) - GetBackgroundColor(dc.context, tkwin, 0, fill); - bgColor = [NSColor colorWithColorSpace: deviceRGB components: fill - count: 4]; - CGContextSetFillColorSpace(dc.context, deviceRGB.CGColorSpace); - CGContextSetFillColorWithColor(dc.context, bgColor.CGColor); - CGContextFillRect(dc.context, bounds); - END_DRAWING -#else /* if MAC_OS_X_VERSION_MIN_REQUIRED > 1080 */ - ThemeBrush brush = (state & TTK_STATE_BACKGROUND) - ? kThemeBrushModelessDialogBackgroundInactive - : kThemeBrushModelessDialogBackgroundActive; - BEGIN_DRAWING(d) - ChkErr(HIThemeSetFill, brush, NULL, dc.context, HIOrientation); - //QDSetPatternOrigin(PatternOrigin(tkwin, d)); - CGContextFillRect(dc.context, bounds); - END_DRAWING -#endif /* if MAC_OS_X_VERSION_MIN_REQUIRED > 1080 */ + if ([NSApp macMinorVersion] > 8) { + NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; + NSColor *bgColor; + CGFloat fill[4]; + BEGIN_DRAWING(d) + GetBackgroundColor(dc.context, tkwin, 0, fill); + bgColor = [NSColor colorWithColorSpace: deviceRGB components: fill + count: 4]; + CGContextSetFillColorSpace(dc.context, deviceRGB.CGColorSpace); + CGContextSetFillColorWithColor(dc.context, CGCOLOR(bgColor)); + CGContextFillRect(dc.context, bounds); + END_DRAWING + } else { + ThemeBrush brush = (state & TTK_STATE_BACKGROUND) + ? kThemeBrushModelessDialogBackgroundInactive + : kThemeBrushModelessDialogBackgroundActive; + BEGIN_DRAWING(d) + ChkErr(HIThemeSetFill, brush, NULL, dc.context, HIOrientation); + //QDSetPatternOrigin(PatternOrigin(tkwin, d)); + CGContextFillRect(dc.context, bounds); + END_DRAWING + } } static void BackgroundElementDraw( @@ -2821,7 +2807,6 @@ static void TreeHeaderElementDraw( BEGIN_DRAWING(d) if ([NSApp macMinorVersion] > 8) { -#if MAC_OS_X_VERSION_MIN_REQUIRED > 1080 /* * Compensate for the padding added in TreeHeaderElementSize, so @@ -2830,13 +2815,10 @@ static void TreeHeaderElementDraw( bounds.origin.y -= 4; if (TkMacOSXInDarkMode(tkwin)) { -#if MAC_OS_X_VERSION_MIN_REQUIRED > 101300 DrawDarkListHeader(bounds, dc.context, tkwin, state); -#endif } else { DrawListHeader(bounds, dc.context, tkwin, state); } -#endif /* MAC_OS_X_VERSION_MIN_REQUIRED > 1080 */ } else { ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); -- cgit v0.12 From 460822733ea7bd7f99696e4a0f90e02467e707a1 Mon Sep 17 00:00:00 2001 From: dkf Date: Fri, 19 Apr 2019 07:16:38 +0000 Subject: Some things must be conditionally compiled. Really. --- macosx/tkMacOSXWm.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index 07230bd..18bbf21 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -5917,26 +5917,21 @@ WmWinAppearance( NSAppearanceName appearance; #else NSString *appearance; -#endif - const char *resultString; +#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 + const char *resultString = "unrecognized"; NSWindow *win = TkMacOSXDrawableWindow(winPtr->window); if (win) { -#if MAC_OS_X_VERSION_MAX_ALLOWED > 1090 appearance = win.appearance.name; if (appearance == nil) { resultString = appearanceStrings[APPEARANCE_AUTO]; } else if (appearance == NSAppearanceNameAqua) { resultString = appearanceStrings[APPEARANCE_AQUA]; - } else if (@available(macOS 10.14, *)) { - if (appearance == NSAppearanceNameDarkAqua) { - resultString = appearanceStrings[APPEARANCE_DARKAQUA]; - } - } else { - resultString = "unrecognized"; +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 + } else if (@available(macOS 10.14, *) && + appearance == NSAppearanceNameDarkAqua) { + resultString = appearanceStrings[APPEARANCE_DARKAQUA]; +#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 } -#else - resultString = appearanceStrings[APPEARANCE_AQUA]; -#endif result = Tcl_NewStringObj(resultString, strlen(resultString)); } if (result == NULL) { @@ -5963,11 +5958,11 @@ WmWinAppearance( default: win.appearance = nil; } -#endif +#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 } Tcl_SetObjResult(interp, result); return TCL_OK; -#endif +#endif // MAC_OS_X_VERSION_MAX_ALLOWED > 1090 return TCL_ERROR; } -- cgit v0.12 From a4dc7397e54ece7f5b18a85917c0d30b6bf372f0 Mon Sep 17 00:00:00 2001 From: culler Date: Fri, 19 Apr 2019 14:40:07 +0000 Subject: Fine tune aqua ttk colors. Fix availability errors introduced in 6cafd6f7. --- library/ttk/aquaTheme.tcl | 34 +++++++--------------------- macosx/tkMacOSXColor.c | 57 ++++++++++++++++++++++++++++++----------------- macosx/tkMacOSXWm.c | 16 +++++++------ 3 files changed, 54 insertions(+), 53 deletions(-) diff --git a/library/ttk/aquaTheme.tcl b/library/ttk/aquaTheme.tcl index ffcad2c..92689d8 100644 --- a/library/ttk/aquaTheme.tcl +++ b/library/ttk/aquaTheme.tcl @@ -15,43 +15,26 @@ namespace eval ttk::theme::aqua { -insertwidth 1 ttk::style map . \ - -foreground { - disabled systemLabelColor + -foreground { + disabled systemDisabledControlTextColor background systemLabelColor} \ -selectbackground { - background systemHighlight - !focus systemHighlightSecondary} \ + background systemSelectedTextBackgroundColor + !focus systemSelectedTextBackgroundColor} \ -selectforeground { - background systemLabelColor - !focus systemDialogActiveText} + background systemSelectedTextColor + !focus systemSelectedTextColor} # Button ttk::style configure TButton -anchor center -width -6\ -foreground systemControlTextColor - ttk::style map TButton \ - -foreground { - disabled systemDisabledControlTextColor} - ttk::style map TCheckbutton \ - -foreground { - disabled systemDisabledControlTextColor} - ttk::style map TRadiobutton \ - -foreground { - disabled systemDisabledControlTextColor} ttk::style configure TMenubutton -anchor center -padding {2 0 0 2} ttk::style configure Toolbutton -anchor center - ttk::style map Toolbutton \ - -foreground { - disabled systemDisabledControlTextColor - } # Entry ttk::style configure TEntry \ -foreground systemTextColor \ -background systemTextBackgroundColor \ - -selectforeground systemSelectedTextColor - ttk::style map TEntry \ - -foreground { - disabled systemDisabledControlTextColor} # Workaround for #1100117: # Actually, on Aqua we probably shouldn't stipple images in @@ -65,10 +48,9 @@ namespace eval ttk::theme::aqua { ttk::style configure TNotebook.Tab -foreground systemControlTextColor ttk::style map TNotebook.Tab \ -foreground { - {background !disabled !selected} systemControlTextColor - {background selected} systemTextBackgroundColor + background systemControlTextColor disabled systemDisabledControlTextColor - !selected systemControlTextColor} + selected systemSelectedTabTextColor} # Combobox: ttk::style configure TCombobox \ diff --git a/macosx/tkMacOSXColor.c b/macosx/tkMacOSXColor.c index e89d42d..8372ccc 100644 --- a/macosx/tkMacOSXColor.c +++ b/macosx/tkMacOSXColor.c @@ -207,13 +207,14 @@ static const struct SystemColorMapEntry systemColorMap[] = { { "LabelColor", semantic, 2 }, /* 176 */ { "ControlTextColor", semantic, 3 }, /* 177 */ { "DisabledControlTextColor", semantic, 4 }, /* 178 */ - { "TextBackgroundColor", semantic, 5 }, /* 179 */ - { "SelectedTextBackgroundColor", semantic, 6 }, /* 180 */ - { "ControlAccentColor", semantic, 7 }, /* 181 */ + { "SelectedTabTextColor", semantic, 5 }, /* 179 */ + { "TextBackgroundColor", semantic, 6 }, /* 180 */ + { "SelectedTextBackgroundColor", semantic, 7 }, /* 181 */ + { "ControlAccentColor", semantic, 8 }, /* 182 */ { NULL, 0, 0 } }; #define FIRST_SEMANTIC_COLOR 166 -#define MAX_PIXELCODE 181 +#define MAX_PIXELCODE 182 /* *---------------------------------------------------------------------- @@ -349,31 +350,47 @@ SetCGColorComponents( deviceRGB]; break; case 5: + if ([NSApp macMinorVersion] > 6) { + color = [[NSColor whiteColor] colorUsingColorSpace: + deviceRGB]; + } else { + color = [[NSColor blackColor] colorUsingColorSpace: + deviceRGB]; + } + break; + case 6: color = [[NSColor textBackgroundColor] colorUsingColorSpace: deviceRGB]; break; - case 6: + case 7: color = [[NSColor selectedTextBackgroundColor] colorUsingColorSpace: deviceRGB]; break; - case 7: -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 + case 8: if ([NSApp macMinorVersion] >= 14) { - color = [[NSColor controlAccentColor] colorUsingColorSpace: - deviceRGB]; - break; - } +#if MAC_OS_X_VERSION_MAX_ALLOWED > 1090 + if (@available(macOS 10.14, *)) { + color = [[NSColor controlAccentColor] colorUsingColorSpace: + deviceRGB]; + break; + } else { + color = [NSColor colorWithColorSpace: deviceRGB + components: blueAccentRGBA + count: 4]; + } #endif - colorVariant = [[NSUserDefaults standardUserDefaults] - integerForKey:@"AppleAquaColorVariant"]; - if (colorVariant == 6) { - color = [NSColor colorWithColorSpace: deviceRGB - components: graphiteAccentRGBA - count: 4]; } else { - color = [NSColor colorWithColorSpace: deviceRGB - components: blueAccentRGBA - count: 4]; + colorVariant = [[NSUserDefaults standardUserDefaults] + integerForKey:@"AppleAquaColorVariant"]; + if (colorVariant == 6) { + color = [NSColor colorWithColorSpace: deviceRGB + components: graphiteAccentRGBA + count: 4]; + } else { + color = [NSColor colorWithColorSpace: deviceRGB + components: blueAccentRGBA + count: 4]; + } } break; default: diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index 18bbf21..8c30fe7 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -5927,11 +5927,12 @@ WmWinAppearance( } else if (appearance == NSAppearanceNameAqua) { resultString = appearanceStrings[APPEARANCE_AQUA]; #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 - } else if (@available(macOS 10.14, *) && - appearance == NSAppearanceNameDarkAqua) { - resultString = appearanceStrings[APPEARANCE_DARKAQUA]; -#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 + } else if (@available(macOS 10.14, *)) { + if (appearance == NSAppearanceNameDarkAqua) { + resultString = appearanceStrings[APPEARANCE_DARKAQUA]; + } } +#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 result = Tcl_NewStringObj(resultString, strlen(resultString)); } if (result == NULL) { @@ -5943,27 +5944,28 @@ WmWinAppearance( sizeof(char *), "appearancename", 0, &index) != TCL_OK) { return TCL_ERROR; } -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 switch ((enum appearances) index) { case APPEARANCE_AQUA: win.appearance = [NSAppearance appearanceNamed: NSAppearanceNameAqua]; break; case APPEARANCE_DARKAQUA: +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 if (@available(macOS 10.14, *)) { win.appearance = [NSAppearance appearanceNamed: NSAppearanceNameDarkAqua]; } +#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 break; default: win.appearance = nil; } -#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 } Tcl_SetObjResult(interp, result); return TCL_OK; -#endif // MAC_OS_X_VERSION_MAX_ALLOWED > 1090 +#else // MAC_OS_X_VERSION_MAX_ALLOWED > 1090 return TCL_ERROR; +#endif } /* -- cgit v0.12 From 2700604e2ded309b8fa397c011e6df5ac33b9682 Mon Sep 17 00:00:00 2001 From: culler Date: Fri, 19 Apr 2019 19:03:00 +0000 Subject: Put the brace outside the #endif where it belongs. --- macosx/tkMacOSXWm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index 8c30fe7..e68f1d5 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -5931,8 +5931,8 @@ WmWinAppearance( if (appearance == NSAppearanceNameDarkAqua) { resultString = appearanceStrings[APPEARANCE_DARKAQUA]; } - } #endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 + } result = Tcl_NewStringObj(resultString, strlen(resultString)); } if (result == NULL) { -- cgit v0.12 From ce9b2bd67a12a2007fa58b7de76f4c36a6296b2c Mon Sep 17 00:00:00 2001 From: fvogel Date: Fri, 19 Apr 2019 21:01:36 +0000 Subject: Fix [6286fda787]: unix: checkbutton -selectcolor not restored properly when changed in -command. Patch by ralfixx --- library/button.tcl | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/library/button.tcl b/library/button.tcl index 80d8bf9..88e26e5 100644 --- a/library/button.tcl +++ b/library/button.tcl @@ -748,11 +748,15 @@ proc ::tk::CheckLeave {w} { $w configure -state normal } - # Restore the original button "selected" color; assume that the user - # wasn't monkeying around with things too much. + # Restore the original button "selected" color; but only if the user + # has not changed it in the meantime. if {![$w cget -indicatoron] && [info exist Priv($w,selectcolor)]} { - $w configure -selectcolor $Priv($w,selectcolor) + if {[$w cget -selectcolor] eq $Priv($w,selectcolor) + || ([info exist Priv($w,aselectcolor)] && + [$w cget -selectcolor] eq $Priv($w,aselectcolor))} { + $w configure -selectcolor $Priv($w,selectcolor) + } } unset -nocomplain Priv($w,selectcolor) Priv($w,aselectcolor) -- cgit v0.12 From 8c0226fa4dd91e69502960bebbee4a44bba73fca Mon Sep 17 00:00:00 2001 From: culler Date: Sat, 20 Apr 2019 03:40:21 +0000 Subject: On macOS, squelch more availability warnings. Fix a hard to find bug [40ada90762] which could sometimes cause a segfault. --- macosx/tkMacOSXButton.c | 5 +++- macosx/tkMacOSXColor.c | 64 +++++++++++++++++++++++++------------------------ tests/frame.test | 7 +++++- 3 files changed, 43 insertions(+), 33 deletions(-) diff --git a/macosx/tkMacOSXButton.c b/macosx/tkMacOSXButton.c index ac3c122..1b40e5e 100644 --- a/macosx/tkMacOSXButton.c +++ b/macosx/tkMacOSXButton.c @@ -185,7 +185,10 @@ TkpDisplayButton( Pixmap pixmap; DrawParams* dpPtr = &macButtonPtr->drawParams; int needhighlight = 0; - + + if (butPtr->flags & BUTTON_DELETED) { + return; + } butPtr->flags &= ~REDRAW_PENDING; if ((butPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) { return; diff --git a/macosx/tkMacOSXColor.c b/macosx/tkMacOSXColor.c index 8372ccc..cb3bde3 100644 --- a/macosx/tkMacOSXColor.c +++ b/macosx/tkMacOSXColor.c @@ -265,9 +265,9 @@ GetEntryFromPixelCode( */ static NSColorSpace* deviceRGB = NULL; -static CGFloat blueAccentRGBA[4] = {0, 122.0/255, 1.0, 1.0}; -static CGFloat graphiteAccentRGBA[4] = {152.0/255, 152.0/255, 152.0/255, 1.0}; -static CGFloat windowBackground[4] = {236.0/255, 236.0/255, 236.0/255, 1.0}; +static CGFloat blueAccentRGBA[4] = {0, 122.0 / 255, 1.0, 1.0}; +static CGFloat windowBackground[4] = + {236.0 / 255, 236.0 / 255, 236.0 / 255, 1.0}; static OSStatus SetCGColorComponents( @@ -278,7 +278,11 @@ SetCGColorComponents( OSStatus err = noErr; NSColor *bgColor, *color; CGFloat rgba[4] = {0, 0, 0, 1}; - NSInteger colorVariant = 1; +#if MAC_OS_X_VERSION_MAX_ALLOWED < 101400 + NSInteger colorVariant; + static CGFloat graphiteAccentRGBA[4] = + {152.0 / 255, 152.0 / 255, 152.0 / 255, 1.0}; +#endif if (!deviceRGB) { deviceRGB = [NSColorSpace deviceRGBColorSpace]; @@ -318,11 +322,11 @@ 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; @@ -335,7 +339,7 @@ SetCGColorComponents( color = [[NSColor selectedTextColor] colorUsingColorSpace: deviceRGB]; break; case 2: -#if MAC_OS_X_VERSION_MIN_REQUIRED > 101000 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000 color = [[NSColor labelColor] colorUsingColorSpace: deviceRGB]; #else color = [[NSColor textColor] colorUsingColorSpace: deviceRGB]; @@ -367,31 +371,28 @@ SetCGColorComponents( deviceRGB]; break; case 8: - if ([NSApp macMinorVersion] >= 14) { -#if MAC_OS_X_VERSION_MAX_ALLOWED > 1090 - if (@available(macOS 10.14, *)) { - color = [[NSColor controlAccentColor] colorUsingColorSpace: - deviceRGB]; - break; - } else { - color = [NSColor colorWithColorSpace: deviceRGB - components: blueAccentRGBA - count: 4]; - } -#endif +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 + if (@available(macOS 10.14, *)) { + color = [[NSColor controlAccentColor] colorUsingColorSpace: + deviceRGB]; } else { - colorVariant = [[NSUserDefaults standardUserDefaults] - integerForKey:@"AppleAquaColorVariant"]; - if (colorVariant == 6) { - color = [NSColor colorWithColorSpace: deviceRGB - components: graphiteAccentRGBA - count: 4]; - } else { - color = [NSColor colorWithColorSpace: deviceRGB - components: blueAccentRGBA - count: 4]; - } + color = [NSColor colorWithColorSpace: deviceRGB + components: blueAccentRGBA + count: 4]; } +#else + colorVariant = [[NSUserDefaults standardUserDefaults] + integerForKey:@"AppleAquaColorVariant"]; + if (colorVariant == 6) { + color = [NSColor colorWithColorSpace: deviceRGB + components: graphiteAccentRGBA + count: 4]; + } else { + color = [NSColor colorWithColorSpace: deviceRGB + components: blueAccentRGBA + count: 4]; + } +#endif break; default: #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000 @@ -674,7 +675,7 @@ TkMacOSXSetColorInContext( struct SystemColorMapEntry entry; CGRect rect; int code = (pixel >> 24) & 0xff; - HIThemeBackgroundDrawInfo info = { 0, kThemeStateActive, entry.value }; + HIThemeBackgroundDrawInfo info = {0, kThemeStateActive, 0};; static CGColorSpaceRef deviceRGBSpace = NULL; if (!deviceRGBSpace) { @@ -698,6 +699,7 @@ TkMacOSXSetColorInContext( kHIThemeOrientationNormal); break; case HIBackground: + info.kind = entry.value; rect = CGContextGetClipBoundingBox(context); err = ChkErr(HIThemeApplyBackground, &rect, &info, context, kHIThemeOrientationNormal); diff --git a/tests/frame.test b/tests/frame.test index 45a91b3..e374326 100644 --- a/tests/frame.test +++ b/tests/frame.test @@ -664,11 +664,16 @@ test frame-3.9 {TkCreateFrame procedure, -use option} -constraints { wm geometry .t +0+0 toplevel .x -width 140 -height 300 -use [winfo id .t] -bg green tkwait visibility .x - update idletasks list [expr {[winfo rootx .x] - [winfo rootx .t]}] \ [expr {[winfo rooty .x] - [winfo rooty .t]}] \ [winfo width .t] [winfo height .t] } -cleanup { +# This call to update idletasks was added to prevent a crash that was +# observed on OSX 10.12 (Sierra) only. Any change, such as using the +# Development version to make debugging symbols available, adding a print +# statement, or calling update idletasks here, would make the test pass +# with no segfault. + update idletasks deleteWindows } -result {0 0 140 300} test frame-3.10 {TkCreateFrame procedure, -use option} -constraints { -- cgit v0.12 From e2d80191d706d8c9efed09c06b55ba96f48fdc7f Mon Sep 17 00:00:00 2001 From: culler Date: Sat, 20 Apr 2019 15:03:00 +0000 Subject: On macOS, edit comments and documentation; fix compiler warnings. --- doc/colors.n | 1 + macosx/README | 6 ++++-- macosx/tkMacOSXInit.c | 2 +- macosx/tkMacOSXTest.c | 12 ++++++++++-- macosx/tkMacOSXXStubs.c | 2 +- macosx/ttkMacOSXTheme.c | 42 +++++++++++++++++++++++------------------- 6 files changed, 40 insertions(+), 25 deletions(-) diff --git a/doc/colors.n b/doc/colors.n index 41d6ed0..7a7b5b3 100644 --- a/doc/colors.n +++ b/doc/colors.n @@ -901,6 +901,7 @@ systemScrollBarDelimiterActive systemScrollBarDelimiterInactive systemSecondaryGroupBoxBackground systemSecondaryHighlightColor +systemSelectedTabTextColor systemSheetBackground systemSheetBackgroundOpaque systemSheetBackgroundTransparent diff --git a/macosx/README b/macosx/README index 37225c8..d7333e8 100644 --- a/macosx/README +++ b/macosx/README @@ -303,7 +303,7 @@ 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 +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 @@ -311,7 +311,9 @@ 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. +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 diff --git a/macosx/tkMacOSXInit.c b/macosx/tkMacOSXInit.c index e90e97b..89d6983 100644 --- a/macosx/tkMacOSXInit.c +++ b/macosx/tkMacOSXInit.c @@ -151,7 +151,7 @@ static char scriptPath[PATH_MAX + 1] = ""; * Record the OS version we are running on. */ int minorVersion; -#if MAC_OS_X_VERSION_MIN_REQUIRED < 101000 +#if MAC_OS_X_VERSION_MAX_ALLOWED < 101000 Gestalt(gestaltSystemVersionMinor, (SInt32*)&minorVersion); #else NSOperatingSystemVersion systemVersion; diff --git a/macosx/tkMacOSXTest.c b/macosx/tkMacOSXTest.c index b7923b0..9192fd6 100644 --- a/macosx/tkMacOSXTest.c +++ b/macosx/tkMacOSXTest.c @@ -18,8 +18,11 @@ * 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[]); + int objc, Tcl_Obj *const objv[]); +#endif + /* *---------------------------------------------------------------------- @@ -46,8 +49,10 @@ TkplatformtestInit( * 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; } @@ -57,7 +62,8 @@ TkplatformtestInit( * * DebuggerObjCmd -- * - * This procedure simply calls the low level debugger. + * This procedure simply calls the low level debugger, which was + * deprecated in OSX 10.8. * * Results: * A standard Tcl result. @@ -68,6 +74,7 @@ TkplatformtestInit( *---------------------------------------------------------------------- */ +#if MAC_OS_X_VERSION_MAX_ALLOWED < 1080 static int DebuggerObjCmd( ClientData clientData, /* Not used. */ @@ -78,6 +85,7 @@ DebuggerObjCmd( Debugger(); return TCL_OK; } +#endif /* *---------------------------------------------------------------------- diff --git a/macosx/tkMacOSXXStubs.c b/macosx/tkMacOSXXStubs.c index 448736e..13cba84 100644 --- a/macosx/tkMacOSXXStubs.c +++ b/macosx/tkMacOSXXStubs.c @@ -178,7 +178,7 @@ TkpOpenDisplay( { int major, minor, patch; -#if MAC_OS_X_VERSION_MIN_REQUIRED < 101000 +#if MAC_OS_X_VERSION_MAX_ALLOWED < 101000 Gestalt(gestaltSystemVersionMajor, (SInt32*)&major); Gestalt(gestaltSystemVersionMinor, (SInt32*)&minor); Gestalt(gestaltSystemVersionBugFix, (SInt32*)&patch); diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index ec606ac..82b94f3 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -101,10 +101,9 @@ static CGFloat darkSelectedGradient[8] = { * 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 + * 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 @@ -215,10 +214,10 @@ 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 + * 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. */ @@ -358,7 +357,7 @@ static void DrawUpDownArrows( * +++ FillButtonBackground -- * * Fills a rounded rectangle with a transparent black gradient. - * This is a no-op if not building on 10.9 or higher. + * This is a no-op if building on 10.8 or older. */ static void FillButtonBackground( @@ -419,7 +418,8 @@ static void HighlightButtonBorder( * DrawGroupBox -- * * This is a standalone drawing procedure which draws the contrasting - * rounded rectangular box for LabelFrames and Notebook panes. + * rounded rectangular box for LabelFrames and Notebook panes used in + * more recent versions of macOS. */ static void DrawGroupBox( @@ -1225,8 +1225,7 @@ static void ButtonElementMinSize( /* * 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 + * text to be left justified, no matter what -anchor setting is used in * the style. */ @@ -2300,16 +2299,16 @@ static void ThumbElementDraw( /* * 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 + * 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 + * 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 + * 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. */ @@ -2554,7 +2553,7 @@ static Ttk_ElementSpec SizegripElementSpec = { * 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 + * 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. * @@ -2699,6 +2698,7 @@ static Ttk_ElementOptionSpec FieldElementOptions[] = { Tk_Offset(FieldElement, backgroundObj), "white"}, {NULL, 0, 0, NULL} }; + static void FieldElementDraw( void *clientData, void *elementRecord, @@ -2727,7 +2727,9 @@ static Ttk_ElementSpec FieldElementSpec = { /*---------------------------------------------------------------------- * +++ Treeview headers -- * - * Redefine the header to use a kThemeListHeaderButton. + * 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[] = { @@ -2735,6 +2737,7 @@ static Ttk_StateTable TreeHeaderValueTable[] = { {kThemeButtonOn, TTK_STATE_SELECTED}, {kThemeButtonOff, 0} }; + static Ttk_StateTable TreeHeaderAdornmentTable[] = { {kThemeAdornmentHeaderButtonSortUp, TTK_STATE_ALTERNATE | TTK_TREEVIEW_STATE_SORTARROW}, @@ -2745,6 +2748,7 @@ static Ttk_StateTable TreeHeaderAdornmentTable[] = { {kThemeAdornmentFocus, TTK_STATE_FOCUS}, {kThemeAdornmentNone, 0} }; + static void TreeAreaElementSize ( void *clientData, void *elementRecord, -- cgit v0.12 From f43a38c216438267b70e6141ecb1b6fd5194fd9c Mon Sep 17 00:00:00 2001 From: fvogel Date: Mon, 22 Apr 2019 22:09:50 +0000 Subject: Fix [2513186fff] and [f9343d8f72]: ttk::entry xview sub-command forces use of update idletasks. Thanks to cjmcdonald. --- generic/ttk/ttkEntry.c | 7 +++++++ library/ttk/entry.tcl | 1 - 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/generic/ttk/ttkEntry.c b/generic/ttk/ttkEntry.c index ebc485e..0f1707b 100644 --- a/generic/ttk/ttkEntry.c +++ b/generic/ttk/ttkEntry.c @@ -1651,6 +1651,13 @@ static int EntryXViewCommand( void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Entry *entryPtr = recordPtr; + + /* + * Ensure that the scroll info is up-to-date before a scrolling command. + */ + + EntryDoLayout(recordPtr); + if (objc == 3) { int newFirst; if (EntryIndex(interp, entryPtr, objv[2], &newFirst) != TCL_OK) { diff --git a/library/ttk/entry.tcl b/library/ttk/entry.tcl index c123bc9..e9f249c 100644 --- a/library/ttk/entry.tcl +++ b/library/ttk/entry.tcl @@ -211,7 +211,6 @@ proc ttk::entry::ClosestGap {w x} { ## See $index -- Make sure that the character at $index is visible. # proc ttk::entry::See {w {index insert}} { - update idletasks ;# ensure scroll data up-to-date set c [$w index $index] # @@@ OR: check [$w index left] / [$w index right] if {$c < [$w index @0] || $c >= [$w index @[winfo width $w]]} { -- cgit v0.12 From 40eb1fce5bbde4a49fd24fa146e34c292b729131 Mon Sep 17 00:00:00 2001 From: culler Date: Wed, 24 Apr 2019 15:52:16 +0000 Subject: Fix bug [4d2e8d4d5c]: Aqua notebooks sometimes do not draw a new pane immediately --- macosx/tkMacOSXKeyEvent.c | 10 ++++++++++ macosx/tkMacOSXPrivate.h | 6 ++++++ macosx/tkMacOSXSubwindows.c | 39 ++++++++++++++++++++------------------- macosx/tkMacOSXWindowEvent.c | 39 +++++++++++++++++++++++++++++++++++++-- 4 files changed, 73 insertions(+), 21 deletions(-) diff --git a/macosx/tkMacOSXKeyEvent.c b/macosx/tkMacOSXKeyEvent.c index 6cf3783..8691ce2 100644 --- a/macosx/tkMacOSXKeyEvent.c +++ b/macosx/tkMacOSXKeyEvent.c @@ -257,6 +257,14 @@ unsigned short releaseCode; @implementation TKContentView + +-(id)init { + if (self = [super init]) { + _needsRedisplay = NO; + } + return self; +} + /* implementation (called through interpretKeyEvents:]). */ /* : called when done composing; @@ -449,6 +457,8 @@ unsigned short releaseCode; return str; } /* End impl. */ + +@synthesize needsRedisplay = _needsRedisplay; @end diff --git a/macosx/tkMacOSXPrivate.h b/macosx/tkMacOSXPrivate.h index 105317d..fe913ec 100644 --- a/macosx/tkMacOSXPrivate.h +++ b/macosx/tkMacOSXPrivate.h @@ -332,8 +332,14 @@ VISIBILITY_HIDDEN VISIBILITY_HIDDEN @interface TKContentView : NSView { +@private NSString *privateWorkingText; +#ifdef __i386__ + /* The Objective C runtime used on i386 requires this. */ + Bool _needsRedisplay; +#endif } +@property Bool needsRedisplay; @end @interface TKContentView(TKKeyEvent) diff --git a/macosx/tkMacOSXSubwindows.c b/macosx/tkMacOSXSubwindows.c index 06aaa9d..853abc2 100644 --- a/macosx/tkMacOSXSubwindows.c +++ b/macosx/tkMacOSXSubwindows.c @@ -130,6 +130,8 @@ XMapWindow( Window window) /* Window. */ { MacDrawable *macWin = (MacDrawable *) window; + TkWindow *winPtr = macWin->winPtr; + NSWindow *win = TkMacOSXDrawableWindow(window); XEvent event; /* @@ -145,10 +147,9 @@ XMapWindow( } display->request++; - macWin->winPtr->flags |= TK_MAPPED; - if (Tk_IsTopLevel(macWin->winPtr)) { - if (!Tk_IsEmbedded(macWin->winPtr)) { - NSWindow *win = TkMacOSXDrawableWindow(window); + winPtr->flags |= TK_MAPPED; + if (Tk_IsTopLevel(winPtr)) { + if (!Tk_IsEmbedded(winPtr)) { /* * We want to activate Tk when a toplevel is mapped but we must not @@ -158,7 +159,7 @@ XMapWindow( * bar unresponsive. */ - TkMacOSXApplyWindowAttributes(macWin->winPtr, win); + TkMacOSXApplyWindowAttributes(winPtr, win); [win setExcludedFromWindowsMenu:NO]; [NSApp activateIgnoringOtherApps:NO]; [[win contentView] setNeedsDisplay:YES]; @@ -177,18 +178,18 @@ XMapWindow( while (Tcl_DoOneEvent(TCL_WINDOW_EVENTS| TCL_DONT_WAIT)) {} [NSApp _unlockAutoreleasePool]; } else { + TkWindow *contWinPtr = TkpGetOtherWindow(winPtr); /* * Rebuild the container's clipping region and display * the window. */ - TkWindow *contWinPtr = TkpGetOtherWindow(macWin->winPtr); - TkMacOSXInvalClipRgns((Tk_Window) contWinPtr); TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW); } - TkMacOSXInvalClipRgns((Tk_Window) macWin->winPtr); + + TkMacOSXInvalClipRgns((Tk_Window) winPtr); /* * We only need to send the MapNotify event for toplevel windows. @@ -201,15 +202,21 @@ XMapWindow( event.xmap.window = window; event.xmap.type = MapNotify; event.xmap.event = window; - event.xmap.override_redirect = macWin->winPtr->atts.override_redirect; + event.xmap.override_redirect = winPtr->atts.override_redirect; Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); } else { + /* - * Rebuild the parent's clipping region and display the window. + * For non-toplevel windows, rebuild the parent's clipping region + * and redisplay the window. */ - TkMacOSXInvalClipRgns((Tk_Window) macWin->winPtr->parentPtr); - TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW); + TkMacOSXInvalClipRgns((Tk_Window) winPtr->parentPtr); + if ([NSApp isDrawing]) { + [[win contentView] setNeedsRedisplay:YES]; + } else { + [[win contentView] setNeedsDisplay:YES]; + } } /* @@ -220,13 +227,7 @@ XMapWindow( event.xany.display = display; event.xvisibility.type = VisibilityNotify; event.xvisibility.state = VisibilityUnobscured; - NotifyVisibility(macWin->winPtr, &event); - - /* - * This seems to be needed to ensure that all subwindows get displayed. - */ - - GenerateConfigureNotify(macWin->winPtr, 1); + NotifyVisibility(winPtr, &event); } /* diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c index 6b80761..327132c 100644 --- a/macosx/tkMacOSXWindowEvent.c +++ b/macosx/tkMacOSXWindowEvent.c @@ -856,7 +856,10 @@ Tk_MacOSXIsAppInFront(void) * */ -/*Restrict event processing to Expose events.*/ +/* + * Restrict event processing to Expose events. + */ + static Tk_RestrictAction ExposeRestrictProc( ClientData arg, @@ -866,7 +869,10 @@ ExposeRestrictProc( ? TK_PROCESS_EVENT : TK_DEFER_EVENT); } -/*Restrict event processing to ConfigureNotify events.*/ +/* + * Restrict event processing to ConfigureNotify events. + */ + static Tk_RestrictAction ConfigureRestrictProc( ClientData arg, @@ -875,6 +881,30 @@ ConfigureRestrictProc( return (eventPtr->type==ConfigureNotify ? TK_PROCESS_EVENT : TK_DEFER_EVENT); } +/* + * If a window gets mapped inside the drawRect method, this will be run as an + * idle task, after drawRect returns, to clean up the mess. + */ + +static void +RedisplayView( + ClientData clientdata) +{ + NSView *view = (NSView *) clientdata; + + /* + * Make sure that we are not trying to displaying a view that no longer + * exists. + */ + + for (NSWindow *w in [NSApp orderedWindows]) { + if ([w contentView] == view) { + [view setNeedsDisplay:YES]; + break; + } + } +} + @implementation TKContentView(TKWindowEvent) - (void) drawRect: (NSRect) rect @@ -921,6 +951,11 @@ ConfigureRestrictProc( CFRelease(drawShape); [NSApp setIsDrawing: NO]; + if ([self needsRedisplay]) { + [self setNeedsRedisplay:NO]; + Tcl_DoWhenIdle(RedisplayView, self); + } + #ifdef TK_MAC_DEBUG_DRAWING fprintf(stderr, "drawRect: done.\n"); #endif -- cgit v0.12 From 70af19ebc9a255f667aa2a143a8f57fe2576a2e4 Mon Sep 17 00:00:00 2001 From: culler Date: Thu, 25 Apr 2019 18:16:49 +0000 Subject: Fix textWind.test: make sure that the test window is mapped before running tests (needed on macOS). --- tests/textWind.test | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/textWind.test b/tests/textWind.test index e189663..788c245 100644 --- a/tests/textWind.test +++ b/tests/textWind.test @@ -39,6 +39,11 @@ wm minsize . 1 1 wm positionfrom . user wm deiconify . +# This update is needed on MacOS to make sure that the window is mapped +# when the tests begin. + +update + set bw [.t cget -borderwidth] set px [.t cget -padx] set py [.t cget -pady] -- cgit v0.12 From 35782df88f307dee00acfea69fa902c13291bc14 Mon Sep 17 00:00:00 2001 From: fvogel Date: Fri, 26 Apr 2019 21:11:42 +0000 Subject: Optimize the fix: the layout calculation is only needed if the display is out of date. --- generic/ttk/ttkEntry.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/generic/ttk/ttkEntry.c b/generic/ttk/ttkEntry.c index 0f1707b..148bc47 100644 --- a/generic/ttk/ttkEntry.c +++ b/generic/ttk/ttkEntry.c @@ -1651,12 +1651,15 @@ static int EntryXViewCommand( void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Entry *entryPtr = recordPtr; + WidgetCore *corePtr = recordPtr; /* * Ensure that the scroll info is up-to-date before a scrolling command. */ - EntryDoLayout(recordPtr); + if (corePtr->flags & REDISPLAY_PENDING) { + EntryDoLayout(recordPtr); + } if (objc == 3) { int newFirst; -- cgit v0.12 From c31fa24c60b3a3c8a9d5687f627f660d3649fdc0 Mon Sep 17 00:00:00 2001 From: fvogel Date: Fri, 26 Apr 2019 22:02:59 +0000 Subject: Write code more consistently with the rest of the ttkEntry.c file --- generic/ttk/ttkEntry.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/generic/ttk/ttkEntry.c b/generic/ttk/ttkEntry.c index 148bc47..1ef2423 100644 --- a/generic/ttk/ttkEntry.c +++ b/generic/ttk/ttkEntry.c @@ -1651,14 +1651,13 @@ static int EntryXViewCommand( void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Entry *entryPtr = recordPtr; - WidgetCore *corePtr = recordPtr; /* * Ensure that the scroll info is up-to-date before a scrolling command. */ - if (corePtr->flags & REDISPLAY_PENDING) { - EntryDoLayout(recordPtr); + if (entryPtr->core.flags & REDISPLAY_PENDING) { + EntryDoLayout(entryPtr); } if (objc == 3) { -- cgit v0.12 From 24b4a3cdfb7412ee9337695296ec28a02a1f08ad Mon Sep 17 00:00:00 2001 From: fvogel Date: Sat, 27 Apr 2019 15:49:23 +0000 Subject: More generic fix, for [8261c517af] and [2513186fff]. --- generic/ttk/ttkEntry.c | 8 -------- generic/ttk/ttkScroll.c | 19 ++++++++++++++++++- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/generic/ttk/ttkEntry.c b/generic/ttk/ttkEntry.c index 1ef2423..e6365b2 100644 --- a/generic/ttk/ttkEntry.c +++ b/generic/ttk/ttkEntry.c @@ -1652,14 +1652,6 @@ static int EntryXViewCommand( { Entry *entryPtr = recordPtr; - /* - * Ensure that the scroll info is up-to-date before a scrolling command. - */ - - if (entryPtr->core.flags & REDISPLAY_PENDING) { - EntryDoLayout(entryPtr); - } - if (objc == 3) { int newFirst; if (EntryIndex(interp, entryPtr, objv[2], &newFirst) != TCL_OK) { diff --git a/generic/ttk/ttkScroll.c b/generic/ttk/ttkScroll.c index 184f5f2..60f0480 100644 --- a/generic/ttk/ttkScroll.c +++ b/generic/ttk/ttkScroll.c @@ -197,7 +197,16 @@ int TtkScrollviewCommand( if (objc == 2) { Tcl_Obj *result[2]; - result[0] = Tcl_NewDoubleObj((double)s->first / s->total); + + /* + * Update the scroll info (first, last, total) if needed. + */ + + if (h->corePtr->flags & REDISPLAY_PENDING) { + h->corePtr->widgetSpec->layoutProc(h->corePtr); + } + + result[0] = Tcl_NewDoubleObj((double)s->first / s->total); result[1] = Tcl_NewDoubleObj((double)s->last / s->total); Tcl_SetObjResult(interp, Tcl_NewListObj(2, result)); return TCL_OK; @@ -235,6 +244,14 @@ void TtkScrollTo(ScrollHandle h, int newFirst) { Scrollable *s = h->scrollPtr; + /* + * Update the scroll info (first, last, total) if needed. + */ + + if (h->corePtr->flags & REDISPLAY_PENDING) { + h->corePtr->widgetSpec->layoutProc(h->corePtr); + } + if (newFirst >= s->total) newFirst = s->total - 1; if (newFirst > s->first && s->last >= s->total) /* don't scroll past end */ -- cgit v0.12 From 4c2a79de161bcf55a617eba4a6f0eb8a1e27ed8b Mon Sep 17 00:00:00 2001 From: fvogel Date: Sat, 27 Apr 2019 15:55:08 +0000 Subject: Revert irrelevant blank changes --- generic/ttk/ttkEntry.c | 1 - generic/ttk/ttkScroll.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/generic/ttk/ttkEntry.c b/generic/ttk/ttkEntry.c index e6365b2..ebc485e 100644 --- a/generic/ttk/ttkEntry.c +++ b/generic/ttk/ttkEntry.c @@ -1651,7 +1651,6 @@ static int EntryXViewCommand( void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Entry *entryPtr = recordPtr; - if (objc == 3) { int newFirst; if (EntryIndex(interp, entryPtr, objv[2], &newFirst) != TCL_OK) { diff --git a/generic/ttk/ttkScroll.c b/generic/ttk/ttkScroll.c index 60f0480..21b23b8 100644 --- a/generic/ttk/ttkScroll.c +++ b/generic/ttk/ttkScroll.c @@ -206,7 +206,7 @@ int TtkScrollviewCommand( h->corePtr->widgetSpec->layoutProc(h->corePtr); } - result[0] = Tcl_NewDoubleObj((double)s->first / s->total); + result[0] = Tcl_NewDoubleObj((double)s->first / s->total); result[1] = Tcl_NewDoubleObj((double)s->last / s->total); Tcl_SetObjResult(interp, Tcl_NewListObj(2, result)); return TCL_OK; -- cgit v0.12 From a45cd9e5e3fc6da137e7a23ebd4b507b3905c142 Mon Sep 17 00:00:00 2001 From: fvogel Date: Sun, 28 Apr 2019 10:45:38 +0000 Subject: Add a missing scroll info update needed to make x|yview moveto|units|pages work without an update idletasks call beforehand. --- generic/ttk/ttkScroll.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/generic/ttk/ttkScroll.c b/generic/ttk/ttkScroll.c index 21b23b8..84fbff2 100644 --- a/generic/ttk/ttkScroll.c +++ b/generic/ttk/ttkScroll.c @@ -218,6 +218,14 @@ int TtkScrollviewCommand( double fraction; int count; + /* + * Update the scroll info (first, last, total) if needed. + */ + + if (h->corePtr->flags & REDISPLAY_PENDING) { + h->corePtr->widgetSpec->layoutProc(h->corePtr); + } + switch (Tk_GetScrollInfoObj(interp, objc, objv, &fraction, &count)) { case TK_SCROLL_ERROR: return TCL_ERROR; -- cgit v0.12 From faf3d3197da965a56835db30b149ef85ce2384f1 Mon Sep 17 00:00:00 2001 From: fvogel Date: Sun, 28 Apr 2019 12:52:43 +0000 Subject: Factorize the code a bit, and avoid calling the layoutProc twice when calling xview moveto|units|pages. --- generic/ttk/ttkEntry.c | 2 +- generic/ttk/ttkScroll.c | 47 +++++++++++++++++++++-------------------------- generic/ttk/ttkTreeview.c | 4 ++-- generic/ttk/ttkWidget.h | 2 +- 4 files changed, 25 insertions(+), 30 deletions(-) diff --git a/generic/ttk/ttkEntry.c b/generic/ttk/ttkEntry.c index ebc485e..e306953 100644 --- a/generic/ttk/ttkEntry.c +++ b/generic/ttk/ttkEntry.c @@ -1656,7 +1656,7 @@ static int EntryXViewCommand( if (EntryIndex(interp, entryPtr, objv[2], &newFirst) != TCL_OK) { return TCL_ERROR; } - TtkScrollTo(entryPtr->entry.xscrollHandle, newFirst); + TtkScrollTo(entryPtr->entry.xscrollHandle, newFirst, 1); return TCL_OK; } return TtkScrollviewCommand(interp, objc, objv, entryPtr->entry.xscrollHandle); diff --git a/generic/ttk/ttkScroll.c b/generic/ttk/ttkScroll.c index 84fbff2..47db6ac 100644 --- a/generic/ttk/ttkScroll.c +++ b/generic/ttk/ttkScroll.c @@ -181,6 +181,19 @@ void TtkScrollbarUpdateRequired(ScrollHandle h) h->flags |= SCROLL_UPDATE_REQUIRED; } +/* TtkUpdateScrollInfo -- + * Call the layoutProc to update the scroll info first, last, and total. + * Do it only if needed, that is when a redisplay is pending (which + * indicates scroll info are possibly out of date). + */ + +void TtkUpdateScrollInfo(ScrollHandle h) +{ + if (h->corePtr->flags & REDISPLAY_PENDING) { + h->corePtr->widgetSpec->layoutProc(h->corePtr); + } +} + /* TtkScrollviewCommand -- * Widget [xy]view command implementation. * @@ -193,19 +206,13 @@ int TtkScrollviewCommand( Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], ScrollHandle h) { Scrollable *s = h->scrollPtr; - int newFirst = s->first; + int newFirst; + + TtkUpdateScrollInfo(h); + newFirst = s->first; if (objc == 2) { Tcl_Obj *result[2]; - - /* - * Update the scroll info (first, last, total) if needed. - */ - - if (h->corePtr->flags & REDISPLAY_PENDING) { - h->corePtr->widgetSpec->layoutProc(h->corePtr); - } - result[0] = Tcl_NewDoubleObj((double)s->first / s->total); result[1] = Tcl_NewDoubleObj((double)s->last / s->total); Tcl_SetObjResult(interp, Tcl_NewListObj(2, result)); @@ -218,14 +225,6 @@ int TtkScrollviewCommand( double fraction; int count; - /* - * Update the scroll info (first, last, total) if needed. - */ - - if (h->corePtr->flags & REDISPLAY_PENDING) { - h->corePtr->widgetSpec->layoutProc(h->corePtr); - } - switch (Tk_GetScrollInfoObj(interp, objc, objv, &fraction, &count)) { case TK_SCROLL_ERROR: return TCL_ERROR; @@ -243,21 +242,17 @@ int TtkScrollviewCommand( } } - TtkScrollTo(h, newFirst); + TtkScrollTo(h, newFirst, 0); return TCL_OK; } -void TtkScrollTo(ScrollHandle h, int newFirst) +void TtkScrollTo(ScrollHandle h, int newFirst, int updateScrollInfo) { Scrollable *s = h->scrollPtr; - /* - * Update the scroll info (first, last, total) if needed. - */ - - if (h->corePtr->flags & REDISPLAY_PENDING) { - h->corePtr->widgetSpec->layoutProc(h->corePtr); + if (updateScrollInfo) { + TtkUpdateScrollInfo(h); } if (newFirst >= s->total) diff --git a/generic/ttk/ttkTreeview.c b/generic/ttk/ttkTreeview.c index 68a9b6d..d78df5f 100644 --- a/generic/ttk/ttkTreeview.c +++ b/generic/ttk/ttkTreeview.c @@ -2845,10 +2845,10 @@ static int TreeviewSeeCommand( */ rowNumber = RowNumber(tv, item); if (rowNumber < tv->tree.yscroll.first) { - TtkScrollTo(tv->tree.yscrollHandle, rowNumber); + TtkScrollTo(tv->tree.yscrollHandle, rowNumber, 1); } else if (rowNumber >= tv->tree.yscroll.last) { TtkScrollTo(tv->tree.yscrollHandle, - tv->tree.yscroll.first + (1+rowNumber - tv->tree.yscroll.last)); + tv->tree.yscroll.first + (1+rowNumber - tv->tree.yscroll.last), 1); } return TCL_OK; diff --git a/generic/ttk/ttkWidget.h b/generic/ttk/ttkWidget.h index e4dd712..7ccc1f3 100644 --- a/generic/ttk/ttkWidget.h +++ b/generic/ttk/ttkWidget.h @@ -195,7 +195,7 @@ MODULE_SCOPE void TtkFreeScrollHandle(ScrollHandle); MODULE_SCOPE int TtkScrollviewCommand( Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], ScrollHandle); -MODULE_SCOPE void TtkScrollTo(ScrollHandle, int newFirst); +MODULE_SCOPE void TtkScrollTo(ScrollHandle, int newFirst, int updateScrollInfo); MODULE_SCOPE void TtkScrolled(ScrollHandle, int first, int last, int total); MODULE_SCOPE void TtkScrollbarUpdateRequired(ScrollHandle); -- cgit v0.12 From 6afd4e02fc9f197853203afaa1df7347a989e8cf Mon Sep 17 00:00:00 2001 From: fvogel Date: Sun, 28 Apr 2019 13:57:09 +0000 Subject: Fix '.e index @'. The returned answer could be wrong if the scroll info was not yet updated. --- generic/ttk/ttkEntry.c | 1 + generic/ttk/ttkWidget.h | 1 + 2 files changed, 2 insertions(+) diff --git a/generic/ttk/ttkEntry.c b/generic/ttk/ttkEntry.c index e306953..186ded0 100644 --- a/generic/ttk/ttkEntry.c +++ b/generic/ttk/ttkEntry.c @@ -1362,6 +1362,7 @@ EntryIndex( *indexPtr = Tk_PointToChar(entryPtr->entry.textLayout, x - entryPtr->entry.layoutX, 0); + TtkUpdateScrollInfo(entryPtr->entry.xscrollHandle); if (*indexPtr < entryPtr->entry.xscroll.first) { *indexPtr = entryPtr->entry.xscroll.first; } diff --git a/generic/ttk/ttkWidget.h b/generic/ttk/ttkWidget.h index 7ccc1f3..8a94bb7 100644 --- a/generic/ttk/ttkWidget.h +++ b/generic/ttk/ttkWidget.h @@ -195,6 +195,7 @@ MODULE_SCOPE void TtkFreeScrollHandle(ScrollHandle); MODULE_SCOPE int TtkScrollviewCommand( Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], ScrollHandle); +MODULE_SCOPE void TtkUpdateScrollInfo(ScrollHandle h); MODULE_SCOPE void TtkScrollTo(ScrollHandle, int newFirst, int updateScrollInfo); MODULE_SCOPE void TtkScrolled(ScrollHandle, int first, int last, int total); MODULE_SCOPE void TtkScrollbarUpdateRequired(ScrollHandle); -- cgit v0.12 From 8769a171d064001c6ee11448139a564f91bd29ca Mon Sep 17 00:00:00 2001 From: fvogel Date: Sun, 28 Apr 2019 14:34:41 +0000 Subject: Add tests checking the scroll info correct update when xview / yview is called. All the new (or modified) tests fail in core-8-6-branch. --- tests/ttk/entry.test | 29 ++++++++++++++++++++++++++++- tests/ttk/treeview.test | 12 ++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/tests/ttk/entry.test b/tests/ttk/entry.test index d95ef31..a920042 100644 --- a/tests/ttk/entry.test +++ b/tests/ttk/entry.test @@ -103,10 +103,37 @@ test entry-3.1 "bbox widget command" -body { test entry-3.2 "xview" -body { .e delete 0 end; .e insert end [string repeat "0" 40] - update idletasks set result [.e xview] } -result {0.0 0.5} +test entry-3.3 "xview" -body { + .e delete 0 end; + .e insert end abcdefghijklmnopqrstuvwxyz + .e xview end + set result [.e index @0] +} -result {7} + +test entry-3.4 "xview" -body { + .e delete 0 end; + .e insert end abcdefghijklmnopqrstuvwxyz + .e xview moveto 1.0 + set result [.e index @0] +} -result {7} + +test entry-3.5 "xview" -body { + .e delete 0 end; + .e insert end abcdefghijklmnopqrstuvwxyz + .e xview scroll 5 units + set result [.e index @0] +} -result {5} + +test entry-3.6 "xview" -body { + .e delete 0 end; + .e insert end [string repeat abcdefghijklmnopqrstuvwxyz 5] + .e xview scroll 2 pages + set result [.e index @0] +} -result {40} + test entry-3.last "Series 3 cleanup" -body { destroy .e } diff --git a/tests/ttk/treeview.test b/tests/ttk/treeview.test index be82f68..a36e3d1 100644 --- a/tests/ttk/treeview.test +++ b/tests/ttk/treeview.test @@ -471,6 +471,18 @@ test treeview-9.0 "scroll callback - empty tree" -body { set ::scrolldata } -result [list 0.0 1.0] +test treeview-9.1 "scrolling" -setup { + pack [ttk::treeview .tree -show tree] -fill y + for {set i 1} {$i < 100} {incr i} { + .tree insert {} end -text $i + } +} -body { + .tree yview scroll 5 units + .tree identify item 2 2 +} -cleanup { + destroy .tree +} -result {I006} + ### identify tests: # proc identify* {tv comps args} { -- cgit v0.12 From e1c72469006c017837637353b241baf64dbb5e38 Mon Sep 17 00:00:00 2001 From: fvogel Date: Sun, 28 Apr 2019 19:27:22 +0000 Subject: Fix documentation for xview/yview: make it generic and available for ttk::entry and ttk::treeview --- doc/ttk_entry.n | 41 +--------------------------- doc/ttk_treeview.n | 13 ++++----- doc/ttk_widget.n | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 46 deletions(-) diff --git a/doc/ttk_entry.n b/doc/ttk_entry.n index 3a30e4d..adc4f16 100644 --- a/doc/ttk_entry.n +++ b/doc/ttk_entry.n @@ -222,52 +222,13 @@ by the \fB\-validate\fR option. Returns 0 if validation fails, 1 if it succeeds. Sets or clears the \fBinvalid\fR state accordingly. See \fBVALIDATION\fR below for more details. -.TP -\fIpathName \fBxview \fIargs\fR -This command is used to query and change the horizontal position of the -text in the widget's window. It can take any of the following -forms: -.RS -.TP -\fIpathName \fBxview\fR -Returns a list containing two elements. -Each element is a real fraction between 0 and 1; together they describe -the horizontal span that is visible in the window. -For example, if the first element is .2 and the second element is .6, -20% of the entry's text is off-screen to the left, the middle 40% is visible -in the window, and 40% of the text is off-screen to the right. -These are the same values passed to scrollbars via the \fB\-xscrollcommand\fR -option. -.TP -\fIpathName \fBxview\fR \fIindex\fR -Adjusts the view in the window so that the character given by \fIindex\fR -is displayed at the left edge of the window. -.TP -\fIpathName \fBxview moveto\fI fraction\fR -Adjusts the view in the window so that the character \fIfraction\fR of the -way through the text appears at the left edge of the window. -\fIFraction\fR must be a fraction between 0 and 1. -.TP -\fIpathName \fBxview scroll \fInumber what\fR -This command shifts the view in the window left or right according to -\fInumber\fR and \fIwhat\fR. -\fINumber\fR must be an integer. -\fIWhat\fR must be either \fBunits\fR or \fBpages\fR. -'\" or an abbreviation of one of these, but we don't document that. -If \fIwhat\fR is \fBunits\fR, the view adjusts left or right by -\fInumber\fR average-width characters on the display; if it is -\fBpages\fR then the view adjusts by \fInumber\fR screenfuls. -If \fInumber\fR is negative then characters farther to the left -become visible; if it is positive then characters farther to the right -become visible. -.RE .PP The entry widget also supports the following generic \fBttk::widget\fR widget subcommands (see \fIttk::widget(n)\fR for details): .DS .ta 5.5c 11c \fBcget\fR \fBconfigure\fR \fBidentify\fR -\fBinstate\fR \fBstate\fR +\fBinstate\fR \fBstate\fR \fBxview\fR .DE .SH VALIDATION .PP diff --git a/doc/ttk_treeview.n b/doc/ttk_treeview.n index 96565a3..5fd5e6d 100644 --- a/doc/ttk_treeview.n +++ b/doc/ttk_treeview.n @@ -388,12 +388,13 @@ If \fIitems\fR is omitted, removes \fItag\fR from each item in the tree. If \fItag\fR is not present for a particular item, then the \fB\-tags\fR for that item are unchanged. .RE -.TP -\fIpathName \fBxview \fIargs\fR -Standard command for horizontal scrolling; see \fIwidget(n)\fR. -.TP -\fIpathName \fByview \fIargs\fR -Standard command for vertical scrolling; see \fIttk::widget(n)\fR. +.PP +The treeview widget also supports the following generic \fBttk::widget\fR +widget subcommands (see \fIttk::widget(n)\fR for details): +.DS +.ta 5.5c 11c +\fBxview\fR \fByview\fR +.DE .SH "ITEM OPTIONS" .PP The following item options may be specified for items diff --git a/doc/ttk_widget.n b/doc/ttk_widget.n index ad90e99..2e47b46 100644 --- a/doc/ttk_widget.n +++ b/doc/ttk_widget.n @@ -192,6 +192,84 @@ will restore \fIpathName\fR to the original state. If \fIstateSpec\fR is not specified, returns a list of the currently-enabled state flags. .RE +.TP +\fIpathName \fBxview \fIargs\fR +This command is used to query and change the horizontal position of the +content in the widget's window. It can take any of the following +forms: +.RS +.TP +\fIpathName \fBxview\fR +Returns a list containing two elements. +Each element is a real fraction between 0 and 1; together they describe +the horizontal span that is visible in the window. +For example, if the first element is .2 and the second element is .6, +20% of the widget's content is off-screen to the left, the middle 40% is visible +in the window, and 40% of the content is off-screen to the right. +These are the same values passed to scrollbars via the \fB\-xscrollcommand\fR +option. +.TP +\fIpathName \fBxview\fR \fIindex\fR +Adjusts the view in the window so that the content given by \fIindex\fR +is displayed at the left edge of the window. +.TP +\fIpathName \fBxview moveto\fI fraction\fR +Adjusts the view in the window so that the character \fIfraction\fR of the +way through the content appears at the left edge of the window. +\fIFraction\fR must be a fraction between 0 and 1. +.TP +\fIpathName \fBxview scroll \fInumber what\fR +This command shifts the view in the window left or right according to +\fInumber\fR and \fIwhat\fR. +\fINumber\fR must be an integer. +\fIWhat\fR must be either \fBunits\fR or \fBpages\fR. +'\" or an abbreviation of one of these, but we don't document that. +If \fIwhat\fR is \fBunits\fR, the view adjusts left or right by +\fInumber\fR average-width characters on the display; if it is +\fBpages\fR then the view adjusts by \fInumber\fR screenfuls. +If \fInumber\fR is negative then characters farther to the left +become visible; if it is positive then characters farther to the right +become visible. +.RE +.TP +\fIpathName \fByview \fIargs\fR +This command is used to query and change the vertical position of the +content in the widget's window. It can take any of the following +forms: +.RS +.TP +\fIpathName \fByview\fR +Returns a list containing two elements. +Each element is a real fraction between 0 and 1; together they describe +the vertical span that is visible in the window. +For example, if the first element is .2 and the second element is .6, +20% of the widget's content is off-screen to the top, the middle 40% is visible +in the window, and 40% of the content is off-screen to the bottom. +These are the same values passed to scrollbars via the \fB\-yscrollcommand\fR +option. +.TP +\fIpathName \fByview\fR \fIindex\fR +Adjusts the view in the window so that the content given by \fIindex\fR +is displayed at the top edge of the window. +.TP +\fIpathName \fByview moveto\fI fraction\fR +Adjusts the view in the window so that the item \fIfraction\fR of the +way through the content appears at the top edge of the window. +\fIFraction\fR must be a fraction between 0 and 1. +.TP +\fIpathName \fBxview scroll \fInumber what\fR +This command shifts the view in the window up or down according to +\fInumber\fR and \fIwhat\fR. +\fINumber\fR must be an integer. +\fIWhat\fR must be either \fBunits\fR or \fBpages\fR. +'\" or an abbreviation of one of these, but we don't document that. +If \fIwhat\fR is \fBunits\fR, the view adjusts up or down by +\fInumber\fR average-width characters on the display; if it is +\fBpages\fR then the view adjusts by \fInumber\fR screenfuls. +If \fInumber\fR is negative then items farther to the top +become visible; if it is positive then items farther to the bottom +become visible. +.RE .SH "WIDGET STATES" The widget state is a bitmap of independent state flags. Widget state flags include: -- cgit v0.12 From e57c2944853f97d7e668f937db46ac3cd40b3994 Mon Sep 17 00:00:00 2001 From: fvogel Date: Sun, 28 Apr 2019 20:12:52 +0000 Subject: Fix typo in man page --- doc/ttk_widget.n | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ttk_widget.n b/doc/ttk_widget.n index 2e47b46..281ce74 100644 --- a/doc/ttk_widget.n +++ b/doc/ttk_widget.n @@ -257,7 +257,7 @@ Adjusts the view in the window so that the item \fIfraction\fR of the way through the content appears at the top edge of the window. \fIFraction\fR must be a fraction between 0 and 1. .TP -\fIpathName \fBxview scroll \fInumber what\fR +\fIpathName \fByview scroll \fInumber what\fR This command shifts the view in the window up or down according to \fInumber\fR and \fIwhat\fR. \fINumber\fR must be an integer. -- cgit v0.12 From 2fa09ced062e7964597b77f6ec9c04fd00001ee4 Mon Sep 17 00:00:00 2001 From: fvogel Date: Sun, 28 Apr 2019 20:27:59 +0000 Subject: Fix inconsistency in the Tk_GetScrollInfoObj man page. Apparently this was a leftover from [a99dde78] --- doc/GetScroll.3 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/GetScroll.3 b/doc/GetScroll.3 index abd0880..a71986d 100644 --- a/doc/GetScroll.3 +++ b/doc/GetScroll.3 @@ -15,10 +15,10 @@ Tk_GetScrollInfoObj, Tk_GetScrollInfo \- parse arguments for scrolling commands \fB#include \fR .sp int -\fBTk_GetScrollInfoObj(\fIinterp, objc, objv, dblPtr, intPtr\fB)\fR +\fBTk_GetScrollInfoObj(\fIinterp, objc, objv, fractionPtr, stepsPtr\fB)\fR .sp int -\fBTk_GetScrollInfo(\fIinterp, argc, argv, dblPtr, intPtr\fB)\fR +\fBTk_GetScrollInfo(\fIinterp, argc, argv, fractionPtr, stepsPtr\fB)\fR .SH ARGUMENTS .AS "Tcl_Interp" *fractionPtr .AP Tcl_Interp *interp in -- cgit v0.12 From b410e77f82bae835dc0daa2606553b43a1442aba Mon Sep 17 00:00:00 2001 From: fvogel Date: Mon, 29 Apr 2019 20:10:46 +0000 Subject: Fix [1ff193f1e3]: style name is Horizontal.TScrollbar or Vertical.TScrollbar in ttk::scrollbar documentation --- doc/ttk_scrollbar.n | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/ttk_scrollbar.n b/doc/ttk_scrollbar.n index 49681a1..cc3dec5 100644 --- a/doc/ttk_scrollbar.n +++ b/doc/ttk_scrollbar.n @@ -76,7 +76,7 @@ Modify or query the widget state; see \fIttk::widget(n)\fR. .SH "INTERNAL COMMANDS" .PP The following widget commands are used internally -by the TScrollbar widget class bindings. +by the \fBTScrollbar\fP widget class bindings. .TP \fIpathName \fBdelta \fIdeltaX deltaY\fR Returns a real number indicating the fractional change in @@ -153,6 +153,7 @@ grid $f.vsb \-row 0 \-column 1 \-sticky nsew grid $f.hsb \-row 1 \-column 0 \-sticky nsew grid columnconfigure $f 0 \-weight 1 grid rowconfigure $f 0 \-weight 1 +pack $f .CE .SH "STYLING OPTIONS" .PP @@ -160,8 +161,8 @@ The class name for a \fBttk::scrollbar\fP is \fBTScrollbar\fP. .PP Dynamic states: \fBactive\fP, \fBdisabled\fP. .PP -\fBTScrollbar\fP styling options configurable with \fBttk::style\fP -are: +\fBVertical.TScrollbar\fP and \fBHorizontal.TScrollbar\fP styling options +that are configurable with \fBttk::style\fP are: .PP \fB\-arrowcolor\fP \fIcolor\fP .br -- cgit v0.12 From 433304287898f929f4b40917815bc1dfe6bb834b Mon Sep 17 00:00:00 2001 From: fvogel Date: Tue, 30 Apr 2019 06:03:24 +0000 Subject: Add missing documentation for -arrowsize in ttk::scrollbar and ttk::combobox man pages. --- doc/ttk_combobox.n | 2 ++ doc/ttk_scrollbar.n | 2 ++ 2 files changed, 4 insertions(+) diff --git a/doc/ttk_combobox.n b/doc/ttk_combobox.n index 9c01409..b8fd2bc 100644 --- a/doc/ttk_combobox.n +++ b/doc/ttk_combobox.n @@ -124,6 +124,8 @@ are: .PP \fB\-arrowcolor\fP \fIcolor\fP .br +\fB\-arrowsize\fP \fIamount\fP +.br \fB\-background\fP \fIcolor\fP .br \fB\-bordercolor\fP \fIcolor\fP diff --git a/doc/ttk_scrollbar.n b/doc/ttk_scrollbar.n index cc3dec5..6e9854f 100644 --- a/doc/ttk_scrollbar.n +++ b/doc/ttk_scrollbar.n @@ -166,6 +166,8 @@ that are configurable with \fBttk::style\fP are: .PP \fB\-arrowcolor\fP \fIcolor\fP .br +\fB\-arrowsize\fP \fIamount\fP +.br \fB\-background\fP \fIcolor\fP .br \fB\-bordercolor\fP \fIcolor\fP -- cgit v0.12 From 43d7f5fb0f3b37902bb0628d71254bf281fe241d Mon Sep 17 00:00:00 2001 From: fvogel Date: Tue, 30 Apr 2019 17:28:13 +0000 Subject: Fix [4f9a99e20b]: crash when specifying wrong -syssize option in ttk::style element create ... vsapi --- win/ttkWinXPTheme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/win/ttkWinXPTheme.c b/win/ttkWinXPTheme.c index b828221..c19ed65 100644 --- a/win/ttkWinXPTheme.c +++ b/win/ttkWinXPTheme.c @@ -1062,7 +1062,7 @@ GetSysFlagFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int *resultPtr) "SM_CXBORDER", "SM_CYBORDER", "SM_CXVSCROLL", "SM_CYVSCROLL", "SM_CXHSCROLL", "SM_CYHSCROLL", "SM_CXMENUCHECK", "SM_CYMENUCHECK", "SM_CXMENUSIZE", "SM_CYMENUSIZE", "SM_CXSIZE", "SM_CYSIZE", "SM_CXSMSIZE", - "SM_CYSMSIZE" + "SM_CYSMSIZE", NULL }; int flags[] = { SM_CXBORDER, SM_CYBORDER, SM_CXVSCROLL, SM_CYVSCROLL, -- cgit v0.12 From a1e66021e7f53ce1485757afa0c700a5ad6ef560 Mon Sep 17 00:00:00 2001 From: fvogel Date: Tue, 30 Apr 2019 17:54:34 +0000 Subject: Refine documentation in ttk::scrollbar --- doc/ttk_scrollbar.n | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/ttk_scrollbar.n b/doc/ttk_scrollbar.n index 6e9854f..6baab04 100644 --- a/doc/ttk_scrollbar.n +++ b/doc/ttk_scrollbar.n @@ -161,8 +161,9 @@ The class name for a \fBttk::scrollbar\fP is \fBTScrollbar\fP. .PP Dynamic states: \fBactive\fP, \fBdisabled\fP. .PP -\fBVertical.TScrollbar\fP and \fBHorizontal.TScrollbar\fP styling options -that are configurable with \fBttk::style\fP are: +\fBTScrollbar\fP (or more specifically \fBVertical.TScrollbar\fP and +\fBHorizontal.TScrollbar\fP) styling options that are configurable with +\fBttk::style\fP are: .PP \fB\-arrowcolor\fP \fIcolor\fP .br -- cgit v0.12 From de3209189e8860aa1a88ed83e190dd8b7e4c9847 Mon Sep 17 00:00:00 2001 From: fvogel Date: Wed, 1 May 2019 18:30:30 +0000 Subject: Fix [51b4b18394]: mac os x: combobox.tcl has old scrollbar for its listbox --- library/ttk/combobox.tcl | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/library/ttk/combobox.tcl b/library/ttk/combobox.tcl index c1b6da6..1355a04 100644 --- a/library/ttk/combobox.tcl +++ b/library/ttk/combobox.tcl @@ -251,30 +251,16 @@ proc ttk::combobox::UnmapPopdown {w} { ttk::releaseGrab $w } -### -# - -namespace eval ::ttk::combobox { - # @@@ Until we have a proper native scrollbar on Aqua, use - # @@@ the regular Tk one. Use ttk::scrollbar on other platforms. - variable scrollbar ttk::scrollbar - if {[tk windowingsystem] eq "aqua"} { - set scrollbar ::scrollbar - } -} - ## PopdownWindow -- # Returns the popdown widget associated with a combobox, # creating it if necessary. # proc ttk::combobox::PopdownWindow {cb} { - variable scrollbar - if {![winfo exists $cb.popdown]} { set poplevel [PopdownToplevel $cb.popdown] set popdown [ttk::frame $poplevel.f -style ComboboxPopdownFrame] - $scrollbar $popdown.sb \ + ttk::scrollbar $popdown.sb \ -orient vertical -command [list $popdown.l yview] listbox $popdown.l \ -listvariable ttk::combobox::Values($cb) \ -- cgit v0.12 From 85ca666e03be25f5cd07ecf59bac5ba1af607f01 Mon Sep 17 00:00:00 2001 From: oehhar Date: Thu, 2 May 2019 16:00:41 +0000 Subject: ttk::scrollbar documentation: added styling options -gripcound and -sliderlength and some explanatory text --- doc/ttk_scrollbar.n | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/ttk_scrollbar.n b/doc/ttk_scrollbar.n index 6baab04..e356b91 100644 --- a/doc/ttk_scrollbar.n +++ b/doc/ttk_scrollbar.n @@ -173,11 +173,15 @@ Dynamic states: \fBactive\fP, \fBdisabled\fP. .br \fB\-bordercolor\fP \fIcolor\fP .br -\fB\-darkcolor\fP \fIcolor\fP +\fB\-darkcolor\fP \fIcolor\fP (color of the dark 3d relief) .br \fB\-foreground\fP \fIcolor\fP .br -\fB\-lightcolor\fP \fIcolor\fP +\fB\-gripcount\fP \fInumber\fP (number of lines on the thumb) +.br +\fB\-lightcolor\fP \fIcolor\fP (color of the light 3d relief) +.br +\fB\-sliderlength\fP \fIamount\fP (minimum length of the thumb) .br \fB\-troughcolor\fP \fIcolor\fP .PP -- cgit v0.12 From 6f3240df379bab104d9d81e2103d74a8de4d6eca Mon Sep 17 00:00:00 2001 From: fvogel Date: Thu, 2 May 2019 20:55:15 +0000 Subject: Homogenize with existing doc for -gripcount in the man page for ttk::panedwindow --- doc/ttk_scrollbar.n | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ttk_scrollbar.n b/doc/ttk_scrollbar.n index e356b91..a93c706 100644 --- a/doc/ttk_scrollbar.n +++ b/doc/ttk_scrollbar.n @@ -177,7 +177,7 @@ Dynamic states: \fBactive\fP, \fBdisabled\fP. .br \fB\-foreground\fP \fIcolor\fP .br -\fB\-gripcount\fP \fInumber\fP (number of lines on the thumb) +\fB\-gripcount\fP \fIcount\fP (number of lines on the thumb) .br \fB\-lightcolor\fP \fIcolor\fP (color of the light 3d relief) .br -- cgit v0.12 From 8f871f2b97e1c60ed300763ff7986bfd0bca168b Mon Sep 17 00:00:00 2001 From: oehhar Date: Fri, 3 May 2019 06:44:14 +0000 Subject: ttk::scrollbar documentation: marked -sliderlength as depreciated as it has no effect --- doc/ttk_scrollbar.n | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ttk_scrollbar.n b/doc/ttk_scrollbar.n index a93c706..5b9bbfb 100644 --- a/doc/ttk_scrollbar.n +++ b/doc/ttk_scrollbar.n @@ -181,7 +181,7 @@ Dynamic states: \fBactive\fP, \fBdisabled\fP. .br \fB\-lightcolor\fP \fIcolor\fP (color of the light 3d relief) .br -\fB\-sliderlength\fP \fIamount\fP (minimum length of the thumb) +\fB\-sliderlength\fP \fIamount\fP (depreciated, no effect) .br \fB\-troughcolor\fP \fIcolor\fP .PP -- cgit v0.12 From 5def4ba26dcbe1563f4bf4a29a68472414f5cbcd Mon Sep 17 00:00:00 2001 From: fvogel Date: Fri, 3 May 2019 19:49:31 +0000 Subject: Remove wrong info from ttk::scrollbar man page --- doc/ttk_scrollbar.n | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/doc/ttk_scrollbar.n b/doc/ttk_scrollbar.n index 5b9bbfb..bd80760 100644 --- a/doc/ttk_scrollbar.n +++ b/doc/ttk_scrollbar.n @@ -173,15 +173,13 @@ Dynamic states: \fBactive\fP, \fBdisabled\fP. .br \fB\-bordercolor\fP \fIcolor\fP .br -\fB\-darkcolor\fP \fIcolor\fP (color of the dark 3d relief) +\fB\-darkcolor\fP \fIcolor\fP (color of the dark part of the 3D relief) .br \fB\-foreground\fP \fIcolor\fP .br \fB\-gripcount\fP \fIcount\fP (number of lines on the thumb) .br -\fB\-lightcolor\fP \fIcolor\fP (color of the light 3d relief) -.br -\fB\-sliderlength\fP \fIamount\fP (depreciated, no effect) +\fB\-lightcolor\fP \fIcolor\fP (color of the light part of the 3D relief) .br \fB\-troughcolor\fP \fIcolor\fP .PP -- cgit v0.12 From 2ec7162d109eca92bb2ef89add0826b71e241e95 Mon Sep 17 00:00:00 2001 From: fvogel Date: Fri, 3 May 2019 19:51:54 +0000 Subject: Fix class name in ttk::scale man page (this copy/paste error was introduced in [d0576d63ff]) --- doc/ttk_scale.n | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ttk_scale.n b/doc/ttk_scale.n index 4e16999..f8f5072 100644 --- a/doc/ttk_scale.n +++ b/doc/ttk_scale.n @@ -93,7 +93,7 @@ corresponding to the current value of the \fB\-value\fR option if \fIvalue\fR is omitted. .SH "STYLING OPTIONS" .PP -The class name for a \fBttk::scale\fP is \fBTProgressbar\fP. +The class name for a \fBttk::scale\fP is \fBTScale\fP. .PP Dynamic states: \fBactive\fP. .PP -- cgit v0.12 From 6b305ada3d3a68c00bc6ddaf163ae327f1c44e05 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 9 May 2019 15:21:43 +0000 Subject: Whitespace cleanup, syncronize a little with "trunk" version. --- generic/tkButton.c | 2 +- generic/tkPlace.c | 2 +- generic/ttk/ttkEntry.c | 2 +- library/button.tcl | 2 +- macosx/tkMacOSXBitmap.c | 2 +- macosx/tkMacOSXButton.c | 5 +++-- macosx/tkMacOSXColor.c | 8 ++++---- macosx/tkMacOSXDefault.h | 7 +++---- macosx/tkMacOSXDialog.c | 2 +- macosx/tkMacOSXInit.c | 3 +-- macosx/tkMacOSXMenu.c | 12 ++++++------ macosx/tkMacOSXMenubutton.c | 2 +- macosx/tkMacOSXMouseEvent.c | 3 +-- macosx/tkMacOSXSubwindows.c | 2 +- macosx/tkMacOSXWindowEvent.c | 2 +- macosx/tkMacOSXWm.c | 4 ++-- macosx/tkMacOSXWm.h | 2 +- macosx/ttkMacOSXTheme.c | 8 ++++---- 18 files changed, 34 insertions(+), 36 deletions(-) diff --git a/generic/tkButton.c b/generic/tkButton.c index dc44189..42d63a7 100644 --- a/generic/tkButton.c +++ b/generic/tkButton.c @@ -1175,7 +1175,7 @@ ConfigureButton( */ if ((butPtr->type == TYPE_RADIO_BUTTON) && - (*Tcl_GetString(butPtr->onValuePtr) == 0)) { + (*Tcl_GetString(butPtr->onValuePtr) == '\0')) { butPtr->flags |= SELECTED; } } diff --git a/generic/tkPlace.c b/generic/tkPlace.c index 1a52114..7aa9b04 100644 --- a/generic/tkPlace.c +++ b/generic/tkPlace.c @@ -695,7 +695,7 @@ ConfigureSlave( Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "LOOP", NULL); goto error; } - + /* * Check for management loops. */ diff --git a/generic/ttk/ttkEntry.c b/generic/ttk/ttkEntry.c index 186ded0..36edf38 100644 --- a/generic/ttk/ttkEntry.c +++ b/generic/ttk/ttkEntry.c @@ -975,7 +975,7 @@ static int EntryConfigure(Tcl_Interp *interp, void *recordPtr, int mask) Ttk_TraceHandle *vt = 0; if (mask & TEXTVAR_CHANGED) { - if (textVarName && *Tcl_GetString(textVarName)) { + if (textVarName && *Tcl_GetString(textVarName) != '\0') { vt = Ttk_TraceVariable(interp, textVarName,EntryTextVariableTrace,entryPtr); if (!vt) return TCL_ERROR; diff --git a/library/button.tcl b/library/button.tcl index 88e26e5..9b13607 100644 --- a/library/button.tcl +++ b/library/button.tcl @@ -753,7 +753,7 @@ proc ::tk::CheckLeave {w} { if {![$w cget -indicatoron] && [info exist Priv($w,selectcolor)]} { if {[$w cget -selectcolor] eq $Priv($w,selectcolor) - || ([info exist Priv($w,aselectcolor)] && + || ([info exist Priv($w,aselectcolor)] && [$w cget -selectcolor] eq $Priv($w,aselectcolor))} { $w configure -selectcolor $Priv($w,selectcolor) } diff --git a/macosx/tkMacOSXBitmap.c b/macosx/tkMacOSXBitmap.c index 1a20bd5..cf46202 100644 --- a/macosx/tkMacOSXBitmap.c +++ b/macosx/tkMacOSXBitmap.c @@ -210,7 +210,7 @@ OSTypeFromString(const char *s, OSType *t) { Tcl_UtfToExternalDString(encoding, s, -1, &ds); if (Tcl_DStringLength(&ds) <= 4) { char string[4] = {}; - memcpy(string, Tcl_DStringValue(&ds), (size_t) Tcl_DStringLength(&ds)); + memcpy(string, Tcl_DStringValue(&ds), Tcl_DStringLength(&ds)); *t = (OSType) string[0] << 24 | (OSType) string[1] << 16 | (OSType) string[2] << 8 | (OSType) string[3]; result = TCL_OK; diff --git a/macosx/tkMacOSXButton.c b/macosx/tkMacOSXButton.c index 25452a4..00c7c9b 100644 --- a/macosx/tkMacOSXButton.c +++ b/macosx/tkMacOSXButton.c @@ -185,7 +185,7 @@ TkpDisplayButton( Pixmap pixmap; DrawParams* dpPtr = &macButtonPtr->drawParams; int needhighlight = 0; - + if (butPtr->flags & BUTTON_DELETED) { return; } @@ -199,7 +199,7 @@ TkpDisplayButton( * Set up clipping region. Make sure the we are using the port * for this button, or we will set the wrong window's clip. */ - + TkMacOSXSetUpClippingRgn(Tk_WindowId(tkwin)); if (TkMacOSXComputeButtonDrawParams(butPtr, dpPtr)) { @@ -1164,6 +1164,7 @@ TkMacOSXComputeButtonDrawParams( * *-------------------------------------------------------------- */ + static void PulseDefaultButtonProc(ClientData clientData) { diff --git a/macosx/tkMacOSXColor.c b/macosx/tkMacOSXColor.c index cb3bde3..f291289 100644 --- a/macosx/tkMacOSXColor.c +++ b/macosx/tkMacOSXColor.c @@ -266,7 +266,7 @@ GetEntryFromPixelCode( static NSColorSpace* deviceRGB = NULL; static CGFloat blueAccentRGBA[4] = {0, 122.0 / 255, 1.0, 1.0}; -static CGFloat windowBackground[4] = +static CGFloat windowBackground[4] = {236.0 / 255, 236.0 / 255, 236.0 / 255, 1.0}; static OSStatus @@ -279,7 +279,7 @@ SetCGColorComponents( NSColor *bgColor, *color; CGFloat rgba[4] = {0, 0, 0, 1}; #if MAC_OS_X_VERSION_MAX_ALLOWED < 101400 - NSInteger colorVariant; + NSInteger colorVariant; static CGFloat graphiteAccentRGBA[4] = {152.0 / 255, 152.0 / 255, 152.0 / 255, 1.0}; #endif @@ -360,7 +360,7 @@ SetCGColorComponents( } else { color = [[NSColor blackColor] colorUsingColorSpace: deviceRGB]; - } + } break; case 6: color = [[NSColor textBackgroundColor] colorUsingColorSpace: @@ -699,7 +699,7 @@ TkMacOSXSetColorInContext( kHIThemeOrientationNormal); break; case HIBackground: - info.kind = entry.value; + info.kind = entry.value; rect = CGContextGetClipBoundingBox(context); err = ChkErr(HIThemeApplyBackground, &rect, &info, context, kHIThemeOrientationNormal); diff --git a/macosx/tkMacOSXDefault.h b/macosx/tkMacOSXDefault.h index 61fee2d..c6d998c 100644 --- a/macosx/tkMacOSXDefault.h +++ b/macosx/tkMacOSXDefault.h @@ -56,7 +56,6 @@ #define DEF_BUTTON_ACTIVE_FG_COLOR ACTIVE_FG #define DEF_CHKRAD_ACTIVE_FG_COLOR DEF_BUTTON_ACTIVE_FG_COLOR #define DEF_BUTTON_ACTIVE_FG_MONO WHITE -/* #define DEF_BUTTON_BG_COLOR "systemButtonFace"*/ #define DEF_BUTTON_BG_COLOR NORMAL_BG #define DEF_BUTTON_BG_MONO WHITE #define DEF_BUTTON_BITMAP "" @@ -184,20 +183,19 @@ #define DEF_ENTRY_FG NORMAL_FG #define DEF_ENTRY_HIGHLIGHT_BG NORMAL_BG #define DEF_ENTRY_HIGHLIGHT BLACK -/* #define DEF_ENTRY_HIGHLIGHT_WIDTH "3" */ #define DEF_ENTRY_HIGHLIGHT_WIDTH "3" #define DEF_ENTRY_INSERT_BG NORMAL_FG #define DEF_ENTRY_INSERT_BD_COLOR "0" #define DEF_ENTRY_INSERT_BD_MONO "0" #define DEF_ENTRY_INSERT_OFF_TIME "300" #define DEF_ENTRY_INSERT_ON_TIME "600" -/* #define DEF_ENTRY_INSERT_WIDTH "2" */ #define DEF_ENTRY_INSERT_WIDTH "1" #define DEF_ENTRY_JUSTIFY "left" +#define DEF_ENTRY_PLACEHOLDER "" +#define DEF_ENTRY_PLACEHOLDERFG "#b3b3b3" #define DEF_ENTRY_READONLY_BG_COLOR NORMAL_BG #define DEF_ENTRY_READONLY_BG_MONO WHITE #define DEF_ENTRY_RELIEF "sunken" -/* #define DEF_ENTRY_RELIEF "solid" */ #define DEF_ENTRY_SCROLL_COMMAND "" #define DEF_ENTRY_SELECT_COLOR SELECT_BG #define DEF_ENTRY_SELECT_MONO BLACK @@ -315,6 +313,7 @@ #define DEF_MENU_ACTIVE_BORDER_WIDTH "0" #define DEF_MENU_ACTIVE_FG_COLOR "systemMenuActiveText" #define DEF_MENU_ACTIVE_FG_MONO WHITE +#define DEF_MENU_ACTIVE_RELIEF "flat" #define DEF_MENU_BG_COLOR "systemMenu" #define DEF_MENU_BG_MONO WHITE #define DEF_MENU_BORDER_WIDTH "0" diff --git a/macosx/tkMacOSXDialog.c b/macosx/tkMacOSXDialog.c index a7997f2..90d0dc7 100644 --- a/macosx/tkMacOSXDialog.c +++ b/macosx/tkMacOSXDialog.c @@ -42,7 +42,7 @@ typedef struct { NSMutableArray *fileTypeExtensions; /* Array of allowed extensions per * name, e.g. "txt", "doc". */ NSMutableArray *fileTypeLabels; /* Displayed string, e.g. "Text - * document (.txt, .doc)". */ + * document (.txt, .doc)". */ NSMutableArray *fileTypeAllowsAll; /* Boolean if the all pattern (*.*) is * included. */ NSMutableArray *allowedExtensions; /* Set of all allowed extensions. */ diff --git a/macosx/tkMacOSXInit.c b/macosx/tkMacOSXInit.c index 89d6983..e403501 100644 --- a/macosx/tkMacOSXInit.c +++ b/macosx/tkMacOSXInit.c @@ -102,7 +102,6 @@ static char scriptPath[PATH_MAX + 1] = ""; _defaultMainMenu = nil; [self _setupMenus]; - /* * Initialize event processing. */ @@ -128,7 +127,7 @@ static char scriptPath[PATH_MAX + 1] = ""; * Process events to ensure that the root window is fully initialized. See * ticket 56a1823c73. */ - + [NSApp _lockAutoreleasePool]; while (Tcl_DoOneEvent(TCL_WINDOW_EVENTS| TCL_DONT_WAIT)) {} [NSApp _unlockAutoreleasePool]; diff --git a/macosx/tkMacOSXMenu.c b/macosx/tkMacOSXMenu.c index 053b374..790b6ff 100644 --- a/macosx/tkMacOSXMenu.c +++ b/macosx/tkMacOSXMenu.c @@ -690,7 +690,7 @@ TkpConfigureMenuEntry( [submenu setTitle:title]; if ([menuItem isEnabled]) { - + /* * This menuItem might have been previously disabled (XXX: * track this), which would have disabled entries; we must @@ -816,7 +816,7 @@ TkpPostMenu( if (itemIndex >= 0) { item = [menu itemAtIndex:itemIndex]; } - + /* * The post commands could have deleted the menu, which means we are dead * and should go away. @@ -1010,8 +1010,8 @@ TkpSetMainMenubar( Tk_Window menubar = NULL; if (winPtr->wmInfoPtr && - winPtr->wmInfoPtr->menuPtr && - winPtr->wmInfoPtr->menuPtr->masterMenuPtr) { + winPtr->wmInfoPtr->menuPtr && + winPtr->wmInfoPtr->menuPtr->masterMenuPtr) { menubar = winPtr->wmInfoPtr->menuPtr->masterMenuPtr->tkwin; } @@ -1037,7 +1037,7 @@ TkpSetMainMenubar( * If we couldn't find a menu, do nothing unless the window belongs to a * different application. In that case, install the default menubar. */ - + if (menu || interp != currentInterp) { [NSApp tkSetMainMenu:menu]; } @@ -1246,7 +1246,7 @@ TkpComputeStandardMenuGeometry( if (menuPtr->tkwin == NULL || menuPtr->masterMenuPtr != menuPtr) { return; } - + menuSize = [(NSMenu *) menuPtr->platformData size]; Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthPtr, &borderWidth); diff --git a/macosx/tkMacOSXMenubutton.c b/macosx/tkMacOSXMenubutton.c index 93300a0..dbad8db 100644 --- a/macosx/tkMacOSXMenubutton.c +++ b/macosx/tkMacOSXMenubutton.c @@ -348,7 +348,7 @@ TkpComputeMenuButtonGeometry(butPtr) } } } - + butPtr->inset = highlightWidth + butPtr->borderWidth; width += LEFT_INSET + RIGHT_INSET + 2*butPtr->inset; height += 2*butPtr->inset; diff --git a/macosx/tkMacOSXMouseEvent.c b/macosx/tkMacOSXMouseEvent.c index 2848a52..adc24b1 100644 --- a/macosx/tkMacOSXMouseEvent.c +++ b/macosx/tkMacOSXMouseEvent.c @@ -244,7 +244,7 @@ enum { /* * For scroll wheel events we need to send the XEvent here. */ - + CGFloat delta; int coarseDelta; XEvent xEvent; @@ -685,7 +685,6 @@ TkMacOSXGetCapture(void) return captureWinPtr; } - /* * Local Variables: * mode: objc diff --git a/macosx/tkMacOSXSubwindows.c b/macosx/tkMacOSXSubwindows.c index 853abc2..21f40ce 100644 --- a/macosx/tkMacOSXSubwindows.c +++ b/macosx/tkMacOSXSubwindows.c @@ -168,7 +168,7 @@ XMapWindow( } else { [win orderFrontRegardless]; } - + /* * In some cases the toplevel will not be drawn unless we process * all pending events now. See ticket 56a1823c73. diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c index 327132c..3eda4ec 100644 --- a/macosx/tkMacOSXWindowEvent.c +++ b/macosx/tkMacOSXWindowEvent.c @@ -896,7 +896,7 @@ RedisplayView( * Make sure that we are not trying to displaying a view that no longer * exists. */ - + for (NSWindow *w in [NSApp orderedWindows]) { if ([w contentView] == view) { [view setNeedsDisplay:YES]; diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index e68f1d5..e69f9ee 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -1745,7 +1745,7 @@ WmCommandCmd( } return TCL_OK; } - if (Tcl_GetString(objv[3])[0] == 0) { + if (*Tcl_GetString(objv[3]) == '\0') { if (wmPtr->commandObj != NULL) { Tcl_DecrRefCount(wmPtr->commandObj); wmPtr->commandObj = NULL; @@ -3608,7 +3608,7 @@ WmTransientCmd( } return TCL_OK; } - if (Tcl_GetString(objv[3])[0] == '\0') { + if (*Tcl_GetString(objv[3]) == '\0') { RemoveTransient(winPtr); } else { if (TkGetWindowFromObj(interp, tkwin, objv[3], &master) != TCL_OK) { diff --git a/macosx/tkMacOSXWm.h b/macosx/tkMacOSXWm.h index 5f07fe6..20bbb6d 100644 --- a/macosx/tkMacOSXWm.h +++ b/macosx/tkMacOSXWm.h @@ -43,7 +43,7 @@ typedef struct ProtocolHandler { typedef struct Transient { TkWindow *winPtr; int flags; - struct Transient *nextPtr; + struct Transient *nextPtr; } Transient; #define WITHDRAWN_BY_MASTER 0x1 diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index 82b94f3..a1d13de 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -276,7 +276,7 @@ static void GetBackgroundColor( /*---------------------------------------------------------------------- * +++ Single Arrow Buttons -- * - * Used in ListHeaders and Comboboxes. + * Used in ListHeaders and Comboboxes. */ static void DrawDownArrow( @@ -326,7 +326,7 @@ static void DrawUpArrow( /*---------------------------------------------------------------------- * +++ Double Arrow Buttons -- * - * Used in MenuButtons and SpinButtons. + * Used in MenuButtons and SpinButtons. */ static void DrawUpDownArrows( @@ -966,7 +966,7 @@ static void DrawDarkTab( CGContextRestoreGState(context); } } else { - + /* * This is the selected tab; paint it blue. If it is first, cover up * the separator line drawn by the second one. (The selected tab is @@ -1144,7 +1144,7 @@ static Ttk_StateTable ButtonValueTable[] = { {kThemeButtonOn, TTK_STATE_SELECTED, 0}, {kThemeButtonOff, 0, 0} - /* + /* * Others: kThemeDisclosureRight, kThemeDisclosureDown, * kThemeDisclosureLeft */ -- cgit v0.12 From 71c5035aac2580da0a2644e9f047364affbe44eb Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 9 May 2019 20:50:33 +0000 Subject: =?UTF-8?q?Fran=C3=A7ois=20Vogel=20review=20(thanks!).=20Streamlin?= =?UTF-8?q?e=20UNIX=20defaults=20with=20MAC/WIN=20defaults.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- macosx/tkMacOSXDefault.h | 3 --- unix/tkUnixDefault.h | 7 +++---- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/macosx/tkMacOSXDefault.h b/macosx/tkMacOSXDefault.h index c6d998c..f965d22 100644 --- a/macosx/tkMacOSXDefault.h +++ b/macosx/tkMacOSXDefault.h @@ -191,8 +191,6 @@ #define DEF_ENTRY_INSERT_ON_TIME "600" #define DEF_ENTRY_INSERT_WIDTH "1" #define DEF_ENTRY_JUSTIFY "left" -#define DEF_ENTRY_PLACEHOLDER "" -#define DEF_ENTRY_PLACEHOLDERFG "#b3b3b3" #define DEF_ENTRY_READONLY_BG_COLOR NORMAL_BG #define DEF_ENTRY_READONLY_BG_MONO WHITE #define DEF_ENTRY_RELIEF "sunken" @@ -313,7 +311,6 @@ #define DEF_MENU_ACTIVE_BORDER_WIDTH "0" #define DEF_MENU_ACTIVE_FG_COLOR "systemMenuActiveText" #define DEF_MENU_ACTIVE_FG_MONO WHITE -#define DEF_MENU_ACTIVE_RELIEF "flat" #define DEF_MENU_BG_COLOR "systemMenu" #define DEF_MENU_BG_MONO WHITE #define DEF_MENU_BORDER_WIDTH "0" diff --git a/unix/tkUnixDefault.h b/unix/tkUnixDefault.h index 21f6276..6ca0b6f 100644 --- a/unix/tkUnixDefault.h +++ b/unix/tkUnixDefault.h @@ -31,8 +31,7 @@ #define ACTIVE_BG "#ececec" #define SELECT_BG "#c3c3c3" #define TROUGH "#b3b3b3" -#define CHECK_INDICATOR WHITE -#define MENU_INDICATOR BLACK +#define INDICATOR WHITE #define DISABLED "#a3a3a3" /* @@ -79,7 +78,7 @@ #define DEF_LABCHKRAD_RELIEF "flat" #define DEF_BUTTON_REPEAT_DELAY "0" #define DEF_BUTTON_REPEAT_INTERVAL "0" -#define DEF_BUTTON_SELECT_COLOR CHECK_INDICATOR +#define DEF_BUTTON_SELECT_COLOR INDICATOR #define DEF_BUTTON_SELECT_MONO BLACK #define DEF_BUTTON_SELECT_IMAGE ((char *) NULL) #define DEF_BUTTON_STATE "normal" @@ -284,7 +283,7 @@ #define DEF_MENU_FG BLACK #define DEF_MENU_POST_COMMAND "" #define DEF_MENU_RELIEF "raised" -#define DEF_MENU_SELECT_COLOR MENU_INDICATOR +#define DEF_MENU_SELECT_COLOR BLACK #define DEF_MENU_SELECT_MONO BLACK #define DEF_MENU_TAKE_FOCUS "0" #define DEF_MENU_TEAROFF "1" -- cgit v0.12