Add wxWebView child window handling

Add new class wxWebViewWindowInfo:
This new class returned by wxWebViewEvent::GetTargetWindowInfo() allows
to get information about the window that is about to be opened and to
set the window that will be used to display the content.
This commit is contained in:
Tobias Taschner 2023-03-07 21:08:08 +01:00
parent 45d5de6a26
commit 01ee3942f8
No known key found for this signature in database
GPG key ID: AE6ECD71294F87FD
8 changed files with 483 additions and 81 deletions

View file

@ -45,6 +45,8 @@ __CRT_UUID_DECL(ICoreWebView2Settings3, 0xfdb5ab74, 0xaf33, 0x4854, 0x84,0xf0,0x
WX_DECLARE_STRING_HASH_MAP(wxSharedPtr<wxWebViewHandler>, wxStringToWebHandlerMap);
class wxWebViewEdgeParentWindowInfo;
class wxWebViewEdgeImpl
{
public:
@ -53,12 +55,15 @@ public:
bool Create();
wxWebViewEdge* CreateChildWebView(std::shared_ptr<wxWebViewEdgeParentWindowInfo> parentWindowInfo);
wxWebViewEdge* m_ctrl;
wxCOMPtr<ICoreWebView2Environment> m_webViewEnvironment;
wxCOMPtr<ICoreWebView2_2> m_webView;
wxCOMPtr<ICoreWebView2Controller> m_webViewController;
wxCOMPtr<ICoreWebView2EnvironmentOptions> m_webViewEnvironmentOptions;
std::shared_ptr<wxWebViewEdgeParentWindowInfo> m_parentWindowInfo;
bool m_initialized;
bool m_isBusy;

View file

@ -120,6 +120,8 @@ private:
void OnTopLevelParentIconized(wxIconizeEvent& event);
wxDECLARE_DYNAMIC_CLASS(wxWebViewEdge);
friend class wxWebViewEdgeImpl;
};
class WXDLLIMPEXP_WEBVIEW wxWebViewFactoryEdge : public wxWebViewFactory

View file

@ -27,12 +27,18 @@
WX_DECLARE_STRING_HASH_MAP(wxSharedPtr<wxWebViewHandler>, wxStringToWebHandlerMap);
class wxWebViewWindowInfoWebKit;
class WXDLLIMPEXP_WEBVIEW wxWebViewWebKit : public wxWebView
{
public:
wxDECLARE_DYNAMIC_CLASS(wxWebViewWebKit);
wxWebViewWebKit() { Init(); }
wxWebViewWebKit(wxWebViewWindowInfoWebKit* parentWindowInfo = nullptr)
{
m_parentWindowInfo = parentWindowInfo;
Init();
}
wxWebViewWebKit(wxWindow *parent,
wxWindowID winID = wxID_ANY,
const wxString& strURL = wxASCII_STR(wxWebViewDefaultURLStr),
@ -118,6 +124,7 @@ private:
OSXWebViewPtr m_webView;
wxStringToWebHandlerMap m_handlers;
wxString m_customUserAgent;
wxWebViewWindowInfoWebKit* m_parentWindowInfo = nullptr;
WX_NSObject m_navigationDelegate;
WX_NSObject m_UIDelegate;

View file

@ -323,6 +323,27 @@ private:
wxDECLARE_ABSTRACT_CLASS(wxWebView);
};
class WXDLLIMPEXP_WEBVIEW wxWebViewWindowInfo
{
public:
virtual ~wxWebViewWindowInfo() = default;
virtual wxPoint GetPosition() const = 0;
virtual wxSize GetSize() const = 0;
virtual bool ShouldDisplayMenuBar() const = 0;
virtual bool ShouldDisplayStatusBar() const = 0;
virtual bool ShouldDisplayToolBar() const = 0;
virtual bool ShouldDisplayScrollBars() const = 0;
virtual wxWebView* CreateChildWebView() = 0;
};
class WXDLLIMPEXP_WEBVIEW wxWebViewEvent : public wxNotifyEvent
{
public:
@ -343,6 +364,7 @@ public:
wxWebViewNavigationActionFlags GetNavigationAction() const { return m_actionFlags; }
const wxString& GetMessageHandler() const { return m_messageHandler; }
wxWebViewWindowInfo* GetTargetWindowInfo() const { return (wxWebViewWindowInfo*)m_clientData; }
virtual wxEvent* Clone() const override { return new wxWebViewEvent(*this); }
private:

View file

@ -161,6 +161,91 @@ enum wxWebViewIE_EmulationLevel
wxWEBVIEWIE_EMU_IE11_FORCE = 11001
};
/**
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 java script within the originating wxWebView.
@since 3.3.0
*/
class WXDLLIMPEXP_WEBVIEW wxWebViewWindowInfo
{
public:
/**
Returns the position of the new window if specified by
a @c window.open() call.
*/
virtual wxPoint GetPosition() const = 0;
/**
Returns the size of the new window if specified by
a @c window.open() call.
*/
virtual wxSize GetSize() const = 0;
/**
Returns @true if the target window is expected to display
a menu bar as specified by a @c window.open() call.
*/
virtual bool ShouldDisplayMenuBar() const = 0;
/**
Returns @true if the target window is expected to display
a status bar as specified by a @c window.open() call.
*/
virtual bool ShouldDisplayStatusBar() const = 0;
/**
Returns @true if the target window is expected to display
a tool bar as specified by a @c window.open() call.
*/
virtual bool ShouldDisplayToolBar() const = 0;
/**
Returns @true if the target window is expected to display
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;
};
/**
@class wxWebViewHandlerRequest
@ -707,7 +792,8 @@ public:
@event{EVT_WEBVIEW_NEWWINDOW(id, func)}
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.
happen, for example to load the page in a new window or tab. For usage
details see wxWebViewWindowInfo::CreateChildWebView().
@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.
@ -1603,7 +1689,8 @@ public:
@event{EVT_WEBVIEW_NEWWINDOW(id, func)}
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.
happen, for example to load the page in a new window or tab. For usage
details see wxWebViewWindowInfo::CreateChildWebView().
@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.
@ -1669,6 +1756,17 @@ public:
*/
const wxString& GetMessageHandler() const;
/**
Get information about the target window. Only valid for events of type
@c wxEVT_WEBVIEW_NEWWINDOW
@note This is only available with the macOS and the Edge backend.
@see wxWebViewWindowInfo
@since 3.3.0
*/
wxWebViewWindowInfo* GetTargetWindowInfo() const;
/**
Returns true the script execution failed. Only valid for events of type
@c wxEVT_WEBVIEW_SCRIPT_RESULT

View file

@ -98,7 +98,7 @@ private:
class WebFrame : public wxFrame
{
public:
WebFrame(const wxString& url);
WebFrame(const wxString& url, bool isMain = true, wxWebViewWindowInfo* newWindowInfo = nullptr);
virtual ~WebFrame();
void UpdateState();
@ -177,6 +177,7 @@ public:
private:
wxTextCtrl* m_url;
wxWebView* m_browser;
bool m_isMainFrame;
wxToolBar* m_toolbar;
wxToolBarToolBase* m_toolbar_back;
@ -333,9 +334,11 @@ bool WebApp::OnInit()
return true;
}
WebFrame::WebFrame(const wxString& url) :
WebFrame::WebFrame(const wxString& url, bool isMain, wxWebViewWindowInfo* newWindowInfo) :
wxFrame(nullptr, wxID_ANY, "wxWebView Sample")
{
m_isMainFrame = isMain;
// set the frame icon
SetIcon(wxICON(sample));
SetTitle("wxWebView Sample");
@ -350,7 +353,7 @@ WebFrame::WebFrame(const wxString& url) :
m_toolbar_forward = m_toolbar->AddTool(wxID_ANY, _("Forward"), wxArtProvider::GetBitmapBundle(wxART_GO_FORWARD, wxART_TOOLBAR));
m_toolbar_stop = m_toolbar->AddTool(wxID_ANY, _("Stop"), wxArtProvider::GetBitmapBundle(wxART_STOP, wxART_TOOLBAR));
m_toolbar_reload = m_toolbar->AddTool(wxID_ANY, _("Reload"), wxArtProvider::GetBitmapBundle(wxART_REFRESH, wxART_TOOLBAR));
m_url = new wxTextCtrl(m_toolbar, wxID_ANY, "", wxDefaultPosition, FromDIP(wxSize(400, -1)), wxTE_PROCESS_ENTER );
m_url = new wxTextCtrl(m_toolbar, wxID_ANY, "", wxDefaultPosition, FromDIP(wxSize(400, -1)), wxTE_PROCESS_ENTER);
m_toolbar->AddControl(m_url, _("URL"));
m_toolbar_tools = m_toolbar->AddTool(wxID_ANY, _("Menu"), wxArtProvider::GetBitmapBundle(wxART_WX_LOGO, wxART_TOOLBAR));
@ -401,7 +404,8 @@ WebFrame::WebFrame(const wxString& url) :
topsizer->Add(m_info, wxSizerFlags().Expand());
// Create a log window
new wxLogWindow(this, _("Logging"), true, false);
if (m_isMainFrame)
new wxLogWindow(this, _("Logging"), true, false);
#if wxUSE_WEBVIEW_EDGE
// Check if a fixed version of edge is present in
@ -416,30 +420,50 @@ WebFrame::WebFrame(const wxString& url) :
}
#endif
// Create the webview
m_browser = wxWebView::New();
m_browser = (newWindowInfo) ? newWindowInfo->CreateChildWebView() : wxWebView::New();
#ifdef __WXMAC__
// With WKWebView handlers need to be registered before creation
m_browser->RegisterHandler(wxSharedPtr<wxWebViewHandler>(new wxWebViewArchiveHandler("wxfs")));
m_browser->RegisterHandler(wxSharedPtr<wxWebViewHandler>(new wxWebViewFSHandler("memory")));
m_browser->RegisterHandler(wxSharedPtr<wxWebViewHandler>(new AdvancedWebViewHandler()));
if (m_isMainFrame)
{
// With WKWebView handlers need to be registered before creation
m_browser->RegisterHandler(wxSharedPtr<wxWebViewHandler>(new wxWebViewArchiveHandler("wxfs")));
m_browser->RegisterHandler(wxSharedPtr<wxWebViewHandler>(new wxWebViewFSHandler("memory")));
m_browser->RegisterHandler(wxSharedPtr<wxWebViewHandler>(new AdvancedWebViewHandler()));
}
#endif
m_browser->Create(this, wxID_ANY, url, wxDefaultPosition, wxDefaultSize);
topsizer->Add(m_browser, wxSizerFlags().Expand().Proportion(1));
// Log backend information
wxLogMessage("Backend: %s Version: %s", m_browser->GetClassInfo()->GetClassName(),
wxWebView::GetBackendVersionInfo().ToString());
wxLogMessage("User Agent: %s", m_browser->GetUserAgent());
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
wxLogMessage("Backend: %s Version: %s", m_browser->GetClassInfo()->GetClassName(),
wxWebView::GetBackendVersionInfo().ToString());
wxLogMessage("User Agent: %s", m_browser->GetUserAgent());
#ifndef __WXMAC__
//We register the wxfs:// protocol for testing purposes
m_browser->RegisterHandler(wxSharedPtr<wxWebViewHandler>(new wxWebViewArchiveHandler("wxfs")));
//And the memory: file system
m_browser->RegisterHandler(wxSharedPtr<wxWebViewHandler>(new wxWebViewFSHandler("memory")));
m_browser->RegisterHandler(wxSharedPtr<wxWebViewHandler>(new AdvancedWebViewHandler()));
//We register the wxfs:// protocol for testing purposes
m_browser->RegisterHandler(wxSharedPtr<wxWebViewHandler>(new wxWebViewArchiveHandler("wxfs")));
//And the memory: file system
m_browser->RegisterHandler(wxSharedPtr<wxWebViewHandler>(new wxWebViewFSHandler("memory")));
m_browser->RegisterHandler(wxSharedPtr<wxWebViewHandler>(new AdvancedWebViewHandler()));
#endif
if (!m_browser->AddScriptMessageHandler("wx"))
wxLogError("Could not add script message handler");
if (!m_browser->AddScriptMessageHandler("wx"))
wxLogError("Could not add script message handler");
}
else
wxLogMessage("Created new window");
SetSizer(topsizer);
@ -949,11 +973,20 @@ 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 just load them in this window as we
//are a single window browser
if(m_tools_handle_new_window->IsChecked())
m_browser->LoadURL(evt.GetURL());
//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();
}
UpdateState();
}
@ -983,9 +1016,11 @@ void WebFrame::OnScriptResult(wxWebViewEvent& evt)
wxLogMessage("Async script result received; value = %s", evt.GetString());
}
void WebFrame::OnWindowCloseRequested(wxWebViewEvent& evt)
void WebFrame::OnWindowCloseRequested(wxWebViewEvent& WXUNUSED(evt))
{
wxLogMessage("Window close requested");
if (!m_isMainFrame)
Close();
}
void WebFrame::OnSetPage(wxCommandEvent& WXUNUSED(evt))

View file

@ -252,6 +252,114 @@ public:
wxCOMPtr<ICoreWebView2WebResourceRequestedEventArgs> m_args;
};
// wxWebViewNewWindowInfoEdge
class wxWebViewNewWindowInfoEdge : public wxWebViewWindowInfo
{
public:
wxWebViewNewWindowInfoEdge(wxWebViewEdgeImpl* impl, ICoreWebView2NewWindowRequestedEventArgs* args):
m_impl(impl),
m_args(args)
{
m_args->get_WindowFeatures(&m_windowFeatures);
}
virtual wxPoint GetPosition() const override
{
wxPoint result(-1, -1);
BOOL hasPosition;
if (SUCCEEDED(m_windowFeatures->get_HasPosition(&hasPosition)) && hasPosition)
{
UINT32 x, y;
if (SUCCEEDED(m_windowFeatures->get_Left(&x)) &&
SUCCEEDED(m_windowFeatures->get_Top(&y)))
result = wxPoint(x, y);
}
return result;
}
virtual wxSize GetSize() const override
{
wxSize result(-1, -1);
BOOL hasSize;
if (SUCCEEDED(m_windowFeatures->get_HasSize(&hasSize)) && hasSize)
{
UINT32 width, height;
if (SUCCEEDED(m_windowFeatures->get_Width(&width)) &&
SUCCEEDED(m_windowFeatures->get_Height(&height)))
result = wxSize(width, height);
}
return result;
}
virtual bool ShouldDisplayMenuBar() const override
{
BOOL result;
if (SUCCEEDED(m_windowFeatures->get_ShouldDisplayMenuBar(&result)))
return result;
else
return true;
}
virtual bool ShouldDisplayStatusBar() const override
{
BOOL result;
if (SUCCEEDED(m_windowFeatures->get_ShouldDisplayStatus(&result)))
return result;
else
return true;
}
virtual bool ShouldDisplayToolBar() const override
{
BOOL result;
if (SUCCEEDED(m_windowFeatures->get_ShouldDisplayToolbar(&result)))
return result;
else
return true;
}
virtual bool ShouldDisplayScrollBars() const override
{
BOOL result;
if (SUCCEEDED(m_windowFeatures->get_ShouldDisplayScrollBars(&result)))
return result;
else
return true;
}
virtual wxWebView* CreateChildWebView() override
{
return m_impl->CreateChildWebView(
std::make_shared<wxWebViewEdgeParentWindowInfo>(m_impl, m_args));
}
private:
wxWebViewEdgeImpl* m_impl;
wxCOMPtr<ICoreWebView2NewWindowRequestedEventArgs> m_args;
wxCOMPtr<ICoreWebView2WindowFeatures> m_windowFeatures;
};
class wxWebViewEdgeParentWindowInfo
{
public:
wxWebViewEdgeParentWindowInfo(wxWebViewEdgeImpl* impl,
ICoreWebView2NewWindowRequestedEventArgs* args):
m_impl(impl),
m_args(args)
{
HRESULT hr = m_args->GetDeferral(&m_deferral);
if (FAILED(hr))
wxLogApiError("GetDeferral", hr);
}
virtual ~wxWebViewEdgeParentWindowInfo() = default;
wxWebViewEdgeImpl* m_impl;
wxCOMPtr<ICoreWebView2NewWindowRequestedEventArgs> m_args;
wxCOMPtr<ICoreWebView2Deferral> m_deferral;
};
#define wxWEBVIEW_EDGE_EVENT_HANDLER_METHOD \
m_inEventCallback = true; \
wxON_BLOCK_EXIT_SET(m_inEventCallback, false);
@ -299,19 +407,34 @@ bool wxWebViewEdgeImpl::Create()
wxString userDataPath = wxStandardPaths::Get().GetUserLocalDataDir();
HRESULT hr = wxCreateCoreWebView2EnvironmentWithOptions(
ms_browserExecutableDir.wc_str(),
userDataPath.wc_str(),
m_webViewEnvironmentOptions,
Callback<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>(this,
&wxWebViewEdgeImpl::OnEnvironmentCreated).Get());
if (FAILED(hr))
if (m_parentWindowInfo)
{
wxLogApiError("CreateWebView2EnvironmentWithOptions", hr);
return false;
OnEnvironmentCreated(S_OK, m_parentWindowInfo->m_impl->m_webViewEnvironment);
return true;
}
else
return true;
{
HRESULT hr = wxCreateCoreWebView2EnvironmentWithOptions(
ms_browserExecutableDir.wc_str(),
userDataPath.wc_str(),
m_webViewEnvironmentOptions,
Callback<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>(this,
&wxWebViewEdgeImpl::OnEnvironmentCreated).Get());
if (FAILED(hr))
{
wxLogApiError("CreateWebView2EnvironmentWithOptions", hr);
return false;
}
else
return true;
}
}
wxWebViewEdge* wxWebViewEdgeImpl::CreateChildWebView(std::shared_ptr<wxWebViewEdgeParentWindowInfo> parentWindowInfo)
{
wxWebViewEdge* childWebView = new wxWebViewEdge();
childWebView->m_impl->m_parentWindowInfo = parentWindowInfo;
return childWebView;
}
HRESULT wxWebViewEdgeImpl::OnEnvironmentCreated(
@ -494,6 +617,7 @@ HRESULT wxWebViewEdgeImpl::OnNavigationCompleted(ICoreWebView2* WXUNUSED(sender)
HRESULT wxWebViewEdgeImpl::OnNewWindowRequested(ICoreWebView2* WXUNUSED(sender), ICoreWebView2NewWindowRequestedEventArgs* args)
{
wxWEBVIEW_EDGE_EVENT_HANDLER_METHOD
wxCoTaskMemPtr<wchar_t> uri;
wxString evtURL;
if (SUCCEEDED(args->get_Uri(&uri)))
@ -504,8 +628,10 @@ HRESULT wxWebViewEdgeImpl::OnNewWindowRequested(ICoreWebView2* WXUNUSED(sender),
if (SUCCEEDED(args->get_IsUserInitiated(&isUserInitiated)) && isUserInitiated)
navFlags = wxWEBVIEW_NAV_ACTION_USER;
wxWebViewEvent evt(wxEVT_WEBVIEW_NEWWINDOW, m_ctrl->GetId(), evtURL, wxString(), navFlags);
m_ctrl->GetEventHandler()->AddPendingEvent(evt);
wxWebViewNewWindowInfoEdge windowInfo(this, args);
wxWebViewEvent evt(wxEVT_WEBVIEW_NEWWINDOW, m_ctrl->GetId(), evtURL, wxString(), navFlags, "");
evt.SetClientData(&windowInfo);
m_ctrl->HandleWindowEvent(evt);
args->put_Handled(true);
return S_OK;
}
@ -734,6 +860,17 @@ HRESULT wxWebViewEdgeImpl::OnWebViewCreated(HRESULT result, ICoreWebView2Control
m_pendingUserScripts.clear();
}
if (m_parentWindowInfo)
{
if (FAILED(m_parentWindowInfo->m_args->put_NewWindow(baseWebView)))
wxLogApiError("WebView2::WebViewCreated (put_NewWindow)", hr);
if (FAILED(m_parentWindowInfo->m_deferral->Complete()))
wxLogApiError("WebView2::WebViewCreated (Complete)", hr);
m_parentWindowInfo.reset();
return S_OK;
}
if (!m_pendingURL.empty())
{
m_ctrl->LoadURL(m_pendingURL);

View file

@ -110,6 +110,86 @@ wxVersionInfo wxWebViewFactoryWebKit::GetVersionInfo()
return wxVersionInfo("WKWebView", verMaj, verMin, verMicro);
}
//-----------------------------------------------------------------------------
// wxWebViewWindowInfoWebKit
//-----------------------------------------------------------------------------
class wxWebViewWindowInfoWebKit: public wxWebViewWindowInfo
{
public:
wxWebViewWindowInfoWebKit(WKWebViewConfiguration* configuration,
WKNavigationAction* navigationAction,
WKWindowFeatures* windowFeatures):
m_configuration(configuration),
m_navigationAction(navigationAction),
m_windowFeatures(windowFeatures)
{
}
virtual wxPoint GetPosition() const override
{
wxPoint pos(-1, -1);
if (m_windowFeatures.y)
pos.y = m_windowFeatures.y.intValue;
if (m_windowFeatures.x)
pos.x = m_windowFeatures.x.intValue;
return pos;
}
virtual wxSize GetSize() const override
{
wxSize size(-1, -1);
if (m_windowFeatures.height)
size.y = m_windowFeatures.height.intValue;
if (m_windowFeatures.width)
size.x = m_windowFeatures.width.intValue;
return size;
}
virtual bool ShouldDisplayMenuBar() const override
{
if (m_windowFeatures.menuBarVisibility)
return m_windowFeatures.menuBarVisibility.boolValue;
else
return true;
}
virtual bool ShouldDisplayStatusBar() const override
{
if (m_windowFeatures.statusBarVisibility)
return m_windowFeatures.statusBarVisibility.boolValue;
else
return true;
}
virtual bool ShouldDisplayToolBar() const override
{
if (m_windowFeatures.toolbarsVisibility)
return m_windowFeatures.toolbarsVisibility.boolValue;
else
return true;
}
virtual bool ShouldDisplayScrollBars() const override
{
return true;
}
virtual wxWebView* CreateChildWebView() override
{
m_childWebView = new wxWebViewWebKit(this);
return m_childWebView;
}
wxWebView* m_childWebView = nullptr;
WKWebViewConfiguration* m_configuration;
WKNavigationAction* m_navigationAction;
WKWindowFeatures* m_windowFeatures;
};
// ----------------------------------------------------------------------------
// creation/destruction
// ----------------------------------------------------------------------------
@ -130,9 +210,10 @@ bool wxWebViewWebKit::Create(wxWindow *parent,
wxControl::Create(parent, winID, pos, size, style, wxDefaultValidator, name);
NSRect r = wxOSXGetFrameForControl( this, pos , size ) ;
WKWebViewConfiguration* webViewConfig = (WKWebViewConfiguration*) m_webViewConfiguration;
WKWebViewConfiguration* webViewConfig = (m_parentWindowInfo) ?
m_parentWindowInfo->m_configuration : (WKWebViewConfiguration*) m_webViewConfiguration;
if (!m_handlers.empty())
if (!m_handlers.empty() && !m_parentWindowInfo)
{
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_13
if ( WX_IS_MACOS_AVAILABLE(10, 13) )
@ -154,9 +235,12 @@ bool wxWebViewWebKit::Create(wxWindow *parent,
MacPostControlCreate(pos, size);
// WKWebView configuration is only used during creation
[m_webViewConfiguration release];
m_webViewConfiguration = nil;
if (!m_parentWindowInfo)
{
// WKWebView configuration is only used during creation
[m_webViewConfiguration release];
m_webViewConfiguration = nil;
}
if (!m_customUserAgent.empty())
SetUserAgent(m_customUserAgent);
@ -178,45 +262,51 @@ bool wxWebViewWebKit::Create(wxWindow *parent,
[m_webView setUIDelegate:uiDelegate];
// Implement javascript fullscreen interface with user script and message handler
AddUserScript("\
document.__wxToggleFullscreen = function (elem) { \
if (!document.__wxStylesAdded) { \
function createClass(name,rules) { \
var style= document.createElement('style'); style.type = 'text/css'; \
document.getElementsByTagName('head')[0].appendChild(style); \
style.sheet.addRule(name, rules); \
if (!m_parentWindowInfo)
{
// Implement javascript fullscreen interface with user script and message handler
AddUserScript("\
document.__wxToggleFullscreen = function (elem) { \
if (!document.__wxStylesAdded) { \
function createClass(name,rules) { \
var style= document.createElement('style'); style.type = 'text/css'; \
document.getElementsByTagName('head')[0].appendChild(style); \
style.sheet.addRule(name, rules); \
} \
createClass(\"body.wxfullscreen\", \"padding: 0; margin: 0; height: 100%;\"); \
createClass(\".wxfullscreen\", \"position: fixed; overflow: hidden; z-index: 1000; left: 0; top: 0; bottom: 0; right: 0;\"); \
createClass(\".wxfullscreenelem\", \"width: 100% !important; height: 100% !important; padding-top: 0 !important;\"); \
document.__wxStylesAdded = true; \
} \
createClass(\"body.wxfullscreen\", \"padding: 0; margin: 0; height: 100%;\"); \
createClass(\".wxfullscreen\", \"position: fixed; overflow: hidden; z-index: 1000; left: 0; top: 0; bottom: 0; right: 0;\"); \
createClass(\".wxfullscreenelem\", \"width: 100% !important; height: 100% !important; padding-top: 0 !important;\"); \
document.__wxStylesAdded = true; \
} \
if (elem) { \
elem.classList.add(\"wxfullscreen\"); \
elem.classList.add(\"wxfullscreenelem\"); \
document.body.classList.add(\"wxfullscreen\"); \
} else if (document.webkitFullscreenElement) { \
document.webkitFullscreenElement.classList.remove(\"wxfullscreen\"); \
document.webkitFullscreenElement.classList.remove(\"wxfullscreenelem\"); \
document.body.classList.remove(\"wxfullscreen\"); \
} \
document.webkitFullscreenElement = elem; \
window.webkit.messageHandlers.__wxfullscreen.postMessage((elem) ? 1: 0); \
document.dispatchEvent(new Event('webkitfullscreenchange')); \
if (document.onwebkitfullscreenchange) document.onwebkitfullscreenchange(); \
}; \
Element.prototype.webkitRequestFullscreen = function() {document.__wxToggleFullscreen(this);}; \
document.webkitExitFullscreen = function() {document.__wxToggleFullscreen(undefined);}; \
document.onwebkitfullscreenchange = null; \
document.webkitFullscreenEnabled = true; \
");
[m_webView.configuration.userContentController addScriptMessageHandler:
[[WebViewScriptMessageHandler alloc] initWithWxWindow:this] name:@"__wxfullscreen"];
if (elem) { \
elem.classList.add(\"wxfullscreen\"); \
elem.classList.add(\"wxfullscreenelem\"); \
document.body.classList.add(\"wxfullscreen\"); \
} else if (document.webkitFullscreenElement) { \
document.webkitFullscreenElement.classList.remove(\"wxfullscreen\"); \
document.webkitFullscreenElement.classList.remove(\"wxfullscreenelem\"); \
document.body.classList.remove(\"wxfullscreen\"); \
} \
document.webkitFullscreenElement = elem; \
window.webkit.messageHandlers.__wxfullscreen.postMessage((elem) ? 1: 0); \
document.dispatchEvent(new Event('webkitfullscreenchange')); \
if (document.onwebkitfullscreenchange) document.onwebkitfullscreenchange(); \
}; \
Element.prototype.webkitRequestFullscreen = function() {document.__wxToggleFullscreen(this);}; \
document.webkitExitFullscreen = function() {document.__wxToggleFullscreen(undefined);}; \
document.onwebkitfullscreenchange = null; \
document.webkitFullscreenEnabled = true; \
");
[m_webView.configuration.userContentController addScriptMessageHandler:
[[WebViewScriptMessageHandler alloc] initWithWxWindow:this] name:@"__wxfullscreen"];
}
m_UIDelegate = uiDelegate;
LoadURL(strURL);
if (m_parentWindowInfo)
[m_webView loadRequest:m_parentWindowInfo->m_navigationAction.request];
else
LoadURL(strURL);
return true;
}
@ -1013,15 +1103,21 @@ WX_API_AVAILABLE_MACOS(10, 13)
wxWEBVIEW_NAV_ACTION_USER :
wxWEBVIEW_NAV_ACTION_OTHER;
wxWebViewWindowInfoWebKit windowInfo(configuration, navigationAction, windowFeatures);
wxWebViewEvent event(wxEVT_WEBVIEW_NEWWINDOW,
webKitWindow->GetId(),
wxCFStringRef::AsString( navigationAction.request.URL.absoluteString ),
"", navFlags);
event.SetClientData(&windowInfo);
if (webKitWindow && webKitWindow->GetEventHandler())
webKitWindow->GetEventHandler()->ProcessEvent(event);
return nil;
if (windowInfo.m_childWebView)
return (WKWebView*) windowInfo.m_childWebView->GetNativeBackend();
else
return nil;
}
- (void)webViewDidClose:(WKWebView *)webView