diff --git a/src/Global/FanyDefines.h b/src/Global/FanyDefines.h index 4a6595a1..ca834962 100644 --- a/src/Global/FanyDefines.h +++ b/src/Global/FanyDefines.h @@ -43,4 +43,9 @@ inline void setTsfPreeditStyle(std::string_view newStyle) namespace GlobalIme { inline std::wstring word_for_creating_word = L""; +} + +namespace Global +{ +inline HWND msgWndHandle = nullptr; } \ No newline at end of file diff --git a/src/IME/MetasequoiaIME.cpp b/src/IME/MetasequoiaIME.cpp index 875a8c7f..919c9b11 100644 --- a/src/IME/MetasequoiaIME.cpp +++ b/src/IME/MetasequoiaIME.cpp @@ -256,7 +256,7 @@ STDAPI CMetasequoiaIME::ActivateEx(ITfThreadMgr *pThreadMgr, TfClientId tfClient } */ // Set up IPC(named pipe) - InitIpc(); + // InitIpc(); // TODO: 去掉共享内存,只保留命名管道 // InitNamedpipe(); @@ -288,6 +288,10 @@ STDAPI CMetasequoiaIME::ActivateEx(ITfThreadMgr *pThreadMgr, TfClientId tfClient Global::dllInstanceHandle, // this); SetWindowLongPtr(_msgWndHandle, GWLP_USERDATA, (LONG_PTR)this); + Global::msgWndHandle = _msgWndHandle; + + /* 连接命名管道 */ + PostMessage(_msgWndHandle, WM_ConnectNamedpipe, 0, 0); /* 创建 IPC 线程 */ _shouldStopIpcThread = false; @@ -334,7 +338,7 @@ STDAPI CMetasequoiaIME::ActivateEx(ITfThreadMgr *pThreadMgr, TfClientId tfClient _pCompositionProcessorEngine->InitializeMetasequoiaIMECompartment(pThreadMgr, tfClientId); // 激活此输入法时,向 server 端发送一个激活的消息 - SendIMEActivationEventToUIProcessViaNamedPipe(); + // SendIMEActivationEventToUIProcessViaNamedPipe(); { HWND hwndTarget = GetFocus(); @@ -378,7 +382,7 @@ ExitError: STDAPI CMetasequoiaIME::Deactivate() { // 注销此输入法时,向 server 端发送一个注销的消息 - SendIMEDeactivationEventToUIProcessViaNamedPipe(); + // SendIMEDeactivationEventToUIProcessViaNamedPipe(); /* 清理 IPC 线程 */ _shouldStopIpcThread = true; @@ -553,6 +557,28 @@ LRESULT CALLBACK CMetasequoiaIME_WindowProc(HWND hWnd, UINT message, WPARAM wPar break; } case WM_ConnectNamedpipe: { + SendToAuxNamedpipe(L"kill"); + Sleep(50); + if (ConnectToAllNamedpipe()) + { + OutputDebugString(fmt::format(L"Connected to named pipe").c_str()); + } + else + { + } + break; + } + case WM_DisconnectNamedpipe: { + CloseNamedpipe(); + break; + } + case WM_ConnectToTsfNamedpipe: { + OutputDebugString(fmt::format(L"Try to Connect to TSF named pipe").c_str()); + Sleep(50); + if (ConnectToTsfNamedpipe()) + { + break; + } break; } default: diff --git a/src/IME/MetasequoiaIME.h b/src/IME/MetasequoiaIME.h index 9721619c..a15d23ae 100644 --- a/src/IME/MetasequoiaIME.h +++ b/src/IME/MetasequoiaIME.h @@ -11,6 +11,8 @@ class CCompositionProcessorEngine; const DWORD WM_CheckGlobalCompartment = WM_USER; const DWORD WM_ConnectNamedpipe = WM_USER + 1; +const DWORD WM_DisconnectNamedpipe = WM_USER + 2; +const DWORD WM_ConnectToTsfNamedpipe = WM_USER + 3; LRESULT CALLBACK CMetasequoiaIME_WindowProc(HWND wndHandle, UINT uMsg, WPARAM wParam, LPARAM lParam); class CMetasequoiaIME : public ITfTextInputProcessorEx, diff --git a/src/IPC/Ipc.cpp b/src/IPC/Ipc.cpp index 6bb25f98..d50be870 100644 --- a/src/IPC/Ipc.cpp +++ b/src/IPC/Ipc.cpp @@ -6,6 +6,8 @@ #include #include #include "Globals.h" +#include "FanyDefines.h" +#include "MetasequoiaIME.h" #include static HANDLE hMapFile = nullptr; @@ -93,7 +95,6 @@ int InitNamedpipe() if (hPipe == INVALID_HANDLE_VALUE) { hPipe = nullptr; - SendToAuxNamedpipe(L"kill"); } else { @@ -116,7 +117,6 @@ int InitNamedpipe() if (hFromServerPipe == INVALID_HANDLE_VALUE) { hFromServerPipe = nullptr; - // SendToAuxNamedpipe(L"kill"); } else { @@ -139,7 +139,6 @@ int InitNamedpipe() if (Global::hToTsfWorkerThreadPipe == INVALID_HANDLE_VALUE) { Global::hToTsfWorkerThreadPipe = nullptr; - // SendToAuxNamedpipe(L"kill"); } else { @@ -160,6 +159,108 @@ int InitNamedpipe() return 1; } +int ConnectToAllNamedpipe() +{ + hPipe = CreateFile( // + FANY_IME_NAMED_PIPE, // + GENERIC_READ | GENERIC_WRITE, // + 0, // + nullptr, // + OPEN_EXISTING, // + 0, // + nullptr // + ); + + if (hPipe == INVALID_HANDLE_VALUE) + { + hPipe = nullptr; + } + else + { + // TODO: Log + } + + hFromServerPipe = CreateFile( // + FANY_IME_TO_TSF_NAMED_PIPE, // + GENERIC_READ | GENERIC_WRITE, // + 0, // + nullptr, // + OPEN_EXISTING, // + 0, // + nullptr // + ); + + if (hFromServerPipe == INVALID_HANDLE_VALUE) + { + hFromServerPipe = nullptr; + } + else + { + // TODO: Log + } + + Global::hToTsfWorkerThreadPipe = CreateFile( // + FANY_IME_TO_TSF_WORKER_THREAD_NAMED_PIPE, // + GENERIC_READ | GENERIC_WRITE, // + 0, // + nullptr, // + OPEN_EXISTING, // + 0, // + nullptr // + ); + + if (Global::hToTsfWorkerThreadPipe == INVALID_HANDLE_VALUE) + { + Global::hToTsfWorkerThreadPipe = nullptr; + } + else + { + // TODO: Log + } + + if (hPipe == nullptr || hPipe == INVALID_HANDLE_VALUE || hFromServerPipe == nullptr || + hFromServerPipe == INVALID_HANDLE_VALUE || Global::hToTsfWorkerThreadPipe == nullptr || + Global::hToTsfWorkerThreadPipe == INVALID_HANDLE_VALUE) + { + hPipe = nullptr; + hFromServerPipe = nullptr; + Global::hToTsfWorkerThreadPipe = nullptr; + return 0; + } + + return 1; +} + +int ConnectToTsfNamedpipe() +{ + if (hFromServerPipe == nullptr || hFromServerPipe == INVALID_HANDLE_VALUE) + { + hFromServerPipe = CreateFile( // + FANY_IME_TO_TSF_NAMED_PIPE, // + GENERIC_READ | GENERIC_WRITE, // + 0, // + nullptr, // + OPEN_EXISTING, // + 0, // + nullptr // + ); + + if (hFromServerPipe == INVALID_HANDLE_VALUE) + { + hFromServerPipe = nullptr; + } + else + { + // TODO: Log + } + } + if (hFromServerPipe == nullptr || hFromServerPipe == INVALID_HANDLE_VALUE) + { + return 0; + } + return 1; +} + int CloseIpc() { // @@ -481,20 +582,26 @@ void SendToNamedpipe() { /* Error handling: 必须将 hPipe 置为无效,否则将留下脏句柄,导致有些情况下无法再次连接 */ DWORD err = GetLastError(); - if (err == ERROR_BROKEN_PIPE || err == ERROR_NO_DATA) - { - /* 将两个方向的管道同时置为无效 */ - CloseHandle(hPipe); - CloseHandle(hFromServerPipe); - hPipe = INVALID_HANDLE_VALUE; - hFromServerPipe = INVALID_HANDLE_VALUE; - /* 向 Server 端发送 kill 同时重置两个管道的 connect */ - SendToAuxNamedpipe(L"kill"); - } + // if (err == ERROR_BROKEN_PIPE || err == ERROR_NO_DATA) + // { + /* 将两个方向的管道同时置为无效 */ + CloseHandle(hPipe); + CloseHandle(hFromServerPipe); + // CloseHandle(Global::hToTsfWorkerThreadPipe); + hPipe = INVALID_HANDLE_VALUE; + hFromServerPipe = INVALID_HANDLE_VALUE; + // Global::hToTsfWorkerThreadPipe = INVALID_HANDLE_VALUE; + /* 向 Server 端发送 kill 同时重置两个管道的 connect */ + SendToAuxNamedpipe(L"kill"); + OutputDebugString(fmt::format(L"SendToNamedpipe failed eventually01.").c_str()); + // } // // 等待 Server 准备好,再重连几次 // + + /* toTsfNamedPipe 放到消息窗口的线程中去处理 */ + PostMessage(Global::msgWndHandle, WM_ConnectToTsfNamedpipe, 0, 0); for (int i = 0; i < 10; ++i) { Sleep(10); @@ -514,6 +621,7 @@ void SendToNamedpipe() if (hPipe == INVALID_HANDLE_VALUE) { // TODO: Log + OutputDebugString(fmt::format(L"SendToNamedpipe failed eventually02.").c_str()); return; } else @@ -533,6 +641,7 @@ void SendToNamedpipe() if (!ret || bytesWritten != sizeof(namedpipeData)) { // TODO: Error handling + OutputDebugString(fmt::format(L"SendToNamedpipe failed eventually03.").c_str()); } return; diff --git a/src/IPC/Ipc.h b/src/IPC/Ipc.h index 3ac27aca..c6061d6a 100644 --- a/src/IPC/Ipc.h +++ b/src/IPC/Ipc.h @@ -93,6 +93,8 @@ struct FanyImeNamedpipeDataToTsfWorkerThread int InitIpc(); int InitNamedpipe(); +int ConnectToAllNamedpipe(); +int ConnectToTsfNamedpipe(); int CloseIpc(); int CloseNamedpipe(); diff --git a/src/Thread/ThreadFocusSink.cpp b/src/Thread/ThreadFocusSink.cpp index fe4d5cf7..783e3dfc 100644 --- a/src/Thread/ThreadFocusSink.cpp +++ b/src/Thread/ThreadFocusSink.cpp @@ -3,6 +3,7 @@ #include "MetasequoiaIME.h" #include "CandidateListUIPresenter.h" #include +#include "fmt/xchar.h" //+--------------------------------------------------------------------------- // diff --git a/src/Thread/ThreadMgrEventSink.cpp b/src/Thread/ThreadMgrEventSink.cpp index fb866d01..df2516e2 100644 --- a/src/Thread/ThreadMgrEventSink.cpp +++ b/src/Thread/ThreadMgrEventSink.cpp @@ -1,4 +1,5 @@ #include "Private.h" +#include "fmt/xchar.h" #include "Globals.h" #include "MetasequoiaIME.h" #include "CandidateListUIPresenter.h" @@ -47,14 +48,13 @@ STDAPI CMetasequoiaIME::OnSetFocus(_In_ ITfDocumentMgr *pDocMgrFocus, _In_ ITfDo if (pDocMgrFocus && !Global::g_connected) { - - InitNamedpipe(); Global::g_connected = true; + PostMessage(_msgWndHandle, WM_ConnectNamedpipe, 0, 0); } else if (!pDocMgrFocus && Global::g_connected) { - CloseNamedpipe(); Global::g_connected = false; + PostMessage(_msgWndHandle, WM_DisconnectNamedpipe, 0, 0); } _InitTextEditSink(pDocMgrFocus);