diff --git a/include/wx/msw/private/webview_edge.h b/include/wx/msw/private/webview_edge.h index f5509006e6..f78d984395 100644 --- a/include/wx/msw/private/webview_edge.h +++ b/include/wx/msw/private/webview_edge.h @@ -41,17 +41,21 @@ public: // WebView Events tokens EventRegistrationToken m_navigationStartingToken = { }; + EventRegistrationToken m_sourceChangedToken = { }; EventRegistrationToken m_navigationCompletedToken = { }; EventRegistrationToken m_newWindowRequestedToken = { }; EventRegistrationToken m_documentTitleChangedToken = { }; EventRegistrationToken m_contentLoadingToken = { }; + EventRegistrationToken m_containsFullScreenElementChangedToken = { }; // WebView Event handlers HRESULT OnNavigationStarting(ICoreWebView2* sender, ICoreWebView2NavigationStartingEventArgs* args); + HRESULT OnSourceChanged(ICoreWebView2* sender, ICoreWebView2SourceChangedEventArgs* args); HRESULT OnNavigationCompleted(ICoreWebView2* sender, ICoreWebView2NavigationCompletedEventArgs* args); HRESULT OnNewWindowRequested(ICoreWebView2* sender, ICoreWebView2NewWindowRequestedEventArgs* args); HRESULT OnDocumentTitleChanged(ICoreWebView2* sender, IUnknown* args); HRESULT OnContentLoading(ICoreWebView2* sender, ICoreWebView2ContentLoadingEventArgs* args); + HRESULT OnContainsFullScreenElementChanged(ICoreWebView2* sender, IUnknown* args); HRESULT OnEnvironmentCreated(HRESULT result, ICoreWebView2Environment* environment); HRESULT OnWebViewCreated(HRESULT result, ICoreWebView2Controller* webViewController); diff --git a/include/wx/webview.h b/include/wx/webview.h index 9a0997ab36..22bcfd8279 100644 --- a/include/wx/webview.h +++ b/include/wx/webview.h @@ -257,6 +257,7 @@ private: static wxStringWebViewFactoryMap::iterator FindFactory(const wxString &backend); bool m_showMenu; + wxString m_findText; static wxStringWebViewFactoryMap m_factoryMap; wxDECLARE_ABSTRACT_CLASS(wxWebView); @@ -294,6 +295,7 @@ wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_WEBVIEW, wxEVT_WEBVIEW_LOADED, wxWebViewEv 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_TITLE_CHANGED, wxWebViewEvent ); +wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_WEBVIEW, wxEVT_WEBVIEW_FULLSCREEN_CHANGED, wxWebViewEvent); typedef void (wxEvtHandler::*wxWebViewEventFunction) (wxWebViewEvent&); diff --git a/interface/wx/webview.h b/interface/wx/webview.h index 9decc0f56b..18581d2c9a 100644 --- a/interface/wx/webview.h +++ b/interface/wx/webview.h @@ -317,7 +317,7 @@ public: Edge WebView2. It is available for Windows 7 and newer. The following features are currently unsupported with this backend: - virtual filesystems, custom urls, find. + virtual filesystems, custom urls. This backend is not enabled by default, to build it follow these steps: - Visual Studio 2015, or newer, is required @@ -428,6 +428,11 @@ public: @event{EVT_WEBVIEW_TITLE_CHANGED(id, func)} Process a @c wxEVT_WEBVIEW_TITLE_CHANGED event, generated when the page title changes. Use GetString to get the title. + @event{EVT_WEBVIEW_FULL_SCREEN_CHANGED(id, func)} + Process a @c EVT_WEBVIEW_FULL_SCREEN_CHANGED event, generated when + the page wants to enter or leave fullscreen. Use GetInt to get the status. + Currently only implemented for the edge and WebKit2GTK+ backend + and is only available in wxWidgets 3.1.5 or later. @endEventTable @since 2.9.3 diff --git a/samples/webview/webview.cpp b/samples/webview/webview.cpp index 368628d88d..ac9512ed89 100644 --- a/samples/webview/webview.cpp +++ b/samples/webview/webview.cpp @@ -120,6 +120,7 @@ public: void OnDocumentLoaded(wxWebViewEvent& evt); void OnNewWindow(wxWebViewEvent& evt); void OnTitleChanged(wxWebViewEvent& evt); + void OnFullScreenChanged(wxWebViewEvent& evt); void OnSetPage(wxCommandEvent& evt); void OnViewSourceRequest(wxCommandEvent& evt); void OnViewTextRequest(wxCommandEvent& evt); @@ -321,7 +322,7 @@ WebFrame::WebFrame(const wxString& url) : m_toolbar_forward = m_toolbar->AddTool(wxID_ANY, _("Forward"), forward); m_toolbar_stop = m_toolbar->AddTool(wxID_ANY, _("Stop"), stop); m_toolbar_reload = m_toolbar->AddTool(wxID_ANY, _("Reload"), refresh); - m_url = new wxTextCtrl(m_toolbar, wxID_ANY, "", wxDefaultPosition, 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"), wxBitmap(wxlogo_xpm)); @@ -409,7 +410,7 @@ WebFrame::WebFrame(const wxString& url) : SetSizer(topsizer); //Set a more sensible size for web browsing - SetSize(wxSize(800, 600)); + SetSize(FromDIP(wxSize(800, 600))); // Create the Tools menu m_tools_menu = new wxMenu(); @@ -536,6 +537,7 @@ WebFrame::WebFrame(const wxString& url) : Bind(wxEVT_WEBVIEW_ERROR, &WebFrame::OnError, this, m_browser->GetId()); Bind(wxEVT_WEBVIEW_NEWWINDOW, &WebFrame::OnNewWindow, 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()); // Connect the menu events Bind(wxEVT_MENU, &WebFrame::OnSetPage, this, setPage->GetId()); @@ -897,6 +899,12 @@ void WebFrame::OnTitleChanged(wxWebViewEvent& evt) wxLogMessage("%s", "Title changed; title='" + evt.GetString() + "'"); } +void WebFrame::OnFullScreenChanged(wxWebViewEvent & evt) +{ + wxLogMessage("Full screen changed; status = %d", evt.GetInt()); + ShowFullScreen(evt.GetInt() != 0); +} + void WebFrame::OnSetPage(wxCommandEvent& WXUNUSED(evt)) { m_browser->SetPage diff --git a/src/common/webview.cpp b/src/common/webview.cpp index d88771feb8..8cbcdd1ced 100644 --- a/src/common/webview.cpp +++ b/src/common/webview.cpp @@ -48,6 +48,7 @@ wxDEFINE_EVENT( wxEVT_WEBVIEW_LOADED, wxWebViewEvent ); wxDEFINE_EVENT( wxEVT_WEBVIEW_ERROR, wxWebViewEvent ); wxDEFINE_EVENT( wxEVT_WEBVIEW_NEWWINDOW, wxWebViewEvent ); wxDEFINE_EVENT( wxEVT_WEBVIEW_TITLE_CHANGED, wxWebViewEvent ); +wxDEFINE_EVENT( wxEVT_WEBVIEW_FULLSCREEN_CHANGED, wxWebViewEvent); wxStringWebViewFactoryMap wxWebView::m_factoryMap; @@ -202,10 +203,23 @@ void wxWebView::SelectAll() RunScript("window.getSelection().selectAllChildren(document.body);"); } -long wxWebView::Find(const wxString& WXUNUSED(text), int WXUNUSED(flags)) +long wxWebView::Find(const wxString& text, int flags) { - // TODO: could probably be implemented by script - return -1; + if (text != m_findText) + ClearSelection(); + m_findText = text; + wxString output; + RunScript(wxString::Format("window.find('%s', %s, %s, %s, %s)", + text, + (flags & wxWEBVIEW_FIND_MATCH_CASE) ? "true" : "false", + (flags & wxWEBVIEW_FIND_BACKWARDS) ? "true" : "false", + (flags & wxWEBVIEW_FIND_WRAP) ? "true" : "false", + (flags & wxWEBVIEW_FIND_ENTIRE_WORD) ? "true" : "false" + ), &output); + if (output.IsSameAs("false", false)) + return wxNOT_FOUND; + else + return 1; } // static diff --git a/src/gtk/webview_webkit2.cpp b/src/gtk/webview_webkit2.cpp index 8ee773b060..9dd87d1393 100644 --- a/src/gtk/webview_webkit2.cpp +++ b/src/gtk/webview_webkit2.cpp @@ -253,6 +253,34 @@ wxgtk_webview_webkit_new_window(WebKitPolicyDecision *decision, return TRUE; } +static gboolean +wxgtk_webview_webkit_enter_fullscreen(WebKitWebView *WXUNUSED(web_view), + wxWebViewWebKit *webKitCtrl) +{ + wxWebViewEvent event(wxEVT_WEBVIEW_FULLSCREEN_CHANGED, + webKitCtrl->GetId(), + wxString(), + wxString()); + event.SetInt(1); + webKitCtrl->HandleWindowEvent(event); + + return FALSE; +} + +static gboolean +wxgtk_webview_webkit_leave_fullscreen(WebKitWebView *WXUNUSED(web_view), + wxWebViewWebKit *webKitCtrl) +{ + wxWebViewEvent event(wxEVT_WEBVIEW_FULLSCREEN_CHANGED, + webKitCtrl->GetId(), + wxString(), + wxString()); + event.SetInt(0); + webKitCtrl->HandleWindowEvent(event); + + return FALSE; +} + static gboolean wxgtk_webview_webkit_decide_policy(WebKitWebView *web_view, WebKitPolicyDecision *decision, @@ -583,6 +611,12 @@ bool wxWebViewWebKit::Create(wxWindow *parent, g_signal_connect(m_web_view, "create", G_CALLBACK(wxgtk_webview_webkit_create_webview), this); + g_signal_connect(m_web_view, "enter-fullscreen", + G_CALLBACK(wxgtk_webview_webkit_enter_fullscreen), this); + + g_signal_connect(m_web_view, "leave-fullscreen", + G_CALLBACK(wxgtk_webview_webkit_leave_fullscreen), this); + WebKitFindController* findctrl = webkit_web_view_get_find_controller(m_web_view); g_signal_connect(findctrl, "counted-matches", G_CALLBACK(wxgtk_webview_webkit_counted_matches), diff --git a/src/msw/webview_edge.cpp b/src/msw/webview_edge.cpp index bdf8ce5b76..355d384e31 100644 --- a/src/msw/webview_edge.cpp +++ b/src/msw/webview_edge.cpp @@ -67,10 +67,12 @@ wxWebViewEdgeImpl::~wxWebViewEdgeImpl() if (m_webView) { m_webView->remove_NavigationCompleted(m_navigationCompletedToken); + m_webView->remove_SourceChanged(m_sourceChangedToken); m_webView->remove_NavigationStarting(m_navigationStartingToken); m_webView->remove_NewWindowRequested(m_newWindowRequestedToken); m_webView->remove_DocumentTitleChanged(m_documentTitleChangedToken); m_webView->remove_ContentLoading(m_contentLoadingToken); + m_webView->remove_ContainsFullScreenElementChanged(m_containsFullScreenElementChangedToken); } } @@ -175,10 +177,27 @@ HRESULT wxWebViewEdgeImpl::OnNavigationStarting(ICoreWebView2* WXUNUSED(sender), return S_OK; } +HRESULT wxWebViewEdgeImpl::OnSourceChanged(ICoreWebView2 * WXUNUSED(sender), ICoreWebView2SourceChangedEventArgs * args) +{ + BOOL isNewDocument; + if (SUCCEEDED(args->get_IsNewDocument(&isNewDocument)) && !isNewDocument) + { + // navigation within the current document, send apropriate events + wxWebViewEvent event(wxEVT_WEBVIEW_NAVIGATING, m_ctrl->GetId(), m_ctrl->GetCurrentURL(), wxString()); + event.SetEventObject(m_ctrl); + m_ctrl->HandleWindowEvent(event); + OnNavigationCompleted(NULL, NULL); + OnContentLoading(NULL, NULL); + } + return S_OK; +} + HRESULT wxWebViewEdgeImpl::OnNavigationCompleted(ICoreWebView2* WXUNUSED(sender), ICoreWebView2NavigationCompletedEventArgs* args) { BOOL isSuccess; - if (FAILED(args->get_IsSuccess(&isSuccess))) + if (!args) + isSuccess = true; + else if (FAILED(args->get_IsSuccess(&isSuccess))) isSuccess = false; m_isBusy = false; wxString uri = m_ctrl->GetCurrentURL(); @@ -186,6 +205,7 @@ HRESULT wxWebViewEdgeImpl::OnNavigationCompleted(ICoreWebView2* WXUNUSED(sender) if (!isSuccess) { COREWEBVIEW2_WEB_ERROR_STATUS status; + bool ignoreStatus = false; wxWebViewEvent event(wxEVT_WEBVIEW_ERROR, m_ctrl->GetId(), uri, wxString()); event.SetEventObject(m_ctrl); @@ -208,12 +228,16 @@ HRESULT wxWebViewEdgeImpl::OnNavigationCompleted(ICoreWebView2* WXUNUSED(sender) WX_ERROR2_CASE(COREWEBVIEW2_WEB_ERROR_STATUS_DISCONNECTED, wxWEBVIEW_NAV_ERR_CONNECTION) WX_ERROR2_CASE(COREWEBVIEW2_WEB_ERROR_STATUS_CANNOT_CONNECT, wxWEBVIEW_NAV_ERR_CONNECTION) WX_ERROR2_CASE(COREWEBVIEW2_WEB_ERROR_STATUS_HOST_NAME_NOT_RESOLVED, wxWEBVIEW_NAV_ERR_CONNECTION) - WX_ERROR2_CASE(COREWEBVIEW2_WEB_ERROR_STATUS_OPERATION_CANCELED, wxWEBVIEW_NAV_ERR_USER_CANCELLED) WX_ERROR2_CASE(COREWEBVIEW2_WEB_ERROR_STATUS_REDIRECT_FAILED, wxWEBVIEW_NAV_ERR_OTHER) WX_ERROR2_CASE(COREWEBVIEW2_WEB_ERROR_STATUS_UNEXPECTED_ERROR, wxWEBVIEW_NAV_ERR_OTHER) + case COREWEBVIEW2_WEB_ERROR_STATUS_OPERATION_CANCELED: + // This status is triggered by vetoing a wxEVT_WEBVIEW_NAVIGATING event + ignoreStatus = true; + break; } } - m_ctrl->HandleWindowEvent(event); + if (!ignoreStatus) + m_ctrl->HandleWindowEvent(event); } else { @@ -278,6 +302,22 @@ HRESULT wxWebViewEdgeImpl::OnContentLoading(ICoreWebView2* WXUNUSED(sender), ICo return S_OK; } +HRESULT wxWebViewEdgeImpl::OnContainsFullScreenElementChanged(ICoreWebView2* WXUNUSED(sender), IUnknown* WXUNUSED(args)) +{ + BOOL containsFullscreenEvent; + HRESULT hr = m_webView->get_ContainsFullScreenElement(&containsFullscreenEvent); + if (FAILED(hr)) + return hr; + + wxWebViewEvent event(wxEVT_WEBVIEW_FULLSCREEN_CHANGED, m_ctrl->GetId(), + m_ctrl->GetCurrentURL(), wxString()); + event.SetEventObject(m_ctrl); + event.SetInt(containsFullscreenEvent); + m_ctrl->HandleWindowEvent(event); + + return S_OK; +} + HRESULT wxWebViewEdgeImpl::OnWebViewCreated(HRESULT result, ICoreWebView2Controller* webViewController) { if (FAILED(result)) @@ -303,6 +343,10 @@ HRESULT wxWebViewEdgeImpl::OnWebViewCreated(HRESULT result, ICoreWebView2Control Callback( this, &wxWebViewEdgeImpl::OnNavigationStarting).Get(), &m_navigationStartingToken); + m_webView->add_SourceChanged( + Callback( + this, &wxWebViewEdgeImpl::OnSourceChanged).Get(), + &m_sourceChangedToken); m_webView->add_NavigationCompleted( Callback( this, &wxWebViewEdgeImpl::OnNavigationCompleted).Get(), @@ -319,6 +363,10 @@ HRESULT wxWebViewEdgeImpl::OnWebViewCreated(HRESULT result, ICoreWebView2Control Callback( this, &wxWebViewEdgeImpl::OnContentLoading).Get(), &m_contentLoadingToken); + m_webView->add_ContainsFullScreenElementChanged( + Callback( + this, &wxWebViewEdgeImpl::OnContainsFullScreenElementChanged).Get(), + &m_containsFullScreenElementChangedToken); if (m_pendingContextMenuEnabled != -1) {