From 009f0099058174bd5aae32ccdff29072b47cbbc8 Mon Sep 17 00:00:00 2001 From: fanlumaster <1730976608@qq.com> Date: Tue, 6 May 2025 05:44:00 +0800 Subject: [PATCH] [feat]: IPC support for uwp/metro apps --- .../CompositionProcessorEngine.cpp | 24 +++ src/IME/SampleIME.cpp | 6 + src/IPC/Ipc.cpp | 138 +++++++++--------- src/IPC/Ipc.h | 11 ++ src/Thread/ThreadFocusSink.cpp | 5 +- src/UI/CandidateListUIPresenter.cpp | 6 +- 6 files changed, 120 insertions(+), 70 deletions(-) diff --git a/src/Composition/CompositionProcessorEngine.cpp b/src/Composition/CompositionProcessorEngine.cpp index 36b8a85e..88d6f4d8 100644 --- a/src/Composition/CompositionProcessorEngine.cpp +++ b/src/Composition/CompositionProcessorEngine.cpp @@ -396,6 +396,30 @@ void CCompositionProcessorEngine::GetReadingStrings(_Inout_ CSampleImeArray *pCandidateList, BOOL isIncrementalWordSearch, BOOL isWildcardSearch) { + // + // We don't use dictionary to get candidate list + // + const std::wstring keystrokeStr(_keystrokeBuffer.Get(), _keystrokeBuffer.GetLength()); + CCandidateListItem *pLI = nullptr; + pLI = pCandidateList->Append(); + if (pLI) + { + pLI->_ItemString.Set(keystrokeStr.c_str(), keystrokeStr.size()); + pLI->_FindKeyCode.Set(keystrokeStr.c_str(), keystrokeStr.size()); + } + for (UINT index = 0; index < pCandidateList->Count();) + { + CCandidateListItem *pLI = pCandidateList->GetAt(index); + CStringRange startItemString; + CStringRange endItemString; + + startItemString.Set(pLI->_ItemString.Get(), 1); + endItemString.Set(pLI->_ItemString.Get() + pLI->_ItemString.GetLength() - 1, 1); + + index++; + } + return; + if (!IsDictionaryAvailable()) { return; diff --git a/src/IME/SampleIME.cpp b/src/IME/SampleIME.cpp index bee9a7f9..406fbff1 100644 --- a/src/IME/SampleIME.cpp +++ b/src/IME/SampleIME.cpp @@ -232,6 +232,10 @@ STDAPI CSampleIME::ActivateEx(ITfThreadMgr *pThreadMgr, TfClientId tfClientId, D _tfClientId = tfClientId; _dwActivateFlags = dwFlags; + OutputDebugString(L"CSampleIME::ActivateEx\n"); + HWND hwnd = GetForegroundWindow(); + GetWindowText(hwnd, Global::app_name, 512); + // Set up spdlog // auto logger = spdlog::basic_logger_mt("file_logger", ::LogFilePath); // spdlog::set_default_logger(logger); @@ -326,6 +330,8 @@ STDAPI CSampleIME::Deactivate() spdlog::info("Close IPC!"); #endif + OutputDebugString(L"CSampleIME::Deactivate\n"); + // Clean spdlog spdlog::drop("file_logger"); diff --git a/src/IPC/Ipc.cpp b/src/IPC/Ipc.cpp index 1a482054..8d60b323 100644 --- a/src/IPC/Ipc.cpp +++ b/src/IPC/Ipc.cpp @@ -1,17 +1,19 @@ #include "Ipc.h" +#include #include #include #include #include +#include "fmt/xchar.h" #include "spdlog/spdlog.h" #include "Globals.h" -static HANDLE hMapFile; +static HANDLE hMapFile = nullptr; static void *pBuf; static FanyImeSharedMemoryData *sharedData; static bool canUseSharedMemory = true; -// static HANDLE hPipe; +static HANDLE hPipe = nullptr; static bool canUseNamedPipe = true; static FanyImeNamedpipeData namedpipeData; @@ -19,50 +21,28 @@ static FanyImeNamedpipeData namedpipeData; int InitIpc() { // - // Shared memory + // Shared memory, open here // - hMapFile = CreateFileMappingW( // - INVALID_HANDLE_VALUE, // - nullptr, // - PAGE_READWRITE, // - 0, // - static_cast(BUFFER_SIZE), // - FANY_IME_SHARED_MEMORY // - ); // + hMapFile = OpenFileMappingW( // + FILE_MAP_ALL_ACCESS, // + FALSE, // + FANY_IME_SHARED_MEMORY // + ); - /* - if (!hMapFile) - { - // Error handling - canUseSharedMemory = false; - spdlog::info("CreateFileMapping error: {}", GetLastError()); + // + // Shared memory is not available, try to use namedpipe + // + InitNamedpipe(); - // - // Shared memory is not available, try to use namedpipe - // - hPipe = CreateFile( // - FANY_IME_NAMED_PIPE, // - GENERIC_READ | GENERIC_WRITE, // - 0, // - NULL, // - OPEN_EXISTING, // - 0, // - NULL // - ); + if (!hMapFile) + { + OutputDebugString(L"CreateFileMapping failed\n"); + // Error handling + canUseSharedMemory = false; + spdlog::info("CreateFileMapping error: {}", GetLastError()); - if (hPipe == INVALID_HANDLE_VALUE) - { - canUseNamedPipe = false; - spdlog::error("Failed to open pipe!"); - return -1; - } - else - { - } - - return 0; - } - */ + return 0; + } bool alreadyExists = (GetLastError() == ERROR_ALREADY_EXISTS); @@ -90,22 +70,29 @@ int InitIpc() sharedData->point[1] = 100; } - // - // Events - // - for (const auto &eventName : FANY_IME_EVENT_ARRAY) + return 0; +} + +int InitNamedpipe() +{ + hPipe = CreateFile( // + FANY_IME_NAMED_PIPE, // + GENERIC_READ | GENERIC_WRITE, // + 0, // + nullptr, // + OPEN_EXISTING, // + 0, // + nullptr // + ); + + if (!hPipe) + { + canUseNamedPipe = false; + OutputDebugString(L"Connect to namedpipe failed\n"); + return -1; + } + else { - HANDLE hEvent = CreateEventW( // - nullptr, // - FALSE, // - FALSE, // Auto reset - eventName.c_str() // - ); // - if (!hEvent) - { - // Error handling - spdlog::info("CreateEvent error: {}", Global::wstring_to_string(eventName)); - } } return 0; @@ -114,15 +101,9 @@ int InitIpc() int CloseIpc() { // - // Named pipe + // Namedpipe // - /* - if (hPipe) - { - CloseHandle(hPipe); - hPipe = nullptr; - } - */ + CloseNamedpipe(); if (!canUseSharedMemory) { @@ -163,6 +144,16 @@ int CloseIpc() return 0; } +int CloseNamedpipe() +{ + if (hPipe) + { + CloseHandle(hPipe); + hPipe = nullptr; + } + return 0; +} + int WriteDataToSharedMemory( // UINT keycode, // UINT modifiers_down, // @@ -269,10 +260,15 @@ int WriteDataToNamedPipe( // int SendKeyEventToUIProcess() { + // OutputDebugString(fmt::format(L"SendKeyEventToUIProcess, canUseSharedMemory = {}, canUseNamedPipe = {}\n", + // canUseSharedMemory, canUseNamedPipe) + // .c_str()); if (!canUseSharedMemory) { + // OutputDebugString(L"SendKeyEventToUIProcessViaNamedPipe\n"); if (canUseNamedPipe) { + // OutputDebugString(L"Really SendKeyEventToUIProcessViaNamedPipe \n"); return SendKeyEventToUIProcessViaNamedPipe(); } } @@ -402,8 +398,14 @@ int SendMoveCandidateWndEventToUIProcess() void SendToNamedpipe() { - HANDLE hPipe = CreateFileW(L"\\\\.\\pipe\\FanyImeNamedPipe", GENERIC_READ | GENERIC_WRITE, 0, nullptr, - OPEN_EXISTING, 0, nullptr); + if (!canUseNamedPipe) + { + return; + } + if (!hPipe) + { + return; + } DWORD bytesWritten = 0; BOOL ret = WriteFile( // hPipe, // @@ -418,7 +420,6 @@ void SendToNamedpipe() DWORD err = GetLastError(); spdlog::info("WriteFile error: {}", err); } - CloseHandle(hPipe); } /** @@ -430,6 +431,7 @@ void SendToNamedpipe() */ int SendKeyEventToUIProcessViaNamedPipe() { + // OutputDebugString(L"first SendKeyEventToUIProcessViaNamedPipe\n"); if (!canUseNamedPipe) { return -1; diff --git a/src/IPC/Ipc.h b/src/IPC/Ipc.h index 2cba9297..0e3682aa 100644 --- a/src/IPC/Ipc.h +++ b/src/IPC/Ipc.h @@ -30,6 +30,12 @@ struct FanyImeSharedMemoryData // For uwp/metro apps, here we do not need candidate_string and selected_candiate_string, // just let server process to handle them // +// event_type +// 0: FanyImeKeyEvent +// 1: FanyHideCandidateWndEvent +// 2: FanyShowCandidateWndEvent +// 3: FanyMoveCandidateWndEvent +// struct FanyImeNamedpipeData { UINT event_type; @@ -41,7 +47,10 @@ struct FanyImeNamedpipeData }; int InitIpc(); +int InitNamedpipe(); int CloseIpc(); +int CloseNamedpipe(); + // // For shared memory // @@ -84,4 +93,6 @@ inline std::wstring PinyinString = L""; inline int firefox_like_cnt = 0; // Apps like firefox, e.g. firefox, zen... inline std::wstring current_process_name = L""; + +inline wchar_t app_name[512] = {0}; } // namespace Global \ No newline at end of file diff --git a/src/Thread/ThreadFocusSink.cpp b/src/Thread/ThreadFocusSink.cpp index 52672064..cd058be1 100644 --- a/src/Thread/ThreadFocusSink.cpp +++ b/src/Thread/ThreadFocusSink.cpp @@ -5,9 +5,11 @@ // // Copyright (c) Microsoft Corporation. All rights reserved +#include "Ipc.h" #include "Private.h" #include "SampleIME.h" #include "CandidateListUIPresenter.h" +#include //+--------------------------------------------------------------------------- // @@ -32,7 +34,7 @@ STDAPI CSampleIME::OnSetThreadFocus() pCandidateListDocumentMgr->Release(); } } - + InitNamedpipe(); return S_OK; } @@ -64,6 +66,7 @@ STDAPI CSampleIME::OnKillThreadFocus() } _pCandidateListUIPresenter->OnKillThreadFocus(); } + CloseNamedpipe(); return S_OK; } diff --git a/src/UI/CandidateListUIPresenter.cpp b/src/UI/CandidateListUIPresenter.cpp index b5dcd39e..1dff8fdb 100644 --- a/src/UI/CandidateListUIPresenter.cpp +++ b/src/UI/CandidateListUIPresenter.cpp @@ -6,6 +6,7 @@ #include "CompositionProcessorEngine.h" #include "SampleIMEBaseStructure.h" #include "define.h" +#include #include #include #include @@ -833,7 +834,8 @@ HRESULT CCandidateListUIPresenter::_StartCandidateList(TfClientId tfClientId, _I hr = MakeCandidateWindow(pContextDocument, wndWidth); if (FAILED(hr)) { - goto Exit; + OutputDebugString(L"MakeCandidateWindow failed\n"); + // goto Exit; } // Show(_isShowMode); @@ -871,6 +873,7 @@ void CCandidateListUIPresenter::_EndCandidateList() void CCandidateListUIPresenter::_NotifyUI() { + // OutputDebugString(L"_NotifyUI\n"); CStringRange keyStringBuffer = _pTextService->GetCompositionProcessorEngine()->GetKeystrokeBuffer(); std::wstring pinyinString(keyStringBuffer.Get(), keyStringBuffer.GetLength()); Global::PinyinLength = pinyinString.length(); @@ -1073,6 +1076,7 @@ void CCandidateListUIPresenter::_MoveWindowToTextExt() VOID CCandidateListUIPresenter::_LayoutChangeNotification(_In_ RECT *lpRect) { + // OutputDebugStringW(L"LayoutChangeNotification\n"); #ifdef FANY_DEBUG spdlog::info("_LayoutChangeNotification firefox cnt {}", Global::firefox_like_cnt); #endif