#include "window_hook.h" #include "config/ime_config.h" #include "ime_windows.h" #include "settings/settings_launcher.h" #include "utils/webview_utils.h" #include "defines/globals.h" #include "defines/defines.h" #include "watchdog/watchdog_protocol.h" #include #include void OnWinEvent(HWND hwnd); bool IsKeyPressed(int vk) { return (GetAsyncKeyState(vk) & 0x8000) != 0; } LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) { // When Alt is held, Windows normally reports the following non-system key // as WM_SYSKEYDOWN rather than WM_KEYDOWN. Handle both; otherwise all of // the Ctrl+Shift+Alt shortcuts depend on modifier press order. if (nCode == HC_ACTION && (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN)) { KBDLLHOOKSTRUCT *p = (KBDLLHOOKSTRUCT *)lParam; bool ctrl = IsKeyPressed(VK_CONTROL); bool alt = IsKeyPressed(VK_MENU); bool shift = IsKeyPressed(VK_SHIFT); bool win = IsKeyPressed(VK_LWIN) || IsKeyPressed(VK_RWIN); // Ctrl + Shift + Win + K opens the standalone screen keyboard. Consume the // shortcut so the foreground application does not receive a stray K. if (ctrl && shift && win && !alt && p->vkCode == 'K') { OpenKeyboardPanelApplication(); return 1; } // // Ctrl + Shift + Alt + T to terminate // if (ctrl && shift && alt && p->vkCode == 'T') { CloseSettingsApplication(); CloseEmojiPanelApplication(); CloseKeyboardPanelApplication(); CloseHandwritingPanelApplication(); ExitProcess(WatchdogProtocol::kStopExitCode); } // // Ctrl + Shift + Alt + R to restart // if (ctrl && shift && alt && p->vkCode == 'R') { UnhookWindowsHookEx(g_hHook); ExitProcess(WatchdogProtocol::kRestartExitCode); } // // Ctrl + Shift + Alt + C to clear ime engine cache // if (ctrl && shift && alt && p->vkCode == 'C') { PostMessage(::global_hwnd, WM_CLEAR_IME_ENGINE_CACHE, 0, 0); } // // Ctrl + Alt + Shift + 1-8 to delete candidate // if (!::is_global_wnd_cand_shown) { return CallNextHookEx(g_hHook, nCode, wParam, lParam); } if (ctrl && alt && shift) { // 只处理主键盘数字 int idx = -1; if (p->vkCode >= '1' && p->vkCode <= '8') idx = p->vkCode - '1'; if (idx >= 0) { // 执行候选项删除逻辑,PostMessage 给窗口过程去执行 #ifdef FANY_DEBUG (void)0; #endif PostMessage(::global_hwnd, WM_DELETE_CANDIDATE, idx + 1, 0); // This is an IME command, not text intended for the foreground // application. Consuming it also prevents an Alt+number side // effect in the application. return 1; } } } // 放行其他程序 return CallNextHookEx(g_hHook, nCode, wParam, lParam); } LRESULT CALLBACK LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam) { if (nCode >= 0) { if (wParam == WM_LBUTTONDOWN || wParam == WM_RBUTTONDOWN) { MSLLHOOKSTRUCT *p = (MSLLHOOKSTRUCT *)lParam; POINT pt = p->pt; RECT rc; GetWindowRect(global_hwnd_menu, &rc); if (!PtInRect(&rc, pt)) { ShowWindow(global_hwnd_menu, SW_HIDE); UnhookWindowsHookEx(g_mouseHook); g_mouseHook = nullptr; } } } return CallNextHookEx(g_mouseHook, nCode, wParam, lParam); } void CALLBACK WinEventProc(HWINEVENTHOOK, DWORD event, HWND hwnd, LONG idObject, LONG, DWORD, DWORD) { if (idObject != OBJID_WINDOW || !hwnd) return; if (event == EVENT_OBJECT_LOCATIONCHANGE || event == EVENT_SYSTEM_FOREGROUND) { OnWinEvent(hwnd); } } static bool g_isHiddenDueToFullscreen = false; void OnWinEvent(HWND hwnd) { if (!IsWindow(hwnd) || !IsWindowVisible(hwnd)) return; hwnd = GetForegroundWindow(); bool nowFullscreen = CheckFullscreen(hwnd); // bool wasFullscreen = g_fullscreen_states[hwnd]; if (nowFullscreen) { if (IsWindowVisible(::global_hwnd_ftb)) { ShowWindow(::global_hwnd_ftb, SW_HIDE); g_isHiddenDueToFullscreen = true; } } else { if (g_isHiddenDueToFullscreen) { ApplyConfiguredFloatingToolbarVisibility(); g_isHiddenDueToFullscreen = false; } } // g_fullscreen_states[hwnd] = nowFullscreen; }