diff --git a/server/src/settings/settings_app.cpp b/server/src/settings/settings_app.cpp index d7f4bbea..b3134f7f 100644 --- a/server/src/settings/settings_app.cpp +++ b/server/src/settings/settings_app.cpp @@ -33,6 +33,7 @@ constexpr wchar_t kWindowClass[] = L"MetasequoiaImeSettingsWindow"; constexpr wchar_t kWindowTitle[] = L"Metasequoia IME Settings"; constexpr wchar_t kSingleInstanceMutex[] = L"Local\\MetasequoiaImeSettings.SingleInstance"; constexpr UINT kActivateExistingWindow = WM_APP + 1; +constexpr UINT kOpenAboutSection = WM_APP + 2; constexpr UINT_PTR kConfigReloadTimer = 1; ComPtr g_controller; @@ -48,6 +49,29 @@ bool g_has_maximize_button_rect = false; bool g_maximize_button_hover = false; bool g_window_active = true; bool g_window_minimized = false; +bool g_open_about_on_ready = false; + +void ShowAboutSection() +{ + if (!g_webview) return; + g_webview->ExecuteScript(LR"JS((() => { + const selectAbout = () => { + const item = document.querySelector('.sidebar .item[data-target="about-settings"]'); + if (!item) return false; + if (!item.classList.contains('active')) item.click(); + const section = document.getElementById('about-settings'); + if (!item.classList.contains('active') || !section || getComputedStyle(section).display === 'none') + return false; + item.scrollIntoView({ block: 'nearest' }); + return true; + }; + if (selectAbout()) return; + const retry = setInterval(() => { + if (selectAbout()) clearInterval(retry); + }, 50); + setTimeout(() => clearInterval(retry), 10000); + })())JS", nullptr); +} void ApplyWindowActivationAppearance() { @@ -440,6 +464,11 @@ HRESULT OnControllerCreated(HWND hwnd, HRESULT result, ICoreWebView2CompositionC PostConfig(); ApplyWindowActivationAppearance(); SetFocus(hwnd); + if (g_open_about_on_ready) + { + ShowAboutSection(); + g_open_about_on_ready = false; + } } return S_OK; }).Get(), @@ -560,6 +589,10 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT message, WPARAM w_param, LPARAM l_pa case kActivateExistingWindow: ActivateWindow(hwnd); return 0; + case kOpenAboutSection: + ActivateWindow(hwnd); + ShowAboutSection(); + return 0; case WM_NCCALCSIZE: if (w_param) { @@ -691,8 +724,9 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT message, WPARAM w_param, LPARAM l_pa } } // namespace -int WINAPI wWinMain(HINSTANCE instance, HINSTANCE, PWSTR, int show_command) +int WINAPI wWinMain(HINSTANCE instance, HINSTANCE, PWSTR command_line, int show_command) { + g_open_about_on_ready = command_line && std::wstring(command_line).find(L"--about") != std::wstring::npos; SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); const HRESULT com_result = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); if (FAILED(com_result)) return 1; @@ -704,7 +738,7 @@ int WINAPI wWinMain(HINSTANCE instance, HINSTANCE, PWSTR, int show_command) HWND existing = FindWindowW(kWindowClass, nullptr); if (existing) { - PostMessageW(existing, kActivateExistingWindow, 0, 0); + PostMessageW(existing, g_open_about_on_ready ? kOpenAboutSection : kActivateExistingWindow, 0, 0); SetForegroundWindow(existing); } return 0; diff --git a/server/src/settings/settings_launcher.cpp b/server/src/settings/settings_launcher.cpp index a01dff28..0a378161 100644 --- a/server/src/settings/settings_launcher.cpp +++ b/server/src/settings/settings_launcher.cpp @@ -11,6 +11,7 @@ constexpr wchar_t kSettingsWindowClass[] = L"MetasequoiaImeSettingsWindow"; constexpr wchar_t kEmojiPanelWindowClass[] = L"msimeui.EmojiPanel"; constexpr wchar_t kKeyboardPanelWindowClass[] = L"msimeui.KeyboardDemo"; constexpr wchar_t kHandwritingPanelWindowClass[] = L"msimeui.HandwritingDemo"; +constexpr UINT kOpenSettingsAbout = WM_APP + 2; bool OpenSiblingApplication(const wchar_t *executable_name, const wchar_t *window_class) { @@ -50,6 +51,27 @@ bool OpenSettingsApplication() return OpenSiblingApplication(L"MetasequoiaImeSettings.exe", kSettingsWindowClass); } +bool OpenSettingsAboutApplication() +{ + if (const HWND existing_window = FindWindowW(kSettingsWindowClass, nullptr)) + { + ShowWindow(existing_window, SW_SHOWNORMAL); + PostMessageW(existing_window, kOpenSettingsAbout, 0, 0); + return SetForegroundWindow(existing_window) != FALSE; + } + + std::wstring module_path(32768, L'\0'); + const DWORD length = GetModuleFileNameW(nullptr, module_path.data(), static_cast(module_path.size())); + if (length == 0 || length >= module_path.size()) return false; + module_path.resize(length); + + const std::filesystem::path application_path = + std::filesystem::path(module_path).parent_path() / L"MetasequoiaImeSettings.exe"; + const HINSTANCE result = ShellExecuteW(nullptr, L"open", application_path.c_str(), L"--about", + application_path.parent_path().c_str(), SW_SHOWNORMAL); + return reinterpret_cast(result) > 32; +} + bool CloseSettingsApplication() { return CloseApplication(kSettingsWindowClass); diff --git a/server/src/settings/settings_launcher.h b/server/src/settings/settings_launcher.h index 4452076c..06c86ad8 100644 --- a/server/src/settings/settings_launcher.h +++ b/server/src/settings/settings_launcher.h @@ -1,6 +1,7 @@ #pragma once bool OpenSettingsApplication(); +bool OpenSettingsAboutApplication(); bool CloseSettingsApplication(); bool OpenEmojiPanelApplication(); bool CloseEmojiPanelApplication(); diff --git a/server/src/webview2/windows_webview2.cpp b/server/src/webview2/windows_webview2.cpp index a6cbb533..09719a36 100644 --- a/server/src/webview2/windows_webview2.cpp +++ b/server/src/webview2/windows_webview2.cpp @@ -801,6 +801,11 @@ HRESULT OnControllerCreatedMenuWnd( // OpenSettingsApplication(); ShowWindow(::global_hwnd_menu, SW_HIDE); } + else if (type == "about") + { + OpenSettingsAboutApplication(); + ShowWindow(::global_hwnd_menu, SW_HIDE); + } else if (type == "emojiSymbols") { OpenEmojiPanelApplication();