void FWindowsTextInputMethodSystem::ApplyDefaults(const TSharedRef<FGenericWindow>& InWindow) { ClearStaleWindowHandles(); KnownWindows.Add(InWindow); const HWND Hwnd = reinterpret_cast<HWND>(InWindow->GetOSWindowHandle()); // Typically we disable the IME when a new window is created, however, we don't want to do that if we have an active context, // as it will immediately disable the IME (which may be undesirable for things like a search suggestions window appearing) // In that case, we set the window to use the same IME context as is currently active. If the window actually takes focus // away from the currently active IME context, then that will be taken care of in DeactivateContext, and all windows using the // IME context will be disabled ITfDocumentMgr* TSFDocumentManagerToSet = nullptr; HIMC IMMContextToSet = nullptr; if(ActiveContext.IsValid()) { TSFThreadManager->GetFocus(&TSFDocumentManagerToSet); IMMContextToSet = IMMContextId; } // TSF Implementation if(TSFDocumentManagerToSet) { TSFThreadManager->SetFocus(TSFDocumentManagerToSet); } else { ITfDocumentMgr* Unused; TSFThreadManager->AssociateFocus(Hwnd, TSFDisabledDocumentManager, &Unused); } // IMM Implementation ::ImmAssociateContext(Hwnd, IMMContextToSet); }
void FWindowsTextInputMethodSystem::DeactivateContext(const TSharedRef<ITextInputMethodContext>& Context) { UE_LOG(LogWindowsTextInputMethodSystem, Verbose, TEXT("Deactivating context %p..."), &(Context.Get())); FInternalContext& InternalContext = ContextToInternalContextMap[Context]; // IMM Implementation HIMC IMMContext = ::ImmGetContext(InternalContext.WindowHandle); InternalContext.IMMContext.IsDeactivating = true; // Request the composition is completed to ensure that the composition input UI is closed, and that a WM_IME_ENDCOMPOSITION message is sent ::ImmNotifyIME(IMMContext, NI_COMPOSITIONSTR, CPS_COMPLETE, 0); ::ImmReleaseContext(InternalContext.WindowHandle, IMMContext); // Ensure all known windows are associated with a disabled IME ClearStaleWindowHandles(); for(const TWeakPtr<FGenericWindow>& Window : KnownWindows) { TSharedPtr<FGenericWindow> WindowPtr = Window.Pin(); if(WindowPtr.IsValid()) { const HWND Hwnd = reinterpret_cast<HWND>(WindowPtr->GetOSWindowHandle()); if(Hwnd) { // TSF Implementation ITfDocumentMgr* Unused; if(FAILED(TSFThreadManager->AssociateFocus(Hwnd, TSFDisabledDocumentManager, &Unused))) { UE_LOG(LogWindowsTextInputMethodSystem, Error, TEXT("Deactivating a context failed while setting focus to the disabled TSF document manager.")); } // IMM Implementation ::ImmAssociateContext(InternalContext.WindowHandle, nullptr); } } } // General Implementation ActiveContext = nullptr; UE_LOG(LogWindowsTextInputMethodSystem, Verbose, TEXT("Deactivated context %p!"), &(Context.Get())); }