From a5cec42bb64d0ad336f66d1dbadf396d9af8730f Mon Sep 17 00:00:00 2001 From: Tobias Taschner Date: Thu, 23 Dec 2021 13:25:01 +0100 Subject: [PATCH] macOS: Use public API for fullscreen in wxWebView To enable fullscreen support with WKWebView private API which was available since macOS 10.11 was used. Beginning with macOS 12.1 this resulted in unpredictable layout issues inside the webview. This reimplementation using java script and message handlers does only use public API. This also makes the fullscreen message more controlable as the webview does no longer put the containing window in fullscreen mode without application code intervention. That also unifies macOS with the way Edge sends this event in MSW. Closes https://github.com/wxWidgets/wxWidgets/pull/2629 --- samples/webview/webview.cpp | 1 + src/osx/webview_webkit.mm | 55 ++++++++++++++++++------------------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/samples/webview/webview.cpp b/samples/webview/webview.cpp index 95f6f784d0..ff5293479f 100644 --- a/samples/webview/webview.cpp +++ b/samples/webview/webview.cpp @@ -306,6 +306,7 @@ WebFrame::WebFrame(const wxString& url) : // set the frame icon SetIcon(wxICON(sample)); SetTitle("wxWebView Sample"); + EnableFullScreenView(); // Enable native fullscreen API on macOS wxBoxSizer* topsizer = new wxBoxSizer(wxVERTICAL); diff --git a/src/osx/webview_webkit.mm b/src/osx/webview_webkit.mm index 8cc462d414..8f4558c591 100644 --- a/src/osx/webview_webkit.mm +++ b/src/osx/webview_webkit.mm @@ -124,11 +124,6 @@ bool wxWebViewWebKit::Create(wxWindow *parent, NSRect r = wxOSXGetFrameForControl( this, pos , size ) ; WKWebViewConfiguration* webViewConfig = [[WKWebViewConfiguration alloc] init]; - // WebKit API available since macOS 10.11 and iOS 9.0 - SEL fullScreenSelector = @selector(_setFullScreenEnabled:); - if ([webViewConfig.preferences respondsToSelector:fullScreenSelector]) - [webViewConfig.preferences performSelector:fullScreenSelector withObject:[NSNumber numberWithBool:YES]]; - if (!m_handlers.empty()) { #if __MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_13 @@ -171,10 +166,22 @@ bool wxWebViewWebKit::Create(wxWindow *parent, [m_webView setUIDelegate:uiDelegate]; - // WebKit API available since macOS 10.13 and iOS 11.0 - SEL fullScreenDelegateSelector = @selector(_setFullscreenDelegate:); - if ([m_webView respondsToSelector:fullScreenDelegateSelector]) - [m_webView performSelector:fullScreenDelegateSelector withObject:uiDelegate]; + // Implement javascript fullscreen interface with user script and message handler + AddUserScript("\ + document.__wxToggleFullscreen = function (elem) { \ + document.fullscreenElement = elem; \ + window.webkit.messageHandlers.__wxfullscreen.postMessage((elem) ? 1: 0); \ + document.dispatchEvent(new Event('fullscreenchange')); \ + }; \ + Element.prototype.requestFullscreen = function() {document.__wxToggleFullscreen(this);}; \ + Element.prototype.webkitRequestFullscreen = Element.prototype.requestFullscreen; \ + document.exitFullscreen = function() {document.__wxToggleFullscreen(undefined);}; \ + document.webkitExitFullscreen = document.exitFullscreen; \ + document.onfullscreenchange = null; \ + document.fullscreenEnabled = true; \ + "); + [m_webView.configuration.userContentController addScriptMessageHandler: + [[WebViewScriptMessageHandler alloc] initWithWxWindow:this] name:@"__wxfullscreen"]; m_UIDelegate = uiDelegate; @@ -978,25 +985,6 @@ WX_API_AVAILABLE_MACOS(10, 12) webKitWindow->Print(); } -- (void)SendFullscreenChangedEvent:(int)status -{ - wxWebViewEvent event(wxEVT_WEBVIEW_FULLSCREEN_CHANGED, webKitWindow->GetId(), - webKitWindow->GetCurrentURL(), wxString()); - event.SetEventObject(webKitWindow); - event.SetInt(status); - webKitWindow->HandleWindowEvent(event); -} - -- (void)_webViewDidEnterFullscreen:(WKWebView *)webView -{ - [self SendFullscreenChangedEvent:1]; -} - -- (void)_webViewDidExitFullscreen:(WKWebView *)webView -{ - [self SendFullscreenChangedEvent:0]; -} - @end @implementation WebViewScriptMessageHandler @@ -1013,6 +1001,17 @@ WX_API_AVAILABLE_MACOS(10, 12) - (void)userContentController:(nonnull WKUserContentController *)userContentController didReceiveScriptMessage:(nonnull WKScriptMessage *)message { + // Handle internal fullscreen message independent of user message handlers + if ([message.name isEqualToString:@"__wxfullscreen"]) + { + wxWebViewEvent event(wxEVT_WEBVIEW_FULLSCREEN_CHANGED, webKitWindow->GetId(), + webKitWindow->GetCurrentURL(), wxString()); + event.SetEventObject(webKitWindow); + event.SetInt(((NSNumber*)message.body).intValue); + webKitWindow->HandleWindowEvent(event); + return; + } + wxWebViewEvent event(wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED, webKitWindow->GetId(), webKitWindow->GetCurrentURL(),