From 61893d79662bfd5e8aa12d48ebc632d560955af5 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Thu, 20 Aug 2020 10:06:20 +0300 Subject: Added system theme setting --- src/app.c | 37 ++++++++++++++++++++++++++++++++++--- src/ui/macos.m | 42 ++++++++++++++++++++++++++++++++++++++++++ src/ui/util.c | 8 +++++--- 3 files changed, 81 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/app.c b/src/app.c index 670adee2..3eb090a6 100644 --- a/src/app.c +++ b/src/app.c @@ -70,6 +70,7 @@ struct Impl_App { float uiScale; int zoomPercent; enum iColorTheme theme; + iBool useSystemTheme; }; static iApp app_; @@ -113,7 +114,8 @@ static iString *serializePrefs_App_(const iApp *d) { appendFormat_String(str, "sidebar.mode arg:%d\n", mode_SidebarWidget(sidebar)); appendFormat_String(str, "uiscale arg:%f\n", uiScale_Window(d->window)); appendFormat_String(str, "zoom.set arg:%d\n", d->zoomPercent); - appendFormat_String(str, "theme.set arg:%d\n", d->theme); + appendFormat_String(str, "theme.set arg:%d auto:1\n", d->theme); + appendFormat_String(str, "ostheme arg:%d\n", d->useSystemTheme); return str; } @@ -234,6 +236,7 @@ static void init_App_(iApp *d, int argc, char **argv) { d->commandEcho = checkArgument_CommandLine(&d->args, "echo") != NULL; d->initialWindowRect = init_Rect(-1, -1, 800, 500); d->theme = dark_ColorTheme; + d->useSystemTheme = iTrue; d->running = iFalse; d->window = NULL; d->retainWindowSize = iTrue; @@ -452,11 +455,20 @@ static iBool handlePrefsCommands_(iWidget *d, const char *cmd) { toFloat_String(text_InputWidget(findChild_Widget(d, "prefs.uiscale")))); postCommandf_App("retainwindow arg:%d", isSelected_Widget(findChild_Widget(d, "prefs.retainwindow"))); + postCommandf_App("ostheme arg:%d", + isSelected_Widget(findChild_Widget(d, "prefs.ostheme"))); destroy_Widget(d); return iTrue; } - else if (equal_Command(cmd, "theme.changed")) { + else if (equal_Command(cmd, "prefs.ostheme.changed")) { + //setToggle_Widget(findChild_Widget(d, "prefs.ostheme"), arg_Command(cmd)); + postCommandf_App("ostheme arg:%d", arg_Command(cmd)); + } + else if (equal_Command(cmd, "theme.changed")) { updatePrefsThemeButtons_(d); + if (!argLabel_Command(cmd, "auto")) { + setToggle_Widget(findChild_Widget(d, "prefs.ostheme"), iFalse); + } } return iFalse; } @@ -601,6 +613,7 @@ iBool handleCommand_App(const char *cmd) { else if (equal_Command(cmd, "preferences")) { iWidget *dlg = makePreferences_Widget(); updatePrefsThemeButtons_(dlg); + setToggle_Widget(findChild_Widget(dlg, "prefs.ostheme"), d->useSystemTheme); setToggle_Widget(findChild_Widget(dlg, "prefs.retainwindow"), d->retainWindowSize); setText_InputWidget(findChild_Widget(dlg, "prefs.uiscale"), collectNewFormat_String("%g", uiScale_Window(d->window))); @@ -641,11 +654,29 @@ iBool handleCommand_App(const char *cmd) { return iTrue; } else if (equal_Command(cmd, "theme.set")) { + const int isAuto = argLabel_Command(cmd, "auto"); d->theme = arg_Command(cmd); + if (!isAuto) { + postCommand_App("ostheme arg:0"); + } setThemePalette_Color(d->theme); - postCommand_App("theme.changed"); + postCommandf_App("theme.changed auto:%d", isAuto); + return iTrue; + } + else if (equal_Command(cmd, "ostheme")) { + d->useSystemTheme = arg_Command(cmd); return iTrue; } + else if (equal_Command(cmd, "os.theme.changed")) { + if (d->useSystemTheme) { + const int dark = argLabel_Command(cmd, "dark"); + const int contrast = argLabel_Command(cmd, "contrast"); + postCommandf_App("theme.set arg:%d auto:1", + dark ? (contrast ? pureBlack_ColorTheme : dark_ColorTheme) + : (contrast ? pureWhite_ColorTheme : light_ColorTheme)); + } + return iFalse; + } else { return iFalse; } diff --git a/src/ui/macos.m b/src/ui/macos.m index 9ff2f96e..75a3ffe4 100644 --- a/src/ui/macos.m +++ b/src/ui/macos.m @@ -91,6 +91,7 @@ enum iTouchBarVariant { @interface MyDelegate : NSResponder { enum iTouchBarVariant touchBarVariant; + NSString *currentAppearanceName; NSObject *sdlDelegate; NSMutableDictionary *menuCommands; } @@ -105,6 +106,7 @@ enum iTouchBarVariant { - (id)initWithSDLDelegate:(NSObject *)sdl { [super init]; + currentAppearanceName = nil; menuCommands = [[NSMutableDictionary alloc] init]; touchBarVariant = default_TouchBarVariant; sdlDelegate = sdl; @@ -113,6 +115,7 @@ enum iTouchBarVariant { - (void)dealloc { [menuCommands release]; + [currentAppearanceName release]; [super dealloc]; } @@ -121,6 +124,24 @@ enum iTouchBarVariant { self.touchBar = nil; } +static void appearanceChanged_MacOS_(NSString *name) { + const iBool isDark = [name containsString:@"Dark"]; + const iBool isHighContrast = [name containsString:@"HighContrast"]; + postCommandf_App("os.theme.changed dark:%d contrast:%d", isDark ? 1 : 0, isHighContrast ? 1 : 0); + printf("Effective appearance changed: %s\n", [name cStringUsingEncoding:NSUTF8StringEncoding]); + fflush(stdout); +} + +- (void)setAppearance:(NSString *)name { + if (!currentAppearanceName || ![name isEqualToString:currentAppearanceName]) { + if (currentAppearanceName) { + [currentAppearanceName release]; + } + currentAppearanceName = [name retain]; + appearanceChanged_MacOS_(currentAppearanceName); + } +} + - (void)setCommand:(NSString *)command forMenuItem:(NSMenuItem *)menuItem { [menuCommands setObject:command forKey:[menuItem title]]; } @@ -133,6 +154,16 @@ enum iTouchBarVariant { [sdlDelegate applicationDidFinishLaunching:notification]; } +- (void)observeValueForKeyPath:(NSString *)keyPath + ofObject:(id)object + change:(NSDictionary *)change + context:(void *)context { + iUnused(object, change); + if ([keyPath isEqualToString:@"effectiveAppearance"] && context == self) { + [self setAppearance:[[NSApp effectiveAppearance] name]]; + } +} + #if 0 - (NSTouchBar *)makeTouchBar { NSTouchBar *bar = [[NSTouchBar alloc] init]; @@ -344,8 +375,10 @@ void enableMomentumScroll_MacOS(void) { void setupApplication_MacOS(void) { NSApplication *app = [NSApplication sharedApplication]; + //appearanceChanged_MacOS_([[app effectiveAppearance] name]); /* Our delegate will override SDL's delegate. */ MyDelegate *myDel = [[MyDelegate alloc] initWithSDLDelegate:app.delegate]; + [myDel setAppearance:[[app effectiveAppearance] name]]; app.delegate = myDel; NSMenu *appMenu = [[[NSApp mainMenu] itemAtIndex:0] submenu]; NSMenuItem *prefsItem = [appMenu itemWithTitle:@"Preferences…"]; @@ -361,6 +394,10 @@ void setupApplication_MacOS(void) { void insertMenuItems_MacOS(const char *menuLabel, int atIndex, const iMenuItem *items, size_t count) { NSApplication *app = [NSApplication sharedApplication]; MyDelegate *myDel = (MyDelegate *) app.delegate; + [app addObserver:myDel + forKeyPath:@"effectiveAppearance" + options:0 + context:myDel]; NSMenu *appMenu = [app mainMenu]; NSMenuItem *mainItem = [appMenu insertItemWithTitle:[NSString stringWithUTF8String:menuLabel] action:nil @@ -417,6 +454,11 @@ void insertMenuItems_MacOS(const char *menuLabel, int atIndex, const iMenuItem * } void handleCommand_MacOS(const char *cmd) { + if (equal_Command(cmd, "prefs.ostheme.changed")) { + if (arg_Command(cmd)) { + appearanceChanged_MacOS_([[NSApp effectiveAppearance] name]); + } + } #if 0 if (equal_Command(cmd, "tabs.changed")) { MyDelegate *myDel = (MyDelegate *) [[NSApplication sharedApplication] delegate]; diff --git a/src/ui/util.c b/src/ui/util.c index 9f4768d9..918a0671 100644 --- a/src/ui/util.c +++ b/src/ui/util.c @@ -702,9 +702,11 @@ iWidget *makePreferences_Widget(void) { page, iClob(new_Widget()), arrangeVertical_WidgetFlag | arrangeSize_WidgetFlag); iWidget *values = addChildFlags_Widget( page, iClob(new_Widget()), arrangeVertical_WidgetFlag | arrangeSize_WidgetFlag); -// setBackgroundColor_Widget(headings, none_ColorId); -// setBackgroundColor_Widget(values, none_ColorId); - addChild_Widget(headings, iClob(makeHeading_Widget("Theme:"))); +#if defined (iPlatformApple) || defined (iPlatformMSys) + addChild_Widget(headings, iClob(makeHeading_Widget("Use system theme:"))); + addChild_Widget(values, iClob(makeToggle_Widget("prefs.ostheme"))); +#endif + addChild_Widget(headings, iClob(makeHeading_Widget("Theme:"))); iWidget *themes = new_Widget(); /* Themes. */ { setId_Widget(addChild_Widget(themes, iClob(new_LabelWidget("Pure Black", 0, 0, "theme.set arg:0"))), "prefs.theme.0"); -- cgit v1.2.3