Add wxWebViewWindowFeatures and event

This replaces the previously implemented wxWebViewWindowInfo.

It explicitly breaks the previous API to enable WebKitGTK
integration and to make the usage in application code less error prone.

A new event wxEVT_WEBVIEW_NEWWINDOW_FEATURES is added to allow
access to the window features and the child web view.
This commit is contained in:
Tobias Taschner 2023-03-23 15:28:24 +01:00
parent 8d0685ee08
commit e15a1ac18e
No known key found for this signature in database
GPG key ID: AE6ECD71294F87FD
10 changed files with 323 additions and 160 deletions

View file

@ -35,6 +35,7 @@ public:
wxWebViewWebKit();
#if wxUSE_WEBVIEW_WEBKIT2
wxWebViewWebKit(WebKitWebView* parentWebView, wxWebViewWebKit* parentWebViewCtrl);
wxWebViewWebKit(const wxWebViewConfiguration& config);
#endif

View file

@ -46,7 +46,7 @@ __CRT_UUID_DECL(ICoreWebView2WindowCloseRequestedEventHandler, 0x5c19e9e0,0x092f
WX_DECLARE_STRING_HASH_MAP(wxSharedPtr<wxWebViewHandler>, wxStringToWebHandlerMap);
class wxWebViewEdgeParentWindowInfo;
class wxWebViewWindowFeaturesEdge;
class wxWebViewEdgeImpl
{
@ -57,15 +57,15 @@ public:
bool Create();
wxWebViewEdge* CreateChildWebView(std::shared_ptr<wxWebViewEdgeParentWindowInfo> parentWindowInfo);
wxWebViewEdge* m_ctrl;
wxWebViewConfiguration m_config;
wxCOMPtr<ICoreWebView2Environment> m_webViewEnvironment;
wxCOMPtr<ICoreWebView2_2> m_webView;
wxCOMPtr<ICoreWebView2Controller> m_webViewController;
std::shared_ptr<wxWebViewEdgeParentWindowInfo> m_parentWindowInfo;
wxCOMPtr<ICoreWebView2NewWindowRequestedEventArgs> m_newWindowArgs;
wxCOMPtr<ICoreWebView2Deferral> m_newWindowDeferral;
bool m_initialized;
bool m_isBusy;

View file

@ -27,13 +27,12 @@
WX_DECLARE_STRING_HASH_MAP(wxSharedPtr<wxWebViewHandler>, wxStringToWebHandlerMap);
class wxWebViewWindowInfoWebKit;
class wxWebViewConfigurationImplWebKit;
class WXDLLIMPEXP_WEBVIEW wxWebViewWebKit : public wxWebView
{
public:
explicit wxWebViewWebKit(const wxWebViewConfiguration& config, wxWebViewWindowInfoWebKit* parentWindowInfo = nullptr);
explicit wxWebViewWebKit(const wxWebViewConfiguration& config, WX_NSObject request = nullptr);
bool Create(wxWindow *parent,
wxWindowID winID = wxID_ANY,
@ -109,7 +108,7 @@ private:
OSXWebViewPtr m_webView;
wxStringToWebHandlerMap m_handlers;
wxString m_customUserAgent;
wxWebViewWindowInfoWebKit* m_parentWindowInfo = nullptr;
WX_NSObject m_request;
WX_NSObject m_navigationDelegate;
WX_NSObject m_UIDelegate;

View file

@ -344,10 +344,14 @@ private:
wxDECLARE_ABSTRACT_CLASS(wxWebView);
};
class WXDLLIMPEXP_WEBVIEW wxWebViewWindowInfo
class WXDLLIMPEXP_WEBVIEW wxWebViewWindowFeatures
{
public:
virtual ~wxWebViewWindowInfo() = default;
wxWebViewWindowFeatures(wxWebView* childWebView);
virtual ~wxWebViewWindowFeatures();
wxWebView* GetChildWebView() const;
virtual wxPoint GetPosition() const = 0;
@ -361,10 +365,11 @@ public:
virtual bool ShouldDisplayScrollBars() const = 0;
virtual wxWebView* CreateChildWebView() = 0;
protected:
mutable bool m_childWebViewWasUsed;
std::unique_ptr<wxWebView> m_childWebView;
};
class WXDLLIMPEXP_WEBVIEW wxWebViewEvent : public wxNotifyEvent
{
public:
@ -385,7 +390,7 @@ public:
wxWebViewNavigationActionFlags GetNavigationAction() const { return m_actionFlags; }
const wxString& GetMessageHandler() const { return m_messageHandler; }
wxWebViewWindowInfo* GetTargetWindowInfo() const { return (wxWebViewWindowInfo*)m_clientData; }
wxWebViewWindowFeatures* GetTargetWindowFeatures() const { return (wxWebViewWindowFeatures*)m_clientData; }
virtual wxEvent* Clone() const override { return new wxWebViewEvent(*this); }
private:
@ -402,6 +407,7 @@ wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_WEBVIEW, wxEVT_WEBVIEW_NAVIGATED, wxWebVie
wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_WEBVIEW, wxEVT_WEBVIEW_LOADED, wxWebViewEvent );
wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_WEBVIEW, wxEVT_WEBVIEW_ERROR, wxWebViewEvent );
wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_WEBVIEW, wxEVT_WEBVIEW_NEWWINDOW, wxWebViewEvent );
wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_WEBVIEW, wxEVT_WEBVIEW_NEWWINDOW_FEATURES, wxWebViewEvent );
wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_WEBVIEW, wxEVT_WEBVIEW_WINDOW_CLOSE_REQUESTED, wxWebViewEvent);
wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_WEBVIEW, wxEVT_WEBVIEW_TITLE_CHANGED, wxWebViewEvent );
wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_WEBVIEW, wxEVT_WEBVIEW_FULLSCREEN_CHANGED, wxWebViewEvent);

View file

@ -163,19 +163,63 @@ enum wxWebViewIE_EmulationLevel
/**
A class describing the window information for a new child window.
This class is available via wxWebViewEvent::GetTargetWindowInfo()
while handling @c wxEVT_WEBVIEW_NEWWINDOW.
If the new window should be created use CreateChildWebView() while
processing the event. This will ensure that the new web view is
accessible from JavaScript within the originating wxWebView.
An object of this class can be obtained using wxWebViewEvent::GetTargetWindowFeatures()
while handling @c wxEVT_WEBVIEW_NEWWINDOW_FEATURES.
If a @c wxEVT_WEBVIEW_NEWWINDOW is not vetoed, a @c wxEVT_WEBVIEW_NEWWINDOW_FEATURES
event will be sent to the application. The application can then create a new
window and call wxWebViewEvent::GetTargetWindowInfo() to get this class providing
information about the new window. A new child web view will be available
via GetChildWebView(). The application can then place the child web view into
the new window by calling wxWebView::Create() on the child web view.
Sample JavaScript opening a new window:
@code
window.open("http://www.wxwidgets.org", "newWindow", "width=400,height=400");
@endcode
Sample C++ code handling a new window request:
@code
// Bind new window handler
m_webView->Bind(wxEVT_WEBVIEW_NEWWINDOW, [](wxWebViewEvent& evt) {
if (evt.GetURL() == "http://badwebsite.com")
evt.Veto(); // Disallow new window for badwebsite.com
else
evt.Skip(); // Allow new window for all other websites
});
// Bind new window features handler
m_webView->Bind(wxEVT_WEBVIEW_NEWWINDOW_FEATURES, [](wxWebViewEvent& evt) {
// Get target window features
wxWebViewWindowFeatures* features = evt.GetTargetWindowFeatures();
// Create a top level window for the child web view
wxWindow* win = new wxWindow(this, wxID_ANY, features->GetPosition(), features->GetSize());
wxSizer* sizer = new wxBoxSizer(wxVERTICAL);
win->SetSizer(sizer);
// Get the child web view
wxWebView* childWebView = features->GetChildWebView();
// Place the child web view into the window
childWebView->Create(win, wxID_ANY);
sizer->Add(childWebView, 1, wxEXPAND);
}
@endcode
@since 3.3.0
*/
class WXDLLIMPEXP_WEBVIEW wxWebViewWindowInfo
class WXDLLIMPEXP_WEBVIEW wxWebViewWindowFeatures
{
public:
/**
Get the child web view for the target window.
This is available in the event handler for @c wxEVT_WEBVIEW_NEWWINDOW_FEATURES
and wxWebView::Create() @b must be called on the child web view directly.
The requested URL will be loaded automatically in the child web view.
*/
wxWebView* GetChildWebView();
/**
Returns the position of the new window if specified by
a @c window.open() call.
@ -211,39 +255,6 @@ public:
scroll bars as specified by a @c window.open() call.
*/
virtual bool ShouldDisplayScrollBars() const = 0;
/**
Create a new child web view for the target window.
This @b must be created in the event handler for @c wxEVT_WEBVIEW_NEWWINDOW
and wxWebView::Create() @b must be called directly.
The requested URL will be loaded automatically in the new child web view.
Sample C++ code handling the event:
@code
// Bind handler
m_webView->Bind(wxEVT_WEBVIEW_NEWWINDOW, [](wxWebViewEvent& evt) {
// Get target window info
wxWebViewWindowInfo* info = evt.GetTargetWindowInfo();
// Create a top level window for the child web view
wxWindow* win = new wxWindow(this, wxID_ANY, info->GetPosition(), info->GetSize());
wxSizer* sizer = new wxBoxSizer(wxVERTICAL);
// Create the child web view
wxWebView* childWebView = info->CreateChildWebView();
// Place the child web view into the window
childWebView->Create(win, wxID_ANY);
sizer->Add(childWebView, 1, wxEXPAND);
});
@endcode
Sample JavaScript opening a new window:
@code
window.open("http://www.wxwidgets.org", "newWindow", "width=400,height=400");
@endcode
*/
virtual wxWebView* CreateChildWebView() = 0;
};
/**
@ -912,7 +923,12 @@ public:
Process a @c wxEVT_WEBVIEW_NEWWINDOW event, generated when a new
window is created. You must handle this event if you want anything to
happen, for example to load the page in a new window or tab. For usage
details see wxWebViewWindowInfo::CreateChildWebView().
details see wxWebViewWindowFeatures.
@event{EVT_WEBVIEW_NEWWINDOW_FEATURES(id, func)}
Process a @c wxEVT_WEBVIEW_NEWWINDOW_FEATURES event, generated when
window features are available for the new window. For usage
details see wxWebViewWindowFeatures.
only available in wxWidgets 3.3.0 or later.
@event{wxEVT_WEBVIEW_WINDOW_CLOSE_REQUESTED(id, func)}
Process a @c wxEVT_WEBVIEW_WINDOW_CLOSE_REQUESTED event, generated when
a window is requested to be closed.
@ -1784,7 +1800,12 @@ public:
Process a @c wxEVT_WEBVIEW_NEWWINDOW event, generated when a new
window is created. You must handle this event if you want anything to
happen, for example to load the page in a new window or tab. For usage
details see wxWebViewWindowInfo::CreateChildWebView().
details see wxWebViewWindowFeatures.
@event{EVT_WEBVIEW_NEWWINDOW_FEATURES(id, func)}
Process a @c wxEVT_WEBVIEW_NEWWINDOW_FEATURES event, generated when
window features are available for the new window. For usage
details see wxWebViewWindowFeatures.
only available in wxWidgets 3.3.0 or later.
@event{wxEVT_WEBVIEW_WINDOW_CLOSE_REQUESTED(id, func)}
Process a @c wxEVT_WEBVIEW_WINDOW_CLOSE_REQUESTED event, generated when
a window is requested to be closed.
@ -1852,14 +1873,14 @@ public:
/**
Get information about the target window. Only valid for events of type
@c wxEVT_WEBVIEW_NEWWINDOW
@c wxEVT_WEBVIEW_NEWWINDOW_FEATURES
@note This is only available with the macOS and the Edge backend.
@note This function is not implemented and always returns @NULL when using WebKit1 or Internet Explorer backend.
@see wxWebViewWindowInfo
@see wxWebViewWindowFeatures
@since 3.3.0
*/
wxWebViewWindowInfo* GetTargetWindowInfo() const;
wxWebViewWindowFeatures* GetTargetWindowFeatures() const;
/**
Returns true the script execution failed. Only valid for events of type
@ -1886,6 +1907,7 @@ wxEventType wxEVT_WEBVIEW_NAVIGATED;
wxEventType wxEVT_WEBVIEW_LOADED;
wxEventType wxEVT_WEBVIEW_ERROR;
wxEventType wxEVT_WEBVIEW_NEWWINDOW;
wxEventType wxEVT_WEBVIEW_NEWWINDOW_FEATURES;
wxEventType wxEVT_WEBVIEW_TITLE_CHANGED;
wxEventType wxEVT_WEBVIEW_FULLSCREEN_CHANGED;
wxEventType wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED;

View file

@ -98,7 +98,7 @@ private:
class WebFrame : public wxFrame
{
public:
WebFrame(const wxString& url, bool isMain = true, wxWebViewWindowInfo* newWindowInfo = nullptr);
WebFrame(const wxString& url, bool isMain = true, wxWebViewWindowFeatures* windowFeatures = nullptr);
virtual ~WebFrame();
void UpdateState();
@ -114,6 +114,7 @@ public:
void OnNavigationComplete(wxWebViewEvent& evt);
void OnDocumentLoaded(wxWebViewEvent& evt);
void OnNewWindow(wxWebViewEvent& evt);
void OnNewWindowFeatures(wxWebViewEvent& evt);
void OnTitleChanged(wxWebViewEvent& evt);
void OnFullScreenChanged(wxWebViewEvent& evt);
void OnScriptMessage(wxWebViewEvent& evt);
@ -334,7 +335,7 @@ bool WebApp::OnInit()
return true;
}
WebFrame::WebFrame(const wxString& url, bool isMain, wxWebViewWindowInfo* newWindowInfo) :
WebFrame::WebFrame(const wxString& url, bool isMain, wxWebViewWindowFeatures* windowFeatures):
wxFrame(nullptr, wxID_ANY, "wxWebView Sample")
{
m_isMainFrame = isMain;
@ -420,7 +421,7 @@ WebFrame::WebFrame(const wxString& url, bool isMain, wxWebViewWindowInfo* newWin
}
#endif
// Create the webview
m_browser = (newWindowInfo) ? newWindowInfo->CreateChildWebView() : wxWebView::New();
m_browser = (windowFeatures) ? windowFeatures->GetChildWebView() : wxWebView::New();
#ifdef __WXMAC__
if (m_isMainFrame)
{
@ -433,18 +434,6 @@ WebFrame::WebFrame(const wxString& url, bool isMain, wxWebViewWindowInfo* newWin
m_browser->Create(this, wxID_ANY, url, wxDefaultPosition, wxDefaultSize);
topsizer->Add(m_browser, wxSizerFlags().Expand().Proportion(1));
if (newWindowInfo)
{
if (newWindowInfo->GetSize().IsFullySpecified())
SetSize(FromDIP(newWindowInfo->GetSize()));
if (newWindowInfo->GetPosition().IsFullySpecified())
Move(FromDIP(newWindowInfo->GetPosition()));
if (!newWindowInfo->ShouldDisplayToolBar())
m_toolbar->Hide();
if (!newWindowInfo->ShouldDisplayMenuBar())
SetMenuBar(nullptr);
}
if (m_isMainFrame)
{
// Log backend information
@ -470,6 +459,18 @@ WebFrame::WebFrame(const wxString& url, bool isMain, wxWebViewWindowInfo* newWin
//Set a more sensible size for web browsing
SetSize(FromDIP(wxSize(800, 600)));
if (windowFeatures)
{
if (windowFeatures->GetSize().IsFullySpecified())
SetSize(FromDIP(windowFeatures->GetSize()));
if (windowFeatures->GetPosition().IsFullySpecified())
Move(FromDIP(windowFeatures->GetPosition()));
if (!windowFeatures->ShouldDisplayToolBar())
m_toolbar->Hide();
if (!windowFeatures->ShouldDisplayMenuBar())
SetMenuBar(nullptr);
}
// Create the Tools menu
m_tools_menu = new wxMenu();
wxMenuItem* print = m_tools_menu->Append(wxID_ANY , _("Print"));
@ -602,6 +603,7 @@ WebFrame::WebFrame(const wxString& url, bool isMain, wxWebViewWindowInfo* newWin
Bind(wxEVT_WEBVIEW_LOADED, &WebFrame::OnDocumentLoaded, this, m_browser->GetId());
Bind(wxEVT_WEBVIEW_ERROR, &WebFrame::OnError, this, m_browser->GetId());
Bind(wxEVT_WEBVIEW_NEWWINDOW, &WebFrame::OnNewWindow, this, m_browser->GetId());
Bind(wxEVT_WEBVIEW_NEWWINDOW_FEATURES, &WebFrame::OnNewWindowFeatures, this, m_browser->GetId());
Bind(wxEVT_WEBVIEW_TITLE_CHANGED, &WebFrame::OnTitleChanged, this, m_browser->GetId());
Bind(wxEVT_WEBVIEW_FULLSCREEN_CHANGED, &WebFrame::OnFullScreenChanged, this, m_browser->GetId());
Bind(wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED, &WebFrame::OnScriptMessage, this, m_browser->GetId());
@ -973,24 +975,41 @@ void WebFrame::OnNewWindow(wxWebViewEvent& evt)
}
wxLogMessage("%s", "New window; url='" + evt.GetURL() + "'" + flag);
wxWebViewWindowInfo* info = evt.GetTargetWindowInfo();
if (info)
{
wxLogMessage(" New window info: Position=%d,%d Size=%d,%d",
info->GetPosition().x, info->GetPosition().y,
info->GetSize().GetWidth(), info->GetSize().GetHeight());
}
//If we handle new window events then create a new frame
if (m_tools_handle_new_window->IsChecked())
{
WebFrame* newFrame = new WebFrame(evt.GetURL(), false, info);
newFrame->Show();
}
if (!m_tools_handle_new_window->IsChecked())
evt.Veto();
UpdateState();
}
void WebFrame::OnNewWindowFeatures(wxWebViewEvent &evt)
{
wxWebViewWindowFeatures* features = evt.GetTargetWindowFeatures();
if (!features)
return;
wxString featureDescription;
if (features->GetPosition().IsFullySpecified())
featureDescription += wxString::Format(" Position: %d, %d; ", features->GetPosition().x, features->GetPosition().y);
if (features->GetSize().IsFullySpecified())
featureDescription += wxString::Format(" Size: %d, %d; ", features->GetSize().x, features->GetSize().y);
if (features->ShouldDisplayMenuBar())
featureDescription += " MenuBar; ";
if (features->ShouldDisplayStatusBar())
featureDescription += " StatusBar; ";
if (features->ShouldDisplayToolBar())
featureDescription += " ToolBar; ";
if (features->ShouldDisplayScrollBars())
featureDescription += " ScrollBars; ";
wxLogMessage("Window features of child webview are available." + featureDescription);
// Create child frame with the features specified by window.open() call
WebFrame* newFrame = new WebFrame(evt.GetURL(), false, features);
newFrame->Show();
}
void WebFrame::OnTitleChanged(wxWebViewEvent& evt)
{
SetTitle(evt.GetString());

View file

@ -50,6 +50,7 @@ wxDEFINE_EVENT( wxEVT_WEBVIEW_NAVIGATED, wxWebViewEvent );
wxDEFINE_EVENT( wxEVT_WEBVIEW_LOADED, wxWebViewEvent );
wxDEFINE_EVENT( wxEVT_WEBVIEW_ERROR, wxWebViewEvent );
wxDEFINE_EVENT( wxEVT_WEBVIEW_NEWWINDOW, wxWebViewEvent );
wxDEFINE_EVENT( wxEVT_WEBVIEW_NEWWINDOW_FEATURES, wxWebViewEvent );
wxDEFINE_EVENT( wxEVT_WEBVIEW_WINDOW_CLOSE_REQUESTED, wxWebViewEvent );
wxDEFINE_EVENT( wxEVT_WEBVIEW_TITLE_CHANGED, wxWebViewEvent );
wxDEFINE_EVENT( wxEVT_WEBVIEW_FULLSCREEN_CHANGED, wxWebViewEvent);
@ -86,6 +87,24 @@ wxString wxWebViewConfiguration::GetDataPath() const
return m_impl->GetDataPath();
}
// wxWebViewWindowFeatures
wxWebViewWindowFeatures::wxWebViewWindowFeatures(wxWebView * childWebView):
m_childWebViewWasUsed(false),
m_childWebView(childWebView)
{ }
wxWebViewWindowFeatures::~wxWebViewWindowFeatures()
{
if (m_childWebViewWasUsed)
m_childWebView.release();
}
wxWebView *wxWebViewWindowFeatures::GetChildWebView() const
{
m_childWebViewWasUsed = true;
return m_childWebView.get();
}
// wxWebViewHandlerRequest
wxString wxWebViewHandlerRequest::GetDataString(const wxMBConv& conv) const
{

View file

@ -88,6 +88,62 @@ bool wxGetStringFromJSResult(WebKitJavascriptResult* js_result, wxString* output
return true;
}
//-----------------------------------------------------------------------------
// wxWebViewWindowFeaturesWebKit
//-----------------------------------------------------------------------------
class wxWebViewWindowFeaturesWebKit : public wxWebViewWindowFeatures
{
public:
wxWebViewWindowFeaturesWebKit(wxWebView* webViewCtrl, WebKitWebView *web_view):
wxWebViewWindowFeatures(webViewCtrl)
{
m_properties = webkit_web_view_get_window_properties(web_view);
webkit_window_properties_get_geometry(m_properties, &m_geometry);
// Treat 0 as -1 to indicate that the value is not set
if (m_geometry.width == 0)
m_geometry.width = -1;
if (m_geometry.height == 0)
m_geometry.height = -1;
if (m_geometry.x == 0)
m_geometry.x = -1;
if (m_geometry.y == 0)
m_geometry.y = -1;
}
virtual wxPoint GetPosition() const override
{
return wxPoint(m_geometry.x, m_geometry.y);
}
virtual wxSize GetSize() const override
{
return wxSize(m_geometry.width, m_geometry.height);
}
virtual bool ShouldDisplayMenuBar() const override
{
return webkit_window_properties_get_toolbar_visible(m_properties);
}
virtual bool ShouldDisplayStatusBar() const override
{
return webkit_window_properties_get_statusbar_visible(m_properties);
}
virtual bool ShouldDisplayToolBar() const override
{
return webkit_window_properties_get_toolbar_visible(m_properties);
}
virtual bool ShouldDisplayScrollBars() const override
{
return webkit_window_properties_get_scrollbars_visible(m_properties);
}
GdkRectangle m_geometry;
WebKitWindowProperties *m_properties;
};
// ----------------------------------------------------------------------------
// GTK callbacks
// ----------------------------------------------------------------------------
@ -378,6 +434,27 @@ static void wxgtk_webview_webkit_close (WebKitWebView *WXUNUSED(web_view),
webKitCtrl->HandleWindowEvent(event);
}
class wxReadyToShowParams
{
public:
wxWebViewWebKit* childWebView;
wxWebViewWebKit* parentWebView;
};
static void wxgtk_webview_webkit_ready_to_show (WebKitWebView *web_view,
wxReadyToShowParams *params)
{
wxWebViewWindowFeaturesWebKit features(params->childWebView, web_view);
wxWebViewEvent event(wxEVT_WEBVIEW_NEWWINDOW_FEATURES,
params->parentWebView->GetId(),
params->childWebView->GetCurrentURL(),
"");
event.SetEventObject(params->parentWebView);
event.SetClientData(&features);
params->parentWebView->HandleWindowEvent(event);
delete params;
}
static gboolean
wxgtk_webview_webkit_decide_policy(WebKitWebView *web_view,
WebKitPolicyDecision *decision,
@ -478,13 +555,25 @@ wxgtk_webview_webkit_context_menu(WebKitWebView *,
static WebKitWebView*
wxgtk_webview_webkit_create_webview(WebKitWebView *web_view,
WebKitNavigationAction *,
WebKitNavigationAction *navigation_action,
wxWebViewWebKit *webKitCtrl)
{
//As we do not know the uri being loaded at this point allow the load to
//continue and catch it in navigation-policy-decision-requested
webKitCtrl->m_creating = true;
return web_view;
auto request = webkit_navigation_action_get_request(navigation_action);
wxString url = wxString::FromUTF8(webkit_uri_request_get_uri(request));
wxWebViewEvent event(wxEVT_WEBVIEW_NEWWINDOW,
webKitCtrl->GetId(),
url,
"");
event.SetEventObject(webKitCtrl);
webKitCtrl->HandleWindowEvent(event);
if ( event.IsAllowed() )
{
wxWebView* childWebView = new wxWebViewWebKit(web_view, webKitCtrl);
return (WebKitWebView*)childWebView->GetNativeBackend();
}
else
return nullptr;
}
static void
@ -738,6 +827,21 @@ wxWebViewWebKit::wxWebViewWebKit():
m_extension = nullptr;
}
wxWebViewWebKit::wxWebViewWebKit(WebKitWebView* parentWebView, wxWebViewWebKit* parentWebViewCtrl):
m_config(parentWebViewCtrl->m_config)
{
m_web_view = (WebKitWebView*) webkit_web_view_new_with_related_view(parentWebView);
m_dbusServer = nullptr;
m_extension = nullptr;
wxReadyToShowParams* params = new wxReadyToShowParams();
params->childWebView = this;
params->parentWebView = parentWebViewCtrl;
g_signal_connect(m_web_view, "ready-to-show",
G_CALLBACK(wxgtk_webview_webkit_ready_to_show), params);
}
wxWebViewWebKit::wxWebViewWebKit(const wxWebViewConfiguration &config):
m_config(config)
{
@ -754,7 +858,6 @@ bool wxWebViewWebKit::Create(wxWindow *parent,
long style,
const wxString& name)
{
m_web_view = nullptr;
m_dbusServer = nullptr;
m_extension = nullptr;
m_busy = false;
@ -762,6 +865,8 @@ bool wxWebViewWebKit::Create(wxWindow *parent,
m_creating = false;
FindClear();
bool isChildWebView = m_web_view != nullptr;
// We currently unconditionally impose scrolling in both directions as it's
// necessary to show arbitrary pages.
style |= wxHSCROLL | wxVSCROLL;
@ -779,6 +884,7 @@ bool wxWebViewWebKit::Create(wxWindow *parent,
G_CALLBACK(wxgtk_initialize_web_extensions),
m_dbusServer);
if (!isChildWebView)
#ifdef wxHAVE_WEBKIT_WEBSITE_DATA_MANAGER
m_web_view = WEBKIT_WEB_VIEW(webkit_web_view_new_with_context(WEBKIT_WEB_CONTEXT(m_config.GetNativeConfiguration())));
#else
@ -825,7 +931,8 @@ bool wxWebViewWebKit::Create(wxWindow *parent,
PostCreation(size);
/* Open a webpage */
webkit_web_view_load_uri(m_web_view, url.utf8_str());
if (!isChildWebView)
webkit_web_view_load_uri(m_web_view, url.utf8_str());
// last to avoid getting signal too early
g_signal_connect(m_web_view, "load-changed",

View file

@ -320,13 +320,13 @@ public:
wxString wxWebViewConfigurationImplEdge::ms_browserExecutableDir;
// wxWebViewNewWindowInfoEdge
// wxWebViewWindowFeaturesEdge
class wxWebViewNewWindowInfoEdge : public wxWebViewWindowInfo
class wxWebViewWindowFeaturesEdge : public wxWebViewWindowFeatures
{
public:
wxWebViewNewWindowInfoEdge(wxWebViewEdgeImpl* impl, ICoreWebView2NewWindowRequestedEventArgs* args):
m_impl(impl),
wxWebViewWindowFeaturesEdge(wxWebView* childWebView, ICoreWebView2NewWindowRequestedEventArgs* args):
wxWebViewWindowFeatures(childWebView),
m_args(args)
{
m_args->get_WindowFeatures(&m_windowFeatures);
@ -395,36 +395,11 @@ public:
return true;
}
virtual wxWebView* CreateChildWebView() override
{
return m_impl->CreateChildWebView(
std::make_shared<wxWebViewEdgeParentWindowInfo>(m_args));
}
private:
wxWebViewEdgeImpl* m_impl;
wxCOMPtr<ICoreWebView2NewWindowRequestedEventArgs> m_args;
wxCOMPtr<ICoreWebView2WindowFeatures> m_windowFeatures;
};
class wxWebViewEdgeParentWindowInfo
{
public:
wxWebViewEdgeParentWindowInfo(ICoreWebView2NewWindowRequestedEventArgs* args):
m_args(args)
{
HRESULT hr = m_args->GetDeferral(&m_deferral);
if (FAILED(hr))
wxLogApiError("GetDeferral", hr);
}
virtual ~wxWebViewEdgeParentWindowInfo() = default;
wxCOMPtr<ICoreWebView2NewWindowRequestedEventArgs> m_args;
wxCOMPtr<ICoreWebView2Deferral> m_deferral;
};
#define wxWEBVIEW_EDGE_EVENT_HANDLER_METHOD \
m_inEventCallback = true; \
wxON_BLOCK_EXIT_SET(m_inEventCallback, false);
@ -476,13 +451,6 @@ bool wxWebViewEdgeImpl::Create()
CreateOrGetEnvironment(this);
}
wxWebViewEdge* wxWebViewEdgeImpl::CreateChildWebView(std::shared_ptr<wxWebViewEdgeParentWindowInfo> parentWindowInfo)
{
wxWebViewEdge* childWebView = new wxWebViewEdge(m_config);
childWebView->m_impl->m_parentWindowInfo = parentWindowInfo;
return childWebView;
}
void wxWebViewEdgeImpl::EnvironmentAvailable(ICoreWebView2Environment* environment)
{
environment->QueryInterface(IID_PPV_ARGS(&m_webViewEnvironment));
@ -684,11 +652,24 @@ HRESULT wxWebViewEdgeImpl::OnNewWindowRequested(ICoreWebView2* WXUNUSED(sender),
if (SUCCEEDED(args->get_IsUserInitiated(&isUserInitiated)) && isUserInitiated)
navFlags = wxWEBVIEW_NAV_ACTION_USER;
wxWebViewNewWindowInfoEdge windowInfo(this, args);
wxWebViewEvent evt(wxEVT_WEBVIEW_NEWWINDOW, m_ctrl->GetId(), evtURL, wxString(), navFlags, "");
evt.SetClientData(&windowInfo);
m_ctrl->HandleWindowEvent(evt);
wxWebViewEvent newWindowEvent(wxEVT_WEBVIEW_NEWWINDOW, m_ctrl->GetId(), evtURL, wxString(), navFlags, "");
m_ctrl->HandleWindowEvent(newWindowEvent);
args->put_Handled(true);
if (newWindowEvent.IsAllowed())
{
wxWebViewEdge* childWebView = new wxWebViewEdge(m_config);
childWebView->m_impl->m_newWindowArgs = args;
HRESULT hr = args->GetDeferral(&childWebView->m_impl->m_newWindowDeferral);
if (FAILED(hr))
wxLogApiError("GetDeferral", hr);
wxWebViewWindowFeaturesEdge windowFeatures(childWebView, args);
wxWebViewEvent featuresEvent(wxEVT_WEBVIEW_NEWWINDOW_FEATURES, m_ctrl->GetId(), evtURL, wxString(), navFlags, "");
featuresEvent.SetClientData(&windowFeatures);
m_ctrl->HandleWindowEvent(featuresEvent);
}
return S_OK;
}
@ -916,13 +897,14 @@ HRESULT wxWebViewEdgeImpl::OnWebViewCreated(HRESULT result, ICoreWebView2Control
m_pendingUserScripts.clear();
}
if (m_parentWindowInfo)
if (m_newWindowArgs)
{
if (FAILED(m_parentWindowInfo->m_args->put_NewWindow(baseWebView)))
if (FAILED(m_newWindowArgs->put_NewWindow(baseWebView)))
SendErrorEventForAPI("WebView2::WebViewCreated (put_NewWindow)", hr);
if (FAILED(m_parentWindowInfo->m_deferral->Complete()))
if (FAILED(m_newWindowDeferral->Complete()))
SendErrorEventForAPI("WebView2::WebViewCreated (Complete)", hr);
m_parentWindowInfo.reset();
m_newWindowArgs.reset();
m_newWindowDeferral.reset();
return S_OK;
}

View file

@ -140,15 +140,17 @@ wxWebViewConfiguration wxWebViewFactoryWebKit::CreateConfiguration()
}
//-----------------------------------------------------------------------------
// wxWebViewWindowInfoWebKit
// wxWebViewWindowFeaturesWebKit
//-----------------------------------------------------------------------------
class wxWebViewWindowInfoWebKit: public wxWebViewWindowInfo
class wxWebViewWindowFeaturesWebKit: public wxWebViewWindowFeatures
{
public:
wxWebViewWindowInfoWebKit(WKWebViewConfiguration* configuration,
WKNavigationAction* navigationAction,
WKWindowFeatures* windowFeatures):
wxWebViewWindowFeaturesWebKit(wxWebView* childWebView,
WKWebViewConfiguration* configuration,
WKNavigationAction* navigationAction,
WKWindowFeatures* windowFeatures):
wxWebViewWindowFeatures(childWebView),
m_configuration(configuration),
m_navigationAction(navigationAction),
m_windowFeatures(windowFeatures)
@ -206,14 +208,6 @@ public:
return true;
}
virtual wxWebView* CreateChildWebView() override
{
m_childWebView = new wxWebViewWebKit(wxWebViewConfiguration(wxWebViewBackendWebKit,
new wxWebViewConfigurationImplWebKit(m_configuration)), this);
return m_childWebView;
}
wxWebView* m_childWebView = nullptr;
WKWebViewConfiguration* m_configuration;
WKNavigationAction* m_navigationAction;
WKWindowFeatures* m_windowFeatures;
@ -224,9 +218,9 @@ public:
// creation/destruction
// ----------------------------------------------------------------------------
wxWebViewWebKit::wxWebViewWebKit(const wxWebViewConfiguration& config, wxWebViewWindowInfoWebKit* parentWindowInfo):
wxWebViewWebKit::wxWebViewWebKit(const wxWebViewConfiguration& config, WX_NSObject request):
m_configuration(config),
m_parentWindowInfo(parentWindowInfo)
m_request(request)
{
}
@ -240,10 +234,12 @@ bool wxWebViewWebKit::Create(wxWindow *parent,
DontCreatePeer();
wxControl::Create(parent, winID, pos, size, style, wxDefaultValidator, name);
bool isChildWebView = m_request != nil;
NSRect r = wxOSXGetFrameForControl( this, pos , size ) ;
WKWebViewConfiguration* webViewConfig = (WKWebViewConfiguration*) m_configuration.GetNativeConfiguration();
if (!m_handlers.empty() && !m_parentWindowInfo)
if (!m_handlers.empty() && !isChildWebView)
{
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_13
if ( WX_IS_MACOS_AVAILABLE(10, 13) )
@ -285,7 +281,7 @@ bool wxWebViewWebKit::Create(wxWindow *parent,
[m_webView setUIDelegate:uiDelegate];
if (!m_parentWindowInfo)
if (!isChildWebView)
{
// Implement javascript fullscreen interface with user script and message handler
AddUserScript("\
@ -326,8 +322,8 @@ bool wxWebViewWebKit::Create(wxWindow *parent,
m_UIDelegate = uiDelegate;
if (m_parentWindowInfo)
[m_webView loadRequest:m_parentWindowInfo->m_navigationAction.request];
if (m_request)
[m_webView loadRequest:(NSURLRequest*)m_request];
else
LoadURL(strURL);
return true;
@ -1126,19 +1122,31 @@ WX_API_AVAILABLE_MACOS(10, 13)
wxWEBVIEW_NAV_ACTION_USER :
wxWEBVIEW_NAV_ACTION_OTHER;
wxWebViewWindowInfoWebKit windowInfo(configuration, navigationAction, windowFeatures);
wxWebViewEvent event(wxEVT_WEBVIEW_NEWWINDOW,
wxWebViewEvent newWinEvent(wxEVT_WEBVIEW_NEWWINDOW,
webKitWindow->GetId(),
wxCFStringRef::AsString( navigationAction.request.URL.absoluteString ),
"", navFlags);
event.SetClientData(&windowInfo);
if (webKitWindow && webKitWindow->GetEventHandler())
webKitWindow->GetEventHandler()->ProcessEvent(event);
webKitWindow->GetEventHandler()->ProcessEvent(newWinEvent);
if (windowInfo.m_childWebView)
return (WKWebView*) windowInfo.m_childWebView->GetNativeBackend();
if (newWinEvent.IsAllowed())
{
wxWebView* childWebView = new wxWebViewWebKit(wxWebViewConfiguration(wxWebViewBackendWebKit,
new wxWebViewConfigurationImplWebKit(configuration)), navigationAction.request);
wxWebViewWindowFeaturesWebKit childWindowFeatures(childWebView, configuration, navigationAction, windowFeatures);
wxWebViewEvent featuresEvent(wxEVT_WEBVIEW_NEWWINDOW_FEATURES,
webKitWindow->GetId(),
wxCFStringRef::AsString( navigationAction.request.URL.absoluteString ),
"", navFlags);
featuresEvent.SetClientData(&childWindowFeatures);
if (webKitWindow && webKitWindow->GetEventHandler())
webKitWindow->GetEventHandler()->ProcessEvent(featuresEvent);
return (WKWebView*) childWebView->GetNativeBackend();
}
else
return nil;
}