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
This commit is contained in:
Tobias Taschner 2021-12-23 13:25:01 +01:00 committed by Vadim Zeitlin
parent c864c9119b
commit a5cec42bb6
2 changed files with 28 additions and 28 deletions

View File

@ -306,6 +306,7 @@ WebFrame::WebFrame(const wxString& url) :
// set the frame icon // set the frame icon
SetIcon(wxICON(sample)); SetIcon(wxICON(sample));
SetTitle("wxWebView Sample"); SetTitle("wxWebView Sample");
EnableFullScreenView(); // Enable native fullscreen API on macOS
wxBoxSizer* topsizer = new wxBoxSizer(wxVERTICAL); wxBoxSizer* topsizer = new wxBoxSizer(wxVERTICAL);

View File

@ -124,11 +124,6 @@ bool wxWebViewWebKit::Create(wxWindow *parent,
NSRect r = wxOSXGetFrameForControl( this, pos , size ) ; NSRect r = wxOSXGetFrameForControl( this, pos , size ) ;
WKWebViewConfiguration* webViewConfig = [[WKWebViewConfiguration alloc] init]; 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 (!m_handlers.empty())
{ {
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_13 #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]; [m_webView setUIDelegate:uiDelegate];
// WebKit API available since macOS 10.13 and iOS 11.0 // Implement javascript fullscreen interface with user script and message handler
SEL fullScreenDelegateSelector = @selector(_setFullscreenDelegate:); AddUserScript("\
if ([m_webView respondsToSelector:fullScreenDelegateSelector]) document.__wxToggleFullscreen = function (elem) { \
[m_webView performSelector:fullScreenDelegateSelector withObject:uiDelegate]; 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; m_UIDelegate = uiDelegate;
@ -978,25 +985,6 @@ WX_API_AVAILABLE_MACOS(10, 12)
webKitWindow->Print(); 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 @end
@implementation WebViewScriptMessageHandler @implementation WebViewScriptMessageHandler
@ -1013,6 +1001,17 @@ WX_API_AVAILABLE_MACOS(10, 12)
- (void)userContentController:(nonnull WKUserContentController *)userContentController - (void)userContentController:(nonnull WKUserContentController *)userContentController
didReceiveScriptMessage:(nonnull WKScriptMessage *)message 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, wxWebViewEvent event(wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED,
webKitWindow->GetId(), webKitWindow->GetId(),
webKitWindow->GetCurrentURL(), webKitWindow->GetCurrentURL(),