From 7181e3bfc08858c5a58374b77e614e56edd69ff7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20Slav=C3=ADk?= Date: Sun, 26 Mar 2023 19:18:38 +0200 Subject: [PATCH 1/3] Build wxWidgets with WebView2 support Add dependency on WebView2 - add required NuGet package, and enable corresponding wx settings. Static version of WebView2 loader is used to avoid a dependency on additional DLL. --- 3rdparty/wx.vcxproj | 19 +++++++++++++++++ 3rdparty/wx.vcxproj.filters | 30 +++++++++++++++++++++++++++ 3rdparty/wxWidgets_setup_h/wx/setup.h | 18 +++++++--------- WinSparkle.vcxproj | 7 +++++++ packages.config | 3 ++- 5 files changed, 65 insertions(+), 12 deletions(-) diff --git a/3rdparty/wx.vcxproj b/3rdparty/wx.vcxproj index b0c15ac6..c79808da 100644 --- a/3rdparty/wx.vcxproj +++ b/3rdparty/wx.vcxproj @@ -456,6 +456,7 @@ + @@ -506,6 +507,7 @@ + @@ -534,12 +536,29 @@ + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + \ No newline at end of file diff --git a/3rdparty/wx.vcxproj.filters b/3rdparty/wx.vcxproj.filters index 9c730e35..3dff3ec7 100644 --- a/3rdparty/wx.vcxproj.filters +++ b/3rdparty/wx.vcxproj.filters @@ -20,6 +20,21 @@ Header Files + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + @@ -550,5 +565,20 @@ Source Files + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + \ No newline at end of file diff --git a/3rdparty/wxWidgets_setup_h/wx/setup.h b/3rdparty/wxWidgets_setup_h/wx/setup.h index bcb299ef..307a002a 100644 --- a/3rdparty/wxWidgets_setup_h/wx/setup.h +++ b/3rdparty/wxWidgets_setup_h/wx/setup.h @@ -585,7 +585,7 @@ #define wxUSE_IPV6 0 // Set to 1 to enable virtual file systems (required by wxHTML) -#define wxUSE_FILESYSTEM 0 +#define wxUSE_FILESYSTEM 1 // Set to 1 to enable virtual ZIP filesystem (requires wxUSE_FILESYSTEM) #define wxUSE_FS_ZIP 0 @@ -792,32 +792,28 @@ // Default is 1 // // Recommended setting: 1 -#define wxUSE_WEBVIEW 0 +#define wxUSE_WEBVIEW 1 // Use the IE wxWebView backend // // Default is 1 on MSW // // Recommended setting: 1 -#ifdef __WXMSW__ -#define wxUSE_WEBVIEW_IE 0 -#else -#define wxUSE_WEBVIEW_IE 0 -#endif +#define wxUSE_WEBVIEW_IE 1 // Use the Edge (Chromium) wxWebView backend (Requires WebView2 SDK) // // Default is 0 because WebView2 is not always available, set it to 1 if you do have it. // -// Recommended setting: 1 when building for Windows with WebView2 SDK -#define wxUSE_WEBVIEW_EDGE 0 +// Recommended setting: 1 when building for Windows with W ebView2 SDK +#define wxUSE_WEBVIEW_EDGE 1 // Use the Edge (Chromium) wxWebView backend without loader DLL // // Default is 0, set it to 1 if you don't want to depend on WebView2Loader.dll. // // Recommended setting: 0 -#define wxUSE_WEBVIEW_EDGE_STATIC 0 +#define wxUSE_WEBVIEW_EDGE_STATIC 1 // Use the WebKit wxWebView backend // @@ -1691,7 +1687,7 @@ // // Recommended setting: 1 if you need to control other applications via OLE // Automation, can be safely set to 0 otherwise -#define wxUSE_OLE_AUTOMATION 0 +#define wxUSE_OLE_AUTOMATION 1 // Set this to 1 to enable wxActiveXContainer class allowing to embed OLE // controls in wx. diff --git a/WinSparkle.vcxproj b/WinSparkle.vcxproj index ba8c9aa9..dacfe564 100644 --- a/WinSparkle.vcxproj +++ b/WinSparkle.vcxproj @@ -450,5 +450,12 @@ + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + \ No newline at end of file diff --git a/packages.config b/packages.config index 13c26ce1..8e77ffc3 100644 --- a/packages.config +++ b/packages.config @@ -1,4 +1,5 @@ - + + \ No newline at end of file From f00e5c1af80f0b30cec6e9ce002b4a8ceca1d1ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20Slav=C3=ADk?= Date: Mon, 27 Mar 2023 11:02:42 +0200 Subject: [PATCH 2/3] Switch to using wxWebView Replace custom loading of MSIE control with wxWebView. This enables using different backends (crucially, WebView2/Edge) and simplifies the code. Fixes #227. --- src/ui.cpp | 115 +++++++++-------------------------------------------- 1 file changed, 18 insertions(+), 97 deletions(-) diff --git a/src/ui.cpp b/src/ui.cpp index 4b081f20..9c898260 100644 --- a/src/ui.cpp +++ b/src/ui.cpp @@ -51,8 +51,9 @@ #include #include #include -#include #include +#include +#include #include #include @@ -465,8 +466,7 @@ class UpdateDialog : public WinSparkleDialog wxSizer *m_updateButtonsSizer; wxSizer *m_releaseNotesSizer; wxPanel *m_browserParent; - - wxAutoOleInterface m_webBrowser; + wxWebView *m_webBrowser; // current appcast data (only valid after StateUpdateAvailable()) Appcast m_appcast; @@ -518,6 +518,8 @@ UpdateDialog::UpdateDialog() wxDefaultPosition, wxSize(PX(RELNOTES_WIDTH), PX(RELNOTES_HEIGHT))); m_browserParent->SetBackgroundColour(*wxWHITE); + m_webBrowser = NULL; + m_releaseNotesSizer->Add ( m_browserParent, @@ -997,110 +999,29 @@ void UpdateDialog::StateUpdateDownloaded(const std::wstring& updateFile, const s void UpdateDialog::ShowReleaseNotes(const Appcast& info) { - if ( !m_webBrowser.IsOk() ) + if ( !m_webBrowser ) { - // Load MSIE control - wxBusyCursor busy; - IWebBrowser2 *browser; - HRESULT hr = CoCreateInstance - ( - CLSID_WebBrowser, - NULL, - CLSCTX_INPROC_SERVER, - IID_IWebBrowser2, - (void**)&browser - ); - - if ( FAILED(hr) ) - { - // hide the notes again, we cannot show them - LayoutChangesGuard guard(this); - HIDE(m_releaseNotesSizer); - MakeResizable(false); - LogError("Failed to create WebBrowser ActiveX control."); - return; - } - - m_webBrowser = browser; - - new wxActiveXContainer(m_browserParent, IID_IWebBrowser2, browser); - - // Poke the browser to initialize it. This is needed when using - // info.Description and does no harm with ReleaseNotesURL. To - // complicate things, it must be done exactly once, which is why it's - // here and not below. - // See https://github.com/vslavik/winsparkle/issues/155 - m_webBrowser->Navigate - ( - wxBasicString("about:blank"), - NULL, // Flags - NULL, // TargetFrameName - NULL, // PostData - NULL // Headers - ); + if (!wxWebView::IsBackendAvailable(wxWebViewBackendEdge)) + wxWebViewIE::MSWSetEmulationLevel(wxWEBVIEWIE_EMU_IE11); + // Note that about:blank is used so that subsequent SetPage() call doesn't fail with + // MSIE. See https://github.com/vslavik/winsparkle/issues/155 and + // https://github.com/wxWidgets/wxWidgets/issues/14768 + m_webBrowser = wxWebView::New(m_browserParent, wxID_ANY, "about:blank", + wxDefaultPosition, wxSize(PX(RELNOTES_WIDTH), PX(RELNOTES_HEIGHT))); + auto sizer = new wxBoxSizer(wxVERTICAL); + sizer->Add(m_webBrowser, wxSizerFlags(1).Expand()); + m_browserParent->SetSizer(sizer); } if( !info.ReleaseNotesURL.empty() ) { - m_webBrowser->Navigate - ( - wxBasicString(info.ReleaseNotesURL), - NULL, // Flags - NULL, // TargetFrameName - NULL, // PostData - NULL // Headers - ); + m_webBrowser->LoadURL(info.ReleaseNotesURL); } else if ( !info.Description.empty() ) { - HRESULT hr = E_FAIL; - IHTMLDocument2 *doc; - hr = m_webBrowser->get_Document((IDispatch **)&doc); - if ( FAILED(hr) || !doc ) - { - LogError("Failed to get HTML document"); - return; - } - - // If the code below looks crazy, that's because it is. Apparently, - // the document may be in some uninitialized state first time around, - // so we need to write an empty string into it first and only then the - // real content. (At least that's what wxWebView does...) - // - // See https://github.com/vslavik/winsparkle/issues/29 - SAFEARRAY *psaStrings = SafeArrayCreateVector(VT_VARIANT, 0, 1); - if ( psaStrings != NULL ) - { - VARIANT *param; - SafeArrayAccessData(psaStrings, (LPVOID*)¶m); - param->vt = VT_BSTR; - param->bstrVal = SysAllocString(OLESTR("")); - SafeArrayUnaccessData(psaStrings); - - doc->write(psaStrings); - doc->close(); - - SafeArrayDestroy(psaStrings); - - psaStrings = SafeArrayCreateVector(VT_VARIANT, 0, 1); - if (psaStrings != NULL) - { - VARIANT *param; - SafeArrayAccessData(psaStrings, (LPVOID*) ¶m); - param->vt = VT_BSTR; - param->bstrVal = wxBasicString(wxString::FromUTF8(info.Description.c_str())).Detach(); - SafeArrayUnaccessData(psaStrings); - - doc->write(psaStrings); - doc->close(); - - SafeArrayDestroy(psaStrings); - } - - doc->Release(); - } + m_webBrowser->SetPage(wxString::FromUTF8(info.Description), ""); } SetWindowStyleFlag(GetWindowStyleFlag() | wxRESIZE_BORDER); From ec271892eaefd48edffd9ec2123fd9f9f09f5113 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20Slav=C3=ADk?= Date: Mon, 27 Mar 2023 11:45:06 +0200 Subject: [PATCH 3/3] Open all release notes links in default browser Intercept all navigation and open links present in release notes in user's default browser instead of inline or in Edge (or worse, MSIE). Fixes #177. --- src/ui.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/ui.cpp b/src/ui.cpp index 9c898260..d4b44f8f 100644 --- a/src/ui.cpp +++ b/src/ui.cpp @@ -1013,6 +1013,17 @@ void UpdateDialog::ShowReleaseNotes(const Appcast& info) auto sizer = new wxBoxSizer(wxVERTICAL); sizer->Add(m_webBrowser, wxSizerFlags(1).Expand()); m_browserParent->SetSizer(sizer); + + // Open all links in the default browser: + m_webBrowser->Bind(wxEVT_WEBVIEW_NAVIGATING, [info](wxWebViewEvent& evt) + { + auto url = evt.GetURL(); + if (url.starts_with("http") && url != info.ReleaseNotesURL) + { + wxLaunchDefaultBrowser(url); + evt.Veto(); + } + }); } if( !info.ReleaseNotesURL.empty() )