diff --git a/lcl/interfaces/cocoa/cocoagdiobjects.pas b/lcl/interfaces/cocoa/cocoagdiobjects.pas index 3de869146e..7155e09ff2 100644 --- a/lcl/interfaces/cocoa/cocoagdiobjects.pas +++ b/lcl/interfaces/cocoa/cocoagdiobjects.pas @@ -1314,8 +1314,13 @@ begin end; procedure TCocoaTextLayout.UpdateColor; +var + lForegroundColor: NSColor; begin - FTextStorage.addAttribute_value_range(NSForegroundColorAttributeName, ColorToNSColor(ForegroundColor), GetTextRange); + lForegroundColor := SysColorToNSColor(SysColorToSysColorIndex(ForegroundColor)); + if lForegroundColor = nil then + lForegroundColor := ColorToNSColor(ColorToRGB(ForegroundColor)); + FTextStorage.addAttribute_value_range(NSForegroundColorAttributeName, lForegroundColor, GetTextRange); FTextStorage.addAttribute_value_range(NSBackgroundColorAttributeName, ColorToNSColor(BackgroundColor), GetTextRange); end; @@ -1688,7 +1693,7 @@ end; procedure TCocoaContext.SetTextColor(AValue: TColor); begin - FText.ForegroundColor := TColor(ColorToRGB(AValue)); + FText.ForegroundColor := AValue; end; procedure TCocoaContext.UpdateContextOfs(const AWindowOfs, AViewOfs: TPoint); diff --git a/lcl/interfaces/cocoa/cocoathemes.pas b/lcl/interfaces/cocoa/cocoathemes.pas index c9d84fb37e..d0fbbefbe6 100644 --- a/lcl/interfaces/cocoa/cocoathemes.pas +++ b/lcl/interfaces/cocoa/cocoathemes.pas @@ -39,10 +39,10 @@ type procedure CellDrawFrame(cell: NSCell; const dst: NSRect); procedure CellDrawEnd(dst: TCocoaContext; cur: NSGraphicsContext); -(* function InitThemes: Boolean; override; function UseThemes: Boolean; override; function ThemedControlsEnabled: Boolean; override; +(* procedure InternalDrawParentBackground({%H-}Window: HWND; {%H-}Target: HDC; {%H-}Bounds: PRect); override; *) function GetDrawState(Details: TThemedElementDetails): ThemeDrawState; @@ -73,25 +73,6 @@ type function GetOption(AOption: TThemeOption): Integer; override; end; -// "dark" is not a good reference, as Apple might add more and more themes -function IsDarkPossible: Boolean; inline; - -// returns if the application appearance is set to dark -function IsAppDark: Boolean; - -// returns if the window appearance is set to dark -function IsWinDark(win: NSWindow): Boolean; - -// Returns the appearance object that is active on the current thread. -// returns true, if currently drawn (Painted) UI control is in Dark theme. -function IsPaintDark: Boolean; - -// returns true, if Appear is assigned and bears name of Dark theme -function IsAppearDark(Appear: NSAppearance): Boolean; inline; - -// weak-referenced NSAppearnceClass. Returns nil on any OS prior to 10.13 -function NSAppearanceClass: pobjc_class; - implementation type @@ -105,80 +86,6 @@ type const IntBool : array [Boolean] of NSInteger = (0,1); -var - _NSAppearanceClass : pobjc_class = nil; - _NSAppearanceClassRead: Boolean = false; - -const - DarkName = 'NSAppearanceNameDarkAqua'; // used in 10.14 - DarkNameVibrant = 'NSAppearanceNameVibrantDark'; // used in 10.13 - -function NSAppearanceClass: pobjc_class; -begin - if not _NSAppearanceClassRead then - begin - _NSAppearanceClass := objc_getClass('NSAppearance'); - _NSAppearanceClassRead := true; - end; - Result := _NSAppearanceClass; -end; - -function IsAppearDark(Appear: NSAppearance): Boolean; inline; -begin - Result := Assigned(Appear) - and ( - Appear.name.isEqualToString(NSSTR(DarkName)) - or - Appear.name.isEqualToString(NSSTR(DarkNameVibrant)) - ) -end; - -function IsDarkPossible: Boolean; inline; -begin - Result := NSAppKitVersionNumber > NSAppKitVersionNumber10_12; -end; - -function IsAppDark: Boolean; -var - Appear: NSAppearance; -begin - if not isDarkPossible then - begin - Result := false; - Exit; - end; - if (not NSApplication(NSApp).respondsToSelector(ObjCSelector('effectiveAppearance'))) then begin - Result := false; - Exit; - end; - - Result := IsAppearDark(NSApplication(NSApp).effectiveAppearance); -end; - -function IsWinDark(win: NSWindow): Boolean; -begin - if not Assigned(win) or not isDarkPossible then - begin - Result := false; - Exit; - end; - if (not win.respondsToSelector(ObjCSelector('effectiveAppearance'))) then begin - Result := false; - Exit; - end; - - Result := IsAppearDark(win.effectiveAppearance); -end; - -function IsPaintDark: Boolean; -var - cls : pobjc_class; -begin - cls := NSAppearanceClass; - if not Assigned(cls) then Exit; - Result := IsAppearDark(objc_msgSend(cls, ObjCSelector('currentAppearance'))); -end; - { TCocoaThemeServices } {------------------------------------------------------------------------------ @@ -713,34 +620,34 @@ begin Result := CGRectToRect(BtnRect); OffsetRect(Result, Offset.X, Offset.Y); end; - +*) {------------------------------------------------------------------------------ - Method: TCarbonThemeServices.InitThemes + Method: TCocoaThemeServices.InitThemes Returns: If the themes are initialized ------------------------------------------------------------------------------} -function TCarbonThemeServices.InitThemes: Boolean; +function TCocoaThemeServices.InitThemes: Boolean; begin Result := True; end; {------------------------------------------------------------------------------ - Method: TCarbonThemeServices.InitThemes + Method: TCocoaThemeServices.InitThemes Returns: If the themes have to be used ------------------------------------------------------------------------------} -function TCarbonThemeServices.UseThemes: Boolean; +function TCocoaThemeServices.UseThemes: Boolean; begin Result := True; end; {------------------------------------------------------------------------------ - Method: TCarbonThemeServices.ThemedControlsEnabled + Method: TCocoaThemeServices.ThemedControlsEnabled Returns: If the themed controls are enabled ------------------------------------------------------------------------------} -function TCarbonThemeServices.ThemedControlsEnabled: Boolean; +function TCocoaThemeServices.ThemedControlsEnabled: Boolean; begin Result := True; end; - +(* {------------------------------------------------------------------------------ Method: TCarbonThemeServices.ContentRect Params: DC - Carbon device context diff --git a/lcl/interfaces/cocoa/cocoautils.pas b/lcl/interfaces/cocoa/cocoautils.pas index 6205783aae..a2bfb41020 100644 --- a/lcl/interfaces/cocoa/cocoautils.pas +++ b/lcl/interfaces/cocoa/cocoautils.pas @@ -65,6 +65,27 @@ function NSColorToRGB(const Color: NSColor): TColorRef; inline; // extract ColorRef from any NSColor function NSColorToColorRef(const Color: NSColor): TColorRef; function ColorToNSColor(const Color: TColorRef): NSColor; inline; +// convert to known NSColor or nil +function SysColorToNSColor(nIndex: Integer): NSColor; + +// "dark" is not a good reference, as Apple might add more and more themes +function IsDarkPossible: Boolean; inline; + +// returns if the application appearance is set to dark +function IsAppDark: Boolean; + +// returns if the window appearance is set to dark +function IsWinDark(win: NSWindow): Boolean; + +// Returns the appearance object that is active on the current thread. +// returns true, if currently drawn (Painted) UI control is in Dark theme. +function IsPaintDark: Boolean; + +// returns true, if Appear is assigned and bears name of Dark theme +function IsAppearDark(Appear: NSAppearance): Boolean; inline; + +// weak-referenced NSAppearnceClass. Returns nil on any OS prior to 10.13 +function NSAppearanceClass: pobjc_class; const DEFAULT_CFSTRING_ENCODING = kCFStringEncodingUTF8; @@ -445,6 +466,173 @@ begin ((Color shr 16) and $FF) / $FF, 1); end; +function SysColorToNSColor(nIndex: Integer): NSColor; +const + ToolTipBack = $C9FCF9; + ToolTipBack1010 = $EDEDED; + ToolTipBack1014 = $f0f0f0; + ToolTipBack1014Dark = $343434; +begin + case NIndex of + COLOR_GRADIENTACTIVECAPTION, COLOR_ACTIVECAPTION, + COLOR_WINDOWFRAME, COLOR_ACTIVEBORDER: + Result := NSColor.windowFrameColor; + COLOR_GRADIENTINACTIVECAPTION, COLOR_INACTIVECAPTION, COLOR_INACTIVEBORDER: + Result := NSColor.windowBackgroundColor; + COLOR_CAPTIONTEXT, + COLOR_INACTIVECAPTIONTEXT: + Result := NSColor.windowFrameTextColor; + COLOR_WINDOW: + Result := NSColor.textBackgroundColor; + COLOR_BACKGROUND, + COLOR_FORM: + Result := NSColor.windowBackgroundColor; + COLOR_MENU: + Result := NSColor.controlBackgroundColor; + COLOR_MENUTEXT: + Result := NSColor.controlTextColor; + COLOR_MENUBAR: + Result := NSColor.selectedTextBackgroundColor; + COLOR_MENUHILIGHT: + Result := NSColor.selectedMenuItemColor; + COLOR_WINDOWTEXT: + Result := NSColor.controlTextColor; + COLOR_APPWORKSPACE: + Result := NSColor.windowBackgroundColor; + COLOR_HIGHLIGHT: + Result := NSColor.selectedControlColor; + COLOR_HOTLIGHT: + Result := NSColor.alternateSelectedControlColor; + COLOR_HIGHLIGHTTEXT: + Result := NSColor.selectedControlTextColor; + COLOR_SCROLLBAR: + Result := NSColor.scrollBarColor; + COLOR_BTNFACE: + Result := NSColor.controlBackgroundColor; + COLOR_BTNSHADOW: // COLOR_3DSHADOW + if NSAppKitVersionNumber >= NSAppKitVersionNumber10_14 then + Result := NSColor.controlColor.shadowWithLevel(0.5) + else + Result := NSColor.controlShadowColor; + COLOR_BTNHIGHLIGHT: + if NSAppKitVersionNumber >= NSAppKitVersionNumber10_14 then + Result := NSColor.controlColor.shadowWithLevel(0.0) + else + Result := NSColor.controlLightHighlightColor;//controlHighlightColor has no contrast with COLOR_BTNFACE which affects TBevel. In Win32 this has value white + COLOR_BTNTEXT: + Result := NSColor.controlTextColor; + COLOR_GRAYTEXT: + Result := NSColor.disabledControlTextColor; + COLOR_3DDKSHADOW: + if NSAppKitVersionNumber >= NSAppKitVersionNumber10_14 then + Result := NSColor.controlColor.shadowWithLevel(0.75) + else + Result := NSColor.controlDarkShadowColor; + COLOR_3DLIGHT: + if NSAppKitVersionNumber >= NSAppKitVersionNumber10_14 then + Result := NSColor.controlColor.shadowWithLevel(0.25) + else + Result := NSColor.controlHighlightColor;// makes a more consistent result (a very light gray) than controlLightHighlightColor (which is white) + + // macOS doesn't provide any API to get the hint window colors. + // default = macosx10.4 yellow color. (See InitInternals below) + // it's likely the tooltip color will change in future. + // Thus the variable is left public, so a user of LCL + // would be able to initialize it properly on start + COLOR_INFOTEXT: + Result := NSColor.controlTextColor; + COLOR_INFOBK: + begin + if NSAppKitVersionNumber >= NSAppKitVersionNumber10_14 then + begin + if IsPaintDark then + Result := ColorToNSColor(ToolTipBack1014Dark) + else + Result := ColorToNSColor(ToolTipBack1014); + end else if NSAppKitVersionNumber >= NSAppKitVersionNumber10_10 then + Result := ColorToNSColor(ToolTipBack1010) + else + Result := ColorToNSColor(ToolTipBack); + end; + else + Result := nil; + end; +end; + +var + _NSAppearanceClass : pobjc_class = nil; + _NSAppearanceClassRead: Boolean = false; + +const + DarkName = 'NSAppearanceNameDarkAqua'; // used in 10.14 + DarkNameVibrant = 'NSAppearanceNameVibrantDark'; // used in 10.13 + +function NSAppearanceClass: pobjc_class; +begin + if not _NSAppearanceClassRead then + begin + _NSAppearanceClass := objc_getClass('NSAppearance'); + _NSAppearanceClassRead := true; + end; + Result := _NSAppearanceClass; +end; + +function IsAppearDark(Appear: NSAppearance): Boolean; inline; +begin + Result := Assigned(Appear) + and ( + Appear.name.isEqualToString(NSSTR(DarkName)) + or + Appear.name.isEqualToString(NSSTR(DarkNameVibrant)) + ) +end; + +function IsDarkPossible: Boolean; inline; +begin + Result := NSAppKitVersionNumber > NSAppKitVersionNumber10_12; +end; + +function IsAppDark: Boolean; +var + Appear: NSAppearance; +begin + if not isDarkPossible then + begin + Result := false; + Exit; + end; + if (not NSApplication(NSApp).respondsToSelector(ObjCSelector('effectiveAppearance'))) then begin + Result := false; + Exit; + end; + + Result := IsAppearDark(NSApplication(NSApp).effectiveAppearance); +end; + +function IsWinDark(win: NSWindow): Boolean; +begin + if not Assigned(win) or not isDarkPossible then + begin + Result := false; + Exit; + end; + if (not win.respondsToSelector(ObjCSelector('effectiveAppearance'))) then begin + Result := false; + Exit; + end; + + Result := IsAppearDark(win.effectiveAppearance); +end; + +function IsPaintDark: Boolean; +var + cls : pobjc_class; +begin + cls := NSAppearanceClass; + if not Assigned(cls) then Exit; + Result := IsAppearDark(objc_msgSend(cls, ObjCSelector('currentAppearance'))); +end; + function CFStringToString(AString: CFStringRef): String; begin result:=CFStringToStr(AString); diff --git a/lcl/interfaces/cocoa/cocoawinapi.inc b/lcl/interfaces/cocoa/cocoawinapi.inc index e224b16ab3..5dc6ed4689 100644 --- a/lcl/interfaces/cocoa/cocoawinapi.inc +++ b/lcl/interfaces/cocoa/cocoawinapi.inc @@ -1701,99 +1701,6 @@ begin end; end; -function SysColorToNSColor(nIndex: Integer): NSColor; -const - ToolTipBack = $C9FCF9; - ToolTipBack1010 = $EDEDED; - ToolTipBack1014 = $f0f0f0; - ToolTipBack1014Dark = $343434; -begin - case NIndex of - COLOR_GRADIENTACTIVECAPTION, COLOR_ACTIVECAPTION, - COLOR_WINDOWFRAME, COLOR_ACTIVEBORDER: - Result := NSColor.windowFrameColor; - COLOR_GRADIENTINACTIVECAPTION, COLOR_INACTIVECAPTION, COLOR_INACTIVEBORDER: - Result := NSColor.windowBackgroundColor; - COLOR_CAPTIONTEXT, - COLOR_INACTIVECAPTIONTEXT: - Result := NSColor.windowFrameTextColor; - COLOR_WINDOW: - Result := NSColor.textBackgroundColor; - COLOR_BACKGROUND, - COLOR_FORM: - Result := NSColor.windowBackgroundColor; - COLOR_MENU: - Result := NSColor.controlBackgroundColor; - COLOR_MENUTEXT: - Result := NSColor.controlTextColor; - COLOR_MENUBAR: - Result := NSColor.selectedTextBackgroundColor; - COLOR_MENUHILIGHT: - Result := NSColor.selectedMenuItemColor; - COLOR_WINDOWTEXT: - Result := NSColor.controlTextColor; - COLOR_APPWORKSPACE: - Result := NSColor.windowBackgroundColor; - COLOR_HIGHLIGHT: - Result := NSColor.selectedControlColor; - COLOR_HOTLIGHT: - Result := NSColor.alternateSelectedControlColor; - COLOR_HIGHLIGHTTEXT: - Result := NSColor.selectedControlTextColor; - COLOR_SCROLLBAR: - Result := NSColor.scrollBarColor; - COLOR_BTNFACE: - Result := NSColor.controlBackgroundColor; - COLOR_BTNSHADOW: // COLOR_3DSHADOW - if NSAppKitVersionNumber >= NSAppKitVersionNumber10_14 then - Result := NSColor.controlColor.shadowWithLevel(0.5) - else - Result := NSColor.controlShadowColor; - COLOR_BTNHIGHLIGHT: - if NSAppKitVersionNumber >= NSAppKitVersionNumber10_14 then - Result := NSColor.controlColor.shadowWithLevel(0.0) - else - Result := NSColor.controlLightHighlightColor;//controlHighlightColor has no contrast with COLOR_BTNFACE which affects TBevel. In Win32 this has value white - COLOR_BTNTEXT: - Result := NSColor.controlTextColor; - COLOR_GRAYTEXT: - Result := NSColor.disabledControlTextColor; - COLOR_3DDKSHADOW: - if NSAppKitVersionNumber >= NSAppKitVersionNumber10_14 then - Result := NSColor.controlColor.shadowWithLevel(0.75) - else - Result := NSColor.controlDarkShadowColor; - COLOR_3DLIGHT: - if NSAppKitVersionNumber >= NSAppKitVersionNumber10_14 then - Result := NSColor.controlColor.shadowWithLevel(0.25) - else - Result := NSColor.controlHighlightColor;// makes a more consistent result (a very light gray) than controlLightHighlightColor (which is white) - - // macOS doesn't provide any API to get the hint window colors. - // default = macosx10.4 yellow color. (See InitInternals below) - // it's likely the tooltip color will change in future. - // Thus the variable is left public, so a user of LCL - // would be able to initialize it properly on start - COLOR_INFOTEXT: - Result := NSColor.controlTextColor; - COLOR_INFOBK: - begin - if NSAppKitVersionNumber >= NSAppKitVersionNumber10_14 then - begin - if IsPaintDark then - Result := ColorToNSColor(ToolTipBack1014Dark) - else - Result := ColorToNSColor(ToolTipBack1014); - end else if NSAppKitVersionNumber >= NSAppKitVersionNumber10_10 then - Result := ColorToNSColor(ToolTipBack1010) - else - Result := ColorToNSColor(ToolTipBack); - end; - else - Result := nil; - end; -end; - function TCocoaWidgetSet.GetSysColor(nIndex: Integer): DWORD; var Color: NSColor; @@ -2759,7 +2666,7 @@ var begin ctx := CheckDC(DC); if Assigned(ctx) then - Result := ctx.TextColor + Result := ColorToRGB(ctx.TextColor) else Result := CLR_INVALID; end;