2 * Copyright (C) 2004, 2006 Apple Computer, Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #import "ScrollView.h"
31 #import "BlockExceptions.h"
33 #import "WebCoreFrameView.h"
36 This class implementation does NOT actually emulate the Qt ScrollView.
37 It does provide an implementation that khtml will use to interact with
38 WebKit's WebFrameView documentView and our NSScrollView subclass.
40 ScrollView's view is a NSScrollView (or subclass of NSScrollView)
41 in most cases. That scrollview is a subview of an
42 WebCoreFrameView. The WebCoreFrameView's documentView will also be
43 the scroll view's documentView.
45 The WebCoreFrameView's size is the frame size. The WebCoreFrameView's documentView
46 corresponds to the frame content size. The scrollview itself is autosized to the
47 WebCoreFrameView's size (see Widget::resize).
52 int ScrollView::visibleWidth() const
54 NSScrollView *view = (NSScrollView *)getView();
56 BEGIN_BLOCK_OBJC_EXCEPTIONS;
57 if ([view isKindOfClass:[NSScrollView class]])
58 return (int)[view documentVisibleRect].size.width;
60 return (int)[view bounds].size.width;
61 END_BLOCK_OBJC_EXCEPTIONS;
66 int ScrollView::visibleHeight() const
68 NSScrollView *view = (NSScrollView *)getView();
70 BEGIN_BLOCK_OBJC_EXCEPTIONS;
71 if ([view isKindOfClass:[NSScrollView class]])
72 return (int)[view documentVisibleRect].size.height;
74 return (int)[view bounds].size.height;
75 END_BLOCK_OBJC_EXCEPTIONS;
80 FloatRect ScrollView::visibleContentRect() const
82 BEGIN_BLOCK_OBJC_EXCEPTIONS;
83 if (NSView *docView = getDocumentView())
84 return [docView visibleRect];
85 END_BLOCK_OBJC_EXCEPTIONS;
89 int ScrollView::contentsWidth() const
91 NSView *docView, *view = getView();
92 docView = getDocumentView();
94 BEGIN_BLOCK_OBJC_EXCEPTIONS;
96 return (int)[docView bounds].size.width;
98 return (int)[view bounds].size.width;
99 END_BLOCK_OBJC_EXCEPTIONS;
104 int ScrollView::contentsHeight() const
106 NSView *docView, *view = getView();
107 docView = getDocumentView();
109 BEGIN_BLOCK_OBJC_EXCEPTIONS;
111 return (int)[docView bounds].size.height;
113 return (int)[view bounds].size.height;
114 END_BLOCK_OBJC_EXCEPTIONS;
119 int ScrollView::contentsX() const
121 NSView *view = getView();
123 BEGIN_BLOCK_OBJC_EXCEPTIONS;
124 if ([view isKindOfClass:[NSScrollView class]])
125 return (int)[(NSScrollView *)view documentVisibleRect].origin.x;
127 return (int)[view visibleRect].origin.x;
128 END_BLOCK_OBJC_EXCEPTIONS;
133 int ScrollView::contentsY() const
135 NSView *view = getView();
137 BEGIN_BLOCK_OBJC_EXCEPTIONS;
138 if ([view isKindOfClass:[NSScrollView class]])
139 return (int)[(NSScrollView *)view documentVisibleRect].origin.y;
141 return (int)[view visibleRect].origin.y;
142 END_BLOCK_OBJC_EXCEPTIONS;
147 IntSize ScrollView::scrollOffset() const
149 NSView *view = getView();
151 BEGIN_BLOCK_OBJC_EXCEPTIONS;
152 if ([view isKindOfClass:[NSScrollView class]])
153 return IntPoint([[(NSScrollView *)view contentView] visibleRect].origin) - IntPoint();
154 END_BLOCK_OBJC_EXCEPTIONS;
158 void ScrollView::scrollBy(int dx, int dy)
160 setContentsPos(contentsX() + dx, contentsY() + dy);
163 void ScrollView::scrollPointRecursively(int x, int y)
167 NSPoint p = NSMakePoint(x,y);
169 BEGIN_BLOCK_OBJC_EXCEPTIONS;
171 NSView *view = getView();
172 docView = getDocumentView();
176 NSView *originalView = view;
178 if ([view isKindOfClass:[NSClipView class]]) {
179 NSPoint viewPoint = [view convertPoint:p fromView:originalView];
180 [view scrollPoint:viewPoint];
182 view = [view superview];
184 END_BLOCK_OBJC_EXCEPTIONS;
187 void ScrollView::setContentsPos(int x, int y)
191 NSPoint p = NSMakePoint(x,y);
193 BEGIN_BLOCK_OBJC_EXCEPTIONS;
195 NSView *view = getView();
196 docView = getDocumentView();
199 [view scrollPoint:p];
200 END_BLOCK_OBJC_EXCEPTIONS;
203 void ScrollView::setVScrollBarMode(ScrollBarMode vMode)
205 NSView* view = getView();
207 BEGIN_BLOCK_OBJC_EXCEPTIONS;
208 if ([view conformsToProtocol:@protocol(WebCoreFrameView)]) {
209 NSView<WebCoreFrameView>* frameView = (NSView<WebCoreFrameView>*)view;
210 [frameView setVerticalScrollingMode: (WebCoreScrollBarMode)vMode];
212 END_BLOCK_OBJC_EXCEPTIONS;
215 void ScrollView::setHScrollBarMode(ScrollBarMode hMode)
217 NSView* view = getView();
219 BEGIN_BLOCK_OBJC_EXCEPTIONS;
220 if ([view conformsToProtocol:@protocol(WebCoreFrameView)]) {
221 NSView<WebCoreFrameView>* frameView = (NSView<WebCoreFrameView>*)view;
222 [frameView setHorizontalScrollingMode: (WebCoreScrollBarMode)hMode];
224 END_BLOCK_OBJC_EXCEPTIONS;
227 void ScrollView::setScrollBarsMode(ScrollBarMode mode)
229 NSView* view = getView();
231 BEGIN_BLOCK_OBJC_EXCEPTIONS;
232 if ([view conformsToProtocol:@protocol(WebCoreFrameView)]) {
233 NSView<WebCoreFrameView>* frameView = (NSView<WebCoreFrameView>*)view;
234 [frameView setScrollingMode: (WebCoreScrollBarMode)mode];
236 END_BLOCK_OBJC_EXCEPTIONS;
239 ScrollBarMode ScrollView::vScrollBarMode() const
241 NSView* view = getView();
243 BEGIN_BLOCK_OBJC_EXCEPTIONS;
244 if ([view conformsToProtocol:@protocol(WebCoreFrameView)]) {
245 NSView<WebCoreFrameView>* frameView = (NSView<WebCoreFrameView>*)view;
246 return (ScrollBarMode)[frameView verticalScrollingMode];
248 END_BLOCK_OBJC_EXCEPTIONS;
250 return ScrollBarAuto;
253 ScrollBarMode ScrollView::hScrollBarMode() const
255 NSView* view = getView();
257 BEGIN_BLOCK_OBJC_EXCEPTIONS;
258 if ([view conformsToProtocol:@protocol(WebCoreFrameView)]) {
259 NSView<WebCoreFrameView>* frameView = (NSView<WebCoreFrameView>*)view;
260 return (ScrollBarMode)[frameView horizontalScrollingMode];
262 END_BLOCK_OBJC_EXCEPTIONS;
264 return ScrollBarAuto;
267 void ScrollView::suppressScrollBars(bool suppressed, bool repaintOnUnsuppress)
269 NSView* view = getView();
271 BEGIN_BLOCK_OBJC_EXCEPTIONS;
272 if ([view conformsToProtocol:@protocol(WebCoreFrameView)]) {
273 NSView<WebCoreFrameView>* frameView = (NSView<WebCoreFrameView>*)view;
274 [frameView setScrollBarsSuppressed: suppressed
275 repaintOnUnsuppress: repaintOnUnsuppress];
277 END_BLOCK_OBJC_EXCEPTIONS;
280 void ScrollView::addChild(Widget* child, int x, int y)
282 ASSERT(child != this);
284 // we don't need to do the offscreen position initialization that KDE needs
288 NSView *thisView = getView();
289 NSView *thisDocView = getDocumentView();
291 thisView = thisDocView;
294 NSView *subview = child->getOuterView();
296 LOG(Frames, "Adding %p %@ at (%d,%d) w %d h %d\n", subview,
297 [(id)[subview class] className], x, y, (int)[subview frame].size.width, (int)[subview frame].size.height);
299 child->addToSuperview(thisView);
302 void ScrollView::removeChild(Widget* child)
304 child->removeFromSuperview();
307 void ScrollView::resizeContents(int w, int h)
309 BEGIN_BLOCK_OBJC_EXCEPTIONS;
313 LOG(Frames, "%p %@ at w %d h %d\n", getView(), [(id)[getView() class] className], w, h);
314 NSView *view = getView();
315 if ([view isKindOfClass:[NSScrollView class]]){
316 view = getDocumentView();
318 LOG(Frames, "%p %@ at w %d h %d\n", view, [(id)[view class] className], w, h);
324 NSSize tempSize = { _w, _h }; // workaround for 4213314
325 [view setFrameSize:tempSize];
329 END_BLOCK_OBJC_EXCEPTIONS;
332 void ScrollView::updateContents(const IntRect &rect, bool now)
334 BEGIN_BLOCK_OBJC_EXCEPTIONS;
336 NSView *view = getView();
338 if ([view isKindOfClass:[NSScrollView class]])
339 view = getDocumentView();
341 // Checking for rect visibility is an important optimization for the case of
342 // Select All of a large document. AppKit does not do this check, and so ends
343 // up building a large complicated NSRegion if we don't perform the check.
344 NSRect dirtyRect = NSIntersectionRect(rect, [view visibleRect]);
345 if (!NSIsEmptyRect(dirtyRect)) {
346 [view setNeedsDisplayInRect:dirtyRect];
348 [[view window] displayIfNeeded];
349 [[view window] flushWindowIfNeeded];
353 END_BLOCK_OBJC_EXCEPTIONS;
356 // "Containing Window" means the NSWindow's coord system, which is origin lower left
358 IntPoint ScrollView::convertToContainingWindow(const IntPoint& contentsPoint) const
360 BEGIN_BLOCK_OBJC_EXCEPTIONS;
363 NSView *view = getView();
365 docView = getDocumentView();
369 NSPoint tempPoint = { contentsPoint.x(), contentsPoint.y() }; // workaround for 4213314
370 NSPoint np = [view convertPoint:tempPoint toView: nil];
373 END_BLOCK_OBJC_EXCEPTIONS;
378 IntPoint ScrollView::convertFromContainingWindow(const IntPoint& point) const
380 BEGIN_BLOCK_OBJC_EXCEPTIONS;
383 NSView *view = getView();
385 docView = getDocumentView();
389 NSPoint tempPoint = { point.x(), point.y() }; // workaround for 4213314
390 NSPoint np = [view convertPoint:tempPoint fromView: nil];
394 END_BLOCK_OBJC_EXCEPTIONS;
399 void ScrollView::setStaticBackground(bool b)
401 NSScrollView *view = (NSScrollView *)getView();
402 BEGIN_BLOCK_OBJC_EXCEPTIONS;
403 if ([view isKindOfClass:[NSScrollView class]])
404 [[view contentView] setCopiesOnScroll: !b];
405 END_BLOCK_OBJC_EXCEPTIONS;
408 NSView *ScrollView::getDocumentView() const
412 BEGIN_BLOCK_OBJC_EXCEPTIONS;
413 if ([view respondsToSelector:@selector(documentView)])
414 return [view documentView];
415 END_BLOCK_OBJC_EXCEPTIONS;
420 bool ScrollView::inWindow() const
422 return [getView() window];
425 void ScrollView::wheelEvent(PlatformWheelEvent&)
427 // Do nothing. NSScrollView handles doing the scroll for us.