diff options
author | B. Stack <bgstack15@gmail.com> | 2025-01-20 19:25:18 -0500 |
---|---|---|
committer | B. Stack <bgstack15@gmail.com> | 2025-01-20 19:25:18 -0500 |
commit | de65d3c0295894f8eafc4c7582dfe180dc58c81e (patch) | |
tree | 3ba8ec770b81468ca4ad83d985b991c5f669de22 /wx+/darkmode.cpp | |
parent | add upstream 13.9 (diff) | |
download | FreeFileSync-master.tar.gz FreeFileSync-master.tar.bz2 FreeFileSync-master.zip |
Diffstat (limited to 'wx+/darkmode.cpp')
-rw-r--r-- | wx+/darkmode.cpp | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/wx+/darkmode.cpp b/wx+/darkmode.cpp new file mode 100644 index 00000000..c8a7ea28 --- /dev/null +++ b/wx+/darkmode.cpp @@ -0,0 +1,110 @@ +// ***************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: https://www.gnu.org/licenses/gpl-3.0 * +// * Copyright (C) Zenju (zenju AT freefilesync DOT org) - All Rights Reserved * +// ***************************************************************************** + +#include "darkmode.h" +#include <zen/sys_version.h> +#include <wx/settings.h> +#include "color_tools.h" + #include <gtk/gtk.h> + +using namespace zen; + + +bool zen::darkModeAvailable() +{ + +#if GTK_MAJOR_VERSION == 2 + return false; +#elif GTK_MAJOR_VERSION >= 3 + return true; +#else +#error unknown GTK version! +#endif + +} + + +namespace +{ +class SysColorsHook : public wxColorHook +{ +public: + + wxColor getColor(wxSystemColour index) const override + { + //fix contrast e.g. Ubuntu's Adwaita-Dark theme and macOS dark mode: + if (index == wxSYS_COLOUR_GRAYTEXT) + return colGreyTextEnhContrast_; +#if 0 + auto colToString = [](wxColor c) + { + const auto& [rh, rl] = hexify(c.Red ()); + const auto& [gh, gl] = hexify(c.Green()); + const auto& [bh, bl] = hexify(c.Blue ()); + const auto& [ah, al] = hexify(c.Alpha()); + return "#" + std::string({rh, rl, gh, gl, bh, bl, ah, al}); + }; + std::cerr << "wxSYS_COLOUR_GRAYTEXT " << colToString(wxSystemSettingsNative::GetColour(wxSYS_COLOUR_GRAYTEXT)) << "\n"; +#endif + return wxSystemSettingsNative::GetColour(index); //fallback + } + +private: + const wxColor colGreyTextEnhContrast_ = + enhanceContrast(wxSystemSettingsNative::GetColour(wxSYS_COLOUR_GRAYTEXT), + wxSystemSettingsNative::GetColour(wxSYS_COLOUR_WINDOWTEXT), + wxSystemSettingsNative::GetColour(wxSYS_COLOUR_WINDOW), 4.5 /*contrastRatioMin*/); //W3C recommends >= 4.5 +}; + + +std::optional<bool> globalDefaultThemeIsDark; +} + + +void zen::colorThemeInit(wxApp& app, ColorTheme colTheme) //throw FileError +{ + assert(!refGlobalColorHook()); + + globalDefaultThemeIsDark = wxSystemSettings::GetAppearance().AreAppsDark(); + ZEN_ON_SCOPE_EXIT(if (!refGlobalColorHook()) refGlobalColorHook() = std::make_unique<SysColorsHook>()); //*after* SetAppearance() and despite errors + + //caveat: on macOS there are more themes than light/dark: https://developer.apple.com/documentation/appkit/nsappearance/name-swift.struct + if (colTheme != ColorTheme::System && //"System" is already the default for macOS/Linux(GTK3) + darkModeAvailable()) + changeColorTheme(colTheme); //throw FileError +} + + +void zen::colorThemeCleanup() +{ + assert(refGlobalColorHook()); + refGlobalColorHook().reset(); +} + + +bool zen::equalAppearance(ColorTheme colTheme1, ColorTheme colTheme2) +{ + if (colTheme1 == ColorTheme::System) colTheme1 = *globalDefaultThemeIsDark ? ColorTheme::Dark : ColorTheme::Light; + if (colTheme2 == ColorTheme::System) colTheme2 = *globalDefaultThemeIsDark ? ColorTheme::Dark : ColorTheme::Light; + return colTheme1 == colTheme2; +} + + +void zen::changeColorTheme(ColorTheme colTheme) //throw FileError +{ + if (colTheme == ColorTheme::System) //SetAppearance(System) isn't working reliably! surprise!? + colTheme = *globalDefaultThemeIsDark ? ColorTheme::Dark : ColorTheme::Light; + + try + { + ZEN_ON_SCOPE_SUCCESS(refGlobalColorHook() = std::make_unique<SysColorsHook>()); //*after* SetAppearance() + if (wxApp::AppearanceResult rv = wxTheApp->SetAppearance(colTheme); + rv != wxApp::AppearanceResult::Ok) + throw SysError(formatSystemError("wxApp::SetAppearance", + rv == wxApp::AppearanceResult::CannotChange ? L"CannotChange" : L"Failure", L"" /*errorMsg*/)); + } + catch (const SysError& e) { throw FileError(_("Failed to update the color theme."), e.toString()); } +} |