1/* 2 * Copyright (C) 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 "WKFormPopover.h" 28 29#if PLATFORM(IOS) 30 31#import "WKContentView.h" 32#import "WKContentViewInteraction.h" 33#import "WebPageProxy.h" 34#import <UIKit/UIPeripheralHost.h> 35#import <UIKit/UIWindow_Private.h> 36#import <wtf/RetainPtr.h> 37 38using namespace WebKit; 39 40@implementation WKFormRotatingAccessoryPopover { 41 WKContentView *_view; 42} 43 44- (id)initWithView:(WKContentView *)view 45{ 46 if (!(self = [super initWithView:view])) 47 return nil; 48 _view = view; 49 self.dismissionDelegate = self; 50 return self; 51} 52 53- (void)accessoryDone 54{ 55 [_view accessoryDone]; 56} 57 58- (UIPopoverArrowDirection)popoverArrowDirections 59{ 60 UIPopoverArrowDirection directions = UIPopoverArrowDirectionUp | UIPopoverArrowDirectionDown; 61 if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]) && [[UIPeripheralHost sharedInstance] isOnScreen]) 62 directions = UIPopoverArrowDirectionLeft | UIPopoverArrowDirectionRight; 63 return directions; 64} 65 66- (void)popoverWasDismissed:(WKRotatingPopover *)popover 67{ 68 [self accessoryDone]; 69} 70 71@end 72 73@interface WKRotatingPopover () <UIPopoverControllerDelegate> 74@end 75 76@implementation WKRotatingPopover { 77 WKContentView *_view; 78 79 BOOL _isRotating; 80 CGPoint _presentationPoint; 81 RetainPtr<UIPopoverController> _popoverController; 82 id <WKRotatingPopoverDelegate> _dismissionDelegate; 83} 84 85- (id)initWithView:(WKContentView *)view 86{ 87 if (!(self = [super init])) 88 return nil; 89 90 _view = view; 91 self.presentationPoint = CGPointZero; 92 93 NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; 94 [center addObserver:self selector:@selector(willRotate:) name:UIWindowWillRotateNotification object:nil]; 95 [center addObserver:self selector:@selector(didRotate:) name:UIWindowDidRotateNotification object:nil]; 96 97 return self; 98} 99 100- (void)dealloc 101{ 102 _view = nil; 103 104 [_popoverController dismissPopoverAnimated:YES]; 105 [_popoverController setDelegate:nil]; 106 self.popoverController = nil; 107 108 NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; 109 [center removeObserver:self name:UIWindowWillRotateNotification object:nil]; 110 [center removeObserver:self name:UIWindowDidRotateNotification object:nil]; 111 112 [super dealloc]; 113} 114 115- (UIPopoverController *)popoverController 116{ 117 return _popoverController.get(); 118} 119 120- (void)setPopoverController:(UIPopoverController *)popoverController 121{ 122 if (_popoverController == popoverController) 123 return; 124 125 [_popoverController setDelegate:nil]; 126 _popoverController = popoverController; 127 [_popoverController setDelegate:self]; 128} 129 130- (UIPopoverArrowDirection)popoverArrowDirections 131{ 132 return UIPopoverArrowDirectionAny; 133} 134 135- (void)presentPopoverAnimated:(BOOL)animated 136{ 137 UIPopoverArrowDirection directions = [self popoverArrowDirections]; 138 139 BOOL presentWithPoint = !CGPointEqualToPoint(self.presentationPoint, CGPointZero); 140 if (presentWithPoint) { 141 CGFloat scale = [_view page]->pageScaleFactor(); 142 [_popoverController presentPopoverFromRect:CGRectIntegral(CGRectMake(self.presentationPoint.x * scale, self.presentationPoint.y * scale, 1, 1)) 143 inView:_view 144 permittedArrowDirections:directions 145 animated:animated]; 146 } else { 147 CGRect boundingBoxOfDOMNode = _view.assistedNodeInformation.elementRect; 148 [_popoverController presentPopoverFromRect:CGRectIntegral(boundingBoxOfDOMNode) 149 inView:_view 150 permittedArrowDirections:directions 151 animated:animated]; 152 } 153} 154 155- (void)dismissPopoverAnimated:(BOOL)animated 156{ 157 [_popoverController dismissPopoverAnimated:animated]; 158} 159 160- (void)willRotate:(NSNotification *)notification 161{ 162 _isRotating = YES; 163 [_popoverController dismissPopoverAnimated:NO]; 164} 165 166- (void)didRotate:(NSNotification *)notification 167{ 168 _isRotating = NO; 169 [self presentPopoverAnimated:NO]; 170} 171 172- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController 173{ 174 if (_isRotating) 175 return; 176 177 [_dismissionDelegate popoverWasDismissed:self]; 178} 179 180@end 181 182#endif // PLATFORM(IOS) 183