1/*
2 * Copyright (C) 2010, 2011 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#if ENABLE(FULLSCREEN_API) && !PLATFORM(IOS)
27
28#import "WebFullScreenController.h"
29
30#import "WebNSWindowExtras.h"
31#import "WebPreferencesPrivate.h"
32#import "WebViewInternal.h"
33#import <WebCore/Document.h>
34#import <WebCore/Element.h>
35#import <WebCore/FloatRect.h>
36#import <WebCore/Frame.h>
37#import <WebCore/FrameView.h>
38#import <WebCore/HTMLElement.h>
39#import <WebCore/IntRect.h>
40#import <WebCore/Page.h>
41#import <WebCore/RenderLayer.h>
42#import <WebCore/RenderLayerBacking.h>
43#import <WebCore/RenderObject.h>
44#import <WebCore/RenderView.h>
45#import <WebCore/SoftLinking.h>
46#import <WebCore/WebCoreFullScreenWindow.h>
47#import <WebCore/WebWindowAnimation.h>
48#import <WebKitSystemInterface.h>
49#import <wtf/RetainPtr.h>
50
51using namespace WebCore;
52
53static const CFTimeInterval defaultAnimationDuration = 0.5;
54
55static IntRect screenRectOfContents(Element* element)
56{
57    ASSERT(element);
58    if (element->renderer() && element->renderer()->hasLayer() && element->renderer()->enclosingLayer()->isComposited()) {
59        FloatQuad contentsBox = static_cast<FloatRect>(element->renderer()->enclosingLayer()->backing()->contentsBox());
60        contentsBox = element->renderer()->localToAbsoluteQuad(contentsBox);
61        return element->renderer()->view().frameView().contentsToScreen(contentsBox.enclosingBoundingBox());
62    }
63    return element->screenRect();
64}
65
66@interface WebFullScreenController(Private)<NSAnimationDelegate>
67- (void)_updateMenuAndDockForFullScreen;
68- (void)_swapView:(NSView*)view with:(NSView*)otherView;
69- (Document*)_document;
70- (void)_startEnterFullScreenAnimationWithDuration:(NSTimeInterval)duration;
71- (void)_startExitFullScreenAnimationWithDuration:(NSTimeInterval)duration;
72@end
73
74static NSRect convertRectToScreen(NSWindow *window, NSRect rect)
75{
76    return [window convertRectToScreen:rect];
77}
78
79@interface NSWindow(IsOnActiveSpaceAdditionForTigerAndLeopard)
80- (BOOL)isOnActiveSpace;
81@end
82
83@implementation WebFullScreenController
84
85#pragma mark -
86#pragma mark Initialization
87- (id)init
88{
89    // Do not defer window creation, to make sure -windowNumber is created (needed by WebWindowScaleAnimation).
90    NSWindow *window = [[WebCoreFullScreenWindow alloc] initWithContentRect:NSZeroRect styleMask:NSClosableWindowMask backing:NSBackingStoreBuffered defer:NO];
91    self = [super initWithWindow:window];
92    [window release];
93    if (!self)
94        return nil;
95    [self windowDidLoad];
96
97    return self;
98}
99
100- (void)dealloc
101{
102    [self setWebView:nil];
103
104    [NSObject cancelPreviousPerformRequestsWithTarget:self];
105
106    [[NSNotificationCenter defaultCenter] removeObserver:self];
107    [super dealloc];
108}
109
110- (void)windowDidLoad
111{
112    [super windowDidLoad];
113
114    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidResignActive:) name:NSApplicationDidResignActiveNotification object:NSApp];
115    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidChangeScreenParameters:) name:NSApplicationDidChangeScreenParametersNotification object:NSApp];
116}
117
118#pragma mark -
119#pragma mark Accessors
120
121- (WebView*)webView
122{
123    return _webView;
124}
125
126- (void)setWebView:(WebView *)webView
127{
128    [webView retain];
129    [_webView release];
130    _webView = webView;
131}
132
133- (NSView*)webViewPlaceholder
134{
135    return _webViewPlaceholder.get();
136}
137
138- (Element*)element
139{
140    return _element.get();
141}
142
143- (void)setElement:(PassRefPtr<Element>)element
144{
145    _element = element;
146}
147
148- (BOOL)isFullScreen
149{
150    return _isFullScreen;
151}
152
153#pragma mark -
154#pragma mark NSWindowController overrides
155
156- (void)cancelOperation:(id)sender
157{
158    [self performSelector:@selector(requestExitFullScreen) withObject:nil afterDelay:0];
159}
160
161#pragma mark -
162#pragma mark Notifications
163
164- (void)applicationDidResignActive:(NSNotification*)notification
165{
166    // Check to see if the fullscreenWindow is on the active space; this function is available
167    // on 10.6 and later, so default to YES if the function is not available:
168    NSWindow* fullscreenWindow = [self window];
169    BOOL isOnActiveSpace = ([fullscreenWindow respondsToSelector:@selector(isOnActiveSpace)] ? [fullscreenWindow isOnActiveSpace] : YES);
170
171    // Replicate the QuickTime Player (X) behavior when losing active application status:
172    // Is the fullscreen screen the main screen? (Note: this covers the case where only a
173    // single screen is available.)  Is the fullscreen screen on the current space? IFF so,
174    // then exit fullscreen mode.
175    if ([fullscreenWindow screen] == [[NSScreen screens] objectAtIndex:0] && isOnActiveSpace)
176         [self cancelOperation:self];
177}
178
179- (void)applicationDidChangeScreenParameters:(NSNotification*)notification
180{
181    // The user may have changed the main screen by moving the menu bar, or they may have changed
182    // the Dock's size or location, or they may have changed the fullscreen screen's dimensions.
183    // Update our presentation parameters, and ensure that the full screen window occupies the
184    // entire screen:
185    [self _updateMenuAndDockForFullScreen];
186    NSWindow* window = [self window];
187    NSRect screenFrame = [[window screen] frame];
188    [window setFrame:screenFrame display:YES];
189    [_backgroundWindow.get() setFrame:screenFrame display:YES];
190}
191
192#pragma mark -
193#pragma mark Exposed Interface
194
195- (void)enterFullScreen:(NSScreen *)screen
196{
197    if (_isFullScreen)
198        return;
199    _isFullScreen = YES;
200
201    [self _updateMenuAndDockForFullScreen];
202
203    if (!screen)
204        screen = [NSScreen mainScreen];
205    NSRect screenFrame = [screen frame];
206
207    NSRect webViewFrame = convertRectToScreen([_webView window], [_webView convertRect:[_webView frame] toView:nil]);
208
209    // Flip coordinate system:
210    webViewFrame.origin.y = NSMaxY([[[NSScreen screens] objectAtIndex:0] frame]) - NSMaxY(webViewFrame);
211
212    CGWindowID windowID = [[_webView window] windowNumber];
213    RetainPtr<CGImageRef> webViewContents = adoptCF(CGWindowListCreateImage(NSRectToCGRect(webViewFrame), kCGWindowListOptionIncludingWindow, windowID, kCGWindowImageShouldBeOpaque));
214
215    // Screen updates to be re-enabled in beganEnterFullScreenWithInitialFrame:finalFrame:
216    NSDisableScreenUpdates();
217    [[self window] setAutodisplay:NO];
218
219    NSResponder *webWindowFirstResponder = [[_webView window] firstResponder];
220    [[self window] setFrame:screenFrame display:NO];
221
222    _initialFrame = screenRectOfContents(_element.get());
223
224    // Swap the webView placeholder into place.
225    if (!_webViewPlaceholder) {
226        _webViewPlaceholder = adoptNS([[NSView alloc] init]);
227        [_webViewPlaceholder.get() setLayer:[CALayer layer]];
228        [_webViewPlaceholder.get() setWantsLayer:YES];
229    }
230    [[_webViewPlaceholder.get() layer] setContents:(id)webViewContents.get()];
231    _scrollPosition = [_webView _mainCoreFrame]->view()->scrollPosition();
232    [self _swapView:_webView with:_webViewPlaceholder.get()];
233
234    // Then insert the WebView into the full screen window
235    NSView* contentView = [[self window] contentView];
236    [contentView addSubview:_webView positioned:NSWindowBelow relativeTo:nil];
237    [_webView setFrame:[contentView bounds]];
238    [[_webViewPlaceholder.get() window] recalculateKeyViewLoop];
239
240    [[self window] makeResponder:webWindowFirstResponder firstResponderIfDescendantOfView:_webView];
241
242    [self _document]->webkitWillEnterFullScreenForElement(_element.get());
243    [self _document]->setAnimatingFullScreen(true);
244    [self _document]->updateLayout();
245
246    _finalFrame = screenRectOfContents(_element.get());
247
248    [self _updateMenuAndDockForFullScreen];
249
250    [self _startEnterFullScreenAnimationWithDuration:defaultAnimationDuration];
251
252    _isEnteringFullScreen = true;
253}
254
255- (void)finishedEnterFullScreenAnimation:(bool)completed
256{
257    if (!_isEnteringFullScreen)
258        return;
259    _isEnteringFullScreen = NO;
260
261    if (completed) {
262        // Screen updates to be re-enabled at the end of this block
263        NSDisableScreenUpdates();
264        [self _document]->setAnimatingFullScreen(false);
265        [self _document]->webkitDidEnterFullScreenForElement(_element.get());
266
267        NSRect windowBounds = [[self window] frame];
268        windowBounds.origin = NSZeroPoint;
269        WKWindowSetClipRect([self window], windowBounds);
270
271        NSWindow *webWindow = [_webViewPlaceholder.get() window];
272        // In Lion, NSWindow will animate into and out of orderOut operations. Suppress that
273        // behavior here, making sure to reset the animation behavior afterward.
274        NSWindowAnimationBehavior animationBehavior = [webWindow animationBehavior];
275        [webWindow setAnimationBehavior:NSWindowAnimationBehaviorNone];
276        [webWindow orderOut:self];
277        [webWindow setAnimationBehavior:animationBehavior];
278
279        [_fadeAnimation.get() stopAnimation];
280        [_fadeAnimation.get() setWindow:nil];
281        _fadeAnimation = nullptr;
282
283        [_backgroundWindow.get() orderOut:self];
284        [_backgroundWindow.get() setFrame:NSZeroRect display:YES];
285        NSEnableScreenUpdates();
286    } else
287        [_scaleAnimation.get() stopAnimation];
288}
289
290- (void)requestExitFullScreen
291{
292    if (!_element)
293        return;
294    _element->document().webkitCancelFullScreen();
295}
296
297- (void)exitFullScreen
298{
299    if (!_isFullScreen)
300        return;
301    _isFullScreen = NO;
302
303    // Screen updates to be re-enabled in beganExitFullScreenWithInitialFrame:finalFrame:
304    NSDisableScreenUpdates();
305    [[self window] setAutodisplay:NO];
306
307    _finalFrame = screenRectOfContents(_element.get());
308
309    [self _document]->webkitWillExitFullScreenForElement(_element.get());
310    [self _document]->setAnimatingFullScreen(true);
311
312    if (_isEnteringFullScreen)
313        [self finishedEnterFullScreenAnimation:NO];
314
315    [self _updateMenuAndDockForFullScreen];
316
317    NSWindow* webWindow = [_webViewPlaceholder.get() window];
318    // In Lion, NSWindow will animate into and out of orderOut operations. Suppress that
319    // behavior here, making sure to reset the animation behavior afterward.
320    NSWindowAnimationBehavior animationBehavior = [webWindow animationBehavior];
321    [webWindow setAnimationBehavior:NSWindowAnimationBehaviorNone];
322    // If the user has moved the fullScreen window into a new space, temporarily change
323    // the collectionBehavior of the webView's window so that it is pulled into the active space:
324    if (!([webWindow respondsToSelector:@selector(isOnActiveSpace)] ? [webWindow isOnActiveSpace] : YES)) {
325        NSWindowCollectionBehavior behavior = [webWindow collectionBehavior];
326        [webWindow setCollectionBehavior:NSWindowCollectionBehaviorCanJoinAllSpaces];
327        [webWindow orderWindow:NSWindowBelow relativeTo:[[self window] windowNumber]];
328        [webWindow setCollectionBehavior:behavior];
329    } else
330        [webWindow orderWindow:NSWindowBelow relativeTo:[[self window] windowNumber]];
331    [webWindow setAnimationBehavior:animationBehavior];
332
333    [self _startExitFullScreenAnimationWithDuration:defaultAnimationDuration];
334    _isExitingFullScreen = YES;
335}
336
337- (void)finishedExitFullScreenAnimation:(bool)completed
338{
339    if (!_isExitingFullScreen)
340        return;
341    _isExitingFullScreen = NO;
342
343    [self _updateMenuAndDockForFullScreen];
344
345    // Screen updates to be re-enabled at the end of this function
346    NSDisableScreenUpdates();
347
348    [self _document]->setAnimatingFullScreen(false);
349    [self _document]->webkitDidExitFullScreenForElement(_element.get());
350
351    NSResponder *firstResponder = [[self window] firstResponder];
352    [self _swapView:_webViewPlaceholder.get() with:_webView];
353    [_webView _mainCoreFrame]->view()->setScrollPosition(_scrollPosition);
354    [[_webView window] makeResponder:firstResponder firstResponderIfDescendantOfView:_webView];
355
356    NSRect windowBounds = [[self window] frame];
357    windowBounds.origin = NSZeroPoint;
358    WKWindowSetClipRect([self window], windowBounds);
359
360    [[self window] orderOut:self];
361    [[self window] setFrame:NSZeroRect display:YES];
362
363    [_fadeAnimation.get() stopAnimation];
364    [_fadeAnimation.get() setWindow:nil];
365    _fadeAnimation = nullptr;
366
367    [_backgroundWindow.get() orderOut:self];
368    [_backgroundWindow.get() setFrame:NSZeroRect display:YES];
369
370    [[_webView window] makeKeyAndOrderFront:self];
371
372    NSEnableScreenUpdates();
373}
374
375- (void)performClose:(id)sender
376{
377    if (_isFullScreen)
378        [self cancelOperation:sender];
379}
380
381- (void)close
382{
383    // We are being asked to close rapidly, most likely because the page
384    // has closed or the web process has crashed.  Just walk through our
385    // normal exit full screen sequence, but don't wait to be called back
386    // in response.
387    if (_isFullScreen)
388        [self exitFullScreen];
389
390    if (_isExitingFullScreen)
391        [self finishedExitFullScreenAnimation:YES];
392
393    [super close];
394}
395
396#pragma mark -
397#pragma mark NSAnimation delegate
398
399- (void)animationDidEnd:(NSAnimation*)animation
400{
401    if (_isFullScreen)
402        [self finishedEnterFullScreenAnimation:YES];
403    else
404        [self finishedExitFullScreenAnimation:YES];
405}
406
407#pragma mark -
408#pragma mark Internal Interface
409
410- (void)_updateMenuAndDockForFullScreen
411{
412    NSApplicationPresentationOptions options = NSApplicationPresentationDefault;
413    NSScreen* fullscreenScreen = [[self window] screen];
414
415    if (_isFullScreen) {
416        // Auto-hide the menu bar if the fullscreenScreen contains the menu bar:
417        // NOTE: if the fullscreenScreen contains the menu bar but not the dock, we must still
418        // auto-hide the dock, or an exception will be thrown.
419        if ([[NSScreen screens] objectAtIndex:0] == fullscreenScreen)
420            options |= (NSApplicationPresentationAutoHideMenuBar | NSApplicationPresentationAutoHideDock);
421        // Check if the current screen contains the dock by comparing the screen's frame to its
422        // visibleFrame; if a dock is present, the visibleFrame will differ. If the current screen
423        // contains the dock, hide it.
424        else if (!NSEqualRects([fullscreenScreen frame], [fullscreenScreen visibleFrame]))
425            options |= NSApplicationPresentationAutoHideDock;
426    }
427
428    if ([NSApp respondsToSelector:@selector(setPresentationOptions:)])
429        [NSApp setPresentationOptions:options];
430    else
431        SetSystemUIMode(_isFullScreen ? kUIModeAllHidden : kUIModeNormal, 0);
432}
433
434#pragma mark -
435#pragma mark Utility Functions
436
437- (Document*)_document
438{
439    return &_element->document();
440}
441
442- (void)_swapView:(NSView*)view with:(NSView*)otherView
443{
444    [CATransaction begin];
445    [CATransaction setDisableActions:YES];
446    [otherView setFrame:[view frame]];
447    [otherView setAutoresizingMask:[view autoresizingMask]];
448    [otherView removeFromSuperview];
449    [[view superview] addSubview:otherView positioned:NSWindowAbove relativeTo:view];
450    [view removeFromSuperview];
451    [CATransaction commit];
452}
453
454static RetainPtr<NSWindow> createBackgroundFullscreenWindow(NSRect frame)
455{
456    NSWindow *window = [[NSWindow alloc] initWithContentRect:frame styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO];
457    [window setOpaque:YES];
458    [window setBackgroundColor:[NSColor blackColor]];
459    [window setReleasedWhenClosed:NO];
460    return adoptNS(window);
461}
462
463static NSRect windowFrameFromApparentFrames(NSRect screenFrame, NSRect initialFrame, NSRect finalFrame)
464{
465    NSRect initialWindowFrame;
466    if (!NSWidth(initialFrame) || !NSWidth(finalFrame) || !NSHeight(initialFrame) || !NSHeight(finalFrame))
467        return screenFrame;
468
469    CGFloat xScale = NSWidth(screenFrame) / NSWidth(finalFrame);
470    CGFloat yScale = NSHeight(screenFrame) / NSHeight(finalFrame);
471    CGFloat xTrans = NSMinX(screenFrame) - NSMinX(finalFrame);
472    CGFloat yTrans = NSMinY(screenFrame) - NSMinY(finalFrame);
473    initialWindowFrame.size = NSMakeSize(NSWidth(initialFrame) * xScale, NSHeight(initialFrame) * yScale);
474    initialWindowFrame.origin = NSMakePoint
475    ( NSMinX(initialFrame) + xTrans / (NSWidth(finalFrame) / NSWidth(initialFrame))
476     , NSMinY(initialFrame) + yTrans / (NSHeight(finalFrame) / NSHeight(initialFrame)));
477    return initialWindowFrame;
478}
479
480- (void)_startEnterFullScreenAnimationWithDuration:(NSTimeInterval)duration
481{
482    NSRect screenFrame = [[[self window] screen] frame];
483    NSRect initialWindowFrame = windowFrameFromApparentFrames(screenFrame, _initialFrame, _finalFrame);
484
485    _scaleAnimation = adoptNS([[WebWindowScaleAnimation alloc] initWithHintedDuration:duration window:[self window] initalFrame:initialWindowFrame finalFrame:screenFrame]);
486
487    [_scaleAnimation.get() setAnimationBlockingMode:NSAnimationNonblocking];
488    [_scaleAnimation.get() setDelegate:self];
489    [_scaleAnimation.get() setCurrentProgress:0];
490    [_scaleAnimation.get() startAnimation];
491
492    // WKWindowSetClipRect takes window coordinates, so convert from screen coordinates here:
493    NSRect finalBounds = _finalFrame;
494#pragma clang diagnostic push
495#pragma clang diagnostic ignored "-Wdeprecated-declarations"
496    finalBounds.origin = [[self window] convertScreenToBase:finalBounds.origin];
497#pragma clang diagnostic pop
498    WKWindowSetClipRect([self window], finalBounds);
499
500    [[self window] makeKeyAndOrderFront:self];
501
502    if (!_backgroundWindow)
503        _backgroundWindow = createBackgroundFullscreenWindow(screenFrame);
504    else
505        [_backgroundWindow.get() setFrame:screenFrame display:NO];
506
507    CGFloat currentAlpha = 0;
508    if (_fadeAnimation) {
509        currentAlpha = [_fadeAnimation.get() currentAlpha];
510        [_fadeAnimation.get() stopAnimation];
511        [_fadeAnimation.get() setWindow:nil];
512    }
513
514    _fadeAnimation = adoptNS([[WebWindowFadeAnimation alloc] initWithDuration:duration
515                                                                       window:_backgroundWindow.get()
516                                                                 initialAlpha:currentAlpha
517                                                                   finalAlpha:1]);
518    [_fadeAnimation.get() setAnimationBlockingMode:NSAnimationNonblocking];
519    [_fadeAnimation.get() setCurrentProgress:0];
520    [_fadeAnimation.get() startAnimation];
521
522    [_backgroundWindow.get() orderWindow:NSWindowBelow relativeTo:[[self window] windowNumber]];
523
524    [[self window] setAutodisplay:YES];
525    [[self window] displayIfNeeded];
526    // Screen updates disabled in enterFullScreen:
527    NSEnableScreenUpdates();
528}
529
530- (void)_startExitFullScreenAnimationWithDuration:(NSTimeInterval)duration
531{
532    NSRect screenFrame = [[[self window] screen] frame];
533    NSRect initialWindowFrame = windowFrameFromApparentFrames(screenFrame, _initialFrame, _finalFrame);
534
535    NSRect currentFrame = _scaleAnimation ? [_scaleAnimation.get() currentFrame] : [[self window] frame];
536    _scaleAnimation = adoptNS([[WebWindowScaleAnimation alloc] initWithHintedDuration:duration window:[self window] initalFrame:currentFrame finalFrame:initialWindowFrame]);
537
538    [_scaleAnimation.get() setAnimationBlockingMode:NSAnimationNonblocking];
539    [_scaleAnimation.get() setDelegate:self];
540    [_scaleAnimation.get() setCurrentProgress:0];
541    [_scaleAnimation.get() startAnimation];
542
543    if (!_backgroundWindow)
544        _backgroundWindow = createBackgroundFullscreenWindow(screenFrame);
545    else
546        [_backgroundWindow.get() setFrame:screenFrame display:NO];
547
548    CGFloat currentAlpha = 1;
549    if (_fadeAnimation) {
550        currentAlpha = [_fadeAnimation.get() currentAlpha];
551        [_fadeAnimation.get() stopAnimation];
552        [_fadeAnimation.get() setWindow:nil];
553    }
554    _fadeAnimation = adoptNS([[WebWindowFadeAnimation alloc] initWithDuration:duration
555                                                                       window:_backgroundWindow.get()
556                                                                 initialAlpha:currentAlpha
557                                                                   finalAlpha:0]);
558    [_fadeAnimation.get() setAnimationBlockingMode:NSAnimationNonblocking];
559    [_fadeAnimation.get() setCurrentProgress:0];
560    [_fadeAnimation.get() startAnimation];
561
562    [_backgroundWindow.get() orderWindow:NSWindowBelow relativeTo:[[self window] windowNumber]];
563
564    // WKWindowSetClipRect takes window coordinates, so convert from screen coordinates here:
565    NSRect finalBounds = _finalFrame;
566#pragma clang diagnostic push
567#pragma clang diagnostic ignored "-Wdeprecated-declarations"
568    finalBounds.origin = [[self window] convertScreenToBase:finalBounds.origin];
569#pragma clang diagnostic pop
570    WKWindowSetClipRect([self window], finalBounds);
571
572    [[self window] setAutodisplay:YES];
573    [[self window] displayIfNeeded];
574
575    // Screen updates disabled in exitFullScreen:
576    NSEnableScreenUpdates();
577}
578
579@end
580
581
582#endif /* ENABLE(FULLSCREEN_API) && !PLATFORM(IOS) */
583