• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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