Remove WebCoreSystemInterface
[WebKit-https.git] / Source / WebCore / platform / ios / wak / WAKWindow.mm
1 /*
2  * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2014 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 #import "config.h"
27 #import "WAKWindow.h"
28
29 #if PLATFORM(IOS)
30
31 #import "LegacyTileCache.h"
32 #import "PlatformScreen.h"
33 #import "WAKViewInternal.h"
34 #import "WebCoreThreadRun.h"
35 #import "WebEvent.h"
36 #import "WKContentObservation.h"
37 #import "WKViewPrivate.h"
38 #import <QuartzCore/QuartzCore.h>
39 #import <wtf/Lock.h>
40
41 WEBCORE_EXPORT NSString * const WAKWindowScreenScaleDidChangeNotification = @"WAKWindowScreenScaleDidChangeNotification";
42 WEBCORE_EXPORT NSString * const WAKWindowVisibilityDidChangeNotification = @"WAKWindowVisibilityDidChangeNotification";
43
44 using namespace WebCore;
45
46 @protocol OrientationProvider
47 - (BOOL)hasLandscapeOrientation;
48 @end
49
50 static WAKWindow *_WAKKeyWindow = nil;        // weak
51 static WebEvent *currentEvent = nil;
52 static id<OrientationProvider> gOrientationProvider;
53
54 @implementation WAKWindow {
55     Lock _exposedScrollViewRectLock;
56     CGRect _exposedScrollViewRect;
57 }
58
59 @synthesize useOrientationDependentFontAntialiasing = _useOrientationDependentFontAntialiasing;
60
61 - (id)initWithLayer:(CALayer *)layer
62 {
63     self = [super init];
64     if (!self)
65         return nil;
66
67     _hostLayer = [layer retain];
68
69     _frame = [_hostLayer frame];
70     _screenScale = screenScaleFactor();
71     
72     _tileCache = new LegacyTileCache(self);
73
74     _frozenVisibleRect = CGRectNull;
75
76     _exposedScrollViewRect = CGRectNull;
77
78     return self;
79 }
80
81 // This is used for WebViews that are not backed by the tile cache. Their content must be painted manually.
82 - (id)initWithFrame:(CGRect)frame
83 {
84     self = [super init];
85     if (!self)
86         return nil;
87
88     _frame = frame;
89     _screenScale = screenScaleFactor();
90
91     _exposedScrollViewRect = CGRectNull;
92
93     return self;
94 }
95
96 - (void)dealloc
97 {
98     delete _tileCache;
99     [_hostLayer release];
100     
101     [super dealloc];
102 }
103
104 - (void)setContentView:(WAKView *)aView
105 {
106     [aView retain];
107     [_contentView release];
108
109     if (aView)
110         _WKViewSetWindow([aView _viewRef], self);
111     _contentView = aView;
112 }
113
114 - (WAKView *)contentView
115 {
116     return _contentView;
117 }
118
119 - (void)close
120 {
121     if (_contentView) {
122         _WKViewSetWindow([_contentView _viewRef], nil);
123         [_contentView release];
124         _contentView = nil;
125     }
126
127     [_responderView release];
128     _responderView = nil;
129 }
130
131 - (WAKView *)firstResponder
132 {
133     return _responderView;
134 }
135
136 - (WAKView *)_newFirstResponderAfterResigning
137 {
138     return _nextResponder;
139 }
140
141 - (NSPoint)convertBaseToScreen:(NSPoint)aPoint
142 {
143     CALayer* rootLayer = _hostLayer;
144     while (rootLayer.superlayer)
145         rootLayer = rootLayer.superlayer;
146     
147     return [_hostLayer convertPoint:aPoint toLayer:rootLayer];
148 }
149
150 - (NSPoint)convertScreenToBase:(NSPoint)aPoint
151 {
152     CALayer* rootLayer = _hostLayer;
153     while (rootLayer.superlayer)
154         rootLayer = rootLayer.superlayer;
155     
156     return [_hostLayer convertPoint:aPoint fromLayer:rootLayer];
157 }
158
159 - (NSRect)convertRectToScreen:(NSRect)windowRect
160 {
161     CALayer* rootLayer = _hostLayer;
162     while (rootLayer.superlayer)
163         rootLayer = rootLayer.superlayer;
164
165     return [_hostLayer convertRect:windowRect toLayer:rootLayer];
166 }
167
168 - (NSRect)convertRectFromScreen:(NSRect)screenRect
169 {
170     CALayer* rootLayer = _hostLayer;
171     while (rootLayer.superlayer)
172         rootLayer = rootLayer.superlayer;
173
174     return [_hostLayer convertRect:screenRect fromLayer:rootLayer];
175 }
176
177 - (BOOL)isKeyWindow
178 {
179     return YES || self == _WAKKeyWindow; 
180 }
181
182 - (void)makeKeyWindow
183 {
184     if ([self isKeyWindow])
185         return;
186     
187     _WAKKeyWindow = self;
188 }
189
190 - (BOOL)isVisible
191 {
192     return _visible;
193 }
194
195 - (void)setVisible:(BOOL)visible
196 {
197     if (_visible == visible)
198         return;
199
200     _visible = visible;
201
202     WebThreadRun(^{
203         [[NSNotificationCenter defaultCenter] postNotificationName:WAKWindowVisibilityDidChangeNotification object:self userInfo:nil];
204     });
205 }
206
207 - (NSSelectionDirection)keyViewSelectionDirection
208 {
209     return (NSSelectionDirection)0;
210 }
211
212 - (BOOL)makeFirstResponder:(NSResponder *)aResponder
213 {
214     if (![aResponder isKindOfClass:[WAKView class]])
215         return NO;
216
217     WAKView *view = static_cast<WAKView*>(aResponder);
218     BOOL result = YES;
219     if (view != _responderView) {
220         // We need to handle the case of the view not accepting to be a first responder,
221         // where we don't need to resign as first responder.
222         BOOL acceptsFirstResponder = view ? WKViewAcceptsFirstResponder([view _viewRef]) : YES;
223         if (acceptsFirstResponder && _responderView) {
224             _nextResponder = view;
225             if (WKViewResignFirstResponder([_responderView _viewRef])) {
226                 _nextResponder = nil;
227                 [_responderView release];
228                 _responderView = nil;
229             }  else {
230                 _nextResponder = nil;
231                 result = NO;
232             }
233         }
234
235         if (result && view) {
236             if (acceptsFirstResponder && WKViewBecomeFirstResponder([view _viewRef]))
237                 _responderView = [view retain];
238             else
239                 result = NO;
240         }
241     }
242
243     return result;
244 }
245
246 // FIXME: This method can lead to incorrect state. Remove if possible.
247 - (void)setFrame:(NSRect)frameRect display:(BOOL)flag
248 {
249     UNUSED_PARAM(flag);
250     _frame = frameRect;
251 }
252
253 // FIXME: the correct value if there is a host layer is likely to return [_hostLayer frame].
254 - (CGRect)frame
255 {
256     return _frame;
257 }
258
259 - (void)setContentRect:(CGRect)rect
260 {
261     if (CGRectEqualToRect(rect, _frame))
262         return;
263     _frame = rect;
264
265     // FIXME: Size of the host layer is directly available so there is no real reason to save it here.
266     // However we currently use this call to catch changes to the host layer size.
267     if (_tileCache)
268         _tileCache->hostLayerSizeChanged();
269 }
270
271 - (void)setScreenSize:(CGSize)size
272 {
273     _screenSize = size;
274 }
275
276 - (CGSize)screenSize
277 {
278     return _screenSize;
279 }
280
281 - (void)setAvailableScreenSize:(CGSize)size
282 {
283     _availableScreenSize = size;
284 }
285
286 - (CGSize)availableScreenSize
287 {
288     return _availableScreenSize;
289 }
290
291 - (void)setScreenScale:(CGFloat)scale
292 {
293     _screenScale = scale;
294
295     WebThreadRun(^{
296         [[NSNotificationCenter defaultCenter] postNotificationName:WAKWindowScreenScaleDidChangeNotification object:self userInfo:nil];
297     });
298 }
299
300 - (CGFloat)screenScale
301 {
302     return _screenScale;
303 }
304
305 - (void)setRootLayer:(CALayer *)layer
306 {
307     _rootLayer = layer;
308 }
309
310 - (CALayer *)rootLayer
311 {
312     return _rootLayer;
313 }
314
315 - (void)sendEvent:(WebEvent *)anEvent
316 {
317     ASSERT(anEvent);
318     WebThreadRun(^{
319         [self sendEventSynchronously:anEvent];
320     });
321 }
322
323 - (void)sendEventSynchronously:(WebEvent *)anEvent
324 {
325     ASSERT(anEvent);
326     ASSERT(WebThreadIsLockedOrDisabled());
327     WebEvent *lastEvent = currentEvent;
328     currentEvent = [anEvent retain];
329
330     switch (anEvent.type) {
331         case WebEventMouseMoved:
332         case WebEventScrollWheel:
333             if (WAKView *hitView = [_contentView hitTest:(anEvent.locationInWindow)])
334                 [hitView handleEvent:anEvent];
335             break;
336
337         case WebEventMouseUp:
338         case WebEventKeyDown:
339         case WebEventKeyUp:
340         case WebEventTouchChange:
341             [_responderView handleEvent:anEvent];
342             break;
343
344         case WebEventMouseDown:
345         case WebEventTouchBegin:
346         case WebEventTouchEnd:
347         case WebEventTouchCancel:
348             if (WAKView *hitView = [_contentView hitTest:(anEvent.locationInWindow)]) {
349                 [self makeFirstResponder:hitView];
350                 [hitView handleEvent:anEvent];
351             }
352             break;
353
354         default:
355             ASSERT_NOT_REACHED();
356             break;
357     }
358
359     [currentEvent release];
360     currentEvent = lastEvent;
361 }
362
363 - (void)sendMouseMoveEvent:(WebEvent *)anEvent contentChange:(WKContentChange *)aContentChange
364 {
365     WebThreadRun(^{
366         [self sendEvent:anEvent];
367
368         if (aContentChange)
369             *aContentChange = WKObservedContentChange();
370     });
371 }
372
373 - (void)setExposedScrollViewRect:(CGRect)exposedScrollViewRect
374 {
375     LockHolder locker(&_exposedScrollViewRectLock);
376     _exposedScrollViewRect = exposedScrollViewRect;
377 }
378
379 - (CGRect)exposedScrollViewRect
380 {
381     {
382         LockHolder locker(&_exposedScrollViewRectLock);
383         if (!CGRectIsNull(_exposedScrollViewRect))
384             return _exposedScrollViewRect;
385     }
386     return [self visibleRect];
387 }
388
389 // Tiling
390
391 - (void)layoutTiles
392 {
393     if (!_tileCache)
394         return;    
395     _tileCache->layoutTiles();
396 }
397
398 - (void)layoutTilesNow
399 {
400     if (!_tileCache)
401         return;
402     _tileCache->layoutTilesNow();
403 }
404
405 - (void)layoutTilesNowForRect:(CGRect)rect
406 {
407     if (!_tileCache)
408         return;
409     _tileCache->layoutTilesNowForRect(enclosingIntRect(rect));
410 }
411
412 - (void)setNeedsDisplay
413 {
414     if (!_tileCache)
415         return;
416     _tileCache->setNeedsDisplay();
417 }
418
419 - (void)setNeedsDisplayInRect:(CGRect)rect
420 {
421     if (!_tileCache)
422         return;
423     _tileCache->setNeedsDisplayInRect(enclosingIntRect(rect));
424 }
425
426 - (BOOL)tilesOpaque
427 {
428     if (!_tileCache)
429         return NO;
430     return _tileCache->tilesOpaque();
431 }
432
433 - (void)setTilesOpaque:(BOOL)opaque
434 {
435     if (!_tileCache)
436         return;
437     _tileCache->setTilesOpaque(opaque);
438 }
439
440 - (void)setIsInSnapshottingPaint:(BOOL)isInSnapshottingPaint
441 {
442     _isInSnapshottingPaint = isInSnapshottingPaint;
443 }
444
445 - (BOOL)isInSnapshottingPaint
446 {
447     return _isInSnapshottingPaint;
448 }
449
450 - (void)setEntireWindowVisibleForTesting:(BOOL)entireWindowVisible
451 {
452     _entireWindowVisibleForTesting = entireWindowVisible;
453 }
454
455 - (CGRect)_visibleRectRespectingMasksToBounds:(BOOL)respectsMasksToBounds
456 {
457     if (!CGRectIsNull(_frozenVisibleRect))
458         return _frozenVisibleRect;
459
460     CALayer* layer = _hostLayer;
461     CGRect bounds = [layer bounds];
462     if (_entireWindowVisibleForTesting)
463         return bounds;
464     CGRect rect = bounds;
465     CALayer* superlayer = [layer superlayer];
466
467     static Class windowClass = NSClassFromString(@"UIWindow");
468
469     while (superlayer && layer != _rootLayer && (!layer.delegate || ![layer.delegate isKindOfClass:windowClass])) {
470         CGRect rectInSuper = [superlayer convertRect:rect fromLayer:layer];
471         if ([superlayer masksToBounds] || !respectsMasksToBounds)
472             rect = CGRectIntersection([superlayer bounds], rectInSuper);
473         else
474             rect = rectInSuper;
475         layer = superlayer;
476         superlayer = [layer superlayer];
477     }
478     
479     if (layer != _hostLayer) {
480         rect = CGRectIntersection([layer bounds], rect);
481         rect = [_hostLayer convertRect:rect fromLayer:layer];
482     }
483     
484     return CGRectIntersection(bounds, rect);
485 }
486
487 - (CGRect)visibleRect
488 {
489     return [self _visibleRectRespectingMasksToBounds:NO];
490 }
491
492 - (CGRect)extendedVisibleRect
493 {
494     return [self _visibleRectRespectingMasksToBounds:YES];
495 }
496
497 - (void)removeAllNonVisibleTiles
498 {
499     if (!_tileCache)
500         return;
501     _tileCache->removeAllNonVisibleTiles();
502 }
503
504 - (void)removeAllTiles
505 {
506     if (!_tileCache)
507         return;
508     _tileCache->removeAllTiles();
509 }
510
511 - (void)removeForegroundTiles
512 {
513     if (!_tileCache)
514         return;
515     _tileCache->removeForegroundTiles();
516 }
517
518 - (void)setTilingMode:(WAKWindowTilingMode)mode
519 {
520     if (!_tileCache)
521         return;
522     _tileCache->setTilingMode((LegacyTileCache::TilingMode)mode);
523 }
524
525 - (WAKWindowTilingMode)tilingMode
526 {
527     if (!_tileCache)
528         return kWAKWindowTilingModeDisabled;
529     return (WAKWindowTilingMode)_tileCache->tilingMode();
530 }
531
532 - (void)setTilingDirection:(WAKTilingDirection)tilingDirection
533 {
534     if (!_tileCache)
535         return;
536     _tileCache->setTilingDirection((LegacyTileCache::TilingDirection)tilingDirection);
537 }
538
539 - (WAKTilingDirection)tilingDirection
540 {
541     if (!_tileCache)
542         return kWAKTilingDirectionDown;
543     return (WAKTilingDirection)_tileCache->tilingDirection();
544 }
545
546 - (void)setZoomedOutTileScale:(float)scale
547 {
548     if (!_tileCache)
549         return;
550     _tileCache->setZoomedOutScale(scale);
551 }
552
553 - (float)zoomedOutTileScale
554 {
555     if (!_tileCache)
556         return 1.0f;
557     return _tileCache->zoomedOutScale();
558 }
559
560 - (void)setCurrentTileScale:(float)scale
561 {
562     if (!_tileCache)
563         return;
564     _tileCache->setCurrentScale(scale);
565 }
566
567 - (float)currentTileScale
568 {
569     if (!_tileCache)
570         return 1.0f;
571     return _tileCache->currentScale();
572 }
573
574 - (void)setKeepsZoomedOutTiles:(BOOL)keepsZoomedOutTiles
575 {
576     if (!_tileCache)
577         return;
578     _tileCache->setKeepsZoomedOutTiles(keepsZoomedOutTiles);
579 }
580
581 - (BOOL)keepsZoomedOutTiles
582 {
583     if (!_tileCache)
584         return NO;
585     return _tileCache->keepsZoomedOutTiles();
586 }
587
588 - (LegacyTileCache*)tileCache
589 {
590     return _tileCache;
591 }
592
593 - (BOOL)hasPendingDraw
594 {
595     if (!_tileCache)
596         return NO;
597      return _tileCache->hasPendingDraw();
598 }
599
600 - (void)setContentReplacementImage:(CGImageRef)contentReplacementImage
601 {
602     if (!_tileCache)
603         return;
604     _tileCache->setContentReplacementImage(contentReplacementImage);
605 }
606
607 - (CGImageRef)contentReplacementImage
608 {
609     if (!_tileCache)
610         return NULL;
611     return _tileCache->contentReplacementImage().get();
612 }
613
614 - (void)displayRect:(NSRect)rect
615 {
616     [[self contentView] displayRect:rect];
617 }
618
619 - (void)willRotate
620 {
621     [self freezeVisibleRect];
622 }
623
624 - (void)didRotate
625 {
626     [self unfreezeVisibleRect];
627 }
628
629 - (void)freezeVisibleRect
630 {
631     _frozenVisibleRect = [self visibleRect];
632 }
633
634 - (void)unfreezeVisibleRect
635 {
636     _frozenVisibleRect = CGRectNull;
637 }
638
639 + (void)setOrientationProvider:(id)provider
640 {
641     // This is really the UIWebDocumentView class that calls into UIApplication to get the orientation.
642     gOrientationProvider = provider;
643 }
644
645 + (BOOL)hasLandscapeOrientation
646 {
647     // this should be perfectly thread safe
648     return [gOrientationProvider hasLandscapeOrientation];
649 }
650
651 - (CALayer*)hostLayer
652 {
653     return _hostLayer;
654 }
655
656 - (void)setTileBordersVisible:(BOOL)visible
657 {
658     if (!_tileCache)
659         return;
660
661     _tileCache->setTileBordersVisible(visible);
662 }
663
664 - (void)setTilePaintCountsVisible:(BOOL)visible
665 {
666     if (!_tileCache)
667         return;
668
669     _tileCache->setTilePaintCountersVisible(visible);
670 }
671
672 - (void)setAcceleratedDrawingEnabled:(BOOL)enabled
673 {
674     if (!_tileCache)
675         return;
676
677     _tileCache->setAcceleratedDrawingEnabled(enabled);
678 }
679
680 - (void)dumpTiles
681 {
682     CGRect savedFrozenVisibleRect = _frozenVisibleRect;
683     NSLog(@"=================");
684     if (!CGRectIsNull(_frozenVisibleRect)) {
685         NSLog(@"VISIBLE RECT IS CACHED: [%6.1f %6.1f %6.1f %6.1f]", _frozenVisibleRect.origin.x, _frozenVisibleRect.origin.y, _frozenVisibleRect.size.width, _frozenVisibleRect.size.height);
686         _frozenVisibleRect = CGRectNull;
687     }
688     CGRect visibleRect = [self visibleRect];
689     NSLog(@"visibleRect = [%6.1f %6.1f %6.1f %6.1f]", visibleRect.origin.x, visibleRect.origin.y, visibleRect.size.width, visibleRect.size.height);
690     _frozenVisibleRect = savedFrozenVisibleRect;
691     _tileCache->dumpTiles();
692 }
693
694 - (void)setTileControllerShouldUseLowScaleTiles:(BOOL)lowScaleTiles 
695
696     if (!_tileCache) 
697         return; 
698
699     _tileCache->setTileControllerShouldUseLowScaleTiles(lowScaleTiles); 
700
701
702 - (NSString *)description
703 {
704     NSMutableString *description = [NSMutableString stringWithFormat:@"<%@: WAK: %p; ", [self class], self];
705
706     CGRect frame = [self frame];
707     [description appendFormat:@"frame = (%g %g; %g %g); ", frame.origin.x, frame.origin.y, frame.size.width, frame.size.height];
708
709     [description appendFormat:@"first responder = WK %p; ", _responderView];
710     [description appendFormat:@"next responder = WK %p; ", _nextResponder];
711
712     [description appendFormat:@"layer = %@>", [_hostLayer description]];
713
714     return description;
715 }
716
717 + (WebEvent *)currentEvent
718 {
719     return currentEvent;
720 }
721
722 - (NSString *)recursiveDescription
723 {
724     NSMutableString *info = [NSMutableString string];
725
726     [info appendString:[self description]];
727
728     [[self contentView] _appendDescriptionToString:info atLevel:1];
729
730     return info;
731 }
732
733 @end
734
735 #endif // PLATFORM(IOS)