Move webview pointer to wxweakref
Uses wx reference counting infrastructure to ensure we have a valid pointer and adds proper null checking for the webview not being instantiated yet
This commit is contained in:
@@ -77,39 +77,32 @@ WEBVIEW_PANEL::WEBVIEW_PANEL( wxWindow* aParent, wxWindowID aId, const wxPoint&
|
||||
m_backend = wxWebViewBackendDefault;
|
||||
#endif
|
||||
|
||||
wxWebView* browser = GetWebView();
|
||||
|
||||
if( !browser )
|
||||
return;
|
||||
|
||||
#ifdef __WXMAC__
|
||||
m_browser->RegisterHandler( wxSharedPtr<wxWebViewHandler>( new wxWebViewArchiveHandler( "wxfs" ) ) );
|
||||
m_browser->RegisterHandler( wxSharedPtr<wxWebViewHandler>( new wxWebViewFSHandler( "memory" ) ) );
|
||||
browser->RegisterHandler( wxSharedPtr<wxWebViewHandler>( new wxWebViewArchiveHandler( "wxfs" ) ) );
|
||||
browser->RegisterHandler( wxSharedPtr<wxWebViewHandler>( new wxWebViewFSHandler( "memory" ) ) );
|
||||
#endif
|
||||
m_browser->SetUserAgent( wxString::Format( "KiCad/%s WebView/%s", GetMajorMinorPatchVersion(), wxGetOsDescription() ) );
|
||||
m_browser->Create( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize );
|
||||
sizer->Add( m_browser, 1, wxEXPAND );
|
||||
browser->SetUserAgent( wxString::Format( "KiCad/%s WebView/%s", GetMajorMinorPatchVersion(), wxGetOsDescription() ) );
|
||||
browser->Create( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize );
|
||||
sizer->Add( browser, 1, wxEXPAND );
|
||||
SetSizer( sizer );
|
||||
|
||||
#ifndef __WXMAC__
|
||||
m_browser->RegisterHandler( wxSharedPtr<wxWebViewHandler>( new wxWebViewArchiveHandler( "wxfs" ) ) );
|
||||
m_browser->RegisterHandler( wxSharedPtr<wxWebViewHandler>( new wxWebViewFSHandler( "memory" ) ) );
|
||||
browser->RegisterHandler( wxSharedPtr<wxWebViewHandler>( new wxWebViewArchiveHandler( "wxfs" ) ) );
|
||||
browser->RegisterHandler( wxSharedPtr<wxWebViewHandler>( new wxWebViewFSHandler( "memory" ) ) );
|
||||
#endif
|
||||
|
||||
Bind( wxEVT_WEBVIEW_NAVIGATING, &WEBVIEW_PANEL::OnNavigationRequest, this, m_browser->GetId() );
|
||||
Bind( wxEVT_WEBVIEW_NEWWINDOW, &WEBVIEW_PANEL::OnNewWindow, this, m_browser->GetId() );
|
||||
Bind( wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED, &WEBVIEW_PANEL::OnScriptMessage, this, m_browser->GetId() );
|
||||
Bind( wxEVT_WEBVIEW_SCRIPT_RESULT, &WEBVIEW_PANEL::OnScriptResult, this, m_browser->GetId() );
|
||||
Bind( wxEVT_WEBVIEW_ERROR, &WEBVIEW_PANEL::OnError, this, m_browser->GetId() );
|
||||
Bind( wxEVT_WEBVIEW_NAVIGATING, &WEBVIEW_PANEL::OnNavigationRequest, this, browser->GetId() );
|
||||
Bind( wxEVT_WEBVIEW_NEWWINDOW, &WEBVIEW_PANEL::OnNewWindow, this, browser->GetId() );
|
||||
Bind( wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED, &WEBVIEW_PANEL::OnScriptMessage, this, browser->GetId() );
|
||||
Bind( wxEVT_WEBVIEW_SCRIPT_RESULT, &WEBVIEW_PANEL::OnScriptResult, this, browser->GetId() );
|
||||
Bind( wxEVT_WEBVIEW_ERROR, &WEBVIEW_PANEL::OnError, this, browser->GetId() );
|
||||
|
||||
m_initRetryTimer.Bind( wxEVT_TIMER, [this]( wxTimerEvent& ) { DoInitHandlers(); } );
|
||||
|
||||
m_browser->Bind( wxEVT_DESTROY, [this]( wxWindowDestroyEvent& evt )
|
||||
{
|
||||
if( evt.GetEventObject() == m_browser )
|
||||
{
|
||||
// During panel teardown, wxWindow destroys children after C++ member
|
||||
// destruction, so m_initRetryTimer may already be gone here.
|
||||
m_browser = nullptr;
|
||||
}
|
||||
|
||||
evt.Skip();
|
||||
} );
|
||||
}
|
||||
|
||||
WEBVIEW_PANEL::~WEBVIEW_PANEL()
|
||||
@@ -121,7 +114,12 @@ void WEBVIEW_PANEL::BindLoadedEvent()
|
||||
if( m_loadedEventBound )
|
||||
return;
|
||||
|
||||
Bind( wxEVT_WEBVIEW_LOADED, &WEBVIEW_PANEL::OnWebViewLoaded, this, m_browser->GetId() );
|
||||
wxWebView* browser = GetWebView();
|
||||
|
||||
if( !browser )
|
||||
return;
|
||||
|
||||
Bind( wxEVT_WEBVIEW_LOADED, &WEBVIEW_PANEL::OnWebViewLoaded, this, browser->GetId() );
|
||||
m_loadedEventBound = true;
|
||||
}
|
||||
|
||||
@@ -132,7 +130,10 @@ void WEBVIEW_PANEL::LoadURL( const wxString& aURL )
|
||||
if( aURL.starts_with( "file:/" ) && !aURL.starts_with( "file:///" ) )
|
||||
{
|
||||
wxString new_url = wxString( "file:///" ) + aURL.AfterFirst( '/' );
|
||||
m_browser->LoadURL( new_url );
|
||||
|
||||
if( wxWebView* browser = GetWebView() )
|
||||
browser->LoadURL( new_url );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -142,13 +143,16 @@ void WEBVIEW_PANEL::LoadURL( const wxString& aURL )
|
||||
return;
|
||||
}
|
||||
|
||||
m_browser->LoadURL( aURL );
|
||||
if( wxWebView* browser = GetWebView() )
|
||||
browser->LoadURL( aURL );
|
||||
}
|
||||
|
||||
void WEBVIEW_PANEL::SetPage( const wxString& aHtmlContent )
|
||||
{
|
||||
wxLogTrace( "webview", "Setting page content" );
|
||||
m_browser->SetPage( aHtmlContent, "file://" );
|
||||
|
||||
if( wxWebView* browser = GetWebView() )
|
||||
browser->SetPage( aHtmlContent, "file://" );
|
||||
}
|
||||
|
||||
bool WEBVIEW_PANEL::AddMessageHandler( const wxString& aName, MESSAGE_HANDLER aHandler )
|
||||
@@ -164,8 +168,13 @@ bool WEBVIEW_PANEL::AddMessageHandler( const wxString& aName, MESSAGE_HANDLER aH
|
||||
|
||||
m_msgHandlers.emplace( aName, std::move( aHandler ) );
|
||||
|
||||
if( m_initialized && m_browser )
|
||||
if( m_initialized )
|
||||
{
|
||||
wxWebView* browser = GetWebView();
|
||||
|
||||
if( !browser )
|
||||
return true;
|
||||
|
||||
wxEventLoopBase* activeLoop = wxEventLoopBase::GetActive();
|
||||
|
||||
if( activeLoop && ( !activeLoop->IsMain() || activeLoop->IsYielding() ) )
|
||||
@@ -174,7 +183,7 @@ bool WEBVIEW_PANEL::AddMessageHandler( const wxString& aName, MESSAGE_HANDLER aH
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !m_browser->AddScriptMessageHandler( aName ) )
|
||||
if( !browser->AddScriptMessageHandler( aName ) )
|
||||
wxLogTrace( "webview", "Could not add script message handler %s", aName );
|
||||
}
|
||||
}
|
||||
@@ -186,10 +195,10 @@ void WEBVIEW_PANEL::ClearMessageHandlers()
|
||||
{
|
||||
wxLogTrace( "webview", "Clearing all message handlers" );
|
||||
|
||||
if( m_browser )
|
||||
if( wxWebView* browser = GetWebView() )
|
||||
{
|
||||
for( const auto& handler : m_msgHandlers )
|
||||
m_browser->RemoveScriptMessageHandler( handler.first );
|
||||
browser->RemoveScriptMessageHandler( handler.first );
|
||||
}
|
||||
|
||||
m_msgHandlers.clear();
|
||||
@@ -212,7 +221,9 @@ void WEBVIEW_PANEL::OnNavigationRequest( wxWebViewEvent& aEvt )
|
||||
|
||||
void WEBVIEW_PANEL::DoInitHandlers()
|
||||
{
|
||||
if( !m_browser )
|
||||
wxWebView* browser = GetWebView();
|
||||
|
||||
if( !browser )
|
||||
return;
|
||||
|
||||
// WebKit's AddScriptMessageHandler internally calls RunScript which yields the
|
||||
@@ -230,11 +241,11 @@ void WEBVIEW_PANEL::DoInitHandlers()
|
||||
|
||||
for( const auto& handler : m_msgHandlers )
|
||||
{
|
||||
if( !m_browser->AddScriptMessageHandler( handler.first ) )
|
||||
if( !browser->AddScriptMessageHandler( handler.first ) )
|
||||
wxLogTrace( "webview", "Could not add script message handler %s", handler.first );
|
||||
}
|
||||
|
||||
m_browser->AddUserScript( R"(
|
||||
browser->AddUserScript( R"(
|
||||
(function() {
|
||||
// Change window.open to navigate in the same window
|
||||
window.open = function(url) { if (url) window.location.href = url; return null; };
|
||||
@@ -278,7 +289,9 @@ void WEBVIEW_PANEL::OnWebViewLoaded( wxWebViewEvent& aEvt )
|
||||
|
||||
void WEBVIEW_PANEL::OnNewWindow( wxWebViewEvent& aEvt )
|
||||
{
|
||||
m_browser->LoadURL( aEvt.GetURL() );
|
||||
if( wxWebView* browser = GetWebView() )
|
||||
browser->LoadURL( aEvt.GetURL() );
|
||||
|
||||
aEvt.Veto(); // Prevent default behavior of opening a new window
|
||||
wxLogTrace( "webview", "New window requested for URL: %s", aEvt.GetURL() );
|
||||
wxLogTrace( "webview", "Target: %s", aEvt.GetTarget() );
|
||||
|
||||
@@ -23,12 +23,27 @@
|
||||
#include <wx/panel.h>
|
||||
#include <wx/timer.h>
|
||||
#include <wx/webview.h>
|
||||
#include <wx/weakref.h>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
|
||||
class TOOL_MANAGER;
|
||||
class TOOL_BASE;
|
||||
|
||||
namespace WEBVIEW_PANEL_DETAIL
|
||||
{
|
||||
template<typename T>
|
||||
T* GetLiveWindow( const wxWeakRef<T>& aWindowRef )
|
||||
{
|
||||
T* window = aWindowRef.get();
|
||||
|
||||
if( window && !window->IsBeingDeleted() )
|
||||
return window;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
} // namespace WEBVIEW_PANEL_DETAIL
|
||||
|
||||
class WEBVIEW_PANEL : public wxPanel
|
||||
{
|
||||
public:
|
||||
@@ -39,7 +54,7 @@ public:
|
||||
TOOL_MANAGER* aToolManager = nullptr, TOOL_BASE* aTool = nullptr );
|
||||
~WEBVIEW_PANEL() override;
|
||||
|
||||
wxWebView* GetWebView() const { return m_browser; }
|
||||
wxWebView* GetWebView() const { return WEBVIEW_PANEL_DETAIL::GetLiveWindow( m_browser ); }
|
||||
const wxString& GetBackend() const { return m_backend; }
|
||||
|
||||
void LoadURL( const wxString& url );
|
||||
@@ -53,7 +68,8 @@ public:
|
||||
|
||||
void RunScriptAsync( const wxString& aScript, void* aClientData = nullptr ) const
|
||||
{
|
||||
m_browser->RunScriptAsync( aScript, aClientData );
|
||||
if( wxWebView* browser = GetWebView() )
|
||||
browser->RunScriptAsync( aScript, aClientData );
|
||||
}
|
||||
|
||||
bool HasLoadError() const { return m_loadError; }
|
||||
@@ -76,7 +92,7 @@ private:
|
||||
bool m_handleExternalLinks;
|
||||
bool m_loadError;
|
||||
bool m_loadedEventBound;
|
||||
wxWebView* m_browser;
|
||||
wxWeakRef<wxWebView> m_browser;
|
||||
wxString m_backend;
|
||||
std::map<wxString, MESSAGE_HANDLER> m_msgHandlers;
|
||||
TOOL_MANAGER* m_toolManager;
|
||||
|
||||
Reference in New Issue
Block a user