Compare commits

...

2 Commits

Author SHA1 Message Date
7e6be53e8b fix(json): fix IME mode incomplete loading 2025-06-24 21:28:35 +08:00
9a83aea6a2 feat(master): add polling tick mode 2025-06-22 18:42:55 +08:00

View File

@ -21,9 +21,17 @@
// ReSharper disable CppDeprecatedEntity
// ReSharper disable CppClangTidyCertErr33C
const std::string LogFilename = "FocusIME.log";
using namespace std::chrono_literals;
const std::string CachedModeFilename = "FocusIME.json";
constexpr bool bEnableCallback = true;
constexpr bool bEnablePolling = true;
constexpr auto TickInterval = 250ms;
constexpr auto IMEMessageDelay = 50ms;
const std::string LogFilename = "FocusIME.log";
const std::string IMEModeFilename = "FocusIME.json";
static_assert(bEnableCallback || bEnablePolling);
std::ofstream GLogStream;
@ -33,8 +41,6 @@ void PrintLog(const std::string& Text);
void Tick()
{
using namespace std::chrono_literals;
// ReSharper disable CppInconsistentNaming
// ReSharper disable CppClangTidyPerformanceEnumSize
@ -52,15 +58,17 @@ void Tick()
Chinese,
};
static std::map<std::string, EIMEConversionMode> CachedIMEMode = []
using FIMEMode = std::map<std::string, EIMEConversionMode>;
auto LoadIMEMode = []() -> FIMEMode
{
std::map<std::string, EIMEConversionMode> Result;
std::ifstream File(CachedModeFilename);
std::ifstream File(IMEModeFilename);
if (!File.is_open())
{
PrintLog("Cached conversion mode configuration file not found");
PrintLog("Conversion mode configuration file not found");
return Result;
}
@ -137,18 +145,17 @@ void Tick()
while (!View.empty() && std::isspace(View.front())) View.remove_prefix(1);
if (View.empty()) return true;
if (Mode != "English" && Mode != "Chinese" && Mode != "Default") return false;
Result.emplace(Process,
Mode == "English" ? EIMEConversionMode::English :
Mode == "Chinese" ? EIMEConversionMode::Chinese : EIMEConversionMode::Default);
if (View.empty()) break;
if (!View.starts_with(',')) return false;
View.remove_prefix(1);
if (Mode != "English" && Mode != "Chinese" && Mode != "Default") return false;
Result[std::string(Process)] =
Mode == "English" ? EIMEConversionMode::English :
Mode == "Chinese" ? EIMEConversionMode::Chinese : EIMEConversionMode::Default;
}
return true;
@ -157,25 +164,24 @@ void Tick()
if (!bSuccessful) break;
PrintLog("Successfully loaded " + std::to_string(Result.size()) + " cached conversion mode items");
PrintLog("Successfully loaded " + std::to_string(Result.size()) + " conversion mode items");
return Result;
}
while (false);
PrintLog("Invalid format detected in cached conversion mode configuration file");
PrintLog("Invalid format detected in conversion mode configuration file");
return Result;
};
} ();
auto SaveCachedIMEMode = []
auto SaveIMEMode = [](const FIMEMode& IMEMode)
{
std::ofstream File(CachedModeFilename);
std::ofstream File(IMEModeFilename);
if (!File.is_open())
{
PrintLog("Error: Failed to save cached conversion mode configuration");
PrintLog("Error: Failed to save conversion mode configuration");
return;
}
@ -184,7 +190,7 @@ void Tick()
bool bFirstItem = true;
for (const auto& [Name, Mode] : CachedIMEMode)
for (const auto& [Name, Mode] : IMEMode)
{
if (!bFirstItem) File << ",";
@ -200,6 +206,8 @@ void Tick()
File.close();
};
static FIMEMode IMEMode = LoadIMEMode();
static HWND LastWindow = nullptr;
static std::string CachedProcess;
@ -208,7 +216,7 @@ void Tick()
{
do
{
if (CachedIMEMode.contains(CachedProcess) && CachedIMEMode[CachedProcess] == EIMEConversionMode::Default) break;
if (IMEMode.contains(CachedProcess) && IMEMode[CachedProcess] == EIMEConversionMode::Default) break;
HKL KeyboardLayout = GetKeyboardLayout(GetWindowThreadProcessId(LastWindow, nullptr));
@ -229,15 +237,15 @@ void Tick()
if (CurrentMode == EIMEConversionMode::Default) break;
if (!CachedIMEMode.contains(CachedProcess) || CachedIMEMode[CachedProcess] != CurrentMode)
if (!IMEMode.contains(CachedProcess) || IMEMode[CachedProcess] != CurrentMode)
{
CachedIMEMode[CachedProcess] = CurrentMode;
IMEMode[CachedProcess] = CurrentMode;
PrintLog("Updated cached conversion mode for process '" + CachedProcess + "' to " +
PrintLog("Updated conversion mode for process '" + CachedProcess + "' to " +
(CurrentMode == EIMEConversionMode::English ? "English" :
CurrentMode == EIMEConversionMode::Chinese ? "Chinese" : "Default"));
SaveCachedIMEMode();
SaveIMEMode(IMEMode);
}
}
}
@ -280,9 +288,10 @@ void Tick()
CachedProcess = Buffer;
if (!CachedIMEMode.contains(CachedProcess) || CachedIMEMode[CachedProcess] == EIMEConversionMode::Default) break;
if (!IMEMode.contains(CachedProcess) || IMEMode[CachedProcess] == EIMEConversionMode::Default) break;
std::this_thread::sleep_for(50ms);
// Sometimes the message will miss if we don't sleep for a little while.
std::this_thread::sleep_for(IMEMessageDelay);
if (const HWND IMEWindow = ImmGetDefaultIMEWnd(LastWindow))
{
@ -291,7 +300,7 @@ void Tick()
if (!OpenStatus) break;
LPARAM TargetMode = CachedIMEMode[CachedProcess] == EIMEConversionMode::Chinese ? 0x0401 : 0x0000;
LPARAM TargetMode = IMEMode[CachedProcess] == EIMEConversionMode::Chinese ? 0x0401 : 0x0000;
if (ConversionMode != TargetMode)
{
@ -369,7 +378,11 @@ int WINAPI WinMain(HINSTANCE Instance, HINSTANCE, LPSTR, int)
ShowWindow(MainWindow, SW_HIDE);
const HWINEVENTHOOK FocusEventHook = SetWinEventHook(
HWINEVENTHOOK FocusEventHook;
if constexpr (bEnableCallback)
{
FocusEventHook = SetWinEventHook(
EVENT_OBJECT_FOCUS, EVENT_OBJECT_FOCUS,
nullptr,
FocusEventHookProc,
@ -386,6 +399,7 @@ int WINAPI WinMain(HINSTANCE Instance, HINSTANCE, LPSTR, int)
return 1;
}
}
# if BUILD_DEBUG || BUILD_DEVELOPMENT
{
@ -432,6 +446,27 @@ int WINAPI WinMain(HINSTANCE Instance, HINSTANCE, LPSTR, int)
MSG Message = { };
if constexpr (bEnablePolling)
{
while (!GShouldExit)
{
if (PeekMessage(&Message, nullptr, 0, 0, PM_REMOVE)) {
if (Message.message == WM_QUIT) break;
TranslateMessage(&Message);
DispatchMessage (&Message);
continue;
}
Tick();
std::this_thread::sleep_for(TickInterval);
}
}
else
{
while (!GShouldExit)
{
const BOOL bResult = GetMessage(&Message, nullptr, 0, 0);
@ -469,6 +504,7 @@ int WINAPI WinMain(HINSTANCE Instance, HINSTANCE, LPSTR, int)
break;
}
}
}
PrintLog("FocusIME application is shutting down");
@ -480,7 +516,10 @@ int WINAPI WinMain(HINSTANCE Instance, HINSTANCE, LPSTR, int)
}
# endif
if constexpr (bEnableCallback)
{
UnhookWinEvent(FocusEventHook);
}
DestroyWindow(MainWindow);