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 COMPUTER, 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 COMPUTER, 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 "IntRect.h" 32#import "Logging.h" 33#import "NotImplemented.h" 34#import "WebCoreFrameView.h" 35 36using namespace std; 37 38@interface NSWindow (WebWindowDetails) 39- (BOOL)_needsToResetDragMargins; 40- (void)_setNeedsToResetDragMargins:(BOOL)needs; 41@end 42 43namespace WebCore { 44 45inline NSScrollView<WebCoreFrameScrollView> *ScrollView::scrollView() const 46{ 47 ASSERT(!platformWidget() || [platformWidget() isKindOfClass:[NSScrollView class]]); 48 ASSERT(!platformWidget() || [platformWidget() conformsToProtocol:@protocol(WebCoreFrameScrollView)]); 49 return static_cast<NSScrollView<WebCoreFrameScrollView> *>(platformWidget()); 50} 51 52NSView *ScrollView::documentView() const 53{ 54 BEGIN_BLOCK_OBJC_EXCEPTIONS; 55 return [scrollView() documentView]; 56 END_BLOCK_OBJC_EXCEPTIONS; 57 return nil; 58} 59 60void ScrollView::platformAddChild(Widget* child) 61{ 62 BEGIN_BLOCK_OBJC_EXCEPTIONS; 63 NSView *parentView = documentView(); 64 NSView *childView = child->getOuterView(); 65 ASSERT(![parentView isDescendantOf:childView]); 66 67 // Suppress the resetting of drag margins since we know we can't affect them. 68 NSWindow *window = [parentView window]; 69 BOOL resetDragMargins = [window _needsToResetDragMargins]; 70 [window _setNeedsToResetDragMargins:NO]; 71 if ([childView superview] != parentView) 72 [parentView addSubview:childView]; 73 [window _setNeedsToResetDragMargins:resetDragMargins]; 74 END_BLOCK_OBJC_EXCEPTIONS; 75} 76 77void ScrollView::platformRemoveChild(Widget* child) 78{ 79 child->removeFromSuperview(); 80} 81 82void ScrollView::platformSetScrollbarModes() 83{ 84 BEGIN_BLOCK_OBJC_EXCEPTIONS; 85 [scrollView() setScrollingModes:m_horizontalScrollbarMode vertical:m_verticalScrollbarMode andLock:NO]; 86 END_BLOCK_OBJC_EXCEPTIONS; 87} 88 89void ScrollView::platformScrollbarModes(ScrollbarMode& horizontal, ScrollbarMode& vertical) const 90{ 91 BEGIN_BLOCK_OBJC_EXCEPTIONS; 92 [scrollView() scrollingModes:&horizontal vertical:&vertical]; 93 END_BLOCK_OBJC_EXCEPTIONS; 94} 95 96void ScrollView::platformSetCanBlitOnScroll(bool canBlitOnScroll) 97{ 98 BEGIN_BLOCK_OBJC_EXCEPTIONS; 99 [[scrollView() contentView] setCopiesOnScroll:canBlitOnScroll]; 100 END_BLOCK_OBJC_EXCEPTIONS; 101} 102 103bool ScrollView::platformCanBlitOnScroll() const 104{ 105 return [[scrollView() contentView] copiesOnScroll]; 106} 107 108IntRect ScrollView::platformVisibleContentRect(bool includeScrollbars) const 109{ 110 BEGIN_BLOCK_OBJC_EXCEPTIONS; 111 if (includeScrollbars) { 112 if (NSView* documentView = this->documentView()) 113 return enclosingIntRect([documentView visibleRect]); 114 } 115 return enclosingIntRect([scrollView() documentVisibleRect]); 116 END_BLOCK_OBJC_EXCEPTIONS; 117 return IntRect(); 118} 119 120IntSize ScrollView::platformContentsSize() const 121{ 122 BEGIN_BLOCK_OBJC_EXCEPTIONS; 123 if (NSView* documentView = this->documentView()) 124 return enclosingIntRect([documentView bounds]).size(); 125 END_BLOCK_OBJC_EXCEPTIONS; 126 return IntSize(); 127} 128 129void ScrollView::platformSetContentsSize() 130{ 131 BEGIN_BLOCK_OBJC_EXCEPTIONS; 132 int w = m_contentsSize.width(); 133 int h = m_contentsSize.height(); 134 LOG(Frames, "%p %@ at w %d h %d\n", documentView(), [(id)[documentView() class] className], w, h); 135 NSSize tempSize = { max(0, w), max(0, h) }; // workaround for 4213314 136 [documentView() setFrameSize:tempSize]; 137 END_BLOCK_OBJC_EXCEPTIONS; 138} 139 140void ScrollView::platformSetScrollbarsSuppressed(bool repaintOnUnsuppress) 141{ 142 BEGIN_BLOCK_OBJC_EXCEPTIONS; 143 [scrollView() setScrollBarsSuppressed:m_scrollbarsSuppressed 144 repaintOnUnsuppress:repaintOnUnsuppress]; 145 END_BLOCK_OBJC_EXCEPTIONS; 146} 147 148void ScrollView::platformSetScrollPosition(const IntPoint& scrollPoint) 149{ 150 BEGIN_BLOCK_OBJC_EXCEPTIONS; 151 NSPoint tempPoint = { max(0, scrollPoint.x()), max(0, scrollPoint.y()) }; // Don't use NSMakePoint to work around 4213314. 152 [documentView() scrollPoint:tempPoint]; 153 END_BLOCK_OBJC_EXCEPTIONS; 154} 155 156bool ScrollView::platformScroll(ScrollDirection, ScrollGranularity) 157{ 158 // FIXME: It would be nice to implement this so that all of the code in WebFrameView could go away. 159 notImplemented(); 160 return false; 161} 162 163void ScrollView::platformRepaintContentRectangle(const IntRect& rect, bool now) 164{ 165 BEGIN_BLOCK_OBJC_EXCEPTIONS; 166 167 NSView *view = documentView(); 168 NSRect visibleRect = visibleContentRect(); 169 170 // FIXME: I don't think this intersection is necessary any more now that 171 // selection doesn't call this method directly (but has to go through FrameView's 172 // repaintContentRectangle, which does the intersection test also). Leaving it in 173 // for now until I'm sure. 174 // Checking for rect visibility is an important optimization for the case of 175 // Select All of a large document. AppKit does not do this check, and so ends 176 // up building a large complicated NSRegion if we don't perform the check. 177 NSRect dirtyRect = NSIntersectionRect(rect, visibleRect); 178 if (!NSIsEmptyRect(dirtyRect)) { 179 [view setNeedsDisplayInRect:dirtyRect]; 180 if (now) { 181 [[view window] displayIfNeeded]; 182 [[view window] flushWindowIfNeeded]; 183 } 184 } 185 186 END_BLOCK_OBJC_EXCEPTIONS; 187} 188 189// "Containing Window" means the NSWindow's coord system, which is origin lower left 190 191IntRect ScrollView::platformContentsToScreen(const IntRect& rect) const 192{ 193 BEGIN_BLOCK_OBJC_EXCEPTIONS; 194 if (NSView* documentView = this->documentView()) { 195 NSRect tempRect = rect; 196 tempRect = [documentView convertRect:tempRect toView:nil]; 197 tempRect.origin = [[documentView window] convertBaseToScreen:tempRect.origin]; 198 return enclosingIntRect(tempRect); 199 } 200 END_BLOCK_OBJC_EXCEPTIONS; 201 return IntRect(); 202} 203 204IntPoint ScrollView::platformScreenToContents(const IntPoint& point) const 205{ 206 BEGIN_BLOCK_OBJC_EXCEPTIONS; 207 if (NSView* documentView = this->documentView()) { 208 NSPoint windowCoord = [[documentView window] convertScreenToBase: point]; 209 return IntPoint([documentView convertPoint:windowCoord fromView:nil]); 210 } 211 END_BLOCK_OBJC_EXCEPTIONS; 212 return IntPoint(); 213} 214 215bool ScrollView::platformIsOffscreen() const 216{ 217 return ![platformWidget() window] || ![[platformWidget() window] isVisible]; 218} 219 220} 221