mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Added WinRT web view
This commit is contained in:
parent
4e7eb0875b
commit
8f3b9036d6
7 changed files with 662 additions and 59 deletions
|
|
@ -63,9 +63,8 @@
|
|||
/** Config: JUCE_USE_WINRT_MIDI
|
||||
Enables the use of the Windows Runtime API for MIDI, allowing connections
|
||||
to Bluetooth Low Energy devices on Windows 10 version 1809 (October 2018
|
||||
Update) and later. If you enable this flag then older, unsupported,
|
||||
versions of Windows will automatically fall back to using the regular
|
||||
Win32 MIDI API.
|
||||
Update) and later. If you enable this flag then older versions of Windows
|
||||
will automatically fall back to using the regular Win32 MIDI API.
|
||||
|
||||
You will need version 10.0.14393.0 of the Windows Standalone SDK to compile
|
||||
and you may need to add the path to the WinRT headers. The path to the
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
#define JUCE_CORE_INCLUDE_COM_SMART_PTR 1
|
||||
#define JUCE_EVENTS_INCLUDE_WIN32_MESSAGE_WINDOW 1
|
||||
|
||||
#if JUCE_USE_WINRT_MIDI
|
||||
#if JUCE_USE_WINRT_MIDI || JUCE_USE_WINRT_WEBVIEW
|
||||
#define JUCE_EVENTS_INCLUDE_WINRT_WRAPPER 1
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@
|
|||
#define JUCE_EXECUTE_APP_SUSPEND_ON_BACKGROUND_TASK 0
|
||||
#endif
|
||||
|
||||
#if JUCE_EVENTS_INCLUDE_WINRT_WRAPPER && JUCE_WINDOWS
|
||||
#if JUCE_WINDOWS && JUCE_EVENTS_INCLUDE_WINRT_WRAPPER
|
||||
// If this header file is missing then you are probably attempting to use WinRT
|
||||
// functionality without the WinRT libraries installed on your system. Try installing
|
||||
// the latest Windows Standalone SDK and maybe also adding the path to the WinRT
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ public:
|
|||
~ComPtr() { release(); }
|
||||
|
||||
operator ComClass*() const noexcept { return p; }
|
||||
ComClass* get() const noexcept { return p; }
|
||||
ComClass& operator*() const noexcept { return *p; }
|
||||
ComClass* operator->() const noexcept { return p; }
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,10 @@
|
|||
#define JUCE_EVENTS_INCLUDE_WIN32_MESSAGE_WINDOW 1
|
||||
#define JUCE_GRAPHICS_INCLUDE_COREGRAPHICS_HELPERS 1
|
||||
|
||||
#if JUCE_USE_WINRT_WEBVIEW
|
||||
#define JUCE_EVENTS_INCLUDE_WINRT_WRAPPER 1
|
||||
#endif
|
||||
|
||||
#ifndef JUCE_PUSH_NOTIFICATIONS
|
||||
#define JUCE_PUSH_NOTIFICATIONS 0
|
||||
#endif
|
||||
|
|
@ -78,6 +82,18 @@
|
|||
#if JUCE_WEB_BROWSER
|
||||
#include <exdisp.h>
|
||||
#include <exdispid.h>
|
||||
#if JUCE_USE_WINRT_WEBVIEW
|
||||
#include <windows.web.ui.h>
|
||||
#include <windows.web.ui.interop.h>
|
||||
#include <windows.foundation.h>
|
||||
#include <windows.foundation.collections.h>
|
||||
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable: 4265)
|
||||
#include <wrl.h>
|
||||
#include <wrl/wrappers/corewrappers.h>
|
||||
#pragma warning (pop)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
|
|
|
|||
|
|
@ -56,6 +56,21 @@
|
|||
#define JUCE_WEB_BROWSER 1
|
||||
#endif
|
||||
|
||||
/** Config: JUCE_USE_WINRT_WEBVIEW
|
||||
Enables the use of the EdgeHTML browser engine on Windows. This will use
|
||||
the Windows Runtime API on Windows 10 version 1809 (October 2018 Update)
|
||||
and later. If you enable this flag then older versions of Windows will
|
||||
automatically fall back to using the regualar Win32 web view.
|
||||
|
||||
You will need version 10.0.14393.0 of the Windows Standalone SDK to compile
|
||||
and you may need to add the path to the WinRT headers. The path to the
|
||||
headers will be something similar to
|
||||
"C:\Program Files (x86)\Windows Kits\10\Include\10.0.14393.0\winrt".
|
||||
*/
|
||||
#ifndef JUCE_USE_WINRT_WEBVIEW
|
||||
#define JUCE_USE_WINRT_WEBVIEW 0
|
||||
#endif
|
||||
|
||||
/** Config: JUCE_ENABLE_LIVE_CONSTANT_EDITOR
|
||||
This lets you turn on the JUCE_ENABLE_LIVE_CONSTANT_EDITOR support (desktop only). By default
|
||||
this will be enabled for debug builds and disabled for release builds. See the documentation
|
||||
|
|
|
|||
|
|
@ -19,6 +19,27 @@
|
|||
namespace juce
|
||||
{
|
||||
|
||||
struct InternalWebViewType
|
||||
{
|
||||
InternalWebViewType() {}
|
||||
virtual ~InternalWebViewType() {}
|
||||
|
||||
virtual void createBrowser() = 0;
|
||||
virtual bool hasBrowserBeenCreated() = 0;
|
||||
|
||||
virtual void goToURL (const String&, const StringArray*, const MemoryBlock*) = 0;
|
||||
|
||||
virtual void stop() = 0;
|
||||
virtual void goBack() = 0;
|
||||
virtual void goForward() = 0;
|
||||
virtual void refresh() = 0;
|
||||
|
||||
virtual void focusGained() {}
|
||||
virtual void setWebViewSize (int, int) = 0;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (InternalWebViewType)
|
||||
};
|
||||
|
||||
#if JUCE_MINGW
|
||||
JUCE_DECLARE_UUID_GETTER (IOleClientSite, "00000118-0000-0000-c000-000000000046")
|
||||
JUCE_DECLARE_UUID_GETTER (IDispatch, "00020400-0000-0000-c000-000000000046")
|
||||
|
|
@ -33,12 +54,17 @@ JUCE_DECLARE_UUID_GETTER (IConnectionPointContainer, "B196B284-BAB4-101A-B69C-00
|
|||
JUCE_DECLARE_UUID_GETTER (IWebBrowser2, "D30C1661-CDAF-11D0-8A3E-00C04FC9E26E")
|
||||
JUCE_DECLARE_UUID_GETTER (WebBrowser, "8856F961-340A-11D0-A96B-00C04FD705A2")
|
||||
|
||||
class WebBrowserComponent::Pimpl : public ActiveXControlComponent
|
||||
//==============================================================================
|
||||
class Win32WebView : public InternalWebViewType,
|
||||
public ActiveXControlComponent
|
||||
{
|
||||
public:
|
||||
Pimpl() {}
|
||||
Win32WebView (WebBrowserComponent& owner)
|
||||
{
|
||||
owner.addAndMakeVisible (this);
|
||||
}
|
||||
|
||||
~Pimpl()
|
||||
~Win32WebView() override
|
||||
{
|
||||
if (connectionPoint != nullptr)
|
||||
connectionPoint->Unadvise (adviseCookie);
|
||||
|
|
@ -47,7 +73,7 @@ public:
|
|||
browser->Release();
|
||||
}
|
||||
|
||||
void createBrowser()
|
||||
void createBrowser() override
|
||||
{
|
||||
auto webCLSID = __uuidof (WebBrowser);
|
||||
createControl (&webCLSID);
|
||||
|
|
@ -63,7 +89,7 @@ public:
|
|||
|
||||
if (connectionPoint != nullptr)
|
||||
{
|
||||
auto* owner = dynamic_cast<WebBrowserComponent*> (getParentComponent());
|
||||
auto* owner = dynamic_cast<WebBrowserComponent*> (Component::getParentComponent());
|
||||
jassert (owner != nullptr);
|
||||
|
||||
auto handler = new EventHandler (*owner);
|
||||
|
|
@ -73,9 +99,12 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void goToURL (const String& url,
|
||||
const StringArray* headers,
|
||||
const MemoryBlock* postData)
|
||||
bool hasBrowserBeenCreated() override
|
||||
{
|
||||
return browser != nullptr;
|
||||
}
|
||||
|
||||
void goToURL (const String& url, const StringArray* headers, const MemoryBlock* postData) override
|
||||
{
|
||||
if (browser != nullptr)
|
||||
{
|
||||
|
|
@ -132,10 +161,63 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
IWebBrowser2* browser = nullptr;
|
||||
void stop() override
|
||||
{
|
||||
if (browser != nullptr)
|
||||
browser->Stop();
|
||||
}
|
||||
|
||||
void goBack() override
|
||||
{
|
||||
if (browser != nullptr)
|
||||
browser->GoBack();
|
||||
}
|
||||
|
||||
void goForward() override
|
||||
{
|
||||
if (browser != nullptr)
|
||||
browser->GoForward();
|
||||
}
|
||||
|
||||
void refresh() override
|
||||
{
|
||||
if (browser != nullptr)
|
||||
browser->Refresh();
|
||||
}
|
||||
|
||||
void focusGained() override
|
||||
{
|
||||
auto iidOleObject = __uuidof (IOleObject);
|
||||
auto iidOleWindow = __uuidof (IOleWindow);
|
||||
|
||||
if (auto oleObject = (IOleObject*) queryInterface (&iidOleObject))
|
||||
{
|
||||
if (auto oleWindow = (IOleWindow*) queryInterface (&iidOleWindow))
|
||||
{
|
||||
IOleClientSite* oleClientSite = nullptr;
|
||||
|
||||
if (SUCCEEDED (oleObject->GetClientSite (&oleClientSite)))
|
||||
{
|
||||
HWND hwnd;
|
||||
oleWindow->GetWindow (&hwnd);
|
||||
oleObject->DoVerb (OLEIVERB_UIACTIVATE, nullptr, oleClientSite, 0, hwnd, nullptr);
|
||||
oleClientSite->Release();
|
||||
}
|
||||
|
||||
oleWindow->Release();
|
||||
}
|
||||
|
||||
oleObject->Release();
|
||||
}
|
||||
}
|
||||
|
||||
void setWebViewSize (int width, int height) override
|
||||
{
|
||||
setSize (width, height);
|
||||
}
|
||||
|
||||
private:
|
||||
IWebBrowser2* browser = nullptr;
|
||||
IConnectionPoint* connectionPoint = nullptr;
|
||||
DWORD adviseCookie = 0;
|
||||
|
||||
|
|
@ -226,19 +308,534 @@ private:
|
|||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (EventHandler)
|
||||
};
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pimpl)
|
||||
};
|
||||
|
||||
#if JUCE_USE_WINRT_WEBVIEW
|
||||
|
||||
extern RTL_OSVERSIONINFOW getWindowsVersionInfo();
|
||||
|
||||
using namespace Microsoft::WRL;
|
||||
|
||||
using namespace ABI::Windows::Foundation;
|
||||
using namespace ABI::Windows::Storage::Streams;
|
||||
using namespace ABI::Windows::Web;
|
||||
using namespace ABI::Windows::Web::UI;
|
||||
using namespace ABI::Windows::Web::UI::Interop;
|
||||
using namespace ABI::Windows::Web::Http;
|
||||
using namespace ABI::Windows::Web::Http::Headers;
|
||||
|
||||
//==============================================================================
|
||||
WebBrowserComponent::WebBrowserComponent (const bool unloadPageWhenBrowserIsHidden_)
|
||||
: browser (new Pimpl()),
|
||||
blankPageShown (false),
|
||||
unloadPageWhenBrowserIsHidden (unloadPageWhenBrowserIsHidden_)
|
||||
class WinRTWebView : public InternalWebViewType,
|
||||
public Component,
|
||||
public ComponentMovementWatcher
|
||||
{
|
||||
public:
|
||||
WinRTWebView (WebBrowserComponent& o)
|
||||
: ComponentMovementWatcher (&o),
|
||||
owner (o)
|
||||
{
|
||||
if (! WinRTWrapper::getInstance()->isInitialised())
|
||||
throw std::runtime_error ("Failed to initialise the WinRT wrapper");
|
||||
|
||||
if (! createWebViewProcess())
|
||||
throw std::runtime_error ("Failed to create the WebViewControlProcess");
|
||||
|
||||
owner.addAndMakeVisible (this);
|
||||
}
|
||||
|
||||
~WinRTWebView() override
|
||||
{
|
||||
if (webViewControl != nullptr)
|
||||
webViewControl->Stop();
|
||||
|
||||
removeEventHandlers();
|
||||
|
||||
webViewProcess->Terminate();
|
||||
}
|
||||
|
||||
void createBrowser() override
|
||||
{
|
||||
if (webViewControl == nullptr)
|
||||
createWebViewControl();
|
||||
}
|
||||
|
||||
bool hasBrowserBeenCreated() override
|
||||
{
|
||||
return webViewControl != nullptr || isCreating;
|
||||
}
|
||||
|
||||
void goToURL (const String& url, const StringArray* headers, const MemoryBlock* postData) override
|
||||
{
|
||||
if (webViewControl != nullptr)
|
||||
{
|
||||
if ((headers != nullptr && ! headers->isEmpty())
|
||||
|| (postData != nullptr && postData->getSize() > 0))
|
||||
{
|
||||
auto requestMessage = createHttpRequestMessage (url, headers, postData);
|
||||
webViewControl->NavigateWithHttpRequestMessage (requestMessage.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
auto uri = createURI (url);
|
||||
webViewControl->Navigate (uri.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void stop() override
|
||||
{
|
||||
if (webViewControl != nullptr)
|
||||
webViewControl->Stop();
|
||||
}
|
||||
|
||||
void goBack() override
|
||||
{
|
||||
if (webViewControl != nullptr)
|
||||
{
|
||||
boolean canGoBack = false;
|
||||
webViewControl->get_CanGoBack (&canGoBack);
|
||||
|
||||
if (canGoBack)
|
||||
webViewControl->GoBack();
|
||||
}
|
||||
}
|
||||
|
||||
void goForward() override
|
||||
{
|
||||
if (webViewControl != nullptr)
|
||||
{
|
||||
boolean canGoForward = false;
|
||||
webViewControl->get_CanGoForward (&canGoForward);
|
||||
|
||||
if (canGoForward)
|
||||
webViewControl->GoForward();
|
||||
}
|
||||
}
|
||||
|
||||
void refresh() override
|
||||
{
|
||||
if (webViewControl != nullptr)
|
||||
webViewControl->Refresh();
|
||||
}
|
||||
|
||||
void setWebViewSize (int width, int height) override
|
||||
{
|
||||
setSize (width, height);
|
||||
}
|
||||
|
||||
void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/) override
|
||||
{
|
||||
if (auto* peer = owner.getTopLevelComponent()->getPeer())
|
||||
setControlBounds (peer->getAreaCoveredBy (owner));
|
||||
}
|
||||
|
||||
void componentPeerChanged() override
|
||||
{
|
||||
componentMovedOrResized (true, true);
|
||||
}
|
||||
|
||||
void componentVisibilityChanged() override
|
||||
{
|
||||
setControlVisible (owner.isShowing());
|
||||
|
||||
componentPeerChanged();
|
||||
owner.visibilityChanged();
|
||||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
template<typename OperationResultType, typename ResultsType>
|
||||
static HRESULT waitForCompletion (IAsyncOperation<OperationResultType>* op, ResultsType* results)
|
||||
{
|
||||
using OperationType = IAsyncOperation<OperationResultType>;
|
||||
using DelegateType = IAsyncOperationCompletedHandler<OperationResultType>;
|
||||
|
||||
struct EventDelegate : public RuntimeClass<RuntimeClassFlags<RuntimeClassType::Delegate>,
|
||||
DelegateType,
|
||||
FtmBase>
|
||||
{
|
||||
EventDelegate() = default;
|
||||
|
||||
~EventDelegate()
|
||||
{
|
||||
CloseHandle (eventCompleted);
|
||||
}
|
||||
|
||||
HRESULT RuntimeClassInitialize()
|
||||
{
|
||||
eventCompleted = CreateEventEx (nullptr, nullptr, 0, EVENT_ALL_ACCESS);
|
||||
return eventCompleted == nullptr ? HRESULT_FROM_WIN32 (GetLastError()) : S_OK;
|
||||
}
|
||||
|
||||
HRESULT Invoke (OperationType*, AsyncStatus newStatus)
|
||||
{
|
||||
status = newStatus;
|
||||
SetEvent (eventCompleted);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
AsyncStatus status = AsyncStatus::Started;
|
||||
HANDLE eventCompleted = nullptr;
|
||||
};
|
||||
|
||||
WinRTWrapper::ComPtr<OperationType> operation = op;
|
||||
WinRTWrapper::ComPtr<EventDelegate> eventCallback;
|
||||
|
||||
auto hr = MakeAndInitialize<EventDelegate> (eventCallback.resetAndGetPointerAddress());
|
||||
|
||||
if (SUCCEEDED (hr))
|
||||
{
|
||||
hr = operation->put_Completed (eventCallback.get());
|
||||
|
||||
if (SUCCEEDED (hr))
|
||||
{
|
||||
HANDLE waitForEvents[1] { eventCallback->eventCompleted };
|
||||
auto handleCount = (ULONG) ARRAYSIZE (waitForEvents);
|
||||
DWORD handleIndex = 0;
|
||||
|
||||
hr = CoWaitForMultipleHandles (COWAIT_DISPATCH_WINDOW_MESSAGES | COWAIT_DISPATCH_CALLS | COWAIT_INPUTAVAILABLE,
|
||||
INFINITE, handleCount, waitForEvents, &handleIndex);
|
||||
|
||||
if (SUCCEEDED (hr))
|
||||
{
|
||||
if (eventCallback->status == AsyncStatus::Completed)
|
||||
{
|
||||
hr = operation->GetResults (results);
|
||||
}
|
||||
else
|
||||
{
|
||||
WinRTWrapper::ComPtr<IAsyncInfo> asyncInfo;
|
||||
|
||||
if (SUCCEEDED (operation->QueryInterface (asyncInfo.resetAndGetPointerAddress())))
|
||||
asyncInfo->get_ErrorCode (&hr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
template<class ArgsType>
|
||||
String getURIStringFromArgs (ArgsType& args)
|
||||
{
|
||||
WinRTWrapper::ComPtr<IUriRuntimeClass> uri;
|
||||
args.get_Uri (uri.resetAndGetPointerAddress());
|
||||
|
||||
if (uri != nullptr)
|
||||
{
|
||||
HSTRING uriString;
|
||||
uri->get_AbsoluteUri (&uriString);
|
||||
|
||||
return WinRTWrapper::getInstance()->hStringToString (uriString);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void addEventHandlers()
|
||||
{
|
||||
if (webViewControl != nullptr)
|
||||
{
|
||||
webViewControl->add_NavigationStarting (Callback<ITypedEventHandler<IWebViewControl*, WebViewControlNavigationStartingEventArgs*>> (
|
||||
[this] (IWebViewControl*, IWebViewControlNavigationStartingEventArgs* args)
|
||||
{
|
||||
auto uriString = getURIStringFromArgs (*args);
|
||||
|
||||
if (uriString.isNotEmpty())
|
||||
args->put_Cancel (! owner.pageAboutToLoad (uriString));
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
).Get(), &navigationStartingToken);
|
||||
|
||||
webViewControl->add_NewWindowRequested (Callback<ITypedEventHandler<IWebViewControl*, WebViewControlNewWindowRequestedEventArgs*>> (
|
||||
[this] (IWebViewControl*, IWebViewControlNewWindowRequestedEventArgs* args)
|
||||
{
|
||||
auto uriString = getURIStringFromArgs (*args);
|
||||
|
||||
if (uriString.isNotEmpty())
|
||||
{
|
||||
owner.newWindowAttemptingToLoad (uriString);
|
||||
args->put_Handled (true);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
).Get(), &newWindowRequestedToken);
|
||||
|
||||
webViewControl->add_NavigationCompleted (Callback<ITypedEventHandler<IWebViewControl*, WebViewControlNavigationCompletedEventArgs*>> (
|
||||
[this] (IWebViewControl*, IWebViewControlNavigationCompletedEventArgs* args)
|
||||
{
|
||||
auto uriString = getURIStringFromArgs (*args);
|
||||
|
||||
if (uriString.isNotEmpty())
|
||||
{
|
||||
boolean success;
|
||||
args->get_IsSuccess (&success);
|
||||
|
||||
if (success)
|
||||
{
|
||||
owner.pageFinishedLoading (uriString);
|
||||
}
|
||||
else
|
||||
{
|
||||
WebErrorStatus status;
|
||||
args->get_WebErrorStatus (&status);
|
||||
|
||||
owner.pageLoadHadNetworkError ("Error code: " + String (status));
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
).Get(), &navigationCompletedToken);
|
||||
}
|
||||
}
|
||||
|
||||
void removeEventHandlers()
|
||||
{
|
||||
if (webViewControl != nullptr)
|
||||
{
|
||||
if (navigationStartingToken.value != 0)
|
||||
webViewControl->remove_NavigationStarting (navigationStartingToken);
|
||||
|
||||
if (newWindowRequestedToken.value != 0)
|
||||
webViewControl->remove_NewWindowRequested (newWindowRequestedToken);
|
||||
|
||||
if (navigationCompletedToken.value != 0)
|
||||
webViewControl->remove_NavigationCompleted (navigationCompletedToken);
|
||||
}
|
||||
}
|
||||
|
||||
bool createWebViewProcess()
|
||||
{
|
||||
auto webViewControlProcessFactory
|
||||
= WinRTWrapper::getInstance()->getWRLFactory<IWebViewControlProcessFactory> (RuntimeClass_Windows_Web_UI_Interop_WebViewControlProcess);
|
||||
|
||||
if (webViewControlProcessFactory == nullptr)
|
||||
{
|
||||
jassertfalse;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto webViewProcessOptions
|
||||
= WinRTWrapper::getInstance()->activateInstance<IWebViewControlProcessOptions> (RuntimeClass_Windows_Web_UI_Interop_WebViewControlProcessOptions,
|
||||
__uuidof (IWebViewControlProcessOptions));
|
||||
|
||||
webViewProcessOptions->put_PrivateNetworkClientServerCapability (WebViewControlProcessCapabilityState_Enabled);
|
||||
webViewControlProcessFactory->CreateWithOptions (webViewProcessOptions.get(), webViewProcess.resetAndGetPointerAddress());
|
||||
|
||||
return webViewProcess != nullptr;
|
||||
}
|
||||
|
||||
void createWebViewControl()
|
||||
{
|
||||
if (auto* peer = getPeer())
|
||||
{
|
||||
ScopedValueSetter<bool> svs (isCreating, true);
|
||||
|
||||
WinRTWrapper::ComPtr<IAsyncOperation<WebViewControl*>> createWebViewAsyncOperation;
|
||||
|
||||
webViewProcess->CreateWebViewControlAsync ((INT64) peer->getNativeHandle(), {},
|
||||
createWebViewAsyncOperation.resetAndGetPointerAddress());
|
||||
|
||||
waitForCompletion (createWebViewAsyncOperation.get(), webViewControl.resetAndGetPointerAddress());
|
||||
|
||||
addEventHandlers();
|
||||
componentMovedOrResized (true, true);
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
WinRTWrapper::ComPtr<IUriRuntimeClass> createURI (const String& url)
|
||||
{
|
||||
auto uriRuntimeFactory
|
||||
= WinRTWrapper::getInstance()->getWRLFactory <IUriRuntimeClassFactory> (RuntimeClass_Windows_Foundation_Uri);
|
||||
|
||||
if (uriRuntimeFactory == nullptr)
|
||||
{
|
||||
jassertfalse;
|
||||
return {};
|
||||
}
|
||||
|
||||
WinRTWrapper::ScopedHString hstr (url);
|
||||
WinRTWrapper::ComPtr<IUriRuntimeClass> uriRuntimeClass;
|
||||
uriRuntimeFactory->CreateUri (hstr.get(), uriRuntimeClass.resetAndGetPointerAddress());
|
||||
|
||||
return uriRuntimeClass;
|
||||
}
|
||||
|
||||
WinRTWrapper::ComPtr<IHttpContent> getPOSTContent (const MemoryBlock& postData)
|
||||
{
|
||||
auto factory = WinRTWrapper::getInstance()->getWRLFactory<IHttpStringContentFactory> (RuntimeClass_Windows_Web_Http_HttpStringContent);
|
||||
|
||||
if (factory == nullptr)
|
||||
{
|
||||
jassertfalse;
|
||||
return {};
|
||||
}
|
||||
|
||||
WinRTWrapper::ScopedHString hStr (postData.toString());
|
||||
|
||||
WinRTWrapper::ComPtr<IHttpContent> content;
|
||||
factory->CreateFromString (hStr.get(), content.resetAndGetPointerAddress());
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
WinRTWrapper::ComPtr<IHttpMethod> getMethod (bool isPOST)
|
||||
{
|
||||
auto methodFactory = WinRTWrapper::getInstance()->getWRLFactory<IHttpMethodStatics> (RuntimeClass_Windows_Web_Http_HttpMethod);
|
||||
|
||||
if (methodFactory == nullptr)
|
||||
{
|
||||
jassertfalse;
|
||||
return {};
|
||||
}
|
||||
|
||||
WinRTWrapper::ComPtr<IHttpMethod> method;
|
||||
|
||||
if (isPOST)
|
||||
methodFactory->get_Post (method.resetAndGetPointerAddress());
|
||||
else
|
||||
methodFactory->get_Get (method.resetAndGetPointerAddress());
|
||||
|
||||
return method;
|
||||
}
|
||||
|
||||
void addHttpHeaders (WinRTWrapper::ComPtr<IHttpRequestMessage>& requestMessage, const StringArray& headers)
|
||||
{
|
||||
WinRTWrapper::ComPtr<IHttpRequestHeaderCollection> headerCollection;
|
||||
requestMessage->get_Headers (headerCollection.resetAndGetPointerAddress());
|
||||
|
||||
for (int i = 0; i < headers.size(); ++i)
|
||||
{
|
||||
WinRTWrapper::ScopedHString headerName (headers[i].upToFirstOccurrenceOf (":", false, false).trim());
|
||||
WinRTWrapper::ScopedHString headerValue (headers[i].fromFirstOccurrenceOf (":", false, false).trim());
|
||||
|
||||
headerCollection->Append (headerName.get(), headerValue.get());
|
||||
}
|
||||
}
|
||||
|
||||
WinRTWrapper::ComPtr<IHttpRequestMessage> createHttpRequestMessage (const String& url,
|
||||
const StringArray* headers,
|
||||
const MemoryBlock* postData)
|
||||
{
|
||||
auto requestFactory
|
||||
= WinRTWrapper::getInstance()->getWRLFactory<IHttpRequestMessageFactory> (RuntimeClass_Windows_Web_Http_HttpRequestMessage);
|
||||
|
||||
if (requestFactory == nullptr)
|
||||
{
|
||||
jassertfalse;
|
||||
return {};
|
||||
}
|
||||
|
||||
bool isPOSTRequest = (postData != nullptr && postData->getSize() > 0);
|
||||
auto method = getMethod (isPOSTRequest);
|
||||
|
||||
auto uri = createURI (url);
|
||||
|
||||
WinRTWrapper::ComPtr<IHttpRequestMessage> requestMessage;
|
||||
requestFactory->Create (method.get(), uri.get(), requestMessage.resetAndGetPointerAddress());
|
||||
|
||||
if (isPOSTRequest)
|
||||
{
|
||||
auto content = getPOSTContent (*postData);
|
||||
requestMessage->put_Content (content.get());
|
||||
}
|
||||
|
||||
if (headers != nullptr && ! headers->isEmpty())
|
||||
addHttpHeaders (requestMessage, *headers);
|
||||
|
||||
return requestMessage;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void setControlBounds (Rectangle<int> newBounds) const
|
||||
{
|
||||
if (webViewControl != nullptr)
|
||||
{
|
||||
#if JUCE_WIN_PER_MONITOR_DPI_AWARE
|
||||
if (auto* peer = owner.getTopLevelComponent()->getPeer())
|
||||
newBounds = (newBounds.toDouble() * peer->getPlatformScaleFactor()).toNearestInt();
|
||||
#endif
|
||||
|
||||
WinRTWrapper::ComPtr<IWebViewControlSite> site;
|
||||
|
||||
if (SUCCEEDED (webViewControl->QueryInterface (site.resetAndGetPointerAddress())))
|
||||
site->put_Bounds ({ static_cast<FLOAT> (newBounds.getX()), static_cast<FLOAT> (newBounds.getY()),
|
||||
static_cast<FLOAT> (newBounds.getWidth()), static_cast<FLOAT> (newBounds.getHeight()) });
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void setControlVisible (bool shouldBeVisible) const
|
||||
{
|
||||
if (webViewControl != 0)
|
||||
{
|
||||
WinRTWrapper::ComPtr<IWebViewControlSite> site;
|
||||
|
||||
if (SUCCEEDED (webViewControl->QueryInterface (site.resetAndGetPointerAddress())))
|
||||
site->put_IsVisible (shouldBeVisible);
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
WebBrowserComponent& owner;
|
||||
|
||||
WinRTWrapper::ComPtr<IWebViewControlProcess> webViewProcess;
|
||||
WinRTWrapper::ComPtr<IWebViewControl> webViewControl;
|
||||
|
||||
EventRegistrationToken navigationStartingToken { 0 },
|
||||
newWindowRequestedToken { 0 },
|
||||
navigationCompletedToken { 0 };
|
||||
|
||||
bool isCreating = false;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
class WebBrowserComponent::Pimpl
|
||||
{
|
||||
public:
|
||||
Pimpl (WebBrowserComponent& owner)
|
||||
{
|
||||
#if JUCE_USE_WINRT_WEBVIEW
|
||||
auto windowsVersionInfo = getWindowsVersionInfo();
|
||||
|
||||
if (windowsVersionInfo.dwMajorVersion >= 10 && windowsVersionInfo.dwBuildNumber >= 17763)
|
||||
{
|
||||
try
|
||||
{
|
||||
internal.reset (new WinRTWebView (owner));
|
||||
}
|
||||
catch (std::runtime_error&) {}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (internal == nullptr)
|
||||
internal.reset (new Win32WebView (owner));
|
||||
}
|
||||
|
||||
InternalWebViewType& getInternalWebView()
|
||||
{
|
||||
return *internal;
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<InternalWebViewType> internal;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
WebBrowserComponent::WebBrowserComponent (bool unloadWhenHidden)
|
||||
: browser (new Pimpl (*this)),
|
||||
unloadPageWhenBrowserIsHidden (unloadWhenHidden)
|
||||
{
|
||||
setOpaque (true);
|
||||
addAndMakeVisible (browser.get());
|
||||
}
|
||||
|
||||
WebBrowserComponent::~WebBrowserComponent()
|
||||
|
|
@ -264,16 +861,15 @@ void WebBrowserComponent::goToURL (const String& url,
|
|||
|
||||
blankPageShown = false;
|
||||
|
||||
if (browser->browser == nullptr)
|
||||
if (! browser->getInternalWebView().hasBrowserBeenCreated())
|
||||
checkWindowAssociation();
|
||||
|
||||
browser->goToURL (url, headers, postData);
|
||||
browser->getInternalWebView().goToURL (url, headers, postData);
|
||||
}
|
||||
|
||||
void WebBrowserComponent::stop()
|
||||
{
|
||||
if (browser->browser != nullptr)
|
||||
browser->browser->Stop();
|
||||
browser->getInternalWebView().stop();
|
||||
}
|
||||
|
||||
void WebBrowserComponent::goBack()
|
||||
|
|
@ -281,28 +877,25 @@ void WebBrowserComponent::goBack()
|
|||
lastURL.clear();
|
||||
blankPageShown = false;
|
||||
|
||||
if (browser->browser != nullptr)
|
||||
browser->browser->GoBack();
|
||||
browser->getInternalWebView().goBack();
|
||||
}
|
||||
|
||||
void WebBrowserComponent::goForward()
|
||||
{
|
||||
lastURL.clear();
|
||||
|
||||
if (browser->browser != nullptr)
|
||||
browser->browser->GoForward();
|
||||
browser->getInternalWebView().goForward();
|
||||
}
|
||||
|
||||
void WebBrowserComponent::refresh()
|
||||
{
|
||||
if (browser->browser != nullptr)
|
||||
browser->browser->Refresh();
|
||||
browser->getInternalWebView().refresh();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void WebBrowserComponent::paint (Graphics& g)
|
||||
{
|
||||
if (browser->browser == nullptr)
|
||||
if (! browser->getInternalWebView().hasBrowserBeenCreated())
|
||||
{
|
||||
g.fillAll (Colours::white);
|
||||
checkWindowAssociation();
|
||||
|
|
@ -313,9 +906,9 @@ void WebBrowserComponent::checkWindowAssociation()
|
|||
{
|
||||
if (isShowing())
|
||||
{
|
||||
if (browser->browser == nullptr && getPeer() != nullptr)
|
||||
if (! browser->getInternalWebView().hasBrowserBeenCreated() && getPeer() != nullptr)
|
||||
{
|
||||
browser->createBrowser();
|
||||
browser->getInternalWebView().createBrowser();
|
||||
reloadLastURL();
|
||||
}
|
||||
else
|
||||
|
|
@ -333,7 +926,7 @@ void WebBrowserComponent::checkWindowAssociation()
|
|||
// page to avoid this..
|
||||
|
||||
blankPageShown = true;
|
||||
browser->goToURL ("about:blank", 0, 0);
|
||||
browser->getInternalWebView().goToURL ("about:blank", 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -354,7 +947,7 @@ void WebBrowserComponent::parentHierarchyChanged()
|
|||
|
||||
void WebBrowserComponent::resized()
|
||||
{
|
||||
browser->setSize (getWidth(), getHeight());
|
||||
browser->getInternalWebView().setWebViewSize (getWidth(), getHeight());
|
||||
}
|
||||
|
||||
void WebBrowserComponent::visibilityChanged()
|
||||
|
|
@ -364,28 +957,7 @@ void WebBrowserComponent::visibilityChanged()
|
|||
|
||||
void WebBrowserComponent::focusGained (FocusChangeType)
|
||||
{
|
||||
auto iidOleObject = __uuidof (IOleObject);
|
||||
auto iidOleWindow = __uuidof (IOleWindow);
|
||||
|
||||
if (auto oleObject = (IOleObject*) browser->queryInterface (&iidOleObject))
|
||||
{
|
||||
if (auto oleWindow = (IOleWindow*) browser->queryInterface (&iidOleWindow))
|
||||
{
|
||||
IOleClientSite* oleClientSite = nullptr;
|
||||
|
||||
if (SUCCEEDED (oleObject->GetClientSite (&oleClientSite)))
|
||||
{
|
||||
HWND hwnd;
|
||||
oleWindow->GetWindow (&hwnd);
|
||||
oleObject->DoVerb (OLEIVERB_UIACTIVATE, nullptr, oleClientSite, 0, hwnd, nullptr);
|
||||
oleClientSite->Release();
|
||||
}
|
||||
|
||||
oleWindow->Release();
|
||||
}
|
||||
|
||||
oleObject->Release();
|
||||
}
|
||||
browser->getInternalWebView().focusGained();
|
||||
}
|
||||
|
||||
void WebBrowserComponent::clearCookies()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue