mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Windows: Add WebView2Preferences struct to modify aspects of WebView2 behaviour
This commit is contained in:
parent
315f6d8fcd
commit
4649bc1b13
6 changed files with 154 additions and 56 deletions
|
|
@ -192,4 +192,11 @@
|
||||||
#if ! JUCE_WINDOWS
|
#if ! JUCE_WINDOWS
|
||||||
juce::ScopedDPIAwarenessDisabler::ScopedDPIAwarenessDisabler() { ignoreUnused (previousContext); }
|
juce::ScopedDPIAwarenessDisabler::ScopedDPIAwarenessDisabler() { ignoreUnused (previousContext); }
|
||||||
juce::ScopedDPIAwarenessDisabler::~ScopedDPIAwarenessDisabler() {}
|
juce::ScopedDPIAwarenessDisabler::~ScopedDPIAwarenessDisabler() {}
|
||||||
|
|
||||||
|
#if JUCE_WEB_BROWSER
|
||||||
|
juce::WebBrowserComponent::WebBrowserComponent (ConstructWithoutPimpl) {}
|
||||||
|
juce::WindowsWebView2WebBrowserComponent::WindowsWebView2WebBrowserComponent (bool unloadWhenHidden,
|
||||||
|
const WebView2Preferences&)
|
||||||
|
: juce::WebBrowserComponent (unloadWhenHidden) {}
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -141,14 +141,17 @@ public:
|
||||||
/** @internal */
|
/** @internal */
|
||||||
class Pimpl;
|
class Pimpl;
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
//==============================================================================
|
|
||||||
friend class WindowsWebView2WebBrowserComponent;
|
friend class WindowsWebView2WebBrowserComponent;
|
||||||
|
|
||||||
explicit WebBrowserComponent (bool unloadPageWhenBrowserIsHidden,
|
struct ConstructWithoutPimpl
|
||||||
const File& dllLocation,
|
{
|
||||||
const File& userDataFolder);
|
explicit ConstructWithoutPimpl (bool unloadOnHide) : unloadWhenHidden (unloadOnHide) {}
|
||||||
|
const bool unloadWhenHidden;
|
||||||
|
};
|
||||||
|
explicit WebBrowserComponent (ConstructWithoutPimpl);
|
||||||
|
|
||||||
|
private:
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
std::unique_ptr<Pimpl> browser;
|
std::unique_ptr<Pimpl> browser;
|
||||||
bool blankPageShown = false, unloadPageWhenHidden;
|
bool blankPageShown = false, unloadPageWhenHidden;
|
||||||
|
|
@ -163,6 +166,72 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
/** Class used to create a set of preferences to pass to the WindowsWebView2WebBrowserComponent
|
||||||
|
wrapper constructor to modify aspects of its behaviour and settings.
|
||||||
|
|
||||||
|
You can chain together a series of calls to this class's methods to create a set of whatever
|
||||||
|
preferences you want to specify.
|
||||||
|
|
||||||
|
@tags{GUI}
|
||||||
|
*/
|
||||||
|
class JUCE_API WebView2Preferences
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//==============================================================================
|
||||||
|
/** Sets a custom location for the WebView2Loader.dll that is not a part of the
|
||||||
|
standard system DLL search paths.
|
||||||
|
*/
|
||||||
|
WebView2Preferences withDLLLocation (const File& location) const { return with (&WebView2Preferences::dllLocation, location); }
|
||||||
|
|
||||||
|
/** Sets a non-default location for storing user data for the browser instance. */
|
||||||
|
WebView2Preferences withUserDataFolder (const File& folder) const { return with (&WebView2Preferences::userDataFolder, folder); }
|
||||||
|
|
||||||
|
/** If this is set, the status bar usually displayed in the lower-left of the webview
|
||||||
|
will be disabled.
|
||||||
|
*/
|
||||||
|
WebView2Preferences withStatusBarDisabled() const { return with (&WebView2Preferences::disableStatusBar, true); }
|
||||||
|
|
||||||
|
/** If this is set, a blank page will be displayed on error instead of the default
|
||||||
|
built-in error page.
|
||||||
|
*/
|
||||||
|
WebView2Preferences withBuiltInErrorPageDisabled() const { return with (&WebView2Preferences::disableBuiltInErrorPage, true); }
|
||||||
|
|
||||||
|
/** Sets the background colour that WebView2 renders underneath all web content.
|
||||||
|
|
||||||
|
This colour must either be fully opaque or transparent. On Windows 7 this
|
||||||
|
colour must be opaque.
|
||||||
|
*/
|
||||||
|
WebView2Preferences withBackgroundColour (const Colour& colour) const
|
||||||
|
{
|
||||||
|
// the background colour must be either fully opaque or transparent!
|
||||||
|
jassert (colour.isOpaque() || colour.isTransparent());
|
||||||
|
|
||||||
|
return with (&WebView2Preferences::backgroundColour, colour);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
File getDLLLocation() const { return dllLocation; }
|
||||||
|
File getUserDataFolder() const { return userDataFolder; }
|
||||||
|
bool getIsStatusBarDisabled() const noexcept { return disableStatusBar; }
|
||||||
|
bool getIsBuiltInErrorPageDisabled() const noexcept { return disableBuiltInErrorPage; }
|
||||||
|
Colour getBackgroundColour() const { return backgroundColour; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
//==============================================================================
|
||||||
|
template <typename Member, typename Item>
|
||||||
|
WebView2Preferences with (Member&& member, Item&& item) const
|
||||||
|
{
|
||||||
|
auto options = *this;
|
||||||
|
options.*member = std::forward<Item> (item);
|
||||||
|
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
File dllLocation, userDataFolder;
|
||||||
|
bool disableStatusBar = false, disableBuiltInErrorPage = false;
|
||||||
|
Colour backgroundColour = Colours::white;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
If you have enabled the JUCE_USE_WIN_WEBVIEW2 flag then this wrapper will attempt to
|
If you have enabled the JUCE_USE_WIN_WEBVIEW2 flag then this wrapper will attempt to
|
||||||
use the Microsoft Edge (Chromium) WebView2 control instead of IE on Windows. It will
|
use the Microsoft Edge (Chromium) WebView2 control instead of IE on Windows. It will
|
||||||
|
|
@ -176,34 +245,38 @@ private:
|
||||||
system DLL, we can't rely on it being found via the normal system DLL search paths.
|
system DLL, we can't rely on it being found via the normal system DLL search paths.
|
||||||
Therefore in order to use WebView2 you need to ensure that WebView2Loader.dll is
|
Therefore in order to use WebView2 you need to ensure that WebView2Loader.dll is
|
||||||
installed either to a location covered by the Windows DLL system search paths or
|
installed either to a location covered by the Windows DLL system search paths or
|
||||||
to the folder specified in the constructor of this class.
|
to the folder specified in the WebView2Preferences.
|
||||||
|
|
||||||
@tags{GUI}
|
@tags{GUI}
|
||||||
*/
|
*/
|
||||||
class WindowsWebView2WebBrowserComponent : public WebBrowserComponent
|
class WindowsWebView2WebBrowserComponent : public WebBrowserComponent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
//==============================================================================
|
||||||
/** Creates a WebBrowserComponent that is compatible with the WebView2 control
|
/** Creates a WebBrowserComponent that is compatible with the WebView2 control
|
||||||
on Windows.
|
on Windows.
|
||||||
|
|
||||||
This allows you to specify a custom location for the WebView2Loader.dll as
|
|
||||||
well as a non-default location for storing user data for the browser instance.
|
|
||||||
|
|
||||||
@param unloadPageWhenBrowserIsHidden if this is true, then when the browser
|
@param unloadPageWhenBrowserIsHidden if this is true, then when the browser
|
||||||
component is taken offscreen, it'll clear the current page
|
component is taken offscreen, it'll clear the current page
|
||||||
and replace it with a blank page - this can be handy to stop
|
and replace it with a blank page - this can be handy to stop
|
||||||
the browser using resources in the background when it's not
|
the browser using resources in the background when it's not
|
||||||
actually being used.
|
actually being used.
|
||||||
@param dllLocation the path to WebView2Loader.dll, if this is empty then the default
|
@param preferences a set of preferences used to control aspects of the webview's
|
||||||
system DLL search paths will be used
|
behaviour.
|
||||||
@param userDataFolder a directory in which the WebView2 user data will be stored, if
|
|
||||||
this is empty then a directory will be created next to the
|
@see WebView2Preferences
|
||||||
executable
|
|
||||||
*/
|
*/
|
||||||
|
WindowsWebView2WebBrowserComponent (bool unloadPageWhenBrowserIsHidden = true,
|
||||||
|
const WebView2Preferences& preferences = {});
|
||||||
|
|
||||||
|
// This constructor has been deprecated. Use the new constructor that takes a
|
||||||
|
// WebView2Preferences instead.
|
||||||
explicit WindowsWebView2WebBrowserComponent (bool unloadPageWhenBrowserIsHidden = true,
|
explicit WindowsWebView2WebBrowserComponent (bool unloadPageWhenBrowserIsHidden = true,
|
||||||
const File& dllLocation = {},
|
const File& dllLocation = {},
|
||||||
const File& userDataFolder = {})
|
const File& userDataFolder = {})
|
||||||
: WebBrowserComponent (unloadPageWhenBrowserIsHidden, dllLocation, userDataFolder)
|
: WindowsWebView2WebBrowserComponent (unloadPageWhenBrowserIsHidden,
|
||||||
|
WebView2Preferences().withDLLLocation (dllLocation)
|
||||||
|
.withUserDataFolder (userDataFolder))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -592,13 +592,6 @@ WebBrowserComponent::WebBrowserComponent (const bool unloadWhenHidden)
|
||||||
addAndMakeVisible (browser.get());
|
addAndMakeVisible (browser.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
WebBrowserComponent::WebBrowserComponent (bool unloadWhenHidden,
|
|
||||||
const File&,
|
|
||||||
const File&)
|
|
||||||
: WebBrowserComponent (unloadWhenHidden)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
WebBrowserComponent::~WebBrowserComponent()
|
WebBrowserComponent::~WebBrowserComponent()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -917,13 +917,6 @@ WebBrowserComponent::WebBrowserComponent (const bool unloadWhenHidden)
|
||||||
browser->init();
|
browser->init();
|
||||||
}
|
}
|
||||||
|
|
||||||
WebBrowserComponent::WebBrowserComponent (bool unloadWhenHidden,
|
|
||||||
const File&,
|
|
||||||
const File&)
|
|
||||||
: WebBrowserComponent (unloadWhenHidden)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
WebBrowserComponent::~WebBrowserComponent()
|
WebBrowserComponent::~WebBrowserComponent()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -684,13 +684,6 @@ WebBrowserComponent::WebBrowserComponent (bool unloadWhenHidden)
|
||||||
addAndMakeVisible (browser.get());
|
addAndMakeVisible (browser.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
WebBrowserComponent::WebBrowserComponent (bool unloadWhenHidden,
|
|
||||||
const File&,
|
|
||||||
const File&)
|
|
||||||
: WebBrowserComponent (unloadWhenHidden)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
WebBrowserComponent::~WebBrowserComponent()
|
WebBrowserComponent::~WebBrowserComponent()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -342,11 +342,12 @@ class WebView2 : public InternalWebViewType,
|
||||||
public ComponentMovementWatcher
|
public ComponentMovementWatcher
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
WebView2 (WebBrowserComponent& o, const File& dllLocation, const File& userDataFolder)
|
WebView2 (WebBrowserComponent& o, const WebView2Preferences& prefs)
|
||||||
: ComponentMovementWatcher (&o),
|
: ComponentMovementWatcher (&o),
|
||||||
owner (o)
|
owner (o),
|
||||||
|
preferences (prefs)
|
||||||
{
|
{
|
||||||
if (! createWebViewEnvironment (dllLocation, userDataFolder))
|
if (! createWebViewEnvironment())
|
||||||
throw std::runtime_error ("Failed to create the CoreWebView2Environemnt");
|
throw std::runtime_error ("Failed to create the CoreWebView2Environemnt");
|
||||||
|
|
||||||
owner.addAndMakeVisible (this);
|
owner.addAndMakeVisible (this);
|
||||||
|
|
@ -604,13 +605,38 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool createWebViewEnvironment (const File& dllLocation, const File& userDataFolder)
|
void setWebViewPreferences()
|
||||||
|
{
|
||||||
|
ComSmartPtr<ICoreWebView2Controller2> controller2;
|
||||||
|
webViewController->QueryInterface (controller2.resetAndGetPointerAddress());
|
||||||
|
|
||||||
|
if (controller2 != nullptr)
|
||||||
|
{
|
||||||
|
const auto bgColour = preferences.getBackgroundColour();
|
||||||
|
|
||||||
|
controller2->put_DefaultBackgroundColor ({ (BYTE) bgColour.getAlpha(),
|
||||||
|
(BYTE) bgColour.getRed(),
|
||||||
|
(BYTE) bgColour.getGreen(),
|
||||||
|
(BYTE) bgColour.getBlue() });
|
||||||
|
}
|
||||||
|
|
||||||
|
ComSmartPtr<ICoreWebView2Settings> settings;
|
||||||
|
webView->get_Settings (settings.resetAndGetPointerAddress());
|
||||||
|
|
||||||
|
if (settings == nullptr)
|
||||||
|
{
|
||||||
|
settings->put_IsStatusBarEnabled (! preferences.getIsStatusBarDisabled());
|
||||||
|
settings->put_IsBuiltInErrorPageEnabled (! preferences.getIsBuiltInErrorPageDisabled());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool createWebViewEnvironment()
|
||||||
{
|
{
|
||||||
using CreateWebViewEnvironmentWithOptionsFunc = HRESULT (*) (PCWSTR, PCWSTR,
|
using CreateWebViewEnvironmentWithOptionsFunc = HRESULT (*) (PCWSTR, PCWSTR,
|
||||||
ICoreWebView2EnvironmentOptions*,
|
ICoreWebView2EnvironmentOptions*,
|
||||||
ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler*);
|
ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler*);
|
||||||
|
|
||||||
auto dllPath = dllLocation.getFullPathName();
|
auto dllPath = preferences.getDLLLocation().getFullPathName();
|
||||||
|
|
||||||
if (dllPath.isEmpty())
|
if (dllPath.isEmpty())
|
||||||
dllPath = "WebView2Loader.dll";
|
dllPath = "WebView2Loader.dll";
|
||||||
|
|
@ -630,9 +656,10 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
auto options = Microsoft::WRL::Make<CoreWebView2EnvironmentOptions>();
|
auto options = Microsoft::WRL::Make<CoreWebView2EnvironmentOptions>();
|
||||||
|
const auto userDataFolder = preferences.getUserDataFolder().getFullPathName();
|
||||||
|
|
||||||
auto hr = createWebViewEnvironmentWithOptions (nullptr,
|
auto hr = createWebViewEnvironmentWithOptions (nullptr,
|
||||||
userDataFolder != File() ? userDataFolder.getFullPathName().toWideCharPointer() : nullptr,
|
userDataFolder.isNotEmpty() ? userDataFolder.toWideCharPointer() : nullptr,
|
||||||
options.Get(),
|
options.Get(),
|
||||||
Callback<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>(
|
Callback<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>(
|
||||||
[weakThis = WeakReference<WebView2> { this }] (HRESULT, ICoreWebView2Environment* env) -> HRESULT
|
[weakThis = WeakReference<WebView2> { this }] (HRESULT, ICoreWebView2Environment* env) -> HRESULT
|
||||||
|
|
@ -667,11 +694,15 @@ private:
|
||||||
weakThis->webViewController = controller;
|
weakThis->webViewController = controller;
|
||||||
controller->get_CoreWebView2 (weakThis->webView.resetAndGetPointerAddress());
|
controller->get_CoreWebView2 (weakThis->webView.resetAndGetPointerAddress());
|
||||||
|
|
||||||
weakThis->addEventHandlers();
|
if (weakThis->webView != nullptr)
|
||||||
weakThis->componentMovedOrResized (true, true);
|
{
|
||||||
|
weakThis->addEventHandlers();
|
||||||
|
weakThis->setWebViewPreferences();
|
||||||
|
weakThis->componentMovedOrResized (true, true);
|
||||||
|
|
||||||
if (weakThis->webView != nullptr && weakThis->urlRequest.url.isNotEmpty())
|
if (weakThis->urlRequest.url.isNotEmpty())
|
||||||
weakThis->webView->Navigate (weakThis->urlRequest.url.toWideCharPointer());
|
weakThis->webView->Navigate (weakThis->urlRequest.url.toWideCharPointer());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -715,6 +746,7 @@ private:
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
WebBrowserComponent& owner;
|
WebBrowserComponent& owner;
|
||||||
|
WebView2Preferences preferences;
|
||||||
|
|
||||||
HMODULE webView2LoaderHandle = nullptr;
|
HMODULE webView2LoaderHandle = nullptr;
|
||||||
|
|
||||||
|
|
@ -734,6 +766,7 @@ private:
|
||||||
StringArray headers;
|
StringArray headers;
|
||||||
MemoryBlock postData;
|
MemoryBlock postData;
|
||||||
};
|
};
|
||||||
|
|
||||||
URLRequest urlRequest;
|
URLRequest urlRequest;
|
||||||
|
|
||||||
bool isCreating = false;
|
bool isCreating = false;
|
||||||
|
|
@ -749,20 +782,22 @@ private:
|
||||||
class WebBrowserComponent::Pimpl
|
class WebBrowserComponent::Pimpl
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Pimpl (WebBrowserComponent& owner, const File& dllLocation, const File& userDataFolder, bool useWebView2)
|
Pimpl (WebBrowserComponent& owner,
|
||||||
|
const WebView2Preferences& preferences,
|
||||||
|
bool useWebView2)
|
||||||
{
|
{
|
||||||
if (useWebView2)
|
if (useWebView2)
|
||||||
{
|
{
|
||||||
#if JUCE_USE_WIN_WEBVIEW2
|
#if JUCE_USE_WIN_WEBVIEW2
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
internal.reset (new WebView2 (owner, dllLocation, userDataFolder));
|
internal.reset (new WebView2 (owner, preferences));
|
||||||
}
|
}
|
||||||
catch (std::runtime_error&) {}
|
catch (const std::runtime_error&) {}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
ignoreUnused (dllLocation, userDataFolder);
|
ignoreUnused (preferences);
|
||||||
|
|
||||||
if (internal == nullptr)
|
if (internal == nullptr)
|
||||||
internal.reset (new Win32WebView (owner));
|
internal.reset (new Win32WebView (owner));
|
||||||
|
|
@ -779,17 +814,14 @@ private:
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
WebBrowserComponent::WebBrowserComponent (bool unloadWhenHidden)
|
WebBrowserComponent::WebBrowserComponent (bool unloadWhenHidden)
|
||||||
: browser (new Pimpl (*this, {}, {}, false)),
|
: browser (new Pimpl (*this, {}, false)),
|
||||||
unloadPageWhenHidden (unloadWhenHidden)
|
unloadPageWhenHidden (unloadWhenHidden)
|
||||||
{
|
{
|
||||||
setOpaque (true);
|
setOpaque (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
WebBrowserComponent::WebBrowserComponent (bool unloadWhenHidden,
|
WebBrowserComponent::WebBrowserComponent (ConstructWithoutPimpl args)
|
||||||
const File& dllLocation,
|
: unloadPageWhenHidden (args.unloadWhenHidden)
|
||||||
const File& userDataFolder)
|
|
||||||
: browser (new Pimpl (*this, dllLocation, userDataFolder, true)),
|
|
||||||
unloadPageWhenHidden (unloadWhenHidden)
|
|
||||||
{
|
{
|
||||||
setOpaque (true);
|
setOpaque (true);
|
||||||
}
|
}
|
||||||
|
|
@ -798,6 +830,13 @@ WebBrowserComponent::~WebBrowserComponent()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WindowsWebView2WebBrowserComponent::WindowsWebView2WebBrowserComponent (bool unloadWhenHidden,
|
||||||
|
const WebView2Preferences& preferences)
|
||||||
|
: WebBrowserComponent (ConstructWithoutPimpl { unloadWhenHidden })
|
||||||
|
{
|
||||||
|
browser = std::make_unique<Pimpl> (*this, preferences, true);
|
||||||
|
}
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
void WebBrowserComponent::goToURL (const String& url,
|
void WebBrowserComponent::goToURL (const String& url,
|
||||||
const StringArray* headers,
|
const StringArray* headers,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue