Files
UnrealEngineUWP/Engine/Source/Runtime/WebBrowser/Private/CEF/CEFImeHandler.cpp
Marc Audy 76a4f7dd9e Merge CEF version 84.0.4147 from the //Portal branch directly into the //UE5/EA branch
- The CEF helper process has been renamed from UnrealCEFSubprocess to EpicWebHelper
- Support for accelerated rendering from CEF has been added (using GPU->GPU texture copies). This works for the Standalone renderer in DX11/macOS-OpenGL and in the D3D11 RHI renderer, otherwise falls back to the default CPU texture copy mode. Accelerated paint can be disabled by adding "-nocefaccelpaint" to the commandline.
- Numerous other bug fixes and perf improvements in the CEF code have been added since we last took a version drop

#jira distro-133
#[fyi] wes.fudala

#ushell-cherrypick of 15635368 by alfred.reynolds

[CL 15651276 by Marc Audy in ue5-main branch]
2021-03-09 01:37:10 -04:00

212 lines
5.5 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "CEF/CEFImeHandler.h"
#if WITH_CEF3 && !PLATFORM_LINUX
#include "CEFTextInputMethodContext.h"
FCEFImeHandler::FCEFImeHandler(CefRefPtr<CefBrowser> Browser)
: InternalCefBrowser(Browser)
, TextInputMethodSystem(nullptr)
{
}
bool FCEFImeHandler::OnProcessMessageReceived(CefRefPtr<CefBrowser> Browser, CefProcessId SourceProcess, CefRefPtr<CefProcessMessage> Message)
{
bool Result = false;
FString MessageName = WCHAR_TO_TCHAR(Message->GetName().ToWString().c_str());
if (MessageName == TEXT("UE::IME::FocusChanged"))
{
Result = HandleFocusChangedMessage(Message->GetArgumentList());
}
return Result;
}
void FCEFImeHandler::SendProcessMessage(CefRefPtr<CefProcessMessage> Message)
{
if (IsValid() && InternalCefBrowser->GetMainFrame())
{
InternalCefBrowser->GetMainFrame()->SendProcessMessage(PID_RENDERER, Message);
}
}
void FCEFImeHandler::BindInputMethodSystem(ITextInputMethodSystem* InTextInputMethodSystem)
{
TextInputMethodSystem = InTextInputMethodSystem;
if (TextInputMethodSystem && TextInputMethodContext.IsValid())
{
TextInputMethodChangeNotifier = TextInputMethodSystem->RegisterContext(TextInputMethodContext.ToSharedRef());
}
}
void FCEFImeHandler::UnbindInputMethodSystem()
{
if (TextInputMethodContext.IsValid())
{
DestroyContext();
}
TextInputMethodSystem = nullptr;
}
void FCEFImeHandler::InitContext()
{
if (!TextInputMethodSystem)
{
return;
}
// Clean up any existing context
DestroyContext();
TextInputMethodContext = FCEFTextInputMethodContext::Create(SharedThis(this));
if (TextInputMethodSystem)
{
TextInputMethodChangeNotifier = TextInputMethodSystem->RegisterContext(TextInputMethodContext.ToSharedRef());
}
if (TextInputMethodChangeNotifier.IsValid())
{
TextInputMethodChangeNotifier->NotifyLayoutChanged(ITextInputMethodChangeNotifier::ELayoutChangeType::Created);
}
TextInputMethodSystem->ActivateContext(TextInputMethodContext.ToSharedRef());
}
void FCEFImeHandler::DeactivateContext()
{
if (!TextInputMethodSystem || !TextInputMethodContext.IsValid())
{
return;
}
TSharedRef<FCEFTextInputMethodContext> TextInputMethodContextRef = TextInputMethodContext.ToSharedRef();
if (TextInputMethodSystem->IsActiveContext(TextInputMethodContextRef))
{
// Make sure that the composition is aborted to avoid any IME calls to EndComposition from trying to mutate our dying owner widget
if (TextInputMethodContextRef->IsComposing())
{
TextInputMethodContextRef->AbortComposition();
if (TextInputMethodChangeNotifier.IsValid())
{
TextInputMethodChangeNotifier->CancelComposition();
}
}
TextInputMethodSystem->DeactivateContext(TextInputMethodContextRef);
}
}
void FCEFImeHandler::DestroyContext()
{
if (!TextInputMethodContext.IsValid())
{
return;
}
if (TextInputMethodSystem)
{
DeactivateContext();
TextInputMethodSystem->UnregisterContext(TextInputMethodContext.ToSharedRef());
}
TextInputMethodChangeNotifier.Reset();
TextInputMethodContext.Reset();
}
bool FCEFImeHandler::HandleFocusChangedMessage(CefRefPtr<CefListValue> MessageArguments)
{
if (MessageArguments->GetSize() == 1 &&
MessageArguments->GetType(0) == VTYPE_STRING)
{
if (TextInputMethodContext.IsValid())
{
DestroyContext();
}
return true;
}
else if (MessageArguments->GetSize() == 8 &&
MessageArguments->GetType(0) == VTYPE_STRING &&
MessageArguments->GetType(1) == VTYPE_STRING &&
MessageArguments->GetType(2) == VTYPE_BOOL &&
MessageArguments->GetType(3) == VTYPE_STRING &&
MessageArguments->GetType(4) == VTYPE_INT &&
MessageArguments->GetType(5) == VTYPE_INT &&
MessageArguments->GetType(6) == VTYPE_INT &&
MessageArguments->GetType(7) == VTYPE_INT)
{
FString Type = WCHAR_TO_TCHAR(MessageArguments->GetString(0).ToWString().c_str());
FString Name = WCHAR_TO_TCHAR(MessageArguments->GetString(1).ToWString().c_str());
bool bIsEditable = MessageArguments->GetBool(2);
if (Type == TEXT("DOM_NODE_TYPE_ELEMENT") &&
(Name == TEXT("INPUT") || Name == TEXT("TEXTAREA")) &&
bIsEditable)
{
// @todo: Make use of the bounds of the text box here to act as a fallback for the initial composition window pos.
InitContext();
}
return true;
}
return false;
}
void FCEFImeHandler::UnbindCefBrowser()
{
if (TextInputMethodContext.IsValid())
{
DestroyContext();
}
InternalCefBrowser = nullptr;
}
void FCEFImeHandler::CacheBrowserSlateInfo(const TSharedRef<SWidget>& Widget)
{
InternalBrowserSlateWidget = Widget;
}
void FCEFImeHandler::SetFocus(bool bHasFocus)
{
if (!TextInputMethodSystem || !TextInputMethodContext.IsValid())
{
return;
}
if (bHasFocus)
{
TextInputMethodSystem->ActivateContext(TextInputMethodContext.ToSharedRef());
}
else
{
DeactivateContext();
}
}
void FCEFImeHandler::UpdateCachedGeometry(const FGeometry& AllottedGeometry)
{
if (TextInputMethodContext.IsValid() &&
TextInputMethodContext->UpdateCachedGeometry(AllottedGeometry))
{
if (TextInputMethodChangeNotifier.IsValid())
{
TextInputMethodChangeNotifier->NotifyLayoutChanged(ITextInputMethodChangeNotifier::ELayoutChangeType::Changed);
}
}
}
void FCEFImeHandler::CEFCompositionRangeChanged(const CefRange& SelectionRange, const CefRenderHandler::RectList& CharacterBounds)
{
if (TextInputMethodContext.IsValid() &&
TextInputMethodContext->CEFCompositionRangeChanged(SelectionRange, CharacterBounds))
{
if (TextInputMethodChangeNotifier.IsValid())
{
TextInputMethodChangeNotifier->NotifyLayoutChanged(ITextInputMethodChangeNotifier::ELayoutChangeType::Changed);
}
}
}
#endif