Files
UnrealEngineUWP/Engine/Source/Developer/WebBrowser/Private/WebBrowserWindow.cpp
Ben Marsh 149375b14b Update copyright notices to 2015.
[CL 2379638 by Ben Marsh in Main branch]
2014-12-07 19:09:38 -05:00

480 lines
12 KiB
C++

// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
#include "WebBrowserPrivatePCH.h"
#include "WebBrowserWindow.h"
#include "SlateCore.h"
#include "SlateBasics.h"
#if WITH_CEF3
FWebBrowserWindow::FWebBrowserWindow(FIntPoint InViewportSize)
: UpdatableTexture(nullptr)
, ViewportSize(InViewportSize)
, bIsClosing(false)
, bHasBeenPainted(false)
{
TextureData.Reserve(ViewportSize.X * ViewportSize.Y * 4);
TextureData.SetNumZeroed(ViewportSize.X * ViewportSize.Y * 4);
if (FSlateApplication::Get().GetRenderer().IsValid())
{
UpdatableTexture = FSlateApplication::Get().GetRenderer()->CreateUpdatableTexture(ViewportSize.X, ViewportSize.Y);
}
}
FWebBrowserWindow::~FWebBrowserWindow()
{
CloseBrowser();
if (FSlateApplication::Get().GetRenderer().IsValid() && UpdatableTexture != nullptr)
{
FSlateApplication::Get().GetRenderer()->ReleaseUpdatableTexture(UpdatableTexture);
}
UpdatableTexture = nullptr;
}
void FWebBrowserWindow::SetViewportSize(FVector2D WindowSize)
{
// Magic number for texture size, can't access GetMax2DTextureDimension easily
FIntPoint ClampedWindowSize = WindowSize.ClampAxes(1, 2048).IntPoint();
// Ignore sizes that can't be seen as it forces CEF to re-render whole image
if (WindowSize >= FVector2D::UnitVector && ViewportSize != ClampedWindowSize)
{
FIntPoint OldViewportSize = MoveTemp(ViewportSize);
TArray<uint8> OldTextureData = MoveTemp(TextureData);
ViewportSize = ClampedWindowSize;
TextureData.SetNumZeroed(ViewportSize.X * ViewportSize.Y * 4);
// copy row by row to avoid texture distortion
const int32 WriteWidth = FMath::Min(OldViewportSize.X, ViewportSize.X) * 4;
const int32 WriteHeight = FMath::Min(OldViewportSize.Y, ViewportSize.Y);
for (int32 RowIndex = 0; RowIndex < WriteHeight; ++RowIndex)
{
FMemory::Memcpy(TextureData.GetData() + ViewportSize.X * RowIndex * 4, OldTextureData.GetData() + OldViewportSize.X * RowIndex * 4, WriteWidth);
}
if (UpdatableTexture != nullptr)
{
UpdatableTexture->ResizeTexture(ViewportSize.X, ViewportSize.Y);
UpdatableTexture->UpdateTexture(TextureData);
}
if (IsValid())
{
InternalCefBrowser->GetHost()->WasResized();
}
}
}
FSlateShaderResource* FWebBrowserWindow::GetTexture()
{
if (UpdatableTexture != nullptr)
{
return UpdatableTexture->GetSlateResource();
}
return nullptr;
}
bool FWebBrowserWindow::IsValid() const
{
return InternalCefBrowser.get() != nullptr;
}
bool FWebBrowserWindow::HasBeenPainted() const
{
return bHasBeenPainted;
}
bool FWebBrowserWindow::IsClosing() const
{
return bIsClosing;
}
FString FWebBrowserWindow::GetTitle() const
{
return Title;
}
void FWebBrowserWindow::OnKeyDown(const FKeyEvent& InKeyEvent)
{
if (IsValid())
{
CefKeyEvent KeyEvent;
KeyEvent.windows_key_code = InKeyEvent.GetKeyCode();
// TODO: Figure out whether this is a system key if we come across problems
/*KeyEvent.is_system_key = message == WM_SYSCHAR ||
message == WM_SYSKEYDOWN ||
message == WM_SYSKEYUP;*/
KeyEvent.type = KEYEVENT_RAWKEYDOWN;
KeyEvent.modifiers = GetCefKeyboardModifiers(InKeyEvent);
InternalCefBrowser->GetHost()->SendKeyEvent(KeyEvent);
}
}
void FWebBrowserWindow::OnKeyUp(const FKeyEvent& InKeyEvent)
{
if (IsValid())
{
CefKeyEvent KeyEvent;
KeyEvent.windows_key_code = InKeyEvent.GetKeyCode();
// TODO: Figure out whether this is a system key if we come across problems
/*KeyEvent.is_system_key = message == WM_SYSCHAR ||
message == WM_SYSKEYDOWN ||
message == WM_SYSKEYUP;*/
KeyEvent.type = KEYEVENT_KEYUP;
KeyEvent.modifiers = GetCefKeyboardModifiers(InKeyEvent);
InternalCefBrowser->GetHost()->SendKeyEvent(KeyEvent);
}
}
void FWebBrowserWindow::OnKeyChar(const FCharacterEvent& InCharacterEvent)
{
if (IsValid())
{
CefKeyEvent KeyEvent;
KeyEvent.windows_key_code = InCharacterEvent.GetCharacter();
// TODO: Figure out whether this is a system key if we come across problems
/*KeyEvent.is_system_key = message == WM_SYSCHAR ||
message == WM_SYSKEYDOWN ||
message == WM_SYSKEYUP;*/
KeyEvent.type = KEYEVENT_CHAR;
KeyEvent.modifiers = GetCefInputModifiers(InCharacterEvent);
InternalCefBrowser->GetHost()->SendKeyEvent(KeyEvent);
}
}
void FWebBrowserWindow::OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
if (IsValid())
{
FKey Button = MouseEvent.GetEffectingButton();
CefBrowserHost::MouseButtonType Type =
(Button == EKeys::LeftMouseButton ? MBT_LEFT : (
Button == EKeys::RightMouseButton ? MBT_RIGHT : MBT_MIDDLE));
CefMouseEvent Event;
FVector2D LocalPos = MyGeometry.AbsoluteToLocal(MouseEvent.GetScreenSpacePosition());
Event.x = LocalPos.X;
Event.y = LocalPos.Y;
Event.modifiers = GetCefMouseModifiers(MouseEvent);
InternalCefBrowser->GetHost()->SendMouseClickEvent(Event, Type, false,1);
}
}
void FWebBrowserWindow::OnMouseButtonUp(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
if (IsValid())
{
FKey Button = MouseEvent.GetEffectingButton();
CefBrowserHost::MouseButtonType Type =
(Button == EKeys::LeftMouseButton ? MBT_LEFT : (
Button == EKeys::RightMouseButton ? MBT_RIGHT : MBT_MIDDLE));
CefMouseEvent Event;
FVector2D LocalPos = MyGeometry.AbsoluteToLocal(MouseEvent.GetScreenSpacePosition());
Event.x = LocalPos.X;
Event.y = LocalPos.Y;
Event.modifiers = GetCefMouseModifiers(MouseEvent);
InternalCefBrowser->GetHost()->SendMouseClickEvent(Event, Type, true, 1);
}
}
void FWebBrowserWindow::OnMouseButtonDoubleClick(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
if (IsValid())
{
FKey Button = MouseEvent.GetEffectingButton();
CefBrowserHost::MouseButtonType Type =
(Button == EKeys::LeftMouseButton ? MBT_LEFT : (
Button == EKeys::RightMouseButton ? MBT_RIGHT : MBT_MIDDLE));
CefMouseEvent Event;
FVector2D LocalPos = MyGeometry.AbsoluteToLocal(MouseEvent.GetScreenSpacePosition());
Event.x = LocalPos.X;
Event.y = LocalPos.Y;
Event.modifiers = GetCefMouseModifiers(MouseEvent);
InternalCefBrowser->GetHost()->SendMouseClickEvent(Event, Type, false, 2);
}
}
void FWebBrowserWindow::OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
if (IsValid())
{
CefMouseEvent Event;
FVector2D LocalPos = MyGeometry.AbsoluteToLocal(MouseEvent.GetScreenSpacePosition());
Event.x = LocalPos.X;
Event.y = LocalPos.Y;
Event.modifiers = GetCefMouseModifiers(MouseEvent);
InternalCefBrowser->GetHost()->SendMouseMoveEvent(Event, false);
}
}
void FWebBrowserWindow::OnMouseWheel(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
if(IsValid())
{
// The original delta is reduced so this should bring it back to what CEF expects
const float SpinFactor = 120.0f;
const float TrueDelta = MouseEvent.GetWheelDelta() * SpinFactor;
CefMouseEvent Event;
FVector2D LocalPos = MyGeometry.AbsoluteToLocal(MouseEvent.GetScreenSpacePosition());
Event.x = LocalPos.X;
Event.y = LocalPos.Y;
Event.modifiers = GetCefMouseModifiers(MouseEvent);
InternalCefBrowser->GetHost()->SendMouseWheelEvent(Event,
MouseEvent.IsShiftDown() ? TrueDelta : 0,
!MouseEvent.IsShiftDown() ? TrueDelta : 0);
}
}
void FWebBrowserWindow::OnFocus(bool SetFocus)
{
if (IsValid())
{
InternalCefBrowser->GetHost()->SendFocusEvent(SetFocus);
}
}
void FWebBrowserWindow::OnCaptureLost()
{
if (IsValid())
{
InternalCefBrowser->GetHost()->SendCaptureLostEvent();
}
}
bool FWebBrowserWindow::CanGoBack() const
{
if (IsValid())
{
return InternalCefBrowser->CanGoBack();
}
return false;
}
void FWebBrowserWindow::GoBack()
{
if (IsValid())
{
InternalCefBrowser->GoBack();
}
}
bool FWebBrowserWindow::CanGoForward() const
{
if (IsValid())
{
return InternalCefBrowser->CanGoForward();
}
return false;
}
void FWebBrowserWindow::GoForward()
{
if (IsValid())
{
InternalCefBrowser->GoForward();
}
}
bool FWebBrowserWindow::IsLoading() const
{
if (IsValid())
{
return InternalCefBrowser->IsLoading();
}
return false;
}
void FWebBrowserWindow::Reload()
{
if (IsValid())
{
InternalCefBrowser->Reload();
}
}
void FWebBrowserWindow::StopLoad()
{
if (IsValid())
{
InternalCefBrowser->StopLoad();
}
}
void FWebBrowserWindow::SetHandler(CefRefPtr<FWebBrowserHandler> InHandler)
{
if (InHandler.get())
{
Handler = InHandler;
Handler->SetBrowserWindow(SharedThis(this));
}
}
void FWebBrowserWindow::CloseBrowser()
{
bIsClosing = true;
if (IsValid())
{
InternalCefBrowser->GetHost()->CloseBrowser(false);
InternalCefBrowser = nullptr;
Handler = nullptr;
}
}
void FWebBrowserWindow::BindCefBrowser(CefRefPtr<CefBrowser> Browser)
{
InternalCefBrowser = Browser;
}
void FWebBrowserWindow::SetTitle(const CefString& InTitle)
{
Title = InTitle.ToWString().c_str();
OnTitleChangedDelegate.Broadcast(Title);
}
bool FWebBrowserWindow::GetViewRect(CefRect& Rect)
{
Rect.x = 0;
Rect.y = 0;
Rect.width = ViewportSize.X;
Rect.height = ViewportSize.Y;
return true;
}
void FWebBrowserWindow::OnPaint(CefRenderHandler::PaintElementType Type, const CefRenderHandler::RectList& DirtyRects, const void* Buffer, int Width, int Height)
{
const int32 BufferSize = Width*Height*4;
if (BufferSize == TextureData.Num())
{
FMemory::Memcpy(TextureData.GetData(), Buffer, BufferSize);
}
else
{
// copy row by row to avoid texture distortion
const int32 WriteWidth = FMath::Min(Width, ViewportSize.X) * 4;
const int32 WriteHeight = FMath::Min(Height, ViewportSize.Y);
for (int32 RowIndex = 0; RowIndex < WriteHeight; ++RowIndex)
{
FMemory::Memcpy(TextureData.GetData() + ViewportSize.X * RowIndex * 4, static_cast<const uint8*>(Buffer) + Width * RowIndex * 4, WriteWidth);
}
}
if (UpdatableTexture != nullptr)
{
UpdatableTexture->UpdateTexture(TextureData);
}
bHasBeenPainted = true;
}
void FWebBrowserWindow::OnCursorChange(CefCursorHandle Cursor)
{
// TODO: Figure out Unreal cursor type from this,
// may need to reload unreal cursors to compare handles
//::SetCursor( Cursor );
}
int32 FWebBrowserWindow::GetCefKeyboardModifiers(const FKeyEvent& KeyEvent)
{
int32 Modifiers = GetCefInputModifiers(KeyEvent);
const FKey Key = KeyEvent.GetKey();
if (Key == EKeys::LeftAlt ||
Key == EKeys::LeftCommand ||
Key == EKeys::LeftControl ||
Key == EKeys::LeftShift)
{
Modifiers |= EVENTFLAG_IS_LEFT;
}
if (Key == EKeys::RightAlt ||
Key == EKeys::RightCommand ||
Key == EKeys::RightControl ||
Key == EKeys::RightShift)
{
Modifiers |= EVENTFLAG_IS_RIGHT;
}
if (Key == EKeys::NumPadZero ||
Key == EKeys::NumPadOne ||
Key == EKeys::NumPadTwo ||
Key == EKeys::NumPadThree ||
Key == EKeys::NumPadFour ||
Key == EKeys::NumPadFive ||
Key == EKeys::NumPadSix ||
Key == EKeys::NumPadSeven ||
Key == EKeys::NumPadEight ||
Key == EKeys::NumPadNine)
{
Modifiers |= EVENTFLAG_IS_KEY_PAD;
}
return Modifiers;
}
int32 FWebBrowserWindow::GetCefMouseModifiers(const FPointerEvent& InMouseEvent)
{
int32 Modifiers = GetCefInputModifiers(InMouseEvent);
if (InMouseEvent.IsMouseButtonDown(EKeys::LeftMouseButton))
{
Modifiers |= EVENTFLAG_LEFT_MOUSE_BUTTON;
}
if (InMouseEvent.IsMouseButtonDown(EKeys::MiddleMouseButton))
{
Modifiers |= EVENTFLAG_MIDDLE_MOUSE_BUTTON;
}
if (InMouseEvent.IsMouseButtonDown(EKeys::RightMouseButton))
{
Modifiers |= EVENTFLAG_RIGHT_MOUSE_BUTTON;
}
return Modifiers;
}
int32 FWebBrowserWindow::GetCefInputModifiers(const FInputEvent& InputEvent)
{
int32 Modifiers = 0;
if (InputEvent.IsShiftDown())
{
Modifiers |= EVENTFLAG_SHIFT_DOWN;
}
if (InputEvent.IsControlDown())
{
Modifiers |= EVENTFLAG_CONTROL_DOWN;
}
if (InputEvent.IsAltDown())
{
Modifiers |= EVENTFLAG_ALT_DOWN;
}
if (InputEvent.IsCommandDown())
{
Modifiers |= EVENTFLAG_COMMAND_DOWN;
}
if (InputEvent.AreCapsLocked())
{
Modifiers |= EVENTFLAG_CAPS_LOCK_ON;
}
// TODO: Add function for this if necessary
/*if (InputEvent.AreNumsLocked())
{
Modifiers |= EVENTFLAG_NUM_LOCK_ON;
}*/
return Modifiers;
}
#endif