Clean up USE(WEB_THREAD)
[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_FAMILY)
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 #if USE(WEB_THREAD)
203     WebThreadRun(^{
204         [[NSNotificationCenter defaultCenter] postNotificationName:WAKWindowVisibilityDidChangeNotification object:self userInfo:nil];
205     });
206 #else
207     [[NSNotificationCenter defaultCenter] postNotificationName:WAKWindowVisibilityDidChangeNotification object:self userInfo:nil];
208 #endif
209 }
210
211 - (NSSelectionDirection)keyViewSelectionDirection
212 {
213     return (NSSelectionDirection)0;
214 }
215
216 - (BOOL)makeFirstResponder:(NSResponder *)aResponder
217 {
218     if (![aResponder isKindOfClass:[WAKView class]])
219         return NO;
220
221     WAKView *view = static_cast<WAKView*>(aResponder);
222     BOOL result = YES;
223     if (view != _responderView) {
224         // We need to handle the case of the view not accepting to be a first responder,
225         // where we don't need to resign as first responder.
226         BOOL acceptsFirstResponder = view ? WKViewAcceptsFirstResponder([view _viewRef]) : YES;
227         if (acceptsFirstResponder && _responderView) {
228             _nextResponder = view;
229             if (WKViewResignFirstResponder([_responderView _viewRef])) {
230                 _nextResponder = nil;
231                 [_responderView release];
232                 _responderView = nil;
233             }  else {
234                 _nextResponder = nil;
235                 result = NO;
236             }
237         }
238
239         if (result && view) {
240             if (acceptsFirstResponder && WKViewBecomeFirstResponder([view _viewRef]))
241                 _responderView = [view retain];
242             else
243                 result = NO;
244         }
245     }
246
247     return result;
248 }
249
250 // FIXME: This method can lead to incorrect state. Remove if possible.
251 - (void)setFrame:(NSRect)frameRect display:(BOOL)flag
252 {
253     UNUSED_PARAM(flag);
254     _frame = frameRect;
255 }
256
257 // FIXME: the correct value if there is a host layer is likely to return [_hostLayer frame].
258 - (CGRect)frame
259 {
260     return _frame;
261 }
262
263 - (void)setContentRect:(CGRect)rect
264 {
265     if (CGRectEqualToRect(rect, _frame))
266         return;
267     _frame = rect;
268
269     // FIXME: Size of the host layer is directly available so there is no real reason to save it here.
270     // However we currently use this call to catch changes to the host layer size.
271     if (_tileCache)
272         _tileCache->hostLayerSizeChanged();
273 }
274
275 - (void)setScreenSize:(CGSize)size
276 {
277     _screenSize = size;
278 }
279
280 - (CGSize)screenSize
281 {
282     return _screenSize;
283 }
284
285 - (void)setAvailableScreenSize:(CGSize)size
286 {
287     _availableScreenSize = size;
288 }
289
290 - (CGSize)availableScreenSize
291 {
292     return _availableScreenSize;
293 }
294
295 - (void)setScreenScale:(CGFloat)scale
296 {
297     _screenScale = scale;
298
299 #if USE(WEB_THREAD)
300     WebThreadRun(^{
301         [[NSNotificationCenter defaultCenter] postNotificationName:WAKWindowScreenScaleDidChangeNotification object:self userInfo:nil];
302     });
303 #else
304     [[NSNotificationCenter defaultCenter] postNotificationName:WAKWindowScreenScaleDidChangeNotification object:self userInfo:nil];
305 #endif
306 }
307
308 - (CGFloat)screenScale
309 {
310     return _screenScale;
311 }
312
313 - (void)setRootLayer:(CALayer *)layer
314 {
315     _rootLayer = layer;
316 }
317
318 - (CALayer *)rootLayer
319 {
320     return _rootLayer;
321 }
322
323 - (void)sendEvent:(WebEvent *)anEvent
324 {
325     ASSERT(anEvent);
326 #if USE(WEB_THREAD)
327     WebThreadRun(^{
328         [self sendEventSynchronously:anEvent];
329     });
330 #else
331     [self sendEventSynchronously:anEvent];
332 #endif
333 }
334
335 - (void)sendEventSynchronously:(WebEvent *)anEvent
336 {
337     ASSERT(anEvent);
338     ASSERT(WebThreadIsLockedOrDisabled());
339     WebEvent *lastEvent = currentEvent;
340     currentEvent = [anEvent retain];
341
342     switch (anEvent.type) {
343     case WebEventMouseMoved:
344     case WebEventScrollWheel:
345         if (WAKView *hitView = [_contentView hitTest:(anEvent.locationInWindow)])
346             [hitView handleEvent:anEvent];
347         break;
348
349     case WebEventMouseUp:
350     case WebEventKeyDown:
351     case WebEventKeyUp:
352     case WebEventTouchChange:
353         [_responderView handleEvent:anEvent];
354         break;
355
356     case WebEventMouseDown:
357     case WebEventTouchBegin:
358     case WebEventTouchEnd:
359     case WebEventTouchCancel:
360         if (WAKView *hitView = [_contentView hitTest:(anEvent.locationInWindow)]) {
361             [self makeFirstResponder:hitView];
362             [hitView handleEvent:anEvent];
363         }
364         break;
365     }
366
367     [currentEvent release];
368     currentEvent = lastEvent;
369 }
370
371 - (void)sendMouseMoveEvent:(WebEvent *)anEvent contentChange:(WKContentChange *)aContentChange
372 {
373 #if USE(WEB_THREAD)
374     WebThreadRun(^{
375 #endif
376         [self sendEvent:anEvent];
377
378         if (aContentChange)
379             *aContentChange = WKObservedContentChange();
380 #if USE(WEB_THREAD)
381     });
382 #endif
383 }
384
385 - (void)setExposedScrollViewRect:(CGRect)exposedScrollViewRect
386 {
387     LockHolder locker(&_exposedScrollViewRectLock);
388     _exposedScrollViewRect = exposedScrollViewRect;
389 }
390
391 - (CGRect)exposedScrollViewRect
392 {
393     {
394         LockHolder locker(&_exposedScrollViewRectLock);
395         if (!CGRectIsNull(_exposedScrollViewRect))
396             return _exposedScrollViewRect;
397     }
398     return [self visibleRect];
399 }
400
401 // Tiling
402
403 - (void)layoutTiles
404 {
405     if (!_tileCache)
406         return;    
407     _tileCache->layoutTiles();
408 }
409
410 - (void)layoutTilesNow
411 {
412     if (!_tileCache)
413         return;
414     _tileCache->layoutTilesNow();
415 }
416
417 - (void)layoutTilesNowForRect:(CGRect)rect
418 {
419     if (!_tileCache)
420         return;
421     _tileCache->layoutTilesNowForRect(enclosingIntRect(rect));
422 }
423
424 - (void)setNeedsDisplay
425 {
426     if (!_tileCache)
427         return;
428     _tileCache->setNeedsDisplay();
429 }
430
431 - (void)setNeedsDisplayInRect:(CGRect)rect
432 {
433     if (!_tileCache)
434         return;
435     _tileCache->setNeedsDisplayInRect(enclosingIntRect(rect));
436 }
437
438 - (BOOL)tilesOpaque
439 {
440     if (!_tileCache)
441         return NO;
442     return _tileCache->tilesOpaque();
443 }
444
445 - (void)setTilesOpaque:(BOOL)opaque
446 {
447     if (!_tileCache)
448         return;
449     _tileCache->setTilesOpaque(opaque);
450 }
451
452 - (void)setIsInSnapshottingPaint:(BOOL)isInSnapshottingPaint
453 {
454     _isInSnapshottingPaint = isInSnapshottingPaint;
455 }
456
457 - (BOOL)isInSnapshottingPaint
458 {
459     return _isInSnapshottingPaint;
460 }
461
462 - (void)setEntireWindowVisibleForTesting:(BOOL)entireWindowVisible
463 {
464     _entireWindowVisibleForTesting = entireWindowVisible;
465 }
466
467 - (CGRect)_visibleRectRespectingMasksToBounds:(BOOL)respectsMasksToBounds
468 {
469     if (!CGRectIsNull(_frozenVisibleRect))
470         return _frozenVisibleRect;
471
472     CALayer* layer = _hostLayer;
473     CGRect bounds = [layer bounds];
474     if (_entireWindowVisibleForTesting)
475         return bounds;
476     CGRect rect = bounds;
477     CALayer* superlayer = [layer superlayer];
478
479     static Class windowClass = NSClassFromString(@"UIWindow");
480
481     while (superlayer && layer != _rootLayer && (!layer.delegate || ![layer.delegate isKindOfClass:windowClass])) {
482         CGRect rectInSuper = [superlayer convertRect:rect fromLayer:layer];
483         if ([superlayer masksToBounds] || !respectsMasksToBounds)
484             rect = CGRectIntersection([superlayer bounds], rectInSuper);
485         else
486             rect = rectInSuper;
487         layer = superlayer;
488         superlayer = [layer superlayer];
489     }
490     
491     if (layer != _hostLayer) {
492         rect = CGRectIntersection([layer bounds], rect);
493         rect = [_hostLayer convertRect:rect fromLayer:layer];
494     }
495     
496     return CGRectIntersection(bounds, rect);
497 }
498
499 - (CGRect)visibleRect
500 {
501     return [self _visibleRectRespectingMasksToBounds:NO];
502 }
503
504 - (CGRect)extendedVisibleRect
505 {
506     return [self _visibleRectRespectingMasksToBounds:YES];
507 }
508
509 - (void)removeAllNonVisibleTiles
510 {
511     if (!_tileCache)
512         return;
513     _tileCache->removeAllNonVisibleTiles();
514 }
515
516 - (void)removeAllTiles
517 {
518     if (!_tileCache)
519         return;
520     _tileCache->removeAllTiles();
521 }
522
523 - (void)removeForegroundTiles
524 {
525     if (!_tileCache)
526         return;
527     _tileCache->removeForegroundTiles();
528 }
529
530 - (void)setTilingMode:(WAKWindowTilingMode)mode
531 {
532     if (!_tileCache)
533         return;
534     _tileCache->setTilingMode((LegacyTileCache::TilingMode)mode);
535 }
536
537 - (WAKWindowTilingMode)tilingMode
538 {
539     if (!_tileCache)
540         return kWAKWindowTilingModeDisabled;
541     return (WAKWindowTilingMode)_tileCache->tilingMode();
542 }
543
544 - (void)setTilingDirection:(WAKTilingDirection)tilingDirection
545 {
546     if (!_tileCache)
547         return;
548     _tileCache->setTilingDirection((LegacyTileCache::TilingDirection)tilingDirection);
549 }
550
551 - (WAKTilingDirection)tilingDirection
552 {
553     if (!_tileCache)
554         return kWAKTilingDirectionDown;
555     return (WAKTilingDirection)_tileCache->tilingDirection();
556 }
557
558 - (void)setZoomedOutTileScale:(float)scale
559 {
560     if (!_tileCache)
561         return;
562     _tileCache->setZoomedOutScale(scale);
563 }
564
565 - (float)zoomedOutTileScale
566 {
567     if (!_tileCache)
568         return 1.0f;
569     return _tileCache->zoomedOutScale();
570 }
571
572 - (void)setCurrentTileScale:(float)scale
573 {
574     if (!_tileCache)
575         return;
576     _tileCache->setCurrentScale(scale);
577 }
578
579 - (float)currentTileScale
580 {
581     if (!_tileCache)
582         return 1.0f;
583     return _tileCache->currentScale();
584 }
585
586 - (void)setKeepsZoomedOutTiles:(BOOL)keepsZoomedOutTiles
587 {
588     if (!_tileCache)
589         return;
590     _tileCache->setKeepsZoomedOutTiles(keepsZoomedOutTiles);
591 }
592
593 - (BOOL)keepsZoomedOutTiles
594 {
595     if (!_tileCache)
596         return NO;
597     return _tileCache->keepsZoomedOutTiles();
598 }
599
600 - (LegacyTileCache*)tileCache
601 {
602     return _tileCache;
603 }
604
605 - (BOOL)hasPendingDraw
606 {
607     if (!_tileCache)
608         return NO;
609      return _tileCache->hasPendingDraw();
610 }
611
612 - (void)setContentReplacementImage:(CGImageRef)contentReplacementImage
613 {
614     if (!_tileCache)
615         return;
616     _tileCache->setContentReplacementImage(contentReplacementImage);
617 }
618
619 - (CGImageRef)contentReplacementImage
620 {
621     if (!_tileCache)
622         return NULL;
623     return _tileCache->contentReplacementImage().get();
624 }
625
626 - (void)displayRect:(NSRect)rect
627 {
628     [[self contentView] displayRect:rect];
629 }
630
631 - (void)willRotate
632 {
633     [self freezeVisibleRect];
634 }
635
636 - (void)didRotate
637 {
638     [self unfreezeVisibleRect];
639 }
640
641 - (void)freezeVisibleRect
642 {
643     _frozenVisibleRect = [self visibleRect];
644 }
645
646 - (void)unfreezeVisibleRect
647 {
648     _frozenVisibleRect = CGRectNull;
649 }
650
651 + (void)setOrientationProvider:(id)provider
652 {
653     // This is really the UIWebDocumentView class that calls into UIApplication to get the orientation.
654     gOrientationProvider = provider;
655 }
656
657 + (BOOL)hasLandscapeOrientation
658 {
659     // this should be perfectly thread safe
660     return [gOrientationProvider hasLandscapeOrientation];
661 }
662
663 - (CALayer*)hostLayer
664 {
665     return _hostLayer;
666 }
667
668 - (void)setTileBordersVisible:(BOOL)visible
669 {
670     if (!_tileCache)
671         return;
672
673     _tileCache->setTileBordersVisible(visible);
674 }
675
676 - (void)setTilePaintCountsVisible:(BOOL)visible
677 {
678     if (!_tileCache)
679         return;
680
681     _tileCache->setTilePaintCountersVisible(visible);
682 }
683
684 - (void)setAcceleratedDrawingEnabled:(BOOL)enabled
685 {
686     if (!_tileCache)
687         return;
688
689     _tileCache->setAcceleratedDrawingEnabled(enabled);
690 }
691
692 - (void)dumpTiles
693 {
694     CGRect savedFrozenVisibleRect = _frozenVisibleRect;
695     NSLog(@"=================");
696     if (!CGRectIsNull(_frozenVisibleRect)) {
697         NSLog(@"Visibility::Visible RECT IS CACHED: [%6.1f %6.1f %6.1f %6.1f]", _frozenVisibleRect.origin.x, _frozenVisibleRect.origin.y, _frozenVisibleRect.size.width, _frozenVisibleRect.size.height);
698         _frozenVisibleRect = CGRectNull;
699     }
700     CGRect visibleRect = [self visibleRect];
701     NSLog(@"visibleRect = [%6.1f %6.1f %6.1f %6.1f]", visibleRect.origin.x, visibleRect.origin.y, visibleRect.size.width, visibleRect.size.height);
702     _frozenVisibleRect = savedFrozenVisibleRect;
703     _tileCache->dumpTiles();
704 }
705
706 - (void)setTileControllerShouldUseLowScaleTiles:(BOOL)lowScaleTiles 
707
708     if (!_tileCache) 
709         return; 
710
711     _tileCache->setTileControllerShouldUseLowScaleTiles(lowScaleTiles); 
712
713
714 - (NSString *)description
715 {
716     NSMutableString *description = [NSMutableString stringWithFormat:@"<%@: WAK: %p; ", [self class], self];
717
718     CGRect frame = [self frame];
719     [description appendFormat:@"frame = (%g %g; %g %g); ", frame.origin.x, frame.origin.y, frame.size.width, frame.size.height];
720
721     [description appendFormat:@"first responder = WK %p; ", _responderView];
722     [description appendFormat:@"next responder = WK %p; ", _nextResponder];
723
724     [description appendFormat:@"layer = %@>", [_hostLayer description]];
725
726     return description;
727 }
728
729 + (WebEvent *)currentEvent
730 {
731     return currentEvent;
732 }
733
734 - (NSString *)recursiveDescription
735 {
736     NSMutableString *info = [NSMutableString string];
737
738     [info appendString:[self description]];
739
740     [[self contentView] _appendDescriptionToString:info atLevel:1];
741
742     return info;
743 }
744
745 @end
746
747 #endif // PLATFORM(IOS_FAMILY)