1/* 2 * Copyright (C) 2004, 2006, 2007, 2008 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. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#import "config.h" 27#import "ScrollView.h" 28 29#import "BlockExceptions.h" 30#import "FloatRect.h" 31#import "FloatSize.h" 32#import "IntRect.h" 33#import "Logging.h" 34#import "NotImplemented.h" 35#import "WebCoreFrameView.h" 36 37@interface NSScrollView (Details) 38- (NSEdgeInsets)contentInsets; 39@property BOOL automaticallyAdjustsContentInsets; 40@end 41 42@interface NSWindow (WebWindowDetails) 43- (BOOL)_needsToResetDragMargins; 44- (void)_setNeedsToResetDragMargins:(BOOL)needs; 45@end 46 47namespace WebCore { 48 49inline NSScrollView<WebCoreFrameScrollView> *ScrollView::scrollView() const 50{ 51 ASSERT(!platformWidget() || [platformWidget() isKindOfClass:[NSScrollView class]]); 52 ASSERT(!platformWidget() || [platformWidget() conformsToProtocol:@protocol(WebCoreFrameScrollView)]); 53 return static_cast<NSScrollView<WebCoreFrameScrollView> *>(platformWidget()); 54} 55 56NSView *ScrollView::documentView() const 57{ 58 BEGIN_BLOCK_OBJC_EXCEPTIONS; 59 return [scrollView() documentView]; 60 END_BLOCK_OBJC_EXCEPTIONS; 61 return nil; 62} 63 64void ScrollView::platformAddChild(Widget* child) 65{ 66 BEGIN_BLOCK_OBJC_EXCEPTIONS; 67 NSView *parentView = documentView(); 68 NSView *childView = child->getOuterView(); 69 ASSERT(![parentView isDescendantOf:childView]); 70 71 // Suppress the resetting of drag margins since we know we can't affect them. 72 NSWindow *window = [parentView window]; 73 BOOL resetDragMargins = [window _needsToResetDragMargins]; 74 [window _setNeedsToResetDragMargins:NO]; 75 if ([childView superview] != parentView) 76 [parentView addSubview:childView]; 77 [window _setNeedsToResetDragMargins:resetDragMargins]; 78 END_BLOCK_OBJC_EXCEPTIONS; 79} 80 81void ScrollView::platformRemoveChild(Widget* child) 82{ 83 child->removeFromSuperview(); 84} 85 86void ScrollView::platformSetScrollbarModes() 87{ 88 BEGIN_BLOCK_OBJC_EXCEPTIONS; 89 [scrollView() setScrollingModes:m_horizontalScrollbarMode vertical:m_verticalScrollbarMode andLock:NO]; 90 END_BLOCK_OBJC_EXCEPTIONS; 91} 92 93void ScrollView::platformScrollbarModes(ScrollbarMode& horizontal, ScrollbarMode& vertical) const 94{ 95 BEGIN_BLOCK_OBJC_EXCEPTIONS; 96 [scrollView() scrollingModes:&horizontal vertical:&vertical]; 97 END_BLOCK_OBJC_EXCEPTIONS; 98} 99 100void ScrollView::platformSetCanBlitOnScroll(bool canBlitOnScroll) 101{ 102 BEGIN_BLOCK_OBJC_EXCEPTIONS; 103 [[scrollView() contentView] setCopiesOnScroll:canBlitOnScroll]; 104 END_BLOCK_OBJC_EXCEPTIONS; 105} 106 107bool ScrollView::platformCanBlitOnScroll() const 108{ 109 return [[scrollView() contentView] copiesOnScroll]; 110} 111 112float ScrollView::platformTopContentInset() const 113{ 114 BEGIN_BLOCK_OBJC_EXCEPTIONS; 115#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000 116 return scrollView().contentInsets.top; 117#endif 118 END_BLOCK_OBJC_EXCEPTIONS; 119 120 return 0; 121} 122 123void ScrollView::platformSetTopContentInset(float topContentInset) 124{ 125 BEGIN_BLOCK_OBJC_EXCEPTIONS; 126#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000 127 if (topContentInset) 128 scrollView().automaticallyAdjustsContentInsets = NO; 129 else 130 scrollView().automaticallyAdjustsContentInsets = YES; 131 132 NSEdgeInsets contentInsets = scrollView().contentInsets; 133 contentInsets.top = topContentInset; 134 scrollView().contentInsets = contentInsets; 135#else 136 UNUSED_PARAM(topContentInset); 137#endif 138 END_BLOCK_OBJC_EXCEPTIONS; 139} 140 141IntRect ScrollView::platformVisibleContentRect(bool includeScrollbars) const 142{ 143 BEGIN_BLOCK_OBJC_EXCEPTIONS; 144 IntRect visibleContentRect = platformVisibleContentRectIncludingObscuredArea(includeScrollbars); 145 146#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 10100 147 visibleContentRect.move(scrollView().contentInsets.left, scrollView().contentInsets.top); 148 visibleContentRect.contract(scrollView().contentInsets.left + scrollView().contentInsets.right, scrollView().contentInsets.top + scrollView().contentInsets.bottom); 149#endif 150 151 return visibleContentRect; 152 END_BLOCK_OBJC_EXCEPTIONS; 153 154 return IntRect(); 155} 156 157IntSize ScrollView::platformVisibleContentSize(bool includeScrollbars) const 158{ 159 return platformVisibleContentRect(includeScrollbars).size(); 160} 161 162IntRect ScrollView::platformVisibleContentRectIncludingObscuredArea(bool includeScrollbars) const 163{ 164 BEGIN_BLOCK_OBJC_EXCEPTIONS; 165 IntRect visibleContentRectIncludingObscuredArea = enclosingIntRect([scrollView() documentVisibleRect]); 166 167 if (includeScrollbars) { 168 IntSize frameSize = IntSize([scrollView() frame].size); 169 visibleContentRectIncludingObscuredArea.setSize(frameSize); 170 } 171 172 return visibleContentRectIncludingObscuredArea; 173 END_BLOCK_OBJC_EXCEPTIONS; 174 175 return IntRect(); 176} 177 178IntSize ScrollView::platformVisibleContentSizeIncludingObscuredArea(bool includeScrollbars) const 179{ 180 return platformVisibleContentRectIncludingObscuredArea(includeScrollbars).size(); 181} 182 183void ScrollView::platformSetContentsSize() 184{ 185 BEGIN_BLOCK_OBJC_EXCEPTIONS; 186 int w = m_contentsSize.width(); 187 int h = m_contentsSize.height(); 188 LOG(Frames, "%p %@ at w %d h %d\n", documentView(), [(id)[documentView() class] className], w, h); 189 [documentView() setFrameSize:NSMakeSize(std::max(0, w), std::max(0, h))]; 190 END_BLOCK_OBJC_EXCEPTIONS; 191} 192 193void ScrollView::platformSetScrollbarsSuppressed(bool repaintOnUnsuppress) 194{ 195 BEGIN_BLOCK_OBJC_EXCEPTIONS; 196 [scrollView() setScrollBarsSuppressed:m_scrollbarsSuppressed 197 repaintOnUnsuppress:repaintOnUnsuppress]; 198 END_BLOCK_OBJC_EXCEPTIONS; 199} 200 201void ScrollView::platformSetScrollPosition(const IntPoint& scrollPoint) 202{ 203 BEGIN_BLOCK_OBJC_EXCEPTIONS; 204 NSPoint floatPoint = scrollPoint; 205 NSPoint tempPoint = { std::max(-[scrollView() scrollOrigin].x, floatPoint.x), std::max(-[scrollView() scrollOrigin].y, floatPoint.y) }; // Don't use NSMakePoint to work around 4213314. 206 207#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000 208 // AppKit has the inset factored into all of its scroll positions. In WebCore, we use positions that ignore 209 // the insets so that they are equivalent whether or not there is an inset. 210 tempPoint.x = tempPoint.x - scrollView().contentInsets.left; 211 tempPoint.y = tempPoint.y - scrollView().contentInsets.top; 212#endif 213 214 [documentView() scrollPoint:tempPoint]; 215 END_BLOCK_OBJC_EXCEPTIONS; 216} 217 218bool ScrollView::platformScroll(ScrollDirection, ScrollGranularity) 219{ 220 // FIXME: It would be nice to implement this so that all of the code in WebFrameView could go away. 221 notImplemented(); 222 return false; 223} 224 225void ScrollView::platformRepaintContentRectangle(const IntRect& rect) 226{ 227 BEGIN_BLOCK_OBJC_EXCEPTIONS; 228 NSView *view = documentView(); 229 [view setNeedsDisplayInRect:rect]; 230 231 END_BLOCK_OBJC_EXCEPTIONS; 232} 233 234// "Containing Window" means the NSWindow's coord system, which is origin lower left 235 236IntRect ScrollView::platformContentsToScreen(const IntRect& rect) const 237{ 238 BEGIN_BLOCK_OBJC_EXCEPTIONS; 239 if (NSView* documentView = this->documentView()) { 240 NSRect tempRect = rect; 241 tempRect = [documentView convertRect:tempRect toView:nil]; 242#pragma clang diagnostic push 243#pragma clang diagnostic ignored "-Wdeprecated-declarations" 244 tempRect.origin = [[documentView window] convertBaseToScreen:tempRect.origin]; 245#pragma clang diagnostic pop 246 return enclosingIntRect(tempRect); 247 } 248 END_BLOCK_OBJC_EXCEPTIONS; 249 return IntRect(); 250} 251 252IntPoint ScrollView::platformScreenToContents(const IntPoint& point) const 253{ 254 BEGIN_BLOCK_OBJC_EXCEPTIONS; 255 if (NSView* documentView = this->documentView()) { 256#pragma clang diagnostic push 257#pragma clang diagnostic ignored "-Wdeprecated-declarations" 258 NSPoint windowCoord = [[documentView window] convertScreenToBase: point]; 259#pragma clang diagnostic pop 260 return IntPoint([documentView convertPoint:windowCoord fromView:nil]); 261 } 262 END_BLOCK_OBJC_EXCEPTIONS; 263 return IntPoint(); 264} 265 266bool ScrollView::platformIsOffscreen() const 267{ 268 return ![platformWidget() window] || ![[platformWidget() window] isVisible]; 269} 270 271static inline NSScrollerKnobStyle toNSScrollerKnobStyle(ScrollbarOverlayStyle style) 272{ 273 switch (style) { 274 case ScrollbarOverlayStyleDark: 275 return NSScrollerKnobStyleDark; 276 case ScrollbarOverlayStyleLight: 277 return NSScrollerKnobStyleLight; 278 default: 279 return NSScrollerKnobStyleDefault; 280 } 281} 282 283void ScrollView::platformSetScrollbarOverlayStyle(ScrollbarOverlayStyle overlayStyle) 284{ 285 [scrollView() setScrollerKnobStyle:toNSScrollerKnobStyle(overlayStyle)]; 286} 287 288void ScrollView::platformSetScrollOrigin(const IntPoint& origin, bool updatePositionAtAll, bool updatePositionSynchronously) 289{ 290 BEGIN_BLOCK_OBJC_EXCEPTIONS; 291 [scrollView() setScrollOrigin:origin updatePositionAtAll:updatePositionAtAll immediately:updatePositionSynchronously]; 292 END_BLOCK_OBJC_EXCEPTIONS; 293} 294 295} // namespace WebCore 296