ScrollViewAndroid.cpp revision 9364f22aed35e1a1e9d07c121510f80be3ab0502
1/*
2**
3** Copyright 2007, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9**     http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#include "config.h"
19#include "ScrollView.h"
20
21#include "FloatRect.h"
22#include "IntRect.h"
23
24#include "WebCoreViewBridge.h"
25
26#define LOG_TAG "WebCore"
27#undef LOG
28#include "utils/Log.h"
29
30/*  hack to allow the DOM to communicate how to interpret inval requests, since
31    it doesn't have the notion of distinguishing between the screen and the DOM
32    but we do, since we have a copy of the display in our picture, and we don't
33    want to rebuild the picture unless the DOM has actually been changed.
34*/
35bool gAndroid_treatInvalForScreen;
36
37#define verifiedOk()    // no need to do anything in this function
38
39/*
40    This class implementation does NOT actually emulate the Qt ScrollView.
41    It does provide an implementation that khtml will use to interact with
42    WebKit's WebFrameView documentView and our NSScrollView subclass.
43
44    ScrollView's view is a NSScrollView (or subclass of NSScrollView)
45    in most cases. That scrollview is a subview of an
46    WebCoreFrameView. The WebCoreFrameView's documentView will also be
47    the scroll view's documentView.
48
49    The WebCoreFrameView's size is the frame size.  The WebCoreFrameView's documentView
50    corresponds to the frame content size.  The scrollview itself is autosized to the
51    WebCoreFrameView's size (see Widget::resize).
52*/
53
54namespace WebCore {
55
56struct ScrollView::ScrollViewPrivate
57{
58public:
59    ScrollViewPrivate() :
60        hasStaticBackground(false), ignoreUpdateContents(false),
61        vScrollbarMode(ScrollbarAuto),
62        hScrollbarMode(ScrollbarAuto) {}
63    IntSize contentsSize;
64    bool hasStaticBackground;
65    bool ignoreUpdateContents;
66    ScrollbarMode vScrollbarMode;
67    ScrollbarMode hScrollbarMode;
68};
69
70ScrollView::ScrollView()
71{
72    m_data = new ScrollViewPrivate;
73}
74
75ScrollView::~ScrollView()
76{
77    delete m_data;
78}
79
80int ScrollView::visibleWidth() const
81{
82    LOG_ASSERT(this->getWebCoreViewBridge(), "ScrollView does not have a WebCoreViewBridge");
83    return this->getWebCoreViewBridge()->width();
84}
85
86int ScrollView::visibleHeight() const
87{
88    LOG_ASSERT(this->getWebCoreViewBridge(), "ScrollView does not have a WebCoreViewBridge");
89    return this->getWebCoreViewBridge()->height();
90}
91
92FloatRect ScrollView::visibleContentRect() const
93{
94    LOG_ASSERT(this->getWebCoreViewBridge(), "ScrollView does not have a WebCoreViewBridge");
95    IntRect rect = this->getWebCoreViewBridge()->getBounds();
96    // FIXME: This is a hack to get subframes drawing correctly. Since subframes cannot
97    // scroll, we know that if this view has a parent, the visible rect is (0, 0, w, h)
98    if (this->getWebCoreViewBridge()->getParent())
99        return FloatRect(0, 0, rect.width(), rect.height());
100    return FloatRect(rect.x(), rect.y(), rect.width(), rect.height());
101}
102
103int ScrollView::contentsWidth() const
104{
105    return m_data->contentsSize.width();
106}
107
108int ScrollView::contentsHeight() const
109{
110    return m_data->contentsSize.height();
111}
112
113int ScrollView::contentsX() const
114{
115    return scrollOffset().width();
116}
117
118int ScrollView::contentsY() const
119{
120    return scrollOffset().height();
121}
122
123IntSize ScrollView::scrollOffset() const
124{
125    LOG_ASSERT(this->getWebCoreViewBridge(), "ScrollView does not have a WebCoreViewBridge");
126    WebCoreViewBridge* bridge = this->getWebCoreViewBridge();
127    // FIXME: This is a hack to get subframes drawing correctly. Since subframes cannot
128    // scroll, we know that if this view has a parent, the scroll offset is always (0, 0)
129    if (bridge->getParent())
130        return IntSize(0, 0);
131    return IntSize(bridge->locX(), bridge->locY());
132}
133
134void ScrollView::scrollBy(int dx, int dy)
135{
136    LOG_ASSERT(this->getWebCoreViewBridge(), "ScrollView does not have a WebCoreViewBridge");
137    this->getWebCoreViewBridge()->scrollBy(dx, dy);
138}
139
140void WebCore::ScrollView::update()
141{
142    LOG_ASSERT(this->getWebCoreViewBridge(), "ScrollView does not have a WebCoreViewBridge");
143    this->getWebCoreViewBridge()->contentInvalidate();
144}
145
146void WebCore::ScrollView::scrollRectIntoViewRecursively(WebCore::IntRect const& r)
147{
148    LOG_ASSERT(this->getWebCoreViewBridge(), "ScrollView does not have a WebCoreViewBridge");
149    int x = r.x();
150    int y = r.y();
151    IntPoint p(x > 0 ? x : 0, y > 0 ? y : 0);
152    ScrollView* view = this;
153    while (view) {
154        view->setContentsPos(p.x(), p.y());
155        p.move(view->x() - view->scrollOffset().width(), view->y() - view->scrollOffset().height());
156        if (view->getWebCoreViewBridge()->getParent())
157            view = static_cast<ScrollView*>(view->getWebCoreViewBridge()->getParent()->widget());
158        else
159            view = NULL;
160    }
161}
162
163WebCore::FloatRect WebCore::ScrollView::visibleContentRectConsideringExternalScrollers() const {
164    return FloatRect(contentsX(), contentsY(), contentsWidth(), contentsHeight());
165}
166
167void ScrollView::setContentsPos(int x, int y)
168{
169    LOG_ASSERT(this->getWebCoreViewBridge(), "ScrollView does not have a WebCoreViewBridge");
170    this->getWebCoreViewBridge()->scrollTo(x, y);
171}
172
173//---------------------------------------------------------------------
174// Scroll bar methods
175//
176// These methods are largely unimplemented meaning that the
177// state of the scroll bars in the only data maintained. If
178// a scroll bar is needed, the set(V|H)ScrollbarMode methods
179// need to update the scroll bar widget through the java
180// layer and display the new scroll bars.
181//
182//---------------------------------------------------------------------
183
184void ScrollView::setVScrollbarMode(ScrollbarMode vMode)
185{
186    m_data->vScrollbarMode = vMode;
187}
188
189void ScrollView::setHScrollbarMode(ScrollbarMode hMode)
190{
191    m_data->hScrollbarMode = hMode;
192}
193
194void ScrollView::setScrollbarsMode(ScrollbarMode mode)
195{
196    m_data->hScrollbarMode = mode;
197    m_data->vScrollbarMode = mode;
198}
199
200ScrollbarMode ScrollView::vScrollbarMode() const
201{
202    return m_data->vScrollbarMode;
203}
204
205ScrollbarMode ScrollView::hScrollbarMode() const
206{
207    return m_data->hScrollbarMode;
208}
209
210void ScrollView::suppressScrollbars(bool suppressed,  bool repaintOnUnsuppress)
211{
212    verifiedOk();
213}
214
215//---------------------------------------------------------------------
216// End Scroll bar methods
217//---------------------------------------------------------------------
218
219void ScrollView::addChild(Widget* child)
220{
221    LOG_ASSERT(this->getWebCoreViewBridge(), "ScrollView does not have a WebCoreViewBridge");
222    WebCoreViewBridge* childBridge = child->getWebCoreViewBridge();
223    // FIXME: For now just check this, it should be an assert down the road.
224    if (!childBridge)
225    {
226        LOGV("childBridge is not set");
227        return;
228    }
229    LOG_ASSERT(child != this, "Child has no view bridge or child == this!");
230    WebCoreViewBridge* thisBridge = this->getWebCoreViewBridge();
231    LOG_ASSERT(thisBridge && thisBridge != childBridge, "Our bridge is not set or thisBridge == childBridge!");
232    LOGV("Adding parent");
233    childBridge->setParent(thisBridge);
234}
235
236void ScrollView::ignoreUpdateContents(bool ignore)
237{
238    m_data->ignoreUpdateContents = ignore;
239}
240
241void ScrollView::removeChild(Widget* child)
242{
243    // FIXME: Make this only an assert once all widgets have views
244    if (!child->getWebCoreViewBridge())
245    {
246        LOGV("child has no bridge");
247        return;
248    }
249    LOG_ASSERT(child->getWebCoreViewBridge(), "Child has no view bridge");
250    child->getWebCoreViewBridge()->setParent(NULL);
251}
252
253void ScrollView::resizeContents(int w, int h)
254{
255    LOG_ASSERT(this->getWebCoreViewBridge(), "ScrollView does not have a WebCoreViewBridge");
256    if (w < 0)
257        w = 0;
258    if (h < 0)
259        h = 0;
260
261    IntSize newSize(w, h);
262    m_data->contentsSize = newSize;
263}
264
265void ScrollView::updateContents(const IntRect &rect, bool now)
266{
267    LOG_ASSERT(this->getWebCoreViewBridge(),
268               "ScrollView does not have a WebCoreViewBridge");
269
270    WebCoreViewBridge* bridge = this->getWebCoreViewBridge();
271
272    if (gAndroid_treatInvalForScreen) {
273//        SkDebugf("------ contentInvalidate sent to viewInvalidate [%d %d]\n", rect.width(), rect.height());
274        bridge->viewInvalidate();
275    } else if (m_data->ignoreUpdateContents == false) {
276        bridge->contentInvalidate(rect);
277    }
278}
279
280IntPoint ScrollView::windowToContents(const IntPoint& contentsPoint) const
281{
282    WebCoreViewBridge* bridge = this->getWebCoreViewBridge();
283    WebCoreViewBridge* parent = bridge->getParent();
284    int x = 0, y= 0;
285    while (parent) {
286        x += bridge->locX();
287        y += bridge->locY();
288        bridge = parent;
289        parent = bridge->getParent();
290    }
291    return IntPoint(contentsPoint.x() - x, contentsPoint.y() - y);
292}
293
294IntPoint ScrollView::contentsToWindow(const IntPoint& viewportPoint) const
295{
296    WebCoreViewBridge* bridge = this->getWebCoreViewBridge();
297    WebCoreViewBridge* parent = bridge->getParent();
298    int x = 0, y= 0;
299    while (parent) {
300        x += bridge->locX();
301        y += bridge->locY();
302        bridge = parent;
303        parent = bridge->getParent();
304    }
305    return IntPoint(viewportPoint.x() + x, viewportPoint.y() + y);
306}
307
308void ScrollView::setStaticBackground(bool)
309{
310    // we don't have any optimizations for this
311    verifiedOk();
312}
313
314bool ScrollView::inWindow() const
315{
316    LOGV("inWindow Unimplemented");
317#if 0
318    return [getView() window];
319#endif
320    return true;
321}
322
323void ScrollView::wheelEvent(PlatformWheelEvent&)
324{
325    verifiedOk();
326}
327
328PlatformScrollbar* ScrollView::scrollbarUnderMouse(const PlatformMouseEvent& mouseEvent)
329{
330    verifiedOk();
331    return NULL;
332}
333
334}
335