Build fix for platforms where we should have automaticallyAdjustsContentInsets but...
[WebKit-https.git] / Source / WebCore / platform / mac / ScrollViewMac.mm
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
47 namespace WebCore {
48
49 inline 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
56 NSView *ScrollView::documentView() const
57 {
58     BEGIN_BLOCK_OBJC_EXCEPTIONS;
59     return [scrollView() documentView];
60     END_BLOCK_OBJC_EXCEPTIONS;
61     return nil;
62 }
63
64 void 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
81 void ScrollView::platformRemoveChild(Widget* child)
82 {
83     child->removeFromSuperview();
84 }
85
86 void 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
93 void 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
100 void ScrollView::platformSetCanBlitOnScroll(bool canBlitOnScroll)
101 {
102     BEGIN_BLOCK_OBJC_EXCEPTIONS;
103     [[scrollView() contentView] setCopiesOnScroll:canBlitOnScroll];
104     END_BLOCK_OBJC_EXCEPTIONS;
105 }
106
107 bool ScrollView::platformCanBlitOnScroll() const
108 {
109     return [[scrollView() contentView] copiesOnScroll];
110 }
111
112 float 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
123 void 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
141 IntRect ScrollView::platformVisibleContentRect(bool includeScrollbars) const
142 {
143     BEGIN_BLOCK_OBJC_EXCEPTIONS;
144
145     IntRect visibleContentRect = enclosingIntRect([scrollView() documentVisibleRect]);
146 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
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     if (includeScrollbars) {
152         IntSize frameSize = IntSize([scrollView() frame].size);
153 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
154         frameSize.contract(scrollView().contentInsets.left + scrollView().contentInsets.right, scrollView().contentInsets.top + scrollView().contentInsets.bottom);
155 #endif
156         visibleContentRect.setSize(frameSize);
157     }
158
159     return visibleContentRect;
160     END_BLOCK_OBJC_EXCEPTIONS;
161
162     return IntRect();
163 }
164
165 IntSize ScrollView::platformVisibleContentSize(bool includeScrollbars) const
166 {
167     return platformVisibleContentRect(includeScrollbars).size();
168 }
169
170 void ScrollView::platformSetContentsSize()
171 {
172     BEGIN_BLOCK_OBJC_EXCEPTIONS;
173     int w = m_contentsSize.width();
174     int h = m_contentsSize.height();
175     LOG(Frames, "%p %@ at w %d h %d\n", documentView(), [(id)[documentView() class] className], w, h);            
176     [documentView() setFrameSize:NSMakeSize(std::max(0, w), std::max(0, h))];
177     END_BLOCK_OBJC_EXCEPTIONS;
178 }
179
180 void ScrollView::platformSetScrollbarsSuppressed(bool repaintOnUnsuppress)
181 {
182     BEGIN_BLOCK_OBJC_EXCEPTIONS;
183     [scrollView() setScrollBarsSuppressed:m_scrollbarsSuppressed
184                       repaintOnUnsuppress:repaintOnUnsuppress];
185     END_BLOCK_OBJC_EXCEPTIONS;
186 }
187
188 void ScrollView::platformSetScrollPosition(const IntPoint& scrollPoint)
189 {
190     BEGIN_BLOCK_OBJC_EXCEPTIONS;
191     NSPoint floatPoint = scrollPoint;
192     NSPoint tempPoint = { std::max(-[scrollView() scrollOrigin].x, floatPoint.x), std::max(-[scrollView() scrollOrigin].y, floatPoint.y) };  // Don't use NSMakePoint to work around 4213314.
193
194 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
195     // AppKit has the inset factored into all of its scroll positions. In WebCore, we use positions that ignore
196     // the insets so that they are equivalent whether or not there is an inset.
197     tempPoint.x = tempPoint.x - scrollView().contentInsets.left;
198     tempPoint.y = tempPoint.y - scrollView().contentInsets.top;
199 #endif
200
201     [documentView() scrollPoint:tempPoint];
202     END_BLOCK_OBJC_EXCEPTIONS;
203 }
204
205 bool ScrollView::platformScroll(ScrollDirection, ScrollGranularity)
206 {
207     // FIXME: It would be nice to implement this so that all of the code in WebFrameView could go away.
208     notImplemented();
209     return false;
210 }
211
212 void ScrollView::platformRepaintContentRectangle(const IntRect& rect)
213 {
214     BEGIN_BLOCK_OBJC_EXCEPTIONS;
215     NSView *view = documentView();
216     [view setNeedsDisplayInRect:rect];
217
218     END_BLOCK_OBJC_EXCEPTIONS;
219 }
220
221 // "Containing Window" means the NSWindow's coord system, which is origin lower left
222
223 IntRect ScrollView::platformContentsToScreen(const IntRect& rect) const
224 {
225     BEGIN_BLOCK_OBJC_EXCEPTIONS;
226     if (NSView* documentView = this->documentView()) {
227         NSRect tempRect = rect;
228         tempRect = [documentView convertRect:tempRect toView:nil];
229 #pragma clang diagnostic push
230 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
231         tempRect.origin = [[documentView window] convertBaseToScreen:tempRect.origin];
232 #pragma clang diagnostic pop
233         return enclosingIntRect(tempRect);
234     }
235     END_BLOCK_OBJC_EXCEPTIONS;
236     return IntRect();
237 }
238
239 IntPoint ScrollView::platformScreenToContents(const IntPoint& point) const
240 {
241     BEGIN_BLOCK_OBJC_EXCEPTIONS;
242     if (NSView* documentView = this->documentView()) {
243 #pragma clang diagnostic push
244 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
245         NSPoint windowCoord = [[documentView window] convertScreenToBase: point];
246 #pragma clang diagnostic pop
247         return IntPoint([documentView convertPoint:windowCoord fromView:nil]);
248     }
249     END_BLOCK_OBJC_EXCEPTIONS;
250     return IntPoint();
251 }
252
253 bool ScrollView::platformIsOffscreen() const
254 {
255     return ![platformWidget() window] || ![[platformWidget() window] isVisible];
256 }
257
258 static inline NSScrollerKnobStyle toNSScrollerKnobStyle(ScrollbarOverlayStyle style)
259 {
260     switch (style) {
261     case ScrollbarOverlayStyleDark:
262         return NSScrollerKnobStyleDark;
263     case ScrollbarOverlayStyleLight:
264         return NSScrollerKnobStyleLight;
265     default:
266         return NSScrollerKnobStyleDefault;
267     }
268 }
269
270 void ScrollView::platformSetScrollbarOverlayStyle(ScrollbarOverlayStyle overlayStyle)
271 {
272     [scrollView() setScrollerKnobStyle:toNSScrollerKnobStyle(overlayStyle)];
273 }
274
275 void ScrollView::platformSetScrollOrigin(const IntPoint& origin, bool updatePositionAtAll, bool updatePositionSynchronously)
276 {
277     BEGIN_BLOCK_OBJC_EXCEPTIONS;
278     [scrollView() setScrollOrigin:origin updatePositionAtAll:updatePositionAtAll immediately:updatePositionSynchronously];
279     END_BLOCK_OBJC_EXCEPTIONS;
280 }
281
282 } // namespace WebCore