From 412de05407ea54bafb5f333de945701d0c786bdc Mon Sep 17 00:00:00 2001 From: Tobias Taschner Date: Wed, 4 Nov 2020 13:59:08 +0100 Subject: [PATCH 1/3] Allow settings modification before WebView Edge init Setting EnableContextMenu and EnableAccessToDevTools where ignored before the webview loaded content. This would often be set directly after creation and work like this with other backends. --- include/wx/msw/private/webview_edge.h | 2 ++ src/msw/webview_edge.cpp | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/include/wx/msw/private/webview_edge.h b/include/wx/msw/private/webview_edge.h index e666f1f1c0..2ebc5a468b 100644 --- a/include/wx/msw/private/webview_edge.h +++ b/include/wx/msw/private/webview_edge.h @@ -36,6 +36,8 @@ public: bool m_initialized; bool m_isBusy; wxString m_pendingURL; + int m_pendingContextMenuEnabled; + int m_pendingAccessToDevToolsEnabled; // WebView Events tokens EventRegistrationToken m_navigationStartingToken = { }; diff --git a/src/msw/webview_edge.cpp b/src/msw/webview_edge.cpp index 4da9765eae..b741a450b5 100644 --- a/src/msw/webview_edge.cpp +++ b/src/msw/webview_edge.cpp @@ -76,6 +76,8 @@ bool wxWebViewEdgeImpl::Create() { m_initialized = false; m_isBusy = false; + m_pendingContextMenuEnabled = -1; + m_pendingAccessToDevToolsEnabled = -1; m_historyLoadingFromList = false; m_historyEnabled = true; @@ -310,6 +312,18 @@ HRESULT wxWebViewEdgeImpl::OnWebViewCreated(HRESULT result, ICoreWebView2Control this, &wxWebViewEdgeImpl::OnContentLoading).Get(), &m_contentLoadingToken); + if (m_pendingContextMenuEnabled != -1) + { + m_ctrl->EnableContextMenu(m_pendingContextMenuEnabled == 1); + m_pendingContextMenuEnabled = -1; + } + + if (m_pendingAccessToDevToolsEnabled != -1) + { + m_ctrl->EnableAccessToDevTools(m_pendingAccessToDevToolsEnabled == 1); + m_pendingContextMenuEnabled = -1; + } + if (!m_pendingURL.empty()) { m_ctrl->LoadURL(m_pendingURL); @@ -706,6 +720,8 @@ void wxWebViewEdge::EnableContextMenu(bool enable) wxCOMPtr settings(m_impl->GetSettings()); if (settings) settings->put_AreDefaultContextMenusEnabled(enable); + else + m_impl->m_pendingContextMenuEnabled = enable ? 1 : 0; } bool wxWebViewEdge::IsContextMenuEnabled() const @@ -727,6 +743,8 @@ void wxWebViewEdge::EnableAccessToDevTools(bool enable) wxCOMPtr settings(m_impl->GetSettings()); if (settings) settings->put_AreDevToolsEnabled(enable); + else + m_impl->m_pendingAccessToDevToolsEnabled = enable ? 1 : 0; } bool wxWebViewEdge::IsAccessToDevToolsEnabled() const From 2d9c08e0cc505a0a4cae9758fc619086fbf4d4e8 Mon Sep 17 00:00:00 2001 From: Tobias Taschner Date: Thu, 5 Nov 2020 09:27:20 +0100 Subject: [PATCH 2/3] WebViewEdge: Forward window visibility to SDK Tell the SDK controller if the control is shown or hidden. This allows creating a hidden webview which will be shown later and might fix other potential issues. --- include/wx/msw/webview_edge.h | 2 ++ src/msw/webview_edge.cpp | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/include/wx/msw/webview_edge.h b/include/wx/msw/webview_edge.h index f969566b33..4b5b4aa410 100644 --- a/include/wx/msw/webview_edge.h +++ b/include/wx/msw/webview_edge.h @@ -134,6 +134,8 @@ private: void OnSize(wxSizeEvent& event); + void OnShow(wxShowEvent& event); + bool RunScriptSync(const wxString& javascript, wxString* output = NULL); wxDECLARE_DYNAMIC_CLASS(wxWebViewEdge); diff --git a/src/msw/webview_edge.cpp b/src/msw/webview_edge.cpp index b741a450b5..6dc1fd3957 100644 --- a/src/msw/webview_edge.cpp +++ b/src/msw/webview_edge.cpp @@ -364,6 +364,7 @@ bool wxWebViewEdge::IsAvailable() wxWebViewEdge::~wxWebViewEdge() { + Unbind(wxEVT_SHOW, &wxWebViewEdge::OnShow, this); delete m_impl; } @@ -388,6 +389,7 @@ bool wxWebViewEdge::Create(wxWindow* parent, if (!m_impl->Create()) return false; Bind(wxEVT_SIZE, &wxWebViewEdge::OnSize, this); + Bind(wxEVT_SHOW, &wxWebViewEdge::OnShow, this); LoadURL(url); return true; @@ -399,6 +401,13 @@ void wxWebViewEdge::OnSize(wxSizeEvent& event) event.Skip(); } +void wxWebViewEdge::OnShow(wxShowEvent& event) +{ + if (m_impl->m_webView) + m_impl->m_webViewController->put_IsVisible(event.IsShown()); + event.Skip(); +} + void wxWebViewEdge::LoadURL(const wxString& url) { if (!m_impl->m_webView) From 46d123b95355a4bee043716f30995276ffc70c38 Mon Sep 17 00:00:00 2001 From: Tobias Taschner Date: Thu, 5 Nov 2020 09:47:58 +0100 Subject: [PATCH 3/3] WebViewEdge: Allow edge webview2 installation during runtime Check if edge webview runtime is available in the call to wxWebView::IsBackendAvailable() instead of only doing it during process initialization. This allows an application to install the Edge WebView2 Runtime during runtime and use the edge webview afterwards without restarting the process. --- include/wx/msw/private/webview_edge.h | 2 +- include/wx/msw/webview_edge.h | 5 +--- include/wx/webview.h | 1 + interface/wx/webview.h | 11 +++++++++ src/common/webview.cpp | 8 +++--- src/msw/webview_edge.cpp | 35 ++++++++++++++------------- 6 files changed, 37 insertions(+), 25 deletions(-) diff --git a/include/wx/msw/private/webview_edge.h b/include/wx/msw/private/webview_edge.h index 2ebc5a468b..765127e9ed 100644 --- a/include/wx/msw/private/webview_edge.h +++ b/include/wx/msw/private/webview_edge.h @@ -65,7 +65,7 @@ public: ICoreWebView2Settings* GetSettings(); - static int ms_isAvailable; + static bool ms_isInitialized; static wxDynamicLibrary ms_loaderDll; static bool Initialize(); diff --git a/include/wx/msw/webview_edge.h b/include/wx/msw/webview_edge.h index 4b5b4aa410..dbdbfc5678 100644 --- a/include/wx/msw/webview_edge.h +++ b/include/wx/msw/webview_edge.h @@ -122,10 +122,6 @@ public: virtual void* GetNativeBackend() const wxOVERRIDE; - // ---- Edge-specific methods - - static bool IsAvailable(); - protected: virtual void DoSetPage(const wxString& html, const wxString& baseUrl) wxOVERRIDE; @@ -155,6 +151,7 @@ public: { return new wxWebViewEdge(parent, id, url, pos, size, style, name); } + virtual bool IsAvailable() wxOVERRIDE; }; #endif // wxUSE_WEBVIEW && wxUSE_WEBVIEW_EDGE && defined(__WXMSW__) diff --git a/include/wx/webview.h b/include/wx/webview.h index 53c78122c2..63ca8199a4 100644 --- a/include/wx/webview.h +++ b/include/wx/webview.h @@ -119,6 +119,7 @@ public: const wxSize& size = wxDefaultSize, long style = 0, const wxString& name = wxASCII_STR(wxWebViewNameStr)) = 0; + virtual bool IsAvailable() { return true; } }; WX_DECLARE_STRING_HASH_MAP(wxSharedPtr, wxStringWebViewFactoryMap); diff --git a/interface/wx/webview.h b/interface/wx/webview.h index 9011577fbd..a1d1ce04e3 100644 --- a/interface/wx/webview.h +++ b/interface/wx/webview.h @@ -220,6 +220,17 @@ public: const wxSize& size = wxDefaultSize, long style = 0, const wxString& name = wxWebViewNameStr) = 0; + /** + Function to check if the backend is available at runtime. The + wxWebView implementation can use this function to check all + runtime requirements without trying to create a wxWebView. + + @return returns @true if the backend can be used or @false if it is + not available during runtime. + + @since 3.1.5 + */ + virtual bool IsAvailable(); }; /** diff --git a/src/common/webview.cpp b/src/common/webview.cpp index ad44a43559..348a2ad75e 100644 --- a/src/common/webview.cpp +++ b/src/common/webview.cpp @@ -88,7 +88,10 @@ void wxWebView::RegisterFactory(const wxString& backend, bool wxWebView::IsBackendAvailable(const wxString& backend) { wxStringWebViewFactoryMap::iterator iter = FindFactory(backend); - return iter != m_factoryMap.end(); + if (iter != m_factoryMap.end()) + return iter->second->IsAvailable(); + else + return false; } // static @@ -111,8 +114,7 @@ void wxWebView::InitFactoryMap() #endif #if wxUSE_WEBVIEW_EDGE - if (wxWebViewEdge::IsAvailable() && - m_factoryMap.find(wxWebViewBackendEdge) == m_factoryMap.end()) + if (m_factoryMap.find(wxWebViewBackendEdge) == m_factoryMap.end()) RegisterFactory(wxWebViewBackendEdge, wxSharedPtr (new wxWebViewFactoryEdge)); #endif diff --git a/src/msw/webview_edge.cpp b/src/msw/webview_edge.cpp index 6dc1fd3957..2dba6fffb1 100644 --- a/src/msw/webview_edge.cpp +++ b/src/msw/webview_edge.cpp @@ -51,7 +51,7 @@ typedef HRESULT(__stdcall *GetAvailableCoreWebView2BrowserVersionString_t)( CreateCoreWebView2EnvironmentWithOptions_t wxCreateCoreWebView2EnvironmentWithOptions = NULL; GetAvailableCoreWebView2BrowserVersionString_t wxGetAvailableCoreWebView2BrowserVersionString = NULL; -int wxWebViewEdgeImpl::ms_isAvailable = -1; +bool wxWebViewEdgeImpl::ms_isInitialized = false; wxDynamicLibrary wxWebViewEdgeImpl::ms_loaderDll; wxWebViewEdgeImpl::wxWebViewEdgeImpl(wxWebViewEdge* webview): @@ -113,6 +113,9 @@ HRESULT wxWebViewEdgeImpl::OnEnvironmentCreated( bool wxWebViewEdgeImpl::Initialize() { + if (ms_isInitialized) + return true; + if (!ms_loaderDll.Load("WebView2Loader.dll", wxDL_DEFAULT | wxDL_QUIET)) return false; @@ -126,7 +129,10 @@ bool wxWebViewEdgeImpl::Initialize() wxCoTaskMemPtr versionStr; HRESULT hr = wxGetAvailableCoreWebView2BrowserVersionString(NULL, &versionStr); if (SUCCEEDED(hr) && versionStr) + { + ms_isInitialized = true; return true; + } else wxLogApiError("GetCoreWebView2BrowserVersionInfo", hr); @@ -135,10 +141,10 @@ bool wxWebViewEdgeImpl::Initialize() void wxWebViewEdgeImpl::Uninitialize() { - if (ms_isAvailable == 1) + if (ms_isInitialized) { ms_loaderDll.Unload(); - ms_isAvailable = -1; + ms_isInitialized = false; } } @@ -349,19 +355,6 @@ ICoreWebView2Settings* wxWebViewEdgeImpl::GetSettings() return settings; } -bool wxWebViewEdge::IsAvailable() -{ - if (wxWebViewEdgeImpl::ms_isAvailable == -1) - { - if (!wxWebViewEdgeImpl::Initialize()) - wxWebViewEdgeImpl::ms_isAvailable = 0; - else - wxWebViewEdgeImpl::ms_isAvailable = 1; - } - - return wxWebViewEdgeImpl::ms_isAvailable == 1; -} - wxWebViewEdge::~wxWebViewEdge() { Unbind(wxEVT_SHOW, &wxWebViewEdge::OnShow, this); @@ -376,7 +369,7 @@ bool wxWebViewEdge::Create(wxWindow* parent, long style, const wxString& name) { - if (!IsAvailable()) + if (!wxWebViewEdgeImpl::Initialize()) return false; if (!wxControl::Create(parent, id, pos, size, style, @@ -869,6 +862,14 @@ void wxWebViewEdge::DoSetPage(const wxString& html, const wxString& WXUNUSED(bas m_impl->m_webView->NavigateToString(html.wc_str()); } +// wxWebViewFactoryEdge + +bool wxWebViewFactoryEdge::IsAvailable() +{ + return wxWebViewEdgeImpl::Initialize(); +} + + // ---------------------------------------------------------------------------- // Module ensuring all global/singleton objects are destroyed on shutdown. // ----------------------------------------------------------------------------