From c4e5d6b223f0a584d71eb4097d38d2381d052aa1 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sun, 5 Jan 2025 05:17:07 -0500 Subject: [PATCH 1/4] Add method that tells the app/backend that we are using a dark mode theme --- Headers/Additions/GNUstepGUI/GSTheme.h | 9 +++++++++ Source/GSTheme.m | 5 +++++ 2 files changed, 14 insertions(+) diff --git a/Headers/Additions/GNUstepGUI/GSTheme.h b/Headers/Additions/GNUstepGUI/GSTheme.h index 643617cac8..e02476acc4 100644 --- a/Headers/Additions/GNUstepGUI/GSTheme.h +++ b/Headers/Additions/GNUstepGUI/GSTheme.h @@ -783,6 +783,15 @@ APPKIT_EXPORT_CLASS */ - (NSString*) license; +/** + * Returns YES if in dark mode, and NO, if not. The reasoning behind this + * is that some applications may display on the screen in dark mode, but + * print with the colors reversed. This method allows GUI and the backend + * to understand when we are using a dark theme and render accordingly when + * printing. The default is NO, as the default theme is not a dark theme. + */ +- (BOOL) isDarkMode; + @end /** diff --git a/Source/GSTheme.m b/Source/GSTheme.m index 2067be731f..066784d695 100644 --- a/Source/GSTheme.m +++ b/Source/GSTheme.m @@ -1339,6 +1339,11 @@ - (NSString *) license return [[self infoDictionary] objectForKey: @"GSThemeLicense"]; } +- (BOOL) isDarkMode +{ + return NO; +} + @end @implementation GSTheme (Private) From 9568ec7fb99120a68ba0fc8640333f2c4e91cbda Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sun, 5 Jan 2025 20:42:06 -0500 Subject: [PATCH 2/4] Add method that tells the app/backend that we are using a dark mode theme --- Headers/Additions/GNUstepGUI/GSTheme.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Headers/Additions/GNUstepGUI/GSTheme.h b/Headers/Additions/GNUstepGUI/GSTheme.h index e02476acc4..8c81090eef 100644 --- a/Headers/Additions/GNUstepGUI/GSTheme.h +++ b/Headers/Additions/GNUstepGUI/GSTheme.h @@ -784,7 +784,7 @@ APPKIT_EXPORT_CLASS - (NSString*) license; /** - * Returns YES if in dark mode, and NO, if not. The reasoning behind this + * Returns YES if in dark mode, or NO, if not. The reasoning behind this * is that some applications may display on the screen in dark mode, but * print with the colors reversed. This method allows GUI and the backend * to understand when we are using a dark theme and render accordingly when From 04c72e874c53e102251a598e2133e666853b81e1 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Wed, 8 Jan 2025 07:45:01 -0500 Subject: [PATCH 3/4] Use GSThemeDarkMode setting in the theme as the return value instead of it being hard coded --- Source/GSTheme.m | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/GSTheme.m b/Source/GSTheme.m index 066784d695..b3a3fbe313 100644 --- a/Source/GSTheme.m +++ b/Source/GSTheme.m @@ -1341,7 +1341,8 @@ - (NSString *) license - (BOOL) isDarkMode { - return NO; + return [[[self infoDictionary] objectForKey: @"GSThemeDarkMode"] + isEqualToString: @"YES"]; } @end From c92bf339b6b92addb088e27cdff69586c456c572 Mon Sep 17 00:00:00 2001 From: Riccardo Mottola Date: Mon, 9 Jun 2025 13:31:52 +0200 Subject: [PATCH 4/4] Split information of what a Theme supports from what is actually being run. In the future, like Aqua, we might support Themes having both Light and Dark Appearance. Change wording from Mode to Appearance, since Apple has NSAppearance. --- Headers/Additions/GNUstepGUI/GSTheme.h | 38 +++++++++++++--- Source/GSTheme.m | 63 ++++++++++++++++++++++++-- 2 files changed, 92 insertions(+), 9 deletions(-) diff --git a/Headers/Additions/GNUstepGUI/GSTheme.h b/Headers/Additions/GNUstepGUI/GSTheme.h index 8c81090eef..e0892984d3 100644 --- a/Headers/Additions/GNUstepGUI/GSTheme.h +++ b/Headers/Additions/GNUstepGUI/GSTheme.h @@ -784,13 +784,39 @@ APPKIT_EXPORT_CLASS - (NSString*) license; /** - * Returns YES if in dark mode, or NO, if not. The reasoning behind this - * is that some applications may display on the screen in dark mode, but - * print with the colors reversed. This method allows GUI and the backend - * to understand when we are using a dark theme and render accordingly when - * printing. The default is NO, as the default theme is not a dark theme. + * Returns YES if Theme is able to display in Light NSAppearance + * For a theme supporting both Light and Dark modes, it should return both + * supportsLightAppearance and supportsDarkAppearance + * Light is the "default" of the GNUstep theme like Cocoa Aqua. */ -- (BOOL) isDarkMode; +- (BOOL) supportsLightAppearance; + +/** + * Returns YES if Theme is able to display in Dark NSAppearance + * For a theme supporting both Light and Dark modes, it should return both + * supportsLightAppearance and supportsDarkAppearance + * Light is the default Aqua and GNUstep "classic", but a GNUstep can be dark only. + */ +- (BOOL) supportsDarkAppearance; + +/** + * Returns YES if displaying in Light NSAppearance (or non-Dark) + * Should match if theme is equivalent to Cocoa names like + * NSAppearanceNameAqua or NSAppearanceNameAccessibilityHighContrastAqua + * + * Being only Light and Dark supported, must be opposite of inDarkAppearance + */ +- (BOOL) inLightAppearance; + +/** + * Returns YES if displaying in dark NSAppearance + * Should match if theme is equivalent to Cocoa names like + * NSAppearanceNameDarkAqua or NSAppearanceNameAccessibilityHighContrastDarkAqua + * + * Being only Light and Dark supported, must be opposite of inLightAppearance + */ +- (BOOL) inDarkAppearance; + @end diff --git a/Source/GSTheme.m b/Source/GSTheme.m index b3a3fbe313..35c214eaf0 100644 --- a/Source/GSTheme.m +++ b/Source/GSTheme.m @@ -1339,12 +1339,69 @@ - (NSString *) license return [[self infoDictionary] objectForKey: @"GSThemeLicense"]; } -- (BOOL) isDarkMode +- (BOOL) supportsLightAppearance { - return [[[self infoDictionary] objectForKey: @"GSThemeDarkMode"] - isEqualToString: @"YES"]; + NSString *val; + BOOL r; + + r = YES; // default themes are light + val = [[self infoDictionary] objectForKey: @"GSThemeSupportsLightAppearance"]; + + if (val && [val isEqualToString: @"YES"]) + r = YES; + + return r; } +- (BOOL) supportsDarkAppearance +{ + NSString *val; + BOOL r; + + r = NO; // default themes are light + val = [[self infoDictionary] objectForKey: @"GSThemeSupportsDarkAppearance"]; + + // Do we have the key or is it an old GSTheme? + if (val == nil) + { + // try heuristic on the theme name + if ([[self name] hasSuffix:@"Dark"]) + { + r = YES; + } + } + else + { + if ([val isEqualToString: @"YES"]) + { + r = YES; + } + } + + return r; +} + +- (BOOL) inLightAppearance +{ + // NOTE: maybe we should cache this in an ivar + if (![self supportsLightAppearance] && [self supportsDarkAppearance]) + { + return NO; + } + return YES; +} + +- (BOOL) inDarkAppearance; +{ + // NOTE: maybe we should cache this in an ivar + if (![self supportsLightAppearance] && [self supportsDarkAppearance]) + { + return YES; + } + return NO; +} + + @end @implementation GSTheme (Private)