From 5855acae88f2824503d6047b5158f69da8f6a731 Mon Sep 17 00:00:00 2001 From: fxliang Date: Sat, 16 Dec 2023 08:38:58 +0800 Subject: [PATCH] feat: style/color_scheme_dark: {string}, auto light/dark mode switching for windows 10 1809+ (#1046) --- RimeWithWeasel/RimeWithWeasel.cpp | 76 ++++++++++++++++++++++++++-- WeaselIPCServer/WeaselServerImpl.cpp | 11 ++++ WeaselIPCServer/WeaselServerImpl.h | 3 ++ include/RimeWithWeasel.h | 3 ++ include/WeaselIPC.h | 1 + include/WeaselUtility.h | 14 +++++ 6 files changed, 105 insertions(+), 3 deletions(-) diff --git a/RimeWithWeasel/RimeWithWeasel.cpp b/RimeWithWeasel/RimeWithWeasel.cpp index b58df17f4..edf6d00b2 100644 --- a/RimeWithWeasel/RimeWithWeasel.cpp +++ b/RimeWithWeasel/RimeWithWeasel.cpp @@ -44,6 +44,7 @@ RimeWithWeaselHandler::RimeWithWeaselHandler(UI *ui) : m_ui(ui) , m_active_session(0) , m_disabled(true) + , m_current_dark_mode(false) , m_show_notifications_when(SHOWN_ALWAYS) , _UpdateUICallback(NULL) { @@ -107,6 +108,15 @@ void RimeWithWeaselHandler::Initialize() { _UpdateUIStyle(&config, m_ui, true); _UpdateShowNotificationsWhen(&config, &m_show_notifications_when); + m_current_dark_mode = IsUserDarkMode(); + if(m_current_dark_mode) { + const int BUF_SIZE = 255; + char buffer[BUF_SIZE + 1] = { 0 }; + if (RimeConfigGetString(&config, "style/color_scheme_dark", buffer, BUF_SIZE)){ + std::string color_name(buffer); + _UpdateUIStyleColor(&config, m_ui->style(), color_name); + } + } m_base_style = m_ui->style(); } _LoadAppOptions(&config, m_app_options); @@ -160,6 +170,7 @@ UINT RimeWithWeaselHandler::AddSession(LPWSTR buffer, EatLine eat) } _UpdateUI(session_id); m_active_session = session_id; + m_color_sync[session_id] = false; return session_id; } @@ -170,6 +181,7 @@ UINT RimeWithWeaselHandler::RemoveSession(UINT session_id) DLOG(INFO) << "Remove session: session_id = " << session_id; // TODO: force committing? otherwise current composition would be lost RimeDestroySession(session_id); + m_color_sync.erase(session_id); m_active_session = 0; return 0; } @@ -185,6 +197,44 @@ namespace ibus }; } +void RimeWithWeaselHandler::UpdateColorTheme(BOOL darkMode) +{ + RimeConfig config = { NULL }; + if (RimeConfigOpen("weasel", &config)) + { + if (m_ui) + { + _UpdateUIStyle(&config, m_ui, true); + m_current_dark_mode = darkMode; + if(darkMode) { + const int BUF_SIZE = 255; + char buffer[BUF_SIZE + 1] = { 0 }; + if (RimeConfigGetString(&config, "style/color_scheme_dark", buffer, BUF_SIZE)) { + std::string color_name(buffer); + _UpdateUIStyleColor(&config, m_ui->style(), color_name); + } + } + m_base_style = m_ui->style(); + } + _LoadAppOptions(&config, m_app_options); + RIME_STRUCT(RimeStatus, status); + if (RimeGetStatus(m_active_session, &status)) + { + _LoadSchemaSpecificSettings(std::string(status.schema_id)); + _LoadAppInlinePreeditSet(m_active_session, true); + _UpdateInlinePreeditStatus(m_active_session); + RimeFreeStatus(&status); + } + RimeConfigClose(&config); + } + + RimeSetOption(m_active_session, "__synced", false); + _LoadAppInlinePreeditSet(m_active_session); + _UpdateInlinePreeditStatus(m_active_session); + for(auto &pair : m_color_sync) + pair.second = false; +} + BOOL RimeWithWeaselHandler::ProcessKeyEvent(KeyEvent keyEvent, UINT session_id, EatLine eat) { DLOG(INFO) << "Process key event: keycode = " << keyEvent.keycode << ", mask = " << keyEvent.mask @@ -467,7 +517,25 @@ void RimeWithWeaselHandler::_LoadSchemaSpecificSettings(const std::string& schem // load schema color style config memset(buffer, '\0', sizeof(buffer)); - if (RimeConfigGetString(&config, "style/color_scheme", buffer, BUF_SIZE)) + if (!m_current_dark_mode && RimeConfigGetString(&config, "style/color_scheme", buffer, BUF_SIZE)) + { + std::string color_name(buffer); + RimeConfigIterator preset = {0}; + if(RimeConfigBeginMap(&preset, &config, ("preset_color_schemes/" + color_name).c_str())) + { + _UpdateUIStyleColor(&config, m_ui->style(), color_name); + } + else + { + RimeConfig weaselconfig; + if (RimeConfigOpen("weasel", &weaselconfig)) + { + _UpdateUIStyleColor(&weaselconfig, m_ui->style(), std::string(buffer)); + RimeConfigClose(&weaselconfig); + } + } + } + else if (m_current_dark_mode && RimeConfigGetString(&config, "style/color_scheme_dark", buffer, BUF_SIZE)) { std::string color_name(buffer); RimeConfigIterator preset = {0}; @@ -720,14 +788,16 @@ bool RimeWithWeaselHandler::_Respond(UINT session_id, EatLine eat) // style bool has_synced = RimeGetOption(session_id, "__synced"); - if (!has_synced) { + if (!has_synced || !m_color_sync[session_id]) { std::wstringstream ss; boost::archive::text_woarchive oa(ss); oa << m_ui->style(); actions.insert("style"); messages.push_back(std::string("style=") + wstring_to_string(ss.str().c_str(), CP_UTF8) + '\n'); - RimeSetOption(session_id, "__synced", true); + if(!has_synced) + RimeSetOption(session_id, "__synced", true); + m_color_sync[session_id] = TRUE; } // summarize diff --git a/WeaselIPCServer/WeaselServerImpl.cpp b/WeaselIPCServer/WeaselServerImpl.cpp index 3ac82d96c..de950f460 100644 --- a/WeaselIPCServer/WeaselServerImpl.cpp +++ b/WeaselIPCServer/WeaselServerImpl.cpp @@ -2,6 +2,7 @@ #include "WeaselServerImpl.h" #include #include +#include namespace weasel { class PipeServer : public PipeChannel @@ -29,6 +30,7 @@ extern CAppModule _Module; ServerImpl::ServerImpl() : m_pRequestHandler(NULL), + m_darkMode(IsUserDarkMode()), channel(std::make_unique(GetPipeName(), sa.get_attr())) { m_hUser32Module = GetModuleHandle(_T("user32.dll")); @@ -56,6 +58,15 @@ void ServerImpl::_Finailize() } } +LRESULT ServerImpl::OnColorChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) +{ + if(IsUserDarkMode() != m_darkMode) { + m_darkMode = IsUserDarkMode(); + m_pRequestHandler->UpdateColorTheme(m_darkMode); + } + return 0; +} + LRESULT ServerImpl::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { // not neccessary... diff --git a/WeaselIPCServer/WeaselServerImpl.h b/WeaselIPCServer/WeaselServerImpl.h index e2ed389bf..930780d4c 100644 --- a/WeaselIPCServer/WeaselServerImpl.h +++ b/WeaselIPCServer/WeaselServerImpl.h @@ -27,9 +27,11 @@ namespace weasel MESSAGE_HANDLER(WM_CLOSE, OnClose) MESSAGE_HANDLER(WM_QUERYENDSESSION, OnQueryEndSystemSession) MESSAGE_HANDLER(WM_ENDSESSION, OnEndSystemSession) + MESSAGE_HANDLER(WM_DWMCOLORIZATIONCOLORCHANGED, OnColorChange) MESSAGE_HANDLER(WM_COMMAND, OnCommand) END_MSG_MAP() + LRESULT OnColorChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); LRESULT OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); @@ -79,6 +81,7 @@ namespace weasel std::map m_MenuHandlers; HMODULE m_hUser32Module; SecurityAttribute sa; + BOOL m_darkMode; }; diff --git a/include/RimeWithWeasel.h b/include/RimeWithWeasel.h index 650ca0d6f..56f31b5d4 100644 --- a/include/RimeWithWeasel.h +++ b/include/RimeWithWeasel.h @@ -40,6 +40,7 @@ class RimeWithWeaselHandler : virtual void StartMaintenance(); virtual void EndMaintenance(); virtual void SetOption(UINT session_id, const std::string &opt, bool val); + virtual void UpdateColorTheme(BOOL darkMode); void OnUpdateUI(std::function const &cb); @@ -76,4 +77,6 @@ class RimeWithWeaselHandler : const char* message_value); static std::string m_message_type; static std::string m_message_value; + std::map m_color_sync; + bool m_current_dark_mode; }; diff --git a/include/WeaselIPC.h b/include/WeaselIPC.h index 3df3aca08..91b869009 100644 --- a/include/WeaselIPC.h +++ b/include/WeaselIPC.h @@ -84,6 +84,7 @@ namespace weasel virtual void StartMaintenance() {} virtual void EndMaintenance() {} virtual void SetOption(UINT session_id, const std::string &opt, bool val) {} + virtual void UpdateColorTheme(BOOL darkMode) {} }; // 處理server端回應之物件 diff --git a/include/WeaselUtility.h b/include/WeaselUtility.h index dfc18a5bc..e2fb5b831 100644 --- a/include/WeaselUtility.h +++ b/include/WeaselUtility.h @@ -32,6 +32,20 @@ std::wstring WeaselUserDataPath(); const char* weasel_shared_data_dir(); const char* weasel_user_data_dir(); +inline BOOL IsUserDarkMode() +{ + constexpr const LPCWSTR key = L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; + constexpr const LPCWSTR value = L"AppsUseLightTheme"; + + DWORD type; + DWORD data; + DWORD size = sizeof(DWORD); + LSTATUS st = RegGetValue(HKEY_CURRENT_USER, key, value, RRF_RT_REG_DWORD, &type, &data, &size); + + if (st == ERROR_SUCCESS && type == REG_DWORD) return data == 0; + return false; +} + inline std::wstring string_to_wstring(const std::string& str, int code_page = CP_ACP) { // support CP_ACP and CP_UTF8 only