Compare commits

...
Author SHA1 Message Date
Hanif Koh 64035de87e Restore Plugin HTML After a Webview Reload
Plugin dialog content is injected with SetPage, so the webview's current URL
stays the base URL and the injected document has none of its own. Reloading the
page (context menu or keyboard shortcut) therefore re-fetches the base URL and
the plugin UI disappears, permanently: load_plugin_content() returned early once
m_content_loaded was set.

Re-inject the plugin HTML whenever a main-frame load arrives after the initial
swap. m_own_page_load marks the load caused by our own SetPage so it is not
mistaken for a reload, and in-document navigation is ignored: the MSW backend
synthesises a wxEVT_WEBVIEW_LOADED when a page changes location.hash, which
would otherwise wipe the page under the user. A post-load error is left alone
too, as it only ever means a failed subresource.
2026-09-16 14:09:46 +08:00
2 changed files with 31 additions and 6 deletions
+29 -6
View File
@@ -55,6 +55,16 @@ wxString web_base_url()
return wxString("file://") + from_u8(dir) + "/";
}
// True when two consecutive main-frame URLs name the same document, i.e. they differ
// only in the fragment. The MSW backend synthesises a wxEVT_WEBVIEW_LOADED for such
// in-document navigation (a page setting location.hash), which must not be mistaken
// for a reload; an identical URL is a genuine reload and is not fragment navigation.
bool is_fragment_navigation(const wxString& from, const wxString& to)
{
return from != to && from.BeforeFirst('#') == to.BeforeFirst('#');
}
} // namespace
PluginWebDialog::PluginWebDialog(wxWindow* parent,
@@ -139,19 +149,32 @@ void PluginWebDialog::destroy_for_plugin(PluginWebDialog* dialog)
void PluginWebDialog::on_bootstrap_event(wxWebViewEvent& event)
{
// The first bootstrap load (or its error) triggers the swap to plugin HTML;
// the resulting plugin-page load is ignored (guarded by m_content_loaded).
load_plugin_content();
// The first bootstrap load (or its error) triggers the swap to plugin HTML. Once that
// page has settled, a further main-frame load is a browser reload (context menu or
// keyboard shortcut): the injected page has no URL of its own, so the reload fetches
// the base URL instead and the plugin HTML has to be put back. In-document navigation
// is not a reload and must be left alone, as is a post-load error, which only ever
// means a failed subresource.
if (!m_content_loaded)
load_plugin_content();
else if (event.GetEventType() == wxEVT_WEBVIEW_LOADED) {
const wxString previous_url = m_last_url;
m_last_url = event.GetURL();
if (m_own_page_load)
m_own_page_load = false;
else if (!is_fragment_navigation(previous_url, m_last_url))
load_plugin_content();
}
event.Skip();
}
void PluginWebDialog::load_plugin_content()
{
if (m_content_loaded)
return;
m_content_loaded = true;
if (wxWebView* wv = browser())
if (wxWebView* wv = browser()) {
m_own_page_load = true;
wv->SetPage(wxString::FromUTF8(m_html), web_base_url());
}
}
void PluginWebDialog::on_script_message(const nlohmann::json& payload)
+2
View File
@@ -72,6 +72,8 @@ private:
std::string m_html;
bool m_content_loaded{false};
bool m_own_page_load{false}; // a SetPage of the plugin HTML is in flight
wxString m_last_url; // URL of the last main-frame load, to spot fragment navigation
bool m_open{true};
bool m_close_fired{false};
std::optional<nlohmann::json> m_result;