Add wxWebView Edge (Chromium) implementation
This backend requires WebView2 SDK and enables usage of Edge (Chromium) on Windows 7 and newer
This commit is contained in:
committed by
Tobias Taschner
parent
1afeaa324d
commit
6a99e7e273
2
.gitignore
vendored
2
.gitignore
vendored
@@ -475,3 +475,5 @@
|
||||
|
||||
# /utils/wxrc/
|
||||
/utils/wxrc/wxrc_vc[789].sln
|
||||
|
||||
/3rdparty/webview2
|
||||
|
@@ -2835,6 +2835,7 @@ set(HTML_CMN_HDR
|
||||
|
||||
set(WEBVIEW_MSW_SRC
|
||||
src/msw/webview_ie.cpp
|
||||
src/msw/webview_edgec.cpp
|
||||
)
|
||||
|
||||
set(WEBVIEW_CMN_SRC
|
||||
|
@@ -34,6 +34,22 @@ endif()
|
||||
|
||||
if(APPLE)
|
||||
wx_lib_link_libraries(webview PUBLIC "-framework WebKit")
|
||||
elseif(WXMSW)
|
||||
if(wxUSE_WEBVIEW_EDGE)
|
||||
wx_lib_include_directories(webview PRIVATE ${PROJECT_SOURCE_DIR}/3rdparty/webview2/build/native/include)
|
||||
|
||||
if (${CMAKE_SIZEOF_VOID_P} EQUAL 4)
|
||||
set(WEBVIEW2_ARCH x86)
|
||||
else()
|
||||
set(WEBVIEW2_ARCH x64)
|
||||
endif()
|
||||
|
||||
wx_lib_link_libraries(webview PUBLIC "${PROJECT_SOURCE_DIR}/3rdparty/webview2/build/native/${WEBVIEW2_ARCH}/WebView2Loader.dll.lib")
|
||||
add_custom_command(TARGET webview POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy
|
||||
"${PROJECT_SOURCE_DIR}/3rdparty/webview2/build/native/${WEBVIEW2_ARCH}/WebView2Loader.dll"
|
||||
$<TARGET_FILE_DIR:webview>/"WebView2Loader.dll")
|
||||
endif()
|
||||
elseif(WXGTK)
|
||||
if(LIBSOUP_FOUND)
|
||||
wx_lib_include_directories(webview PUBLIC ${LIBSOUP_INCLUDE_DIRS})
|
||||
|
@@ -2788,6 +2788,7 @@ HTML_CMN_HDR =
|
||||
|
||||
WEBVIEW_MSW_SRC =
|
||||
src/msw/webview_ie.cpp
|
||||
src/msw/webview_edgec.cpp
|
||||
WEBVIEW_CMN_SRC =
|
||||
src/common/webview.cpp
|
||||
src/common/webviewarchivehandler.cpp
|
||||
@@ -2796,6 +2797,7 @@ WEBVIEW_CMN_SRC =
|
||||
WEBVIEW_MSW_HDR =
|
||||
wx/msw/webviewhistoryitem_ie.h
|
||||
wx/msw/webview_ie.h
|
||||
wx/msw/webview_edgec.h
|
||||
WEBVIEW_CMN_HDR =
|
||||
wx/webview.h
|
||||
wx/webviewarchivehandler.h
|
||||
|
181
include/wx/msw/webview_edgec.h
Normal file
181
include/wx/msw/webview_edgec.h
Normal file
@@ -0,0 +1,181 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: include/wx/msw/webview_edge.h
|
||||
// Purpose: wxMSW Edge Chromium wxWebView backend
|
||||
// Author: Markus Pingel
|
||||
// Created: 2019-12-15
|
||||
// Copyright: (c) 2019 wxWidgets development team
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef wxWebViewEdgeC_H
|
||||
#define wxWebViewEdgeC_H
|
||||
|
||||
#include "wx/setup.h"
|
||||
|
||||
#if wxUSE_WEBVIEW && wxUSE_WEBVIEW_EDGE && defined(__WXMSW__)
|
||||
|
||||
#include "wx/control.h"
|
||||
#include "wx/webview.h"
|
||||
#include "wx/msw/private/comptr.h"
|
||||
|
||||
#include <Webview2.h>
|
||||
|
||||
|
||||
class WXDLLIMPEXP_WEBVIEW wxWebViewEdge : public wxWebView
|
||||
{
|
||||
public:
|
||||
|
||||
wxWebViewEdge() {}
|
||||
|
||||
wxWebViewEdge(wxWindow* parent,
|
||||
wxWindowID id,
|
||||
const wxString& url = wxWebViewDefaultURLStr,
|
||||
const wxPoint& pos = wxDefaultPosition,
|
||||
const wxSize& size = wxDefaultSize,
|
||||
long style = 0,
|
||||
const wxString& name = wxWebViewNameStr)
|
||||
{
|
||||
Create(parent, id, url, pos, size, style, name);
|
||||
}
|
||||
|
||||
~wxWebViewEdge();
|
||||
|
||||
bool Create(wxWindow* parent,
|
||||
wxWindowID id,
|
||||
const wxString& url = wxWebViewDefaultURLStr,
|
||||
const wxPoint& pos = wxDefaultPosition,
|
||||
const wxSize& size = wxDefaultSize,
|
||||
long style = 0,
|
||||
const wxString& name = wxWebViewNameStr) wxOVERRIDE;
|
||||
|
||||
virtual void LoadURL(const wxString& url) wxOVERRIDE;
|
||||
virtual void LoadHistoryItem(wxSharedPtr<wxWebViewHistoryItem> item) wxOVERRIDE;
|
||||
virtual wxVector<wxSharedPtr<wxWebViewHistoryItem> > GetBackwardHistory() wxOVERRIDE;
|
||||
virtual wxVector<wxSharedPtr<wxWebViewHistoryItem> > GetForwardHistory() wxOVERRIDE;
|
||||
|
||||
virtual bool CanGoForward() const wxOVERRIDE;
|
||||
virtual bool CanGoBack() const wxOVERRIDE;
|
||||
virtual void GoBack() wxOVERRIDE;
|
||||
virtual void GoForward() wxOVERRIDE;
|
||||
virtual void ClearHistory() wxOVERRIDE;
|
||||
virtual void EnableHistory(bool enable = true) wxOVERRIDE;
|
||||
virtual void Stop() wxOVERRIDE;
|
||||
virtual void Reload(wxWebViewReloadFlags flags = wxWEBVIEW_RELOAD_DEFAULT) wxOVERRIDE;
|
||||
|
||||
virtual wxString GetPageSource() const wxOVERRIDE;
|
||||
virtual wxString GetPageText() const wxOVERRIDE;
|
||||
|
||||
virtual bool IsBusy() const wxOVERRIDE;
|
||||
virtual wxString GetCurrentURL() const wxOVERRIDE;
|
||||
virtual wxString GetCurrentTitle() const wxOVERRIDE;
|
||||
|
||||
virtual void SetZoomType(wxWebViewZoomType) wxOVERRIDE;
|
||||
virtual wxWebViewZoomType GetZoomType() const wxOVERRIDE;
|
||||
virtual bool CanSetZoomType(wxWebViewZoomType type) const wxOVERRIDE;
|
||||
|
||||
virtual void Print() wxOVERRIDE;
|
||||
|
||||
virtual wxWebViewZoom GetZoom() const wxOVERRIDE;
|
||||
virtual void SetZoom(wxWebViewZoom zoom) wxOVERRIDE;
|
||||
|
||||
//Clipboard functions
|
||||
virtual bool CanCut() const wxOVERRIDE;
|
||||
virtual bool CanCopy() const wxOVERRIDE;
|
||||
virtual bool CanPaste() const wxOVERRIDE;
|
||||
virtual void Cut() wxOVERRIDE;
|
||||
virtual void Copy() wxOVERRIDE;
|
||||
virtual void Paste() wxOVERRIDE;
|
||||
|
||||
//Undo / redo functionality
|
||||
virtual bool CanUndo() const wxOVERRIDE;
|
||||
virtual bool CanRedo() const wxOVERRIDE;
|
||||
virtual void Undo() wxOVERRIDE;
|
||||
virtual void Redo() wxOVERRIDE;
|
||||
|
||||
//Find function
|
||||
virtual long Find(const wxString& text, int flags = wxWEBVIEW_FIND_DEFAULT) wxOVERRIDE;
|
||||
|
||||
//Editing functions
|
||||
virtual void SetEditable(bool enable = true) wxOVERRIDE;
|
||||
virtual bool IsEditable() const wxOVERRIDE;
|
||||
|
||||
//Selection
|
||||
virtual void SelectAll() wxOVERRIDE;
|
||||
virtual bool HasSelection() const wxOVERRIDE;
|
||||
virtual void DeleteSelection() wxOVERRIDE;
|
||||
virtual wxString GetSelectedText() const wxOVERRIDE;
|
||||
virtual wxString GetSelectedSource() const wxOVERRIDE;
|
||||
virtual void ClearSelection() wxOVERRIDE;
|
||||
|
||||
virtual void EnableContextMenu(bool enable = true) wxOVERRIDE;
|
||||
virtual bool IsContextMenuEnabled() const wxOVERRIDE;
|
||||
|
||||
virtual bool RunScript(const wxString& javascript, wxString* output = NULL) wxOVERRIDE;
|
||||
|
||||
virtual void RegisterHandler(wxSharedPtr<wxWebViewHandler> handler) wxOVERRIDE;
|
||||
|
||||
virtual void* GetNativeBackend() const wxOVERRIDE { return m_webView; }
|
||||
|
||||
// ---- Edge-specific methods
|
||||
|
||||
static bool IsAvailable();
|
||||
|
||||
protected:
|
||||
virtual void DoSetPage(const wxString& html, const wxString& baseUrl) wxOVERRIDE;
|
||||
|
||||
private:
|
||||
bool m_initialized = false;
|
||||
bool m_isBusy = false;
|
||||
wxString m_pendingURL;
|
||||
|
||||
wxCOMPtr<IWebView2Environment3> m_webViewEnvironment;
|
||||
wxCOMPtr<IWebView2WebView5> m_webView;
|
||||
|
||||
EventRegistrationToken m_navigationStartingToken = { };
|
||||
EventRegistrationToken m_navigationCompletedToken = { };
|
||||
EventRegistrationToken m_newWindowRequestedToken = { };
|
||||
EventRegistrationToken m_documentStateChangedToken = { };
|
||||
|
||||
void OnSize(wxSizeEvent& event);
|
||||
|
||||
void UpdateBounds();
|
||||
|
||||
void InitWebViewCtrl();
|
||||
|
||||
bool RunScriptSync(const wxString& javascript, wxString* output = NULL);
|
||||
|
||||
static int ms_isAvailable;
|
||||
|
||||
static void Initialize();
|
||||
|
||||
static void Uninitalize();
|
||||
|
||||
friend class wxWebViewEdgeModule;
|
||||
|
||||
wxVector<wxSharedPtr<wxWebViewHistoryItem> > m_historyList;
|
||||
int m_historyPosition;
|
||||
bool m_historyLoadingFromList;
|
||||
bool m_historyEnabled;
|
||||
|
||||
wxDECLARE_DYNAMIC_CLASS(wxWebViewEdge);
|
||||
};
|
||||
|
||||
class WXDLLIMPEXP_WEBVIEW wxWebViewFactoryEdge : public wxWebViewFactory
|
||||
{
|
||||
public:
|
||||
virtual wxWebView* Create() wxOVERRIDE { return new wxWebViewEdge; }
|
||||
virtual wxWebView* Create(wxWindow* parent,
|
||||
wxWindowID id,
|
||||
const wxString& url = wxWebViewDefaultURLStr,
|
||||
const wxPoint& pos = wxDefaultPosition,
|
||||
const wxSize& size = wxDefaultSize,
|
||||
long style = 0,
|
||||
const wxString& name = wxWebViewNameStr) wxOVERRIDE
|
||||
{
|
||||
return new wxWebViewEdge(parent, id, url, pos, size, style, name);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // wxUSE_WEBVIEW && wxUSE_WEBVIEW_EDGE && defined(__WXMSW__)
|
||||
|
||||
#endif // wxWebViewEdgeC_H
|
@@ -11,7 +11,7 @@
|
||||
|
||||
#include "wx/setup.h"
|
||||
|
||||
#if wxUSE_WEBVIEW && wxUSE_WEBVIEW_IE && defined(__WXMSW__)
|
||||
#if wxUSE_WEBVIEW && (wxUSE_WEBVIEW_IE || wxUSE_WEBVIEW_EDGE) && defined(__WXMSW__)
|
||||
|
||||
class WXDLLIMPEXP_WEBVIEW wxWebViewHistoryItem
|
||||
{
|
||||
|
@@ -101,6 +101,7 @@ extern WXDLLIMPEXP_DATA_WEBVIEW(const char) wxWebViewNameStr[];
|
||||
extern WXDLLIMPEXP_DATA_WEBVIEW(const char) wxWebViewDefaultURLStr[];
|
||||
extern WXDLLIMPEXP_DATA_WEBVIEW(const char) wxWebViewBackendDefault[];
|
||||
extern WXDLLIMPEXP_DATA_WEBVIEW(const char) wxWebViewBackendIE[];
|
||||
extern WXDLLIMPEXP_DATA_WEBVIEW(const char) wxWebViewBackendEdge[];
|
||||
extern WXDLLIMPEXP_DATA_WEBVIEW(const char) wxWebViewBackendWebKit[];
|
||||
|
||||
class WXDLLIMPEXP_WEBVIEW wxWebViewFactory : public wxObject
|
||||
|
@@ -279,6 +279,16 @@ public:
|
||||
this</a> article for more information. This backend has full support for
|
||||
custom schemes and virtual file systems.
|
||||
|
||||
@par wxWEBVIEW_BACKEND_EDGE (MSW)
|
||||
|
||||
The Edge (Chromium) backend uses Microsoft's
|
||||
<a href="https://docs.microsoft.com/en-us/microsoft-edge/hosting/webview2">Edge WebView2</a>.
|
||||
It is available for Windows 7 and newer.
|
||||
This backend has currently a few features missing but is still
|
||||
a better choice than IE when just displaying web content. The unsupported
|
||||
features are the following: virtual filesystems, custom urls,
|
||||
text selection, find, source code.
|
||||
|
||||
@par wxWEBVIEW_WEBKIT (GTK)
|
||||
|
||||
Under GTK the WebKit backend uses
|
||||
|
@@ -21,7 +21,7 @@
|
||||
#include "wx/wx.h"
|
||||
#endif
|
||||
|
||||
#if !wxUSE_WEBVIEW_WEBKIT && !wxUSE_WEBVIEW_WEBKIT2 && !wxUSE_WEBVIEW_IE
|
||||
#if !wxUSE_WEBVIEW_WEBKIT && !wxUSE_WEBVIEW_WEBKIT2 && !wxUSE_WEBVIEW_IE && !wxUSE_WEBVIEW_EDGE
|
||||
#error "A wxWebView backend is required by this sample"
|
||||
#endif
|
||||
|
||||
@@ -365,7 +365,12 @@ WebFrame::WebFrame(const wxString& url) :
|
||||
topsizer->Add(m_info, wxSizerFlags().Expand());
|
||||
|
||||
// Create the webview
|
||||
m_browser = wxWebView::New(this, wxID_ANY, url);
|
||||
wxString backend = wxWebViewBackendDefault;
|
||||
#ifdef __WXMSW__
|
||||
if (wxWebView::IsBackendAvailable(wxWebViewBackendEdge))
|
||||
backend = wxWebViewBackendEdge;
|
||||
#endif
|
||||
m_browser = wxWebView::New(this, wxID_ANY, url, wxDefaultPosition, wxDefaultSize, backend);
|
||||
topsizer->Add(m_browser, wxSizerFlags().Expand().Proportion(1));
|
||||
|
||||
//We register the wxfs:// protocol for testing purposes
|
||||
|
@@ -23,6 +23,7 @@
|
||||
#include "wx/gtk/webview_webkit.h"
|
||||
#elif defined(__WXMSW__)
|
||||
#include "wx/msw/webview_ie.h"
|
||||
#include "wx/msw/webview_edgec.h"
|
||||
#endif
|
||||
|
||||
// DLL options compatibility check:
|
||||
@@ -32,6 +33,7 @@ WX_CHECK_BUILD_OPTIONS("wxWEBVIEW")
|
||||
extern WXDLLIMPEXP_DATA_WEBVIEW(const char) wxWebViewNameStr[] = "wxWebView";
|
||||
extern WXDLLIMPEXP_DATA_WEBVIEW(const char) wxWebViewDefaultURLStr[] = "about:blank";
|
||||
extern WXDLLIMPEXP_DATA_WEBVIEW(const char) wxWebViewBackendIE[] = "wxWebViewIE";
|
||||
extern WXDLLIMPEXP_DATA_WEBVIEW(const char) wxWebViewBackendEdge[] = "wxWebViewEdge";
|
||||
extern WXDLLIMPEXP_DATA_WEBVIEW(const char) wxWebViewBackendWebKit[] = "wxWebViewWebKit";
|
||||
|
||||
#ifdef __WXMSW__
|
||||
@@ -108,6 +110,14 @@ void wxWebView::InitFactoryMap()
|
||||
if(m_factoryMap.find(wxWebViewBackendIE) == m_factoryMap.end())
|
||||
RegisterFactory(wxWebViewBackendIE, wxSharedPtr<wxWebViewFactory>
|
||||
(new wxWebViewFactoryIE));
|
||||
|
||||
#if wxUSE_WEBVIEW_EDGE
|
||||
if (wxWebViewEdge::IsAvailable() &&
|
||||
m_factoryMap.find(wxWebViewBackendEdge) == m_factoryMap.end())
|
||||
RegisterFactory(wxWebViewBackendEdge, wxSharedPtr<wxWebViewFactory>
|
||||
(new wxWebViewFactoryEdge));
|
||||
#endif
|
||||
|
||||
#else
|
||||
if(m_factoryMap.find(wxWebViewBackendWebKit) == m_factoryMap.end())
|
||||
RegisterFactory(wxWebViewBackendWebKit, wxSharedPtr<wxWebViewFactory>
|
||||
|
712
src/msw/webview_edgec.cpp
Normal file
712
src/msw/webview_edgec.cpp
Normal file
@@ -0,0 +1,712 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: source/msw/webview_edgec.cpp
|
||||
// Purpose: wxMSW Edge Chromium wxWebView backend implementation
|
||||
// Author: Markus Pingel
|
||||
// Created: 2019-12-15
|
||||
// Copyright: (c) 2019 wxWidgets development team
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// For compilers that support precompilation, includes "wx.h".
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#if defined(__BORLANDC__)
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#include "wx/msw/webview_edgec.h"
|
||||
|
||||
#if wxUSE_WEBVIEW && wxUSE_WEBVIEW_EDGE
|
||||
|
||||
#include "wx/filename.h"
|
||||
#include "wx/module.h"
|
||||
#include "wx/thread.h"
|
||||
#include "wx/private/jsscriptwrapper.h"
|
||||
|
||||
#include <wrl/event.h>
|
||||
|
||||
using namespace Microsoft::WRL;
|
||||
|
||||
wxIMPLEMENT_DYNAMIC_CLASS(wxWebViewEdge, wxWebView);
|
||||
|
||||
#define WX_ERROR2_CASE(error, wxerror) \
|
||||
case error: \
|
||||
event.SetString(#error); \
|
||||
event.SetInt(wxerror); \
|
||||
break;
|
||||
|
||||
int wxWebViewEdge::ms_isAvailable = -1;
|
||||
|
||||
bool wxWebViewEdge::IsAvailable()
|
||||
{
|
||||
if (ms_isAvailable == -1)
|
||||
Initialize();
|
||||
|
||||
return (ms_isAvailable == 1);
|
||||
}
|
||||
|
||||
void wxWebViewEdge::Initialize()
|
||||
{
|
||||
LPWSTR versionStr;
|
||||
if (SUCCEEDED(GetWebView2BrowserVersionInfo(NULL, &versionStr)))
|
||||
{
|
||||
if (versionStr)
|
||||
ms_isAvailable = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void wxWebViewEdge::Uninitalize()
|
||||
{
|
||||
if (ms_isAvailable == 1)
|
||||
{
|
||||
ms_isAvailable = -1;
|
||||
}
|
||||
}
|
||||
|
||||
wxWebViewEdge::~wxWebViewEdge()
|
||||
{
|
||||
if (m_webView)
|
||||
{
|
||||
// TOOD: Remove additional events
|
||||
m_webView->remove_NavigationCompleted(m_navigationCompletedToken);
|
||||
m_webView->remove_NavigationStarting(m_navigationStartingToken);
|
||||
m_webView->remove_DocumentStateChanged(m_documentStateChangedToken);
|
||||
m_webView->remove_NewWindowRequested(m_newWindowRequestedToken);
|
||||
}
|
||||
}
|
||||
|
||||
bool wxWebViewEdge::Create(wxWindow* parent,
|
||||
wxWindowID id,
|
||||
const wxString& url,
|
||||
const wxPoint& pos,
|
||||
const wxSize& size,
|
||||
long style,
|
||||
const wxString& name)
|
||||
{
|
||||
m_initialized = false;
|
||||
m_isBusy = false;
|
||||
|
||||
m_historyLoadingFromList = false;
|
||||
m_historyEnabled = true;
|
||||
m_historyPosition = -1;
|
||||
|
||||
if (!wxControl::Create(parent, id, pos, size, style,
|
||||
wxDefaultValidator, name))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsAvailable())
|
||||
return false;
|
||||
|
||||
m_pendingURL = url;
|
||||
|
||||
Bind(wxEVT_SIZE, &wxWebViewEdge::OnSize, this);
|
||||
|
||||
LPCWSTR subFolder = nullptr;
|
||||
LPCWSTR additionalBrowserSwitches = nullptr;
|
||||
|
||||
HRESULT hr = CreateWebView2EnvironmentWithDetails(
|
||||
subFolder, nullptr, additionalBrowserSwitches,
|
||||
Callback<IWebView2CreateWebView2EnvironmentCompletedHandler>(
|
||||
[this](HRESULT WXUNUSED(result), IWebView2Environment* environment) -> HRESULT
|
||||
{
|
||||
environment->QueryInterface(IID_PPV_ARGS(&m_webViewEnvironment));
|
||||
m_webViewEnvironment->CreateWebView(
|
||||
GetHWND(), Callback<IWebView2CreateWebViewCompletedHandler>(
|
||||
[this](HRESULT WXUNUSED(result), IWebView2WebView* webview) -> HRESULT
|
||||
{
|
||||
webview->QueryInterface(IID_PPV_ARGS(&m_webView));
|
||||
UpdateBounds();
|
||||
InitWebViewCtrl();
|
||||
return S_OK;
|
||||
})
|
||||
.Get());
|
||||
return S_OK;
|
||||
}).Get());
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
|
||||
void wxWebViewEdge::InitWebViewCtrl()
|
||||
{
|
||||
m_initialized = true;
|
||||
UpdateBounds();
|
||||
|
||||
// Connect and handle the various WebView events
|
||||
|
||||
m_webView->add_NavigationStarting(
|
||||
Callback<IWebView2NavigationStartingEventHandler>(
|
||||
[this](IWebView2WebView* WXUNUSED(sender), IWebView2NavigationStartingEventArgs* args) -> HRESULT
|
||||
{
|
||||
m_isBusy = true;
|
||||
wxString evtURL;
|
||||
PWSTR uri;
|
||||
if (SUCCEEDED(args->get_Uri(&uri)))
|
||||
evtURL = wxString(uri);
|
||||
wxWebViewEvent event(wxEVT_WEBVIEW_NAVIGATING, GetId(), evtURL, wxString());
|
||||
event.SetEventObject(this);
|
||||
HandleWindowEvent(event);
|
||||
|
||||
if (!event.IsAllowed())
|
||||
args->put_Cancel(true);
|
||||
|
||||
return S_OK;
|
||||
})
|
||||
.Get(), &m_navigationStartingToken);
|
||||
|
||||
m_webView->add_DocumentStateChanged(
|
||||
Callback<IWebView2DocumentStateChangedEventHandler>(
|
||||
[this](IWebView2WebView* sender, IWebView2DocumentStateChangedEventArgs* WXUNUSED(args)) -> HRESULT
|
||||
{
|
||||
PWSTR uri;
|
||||
sender->get_Source(&uri);
|
||||
wxString evtURL(uri);
|
||||
if (evtURL.Cmp(L"about:blank") == 0)
|
||||
{
|
||||
evtURL = L"";
|
||||
}
|
||||
|
||||
// AddPendingEvent(wxWebViewEvent(wxEVT_WEBVIEW_NAVIGATED, GetId(), uri, wxString()));
|
||||
// SetWindowText(m_toolbar->addressBarWindow, uri.get());
|
||||
return S_OK;
|
||||
})
|
||||
.Get(),
|
||||
&m_documentStateChangedToken);
|
||||
|
||||
m_webView->add_NavigationCompleted(
|
||||
Callback<IWebView2NavigationCompletedEventHandler>(
|
||||
[this](IWebView2WebView* sender, IWebView2NavigationCompletedEventArgs* args) -> HRESULT
|
||||
{
|
||||
BOOL isSuccess;
|
||||
if (FAILED(args->get_IsSuccess(&isSuccess)))
|
||||
isSuccess = false;
|
||||
m_isBusy = false;
|
||||
PWSTR _uri;
|
||||
sender->get_Source(&_uri);
|
||||
wxString uri(_uri);
|
||||
|
||||
if (!isSuccess)
|
||||
{
|
||||
WEBVIEW2_WEB_ERROR_STATUS status;
|
||||
|
||||
wxWebViewEvent event(wxEVT_WEBVIEW_ERROR, GetId(), uri, wxString());
|
||||
event.SetEventObject(this);
|
||||
|
||||
if (SUCCEEDED(args->get_WebErrorStatus(&status)))
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
WX_ERROR2_CASE(WEBVIEW2_WEB_ERROR_STATUS_UNKNOWN, wxWEBVIEW_NAV_ERR_OTHER)
|
||||
WX_ERROR2_CASE(WEBVIEW2_WEB_ERROR_STATUS_CERTIFICATE_COMMON_NAME_IS_INCORRECT, wxWEBVIEW_NAV_ERR_CERTIFICATE)
|
||||
WX_ERROR2_CASE(WEBVIEW2_WEB_ERROR_STATUS_CERTIFICATE_EXPIRED, wxWEBVIEW_NAV_ERR_CERTIFICATE)
|
||||
WX_ERROR2_CASE(WEBVIEW2_WEB_ERROR_STATUS_CLIENT_CERTIFICATE_CONTAINS_ERRORS, wxWEBVIEW_NAV_ERR_CERTIFICATE)
|
||||
WX_ERROR2_CASE(WEBVIEW2_WEB_ERROR_STATUS_CERTIFICATE_REVOKED, wxWEBVIEW_NAV_ERR_CERTIFICATE)
|
||||
WX_ERROR2_CASE(WEBVIEW2_WEB_ERROR_STATUS_CERTIFICATE_IS_INVALID, wxWEBVIEW_NAV_ERR_CERTIFICATE)
|
||||
WX_ERROR2_CASE(WEBVIEW2_WEB_ERROR_STATUS_SERVER_UNREACHABLE, wxWEBVIEW_NAV_ERR_CONNECTION)
|
||||
WX_ERROR2_CASE(WEBVIEW2_WEB_ERROR_STATUS_TIMEOUT, wxWEBVIEW_NAV_ERR_CONNECTION)
|
||||
WX_ERROR2_CASE(WEBVIEW2_WEB_ERROR_STATUS_ERROR_HTTP_INVALID_SERVER_RESPONSE, wxWEBVIEW_NAV_ERR_CONNECTION)
|
||||
WX_ERROR2_CASE(WEBVIEW2_WEB_ERROR_STATUS_CONNECTION_ABORTED, wxWEBVIEW_NAV_ERR_CONNECTION)
|
||||
WX_ERROR2_CASE(WEBVIEW2_WEB_ERROR_STATUS_CONNECTION_RESET, wxWEBVIEW_NAV_ERR_CONNECTION)
|
||||
WX_ERROR2_CASE(WEBVIEW2_WEB_ERROR_STATUS_DISCONNECTED, wxWEBVIEW_NAV_ERR_CONNECTION)
|
||||
WX_ERROR2_CASE(WEBVIEW2_WEB_ERROR_STATUS_CANNOT_CONNECT, wxWEBVIEW_NAV_ERR_CONNECTION)
|
||||
WX_ERROR2_CASE(WEBVIEW2_WEB_ERROR_STATUS_HOST_NAME_NOT_RESOLVED, wxWEBVIEW_NAV_ERR_CONNECTION)
|
||||
WX_ERROR2_CASE(WEBVIEW2_WEB_ERROR_STATUS_OPERATION_CANCELED, wxWEBVIEW_NAV_ERR_USER_CANCELLED)
|
||||
WX_ERROR2_CASE(WEBVIEW2_WEB_ERROR_STATUS_REDIRECT_FAILED, wxWEBVIEW_NAV_ERR_OTHER)
|
||||
WX_ERROR2_CASE(WEBVIEW2_WEB_ERROR_STATUS_UNEXPECTED_ERROR, wxWEBVIEW_NAV_ERR_OTHER)
|
||||
}
|
||||
}
|
||||
HandleWindowEvent(event);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddPendingEvent(wxWebViewEvent(wxEVT_WEBVIEW_NAVIGATED, GetId(), uri, wxString()));
|
||||
if (m_historyEnabled && !m_historyLoadingFromList &&
|
||||
(uri == GetCurrentURL()) ||
|
||||
(GetCurrentURL().substr(0, 4) == "file" &&
|
||||
wxFileName::URLToFileName(GetCurrentURL()).GetFullPath() == uri))
|
||||
{
|
||||
// If we are not at the end of the list, then erase everything
|
||||
// between us and the end before adding the new page
|
||||
if (m_historyPosition != static_cast<int>(m_historyList.size()) - 1)
|
||||
{
|
||||
m_historyList.erase(m_historyList.begin() + m_historyPosition + 1,
|
||||
m_historyList.end());
|
||||
}
|
||||
wxSharedPtr<wxWebViewHistoryItem> item(new wxWebViewHistoryItem(uri, GetCurrentTitle()));
|
||||
m_historyList.push_back(item);
|
||||
m_historyPosition++;
|
||||
}
|
||||
//Reset as we are done now
|
||||
m_historyLoadingFromList = false;
|
||||
}
|
||||
return S_OK;
|
||||
})
|
||||
.Get(), &m_navigationCompletedToken);
|
||||
m_webView->add_NewWindowRequested(
|
||||
Callback<IWebView2NewWindowRequestedEventHandler>(
|
||||
[this](IWebView2WebView* WXUNUSED(sender), IWebView2NewWindowRequestedEventArgs* args) -> HRESULT
|
||||
{
|
||||
PWSTR uri;
|
||||
args->get_Uri(&uri);
|
||||
wxString evtURL(uri);
|
||||
AddPendingEvent(wxWebViewEvent(wxEVT_WEBVIEW_NEWWINDOW, GetId(), evtURL, wxString()));
|
||||
args->put_Handled(true);
|
||||
return S_OK;
|
||||
}).Get(), &m_newWindowRequestedToken);
|
||||
LoadURL(m_pendingURL);
|
||||
}
|
||||
|
||||
void wxWebViewEdge::OnSize(wxSizeEvent& event)
|
||||
{
|
||||
UpdateBounds();
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
void wxWebViewEdge::UpdateBounds()
|
||||
{
|
||||
RECT r;
|
||||
wxCopyRectToRECT(GetClientRect(), r);
|
||||
if (m_webView)
|
||||
m_webView->put_Bounds(r);
|
||||
}
|
||||
|
||||
void wxWebViewEdge::LoadURL(const wxString& url)
|
||||
{
|
||||
if (!m_webView)
|
||||
{
|
||||
m_pendingURL = url;
|
||||
return;
|
||||
}
|
||||
if (FAILED(m_webView->Navigate(url.wc_str())))
|
||||
wxLogError("Could not navigate to URL");
|
||||
}
|
||||
|
||||
void wxWebViewEdge::LoadHistoryItem(wxSharedPtr<wxWebViewHistoryItem> item)
|
||||
{
|
||||
int pos = -1;
|
||||
for (unsigned int i = 0; i < m_historyList.size(); i++)
|
||||
{
|
||||
//We compare the actual pointers to find the correct item
|
||||
if (m_historyList[i].get() == item.get())
|
||||
pos = i;
|
||||
}
|
||||
// TODO: wxASSERT_MSG(pos != static_cast<int>(m_impl->m_historyList.size()), "invalid history item");
|
||||
m_historyLoadingFromList = true;
|
||||
LoadURL(item->GetUrl());
|
||||
m_historyPosition = pos;
|
||||
}
|
||||
|
||||
wxVector<wxSharedPtr<wxWebViewHistoryItem> > wxWebViewEdge::GetBackwardHistory()
|
||||
{
|
||||
wxVector<wxSharedPtr<wxWebViewHistoryItem> > backhist;
|
||||
//As we don't have std::copy or an iterator constructor in the wxwidgets
|
||||
//native vector we construct it by hand
|
||||
for (int i = 0; i < m_historyPosition; i++)
|
||||
{
|
||||
backhist.push_back(m_historyList[i]);
|
||||
}
|
||||
return backhist;
|
||||
}
|
||||
|
||||
wxVector<wxSharedPtr<wxWebViewHistoryItem> > wxWebViewEdge::GetForwardHistory()
|
||||
{
|
||||
wxVector<wxSharedPtr<wxWebViewHistoryItem> > forwardhist;
|
||||
//As we don't have std::copy or an iterator constructor in the wxwidgets
|
||||
//native vector we construct it by hand
|
||||
for (int i = m_historyPosition + 1; i < static_cast<int>(m_historyList.size()); i++)
|
||||
{
|
||||
forwardhist.push_back(m_historyList[i]);
|
||||
}
|
||||
return forwardhist;
|
||||
}
|
||||
|
||||
bool wxWebViewEdge::CanGoForward() const
|
||||
{
|
||||
if (m_historyEnabled)
|
||||
return m_historyPosition != static_cast<int>(m_historyList.size()) - 1;
|
||||
else
|
||||
return false;
|
||||
|
||||
/*
|
||||
BOOL result = false;
|
||||
if (m_webView && SUCCEEDED(m_webView->get_CanGoForward(&result)))
|
||||
return result;
|
||||
else
|
||||
return false;
|
||||
*/
|
||||
}
|
||||
|
||||
bool wxWebViewEdge::CanGoBack() const
|
||||
{
|
||||
if (m_historyEnabled)
|
||||
return m_historyPosition > 0;
|
||||
else
|
||||
return false;
|
||||
/*
|
||||
BOOL result = false;
|
||||
|
||||
if (m_webView && SUCCEEDED(m_webView->get_CanGoBack(&result)))
|
||||
return result;
|
||||
else
|
||||
return false;
|
||||
*/
|
||||
}
|
||||
|
||||
void wxWebViewEdge::GoBack()
|
||||
{
|
||||
LoadHistoryItem(m_historyList[m_historyPosition - 1]);
|
||||
/* if (m_webView)
|
||||
m_webView->GoBack(); */
|
||||
}
|
||||
|
||||
void wxWebViewEdge::GoForward()
|
||||
{
|
||||
LoadHistoryItem(m_historyList[m_historyPosition + 1]);
|
||||
/* if (m_webView)
|
||||
m_webView->GoForward(); */
|
||||
}
|
||||
|
||||
void wxWebViewEdge::ClearHistory()
|
||||
{
|
||||
m_historyList.clear();
|
||||
m_historyPosition = -1;
|
||||
}
|
||||
|
||||
void wxWebViewEdge::EnableHistory(bool enable)
|
||||
{
|
||||
m_historyEnabled = enable;
|
||||
m_historyList.clear();
|
||||
m_historyPosition = -1;
|
||||
}
|
||||
|
||||
void wxWebViewEdge::Stop()
|
||||
{
|
||||
if (m_webView)
|
||||
m_webView->Stop();
|
||||
}
|
||||
|
||||
void wxWebViewEdge::Reload(wxWebViewReloadFlags WXUNUSED(flags))
|
||||
{
|
||||
if (m_webView)
|
||||
m_webView->Reload();
|
||||
}
|
||||
|
||||
wxString wxWebViewEdge::GetPageSource() const
|
||||
{
|
||||
return wxString();
|
||||
}
|
||||
|
||||
wxString wxWebViewEdge::GetPageText() const
|
||||
{
|
||||
return wxString();
|
||||
}
|
||||
|
||||
bool wxWebViewEdge::IsBusy() const
|
||||
{
|
||||
return m_isBusy;
|
||||
}
|
||||
|
||||
wxString wxWebViewEdge::GetCurrentURL() const
|
||||
{
|
||||
LPWSTR uri;
|
||||
if (m_webView && SUCCEEDED(m_webView->get_Source(&uri)))
|
||||
return wxString(uri);
|
||||
else
|
||||
return wxString();
|
||||
}
|
||||
|
||||
wxString wxWebViewEdge::GetCurrentTitle() const
|
||||
{
|
||||
PWSTR _title;
|
||||
if (m_webView && SUCCEEDED(m_webView->get_DocumentTitle(&_title)))
|
||||
return wxString(_title);
|
||||
else
|
||||
return wxString();
|
||||
}
|
||||
|
||||
void wxWebViewEdge::SetZoomType(wxWebViewZoomType)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
wxWebViewZoomType wxWebViewEdge::GetZoomType() const
|
||||
{
|
||||
return wxWEBVIEW_ZOOM_TYPE_LAYOUT;
|
||||
}
|
||||
|
||||
bool wxWebViewEdge::CanSetZoomType(wxWebViewZoomType type) const
|
||||
{
|
||||
return (type == wxWEBVIEW_ZOOM_TYPE_LAYOUT);
|
||||
}
|
||||
|
||||
void wxWebViewEdge::Print()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
wxWebViewZoom wxWebViewEdge::GetZoom() const
|
||||
{
|
||||
double old_zoom_factor = 0.0f;
|
||||
m_webView->get_ZoomFactor(&old_zoom_factor);
|
||||
if (old_zoom_factor > 1.7f)
|
||||
return wxWEBVIEW_ZOOM_LARGEST;
|
||||
if (old_zoom_factor > 1.3f)
|
||||
return wxWEBVIEW_ZOOM_LARGE;
|
||||
if (old_zoom_factor > 0.8f)
|
||||
return wxWEBVIEW_ZOOM_MEDIUM;
|
||||
if (old_zoom_factor > 0.6f)
|
||||
return wxWEBVIEW_ZOOM_SMALL;
|
||||
return wxWEBVIEW_ZOOM_TINY;
|
||||
}
|
||||
|
||||
void wxWebViewEdge::SetZoom(wxWebViewZoom zoom)
|
||||
{
|
||||
double old_zoom_factor = 0.0f;
|
||||
m_webView->get_ZoomFactor(&old_zoom_factor);
|
||||
double zoom_factor = 1.0f;
|
||||
switch (zoom)
|
||||
{
|
||||
case wxWEBVIEW_ZOOM_LARGEST:
|
||||
zoom_factor = 2.0f;
|
||||
break;
|
||||
case wxWEBVIEW_ZOOM_LARGE:
|
||||
zoom_factor = 1.5f;
|
||||
break;
|
||||
case wxWEBVIEW_ZOOM_MEDIUM:
|
||||
zoom_factor = 1.0f;
|
||||
break;
|
||||
case wxWEBVIEW_ZOOM_SMALL:
|
||||
zoom_factor = 0.75f;
|
||||
break;
|
||||
case wxWEBVIEW_ZOOM_TINY:
|
||||
zoom_factor = 0.5f;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
m_webView->put_ZoomFactor(zoom_factor);
|
||||
}
|
||||
|
||||
bool wxWebViewEdge::CanCut() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool wxWebViewEdge::CanCopy() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool wxWebViewEdge::CanPaste() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void wxWebViewEdge::Cut()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void wxWebViewEdge::Copy()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void wxWebViewEdge::Paste()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool wxWebViewEdge::CanUndo() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool wxWebViewEdge::CanRedo() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void wxWebViewEdge::Undo()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void wxWebViewEdge::Redo()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
long wxWebViewEdge::Find(const wxString& WXUNUSED(text), int WXUNUSED(flags))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
//Editing functions
|
||||
void wxWebViewEdge::SetEditable(bool WXUNUSED(enable))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool wxWebViewEdge::IsEditable() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void wxWebViewEdge::SelectAll()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool wxWebViewEdge::HasSelection() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void wxWebViewEdge::DeleteSelection()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
wxString wxWebViewEdge::GetSelectedText() const
|
||||
{
|
||||
return wxString();
|
||||
}
|
||||
|
||||
wxString wxWebViewEdge::GetSelectedSource() const
|
||||
{
|
||||
return wxString();
|
||||
}
|
||||
|
||||
void wxWebViewEdge::ClearSelection()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void wxWebViewEdge::EnableContextMenu(bool enable)
|
||||
{
|
||||
wxCOMPtr<IWebView2Settings> settings;
|
||||
if (SUCCEEDED(m_webView->get_Settings(&settings)))
|
||||
{
|
||||
wxCOMPtr<IWebView2Settings2> settings2;
|
||||
if (SUCCEEDED(settings->QueryInterface(IID_PPV_ARGS(&settings2))))
|
||||
{
|
||||
settings2->put_AreDefaultContextMenusEnabled(enable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool wxWebViewEdge::IsContextMenuEnabled() const
|
||||
{
|
||||
wxCOMPtr<IWebView2Settings> settings;
|
||||
if (SUCCEEDED(m_webView->get_Settings(&settings)))
|
||||
{
|
||||
wxCOMPtr<IWebView2Settings2> settings2;
|
||||
if (SUCCEEDED(settings->QueryInterface(IID_PPV_ARGS(&settings2))))
|
||||
{
|
||||
BOOL menusEnabled = TRUE;
|
||||
settings2->get_AreDefaultContextMenusEnabled(&menusEnabled);
|
||||
|
||||
if (!menusEnabled)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wxWebViewEdge::RunScriptSync(const wxString& javascript, wxString* output)
|
||||
{
|
||||
bool scriptExecuted = false;
|
||||
|
||||
HRESULT hr = m_webView->ExecuteScript(javascript.wc_str(), Callback<IWebView2ExecuteScriptCompletedHandler>(
|
||||
[&scriptExecuted, output](HRESULT error, PCWSTR result) -> HRESULT
|
||||
{
|
||||
if (error == S_OK)
|
||||
{
|
||||
if (output)
|
||||
output->assign(result);
|
||||
}
|
||||
else
|
||||
wxLogError(_("RunScript failed: %.8x"), error);
|
||||
|
||||
scriptExecuted = true;
|
||||
|
||||
return S_OK;
|
||||
}).Get());
|
||||
|
||||
|
||||
while (!scriptExecuted)
|
||||
wxYield();
|
||||
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
|
||||
bool wxWebViewEdge::RunScript(const wxString& javascript, wxString* output)
|
||||
{
|
||||
wxJSScriptWrapper wrapJS(javascript, &m_runScriptCount);
|
||||
|
||||
// This string is also used as an error indicator: it's cleared if there is
|
||||
// no error or used in the warning message below if there is one.
|
||||
wxString result;
|
||||
if (RunScriptSync(wrapJS.GetWrappedCode(), &result)
|
||||
&& result == wxS("true"))
|
||||
{
|
||||
if (RunScriptSync(wrapJS.GetOutputCode(), &result))
|
||||
{
|
||||
if (output)
|
||||
*output = result;
|
||||
result.clear();
|
||||
}
|
||||
|
||||
RunScriptSync(wrapJS.GetCleanUpCode());
|
||||
}
|
||||
|
||||
if (!result.empty())
|
||||
{
|
||||
wxLogWarning(_("Error running JavaScript: %s"), result);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void wxWebViewEdge::RegisterHandler(wxSharedPtr<wxWebViewHandler> handler)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void wxWebViewEdge::DoSetPage(const wxString& html, const wxString& WXUNUSED(baseUrl))
|
||||
{
|
||||
if (m_webView)
|
||||
m_webView->NavigateToString(html.wc_str());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Module ensuring all global/singleton objects are destroyed on shutdown.
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class wxWebViewEdgeModule : public wxModule
|
||||
{
|
||||
public:
|
||||
wxWebViewEdgeModule()
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool OnInit() wxOVERRIDE
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void OnExit() wxOVERRIDE
|
||||
{
|
||||
wxWebViewEdge::Uninitalize();
|
||||
}
|
||||
|
||||
private:
|
||||
wxDECLARE_DYNAMIC_CLASS(wxWebViewEdgeModule);
|
||||
};
|
||||
|
||||
wxIMPLEMENT_DYNAMIC_CLASS(wxWebViewEdgeModule, wxModule);
|
||||
|
||||
#endif // wxUSE_WEBVIEW && wxUSE_WEBVIEW_EDGE
|
Reference in New Issue
Block a user