Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(549)

Side by Side Diff: webkit/port/platform/ScrollViewWin.cpp

Issue 7419: Move many files that were suffixed Win.cpp to Chromium.cpp, and place them in... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 12 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « webkit/port/platform/ScreenWin.cpp ('k') | webkit/port/platform/SearchPopupMenuWin.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2006, 2007 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 #include "config.h"
27 #include "ScrollView.h"
28
29 #include "Chrome.h"
30 #include "ChromeClient.h"
31 #include "FloatRect.h"
32 #include "FocusController.h"
33 #include "Frame.h"
34 #include "FrameView.h"
35 #include "GraphicsContext.h"
36 #include "IntRect.h"
37 #include "NotImplemented.h"
38 #include "Page.h"
39 #include "PlatformScrollBar.h"
40 #include "PlatformMouseEvent.h"
41 #include "PlatformWheelEvent.h"
42 #include "Range.h"
43 #include "RenderTheme.h"
44 #include "ScrollBar.h"
45 #include "SkiaUtils.h"
46 #include "WidgetClientWin.h"
47 #include <algorithm>
48 #include <wtf/Assertions.h>
49 #include <wtf/HashSet.h>
50
51 #undef LOG
52 #include "base/gfx/platform_canvas_win.h"
53 #include "webkit/glue/webframe_impl.h"
54 #include "webkit/glue/webview_impl.h"
55
56 using namespace std;
57
58 namespace WebCore {
59
60 class ScrollView::ScrollViewPrivate : public ScrollbarClient {
61 public:
62 ScrollViewPrivate(ScrollView* view)
63 : m_view(view)
64 , m_hasStaticBackground(false)
65 , m_scrollbarsSuppressed(false)
66 , m_inUpdateScrollbars(false)
67 , m_scrollbarsAvoidingResizer(0)
68 , m_vScrollbarMode(ScrollbarAuto)
69 , m_hScrollbarMode(ScrollbarAuto)
70 , m_visible(false)
71 , m_attachedToWindow(false)
72 , m_panScrollIconPoint(0,0)
73 , m_drawPanScrollIcon(false)
74 {
75 }
76
77 ~ScrollViewPrivate()
78 {
79 setHasHorizontalScrollbar(false);
80 setHasVerticalScrollbar(false);
81 }
82
83 void setHasHorizontalScrollbar(bool hasBar);
84 void setHasVerticalScrollbar(bool hasBar);
85
86 virtual void valueChanged(Scrollbar*);
87 virtual IntRect windowClipRect() const;
88 virtual bool isActive() const;
89
90 void scrollBackingStore(const IntSize& scrollDelta);
91
92 // Get the vector containing the result from the FindInPage operation.
93 const Vector<RefPtr<Range> >* getTickmarks() const;
94
95 // Retrieves the index of the active tickmark for a given frame. If the
96 // frame does not have an active tickmark (for example if the active
97 // tickmark resides in another frame) this function returns kNoTickmark.
98 size_t ScrollView::ScrollViewPrivate::getActiveTickmarkIndex() const;
99
100 // This is a helper function for accessing the bitmaps that have been cached
101 // in the renderer.
102 const SkBitmap* GetPreloadedBitmapFromRenderer(int resource_id) const;
103
104 // Highlight the matches found during FindInPage operation.
105 void highlightMatches(GraphicsContext* context) const;
106
107 // Highlights the node selected in the DOM inspector.
108 void highlightInspectedNode(GraphicsContext* context, Frame* frame) const;
109
110 // Highlight a certain Range on the page.
111 void highlightRange(HDC hdc, HDC mem_dc, RefPtr<Range> range) const;
112
113 void setAllowsScrolling(bool);
114 bool allowsScrolling() const;
115
116 ScrollView* m_view;
117 IntSize m_scrollOffset;
118 IntSize m_contentsSize;
119 bool m_hasStaticBackground;
120 bool m_scrollbarsSuppressed;
121 bool m_inUpdateScrollbars;
122 int m_scrollbarsAvoidingResizer;
123 ScrollbarMode m_vScrollbarMode;
124 ScrollbarMode m_hScrollbarMode;
125 RefPtr<PlatformScrollbar> m_vBar;
126 RefPtr<PlatformScrollbar> m_hBar;
127 HRGN m_dirtyRegion;
128 HashSet<Widget*> m_children;
129 bool m_visible;
130 bool m_attachedToWindow;
131 IntPoint m_panScrollIconPoint;
132 bool m_drawPanScrollIcon;
133 };
134
135 const int panIconSizeLength = 20;
136
137 void ScrollView::ScrollViewPrivate::setHasHorizontalScrollbar(bool hasBar)
138 {
139 if (Scrollbar::hasPlatformScrollbars()) {
140 if (hasBar && !m_hBar) {
141 m_hBar = PlatformScrollbar::create(this, HorizontalScrollbar, Regula rScrollbar);
142 m_view->addChild(m_hBar.get());
143 } else if (!hasBar && m_hBar) {
144 m_view->removeChild(m_hBar.get());
145 m_hBar = 0;
146 }
147 }
148 }
149
150 void ScrollView::ScrollViewPrivate::setHasVerticalScrollbar(bool hasBar)
151 {
152 if (Scrollbar::hasPlatformScrollbars()) {
153 if (hasBar && !m_vBar) {
154 m_vBar = PlatformScrollbar::create(this, VerticalScrollbar, RegularS crollbar);
155 m_view->addChild(m_vBar.get());
156 } else if (!hasBar && m_vBar) {
157 m_view->removeChild(m_vBar.get());
158 m_vBar = 0;
159 }
160 }
161 }
162
163 void ScrollView::ScrollViewPrivate::valueChanged(Scrollbar* bar)
164 {
165 // Figure out if we really moved.
166 IntSize newOffset = m_scrollOffset;
167 if (bar) {
168 if (bar == m_hBar)
169 newOffset.setWidth(bar->value());
170 else if (bar == m_vBar)
171 newOffset.setHeight(bar->value());
172 }
173 IntSize scrollDelta = newOffset - m_scrollOffset;
174 if (scrollDelta == IntSize())
175 return;
176 m_scrollOffset = newOffset;
177
178 if (m_scrollbarsSuppressed)
179 return;
180
181 scrollBackingStore(scrollDelta);
182
183 if (Frame* frame = static_cast<FrameView*>(m_view)->frame()) {
184 frame->sendScrollEvent();
185
186 // Inform the delegate that the scroll position has changed.
187 WidgetClientWin* client =
188 static_cast<WidgetClientWin*>(m_view->client());
189 if (client)
190 client->onScrollPositionChanged(m_view);
191 }
192 }
193
194 void ScrollView::ScrollViewPrivate::scrollBackingStore(const IntSize& scrollDelt a)
195 {
196 // Since scrolling is double buffered, we will be blitting the scroll view's intersection
197 // with the clip rect every time to keep it smooth.
198
199 IntRect clipRect = m_view->windowClipRect();
200 IntRect scrollViewRect = m_view->convertToContainingWindow(IntRect(0, 0, m_v iew->visibleWidth(), m_view->visibleHeight()));
201
202 // Negative when our frame is smaller than the min scrollbar width.
203 if (scrollViewRect.width() < 0)
204 scrollViewRect.setWidth(0);
205 if (scrollViewRect.height() < 0)
206 scrollViewRect.setHeight(0);
207
208 if (!m_hasStaticBackground) { // The main frame can just blit the WebView wi ndow
209 // FIXME: Find a way to blit subframes without blitting overlapping cont ent
210 m_view->scrollBackingStore(-scrollDelta.width(), -scrollDelta.height(), scrollViewRect, clipRect);
211 } else {
212 IntRect updateRect = clipRect;
213 updateRect.intersect(scrollViewRect);
214
215 // We need to go ahead and repaint the entire backing store. Do it now before moving the
216 // plugins.
217 m_view->addToDirtyRegion(updateRect);
218 m_view->updateBackingStore();
219 }
220
221 // This call will move child HWNDs (plugins) and invalidate them as well.
222 m_view->geometryChanged();
223 }
224
225 void ScrollView::ScrollViewPrivate::setAllowsScrolling(bool flag)
226 {
227 if (flag && m_vScrollbarMode == ScrollbarAlwaysOff)
228 m_vScrollbarMode = ScrollbarAuto;
229 else if (!flag)
230 m_vScrollbarMode = ScrollbarAlwaysOff;
231
232 if (flag && m_hScrollbarMode == ScrollbarAlwaysOff)
233 m_hScrollbarMode = ScrollbarAuto;
234 else if (!flag)
235 m_hScrollbarMode = ScrollbarAlwaysOff;
236
237 m_view->updateScrollbars(m_scrollOffset);
238 }
239
240 bool ScrollView::ScrollViewPrivate::allowsScrolling() const
241 {
242 // Return YES if either horizontal or vertical scrolling is allowed.
243 return m_hScrollbarMode != ScrollbarAlwaysOff || m_vScrollbarMode != Scrollb arAlwaysOff;
244 }
245
246 IntRect ScrollView::ScrollViewPrivate::windowClipRect() const
247 {
248 // FrameView::windowClipRect() will exclude the scrollbars, but here we
249 // want to include them, so we are forced to cast to FrameView in order to
250 // call the non-virtual version of windowClipRect :-(
251 //
252 // The non-frame case exists to support FramelessScrollView.
253
254 const FrameView* frameView = static_cast<const FrameView*>(m_view);
255 if (frameView->frame())
256 return frameView->windowClipRect(false);
257
258 return m_view->windowClipRect();
259 }
260
261 bool ScrollView::ScrollViewPrivate::isActive() const
262 {
263 Page* page = static_cast<const FrameView*>(m_view)->frame()->page();
264 return page && page->focusController()->isActive();
265 }
266
267 const Vector<RefPtr<Range> >* ScrollView::ScrollViewPrivate::getTickmarks() cons t
268 {
269 FrameView* view = static_cast<FrameView*>(m_view);
270 ASSERT(view);
271 Frame* frame = view->frame();
272
273 if (!frame)
274 return NULL; // NOTE: Frame can be null for dropdown boxes.
275
276 WidgetClientWin* c = static_cast<WidgetClientWin*>(m_view->client());
277 ASSERT(c);
278 return c->getTickmarks(view->frame());
279 }
280
281 size_t ScrollView::ScrollViewPrivate::getActiveTickmarkIndex() const
282 {
283 FrameView* view = static_cast<FrameView*>(m_view);
284 ASSERT(view);
285 Frame* frame = view->frame();
286
287 // NOTE: Frame can be null for dropdown boxes.
288 if (!frame)
289 return WidgetClientWin::kNoTickmark;
290
291 WidgetClientWin* c = static_cast<WidgetClientWin*>(m_view->client());
292 ASSERT(c);
293 return c->getActiveTickmarkIndex(view->frame());
294 }
295
296 const SkBitmap* ScrollView::ScrollViewPrivate::GetPreloadedBitmapFromRenderer(
297 int resource_id) const
298 {
299 WidgetClientWin* c = static_cast<WidgetClientWin*>(m_view->client());
300 if (!c)
301 return NULL;
302
303 return c->getPreloadedResourceBitmap(resource_id);
304 }
305
306 void ScrollView::ScrollViewPrivate::highlightMatches(
307 GraphicsContext* context) const
308 {
309 if (context->paintingDisabled())
310 return;
311
312 const Vector<RefPtr<Range> >* tickmarks = getTickmarks();
313 if (!tickmarks || tickmarks->isEmpty())
314 return;
315
316 context->save();
317 context->translate(m_view->x(), m_view->y());
318
319 // NOTE: We tolerate the platformContext() call here because the scrollbars
320 // will not be serialized, i.e. composition is done in the renderer and
321 // never in the browser.
322 // Prepare for drawing the arrows along the scroll bar.
323 gfx::PlatformCanvas* canvas = context->platformContext()->canvas();
324
325 int horz_start = 0;
326 int horz_end = m_view->width();
327 int vert_start = 0;
328 int vert_end = m_view->height();
329
330 if (m_vBar) {
331 // Account for the amount of scrolling on the vertical scroll bar.
332 vert_start += m_scrollOffset.height();
333 vert_end += m_scrollOffset.height();
334 // Don't draw atop the vertical scrollbar.
335 horz_end -= PlatformScrollbar::verticalScrollbarWidth() + 1;
336 }
337
338 if (m_hBar) {
339 // Account for the amount of scrolling on the horizontal scroll bar.
340 horz_start += m_scrollOffset.width();
341 horz_end += m_scrollOffset.width();
342 // Don't draw atop the horizontal scrollbar.
343 vert_end -= PlatformScrollbar::horizontalScrollbarHeight() + 1;
344 }
345
346 IntRect view_rect(IntPoint(), m_view->size());
347 HDC hdc = context->getWindowsContext(view_rect);
348
349 // We create a memory DC, copy the bits we want to highlight to the DC and
350 // then MERGE_COPY pieces of it back with a yellow brush selected (which
351 // gives them yellow highlighting).
352 HDC mem_dc = CreateCompatibleDC(hdc);
353 HBITMAP mem_bmp = CreateCompatibleBitmap(hdc, m_view->width(),
354 m_view->height());
355 HGDIOBJ old_bmp = SelectObject(mem_dc, mem_bmp);
356
357 // Now create a brush for hit highlighting. This is needed for the MERGECOPY
358 // to paint a yellow highlight onto the matches found. For more details, see
359 // the documentation for BitBlt.
360 static const COLORREF kFillColor = RGB(255, 250, 150); // Light yellow.
361 HGDIOBJ inactive_brush = CreateSolidBrush(kFillColor);
362 static const COLORREF kFillColorActive = RGB(255, 150, 50); // Orange.
363 HGDIOBJ active_brush = CreateSolidBrush(kFillColorActive);
364 HGDIOBJ old_brush = SelectObject(hdc, inactive_brush);
365
366 // Keep a copy of what's on screen, so we can MERGECOPY it back later for
367 // the purpose of highlighting the text.
368 BitBlt(mem_dc, 0, 0, m_view->width(), m_view->height(),
369 hdc, 0, 0, SRCCOPY);
370
371 const size_t active_tickmark = getActiveTickmarkIndex();
372 for (Vector<RefPtr<Range> >::const_iterator i = tickmarks->begin();
373 i != tickmarks->end(); ++i) {
374 const RefPtr<Range> range = (*i);
375 const IntRect& bounds = range->boundingBox();
376 // To highlight the word, we check if the rectangle boundary is within
377 // the bounds vertically as well as horizontally.
378 if (bounds.bottomRight().y() > vert_start &&
379 bounds.topLeft().y() < vert_end &&
380 bounds.bottomRight().x() > horz_start &&
381 bounds.topLeft().x() < horz_end &&
382 WebFrameImpl::RangeShouldBeHighlighted(range.get())) {
383 // We highlight the active tick-mark with a green color instead
384 // of the normal yellow color.
385 SelectObject(hdc, ((i - tickmarks->begin()) == active_tickmark) ?
386 active_brush : inactive_brush);
387 highlightRange(hdc, mem_dc, range);
388 }
389 }
390
391 SelectObject(mem_dc, old_brush);
392 DeleteObject(active_brush);
393 DeleteObject(inactive_brush);
394
395 SelectObject(mem_dc, old_bmp);
396 DeleteObject(mem_bmp);
397
398 DeleteDC(mem_dc);
399
400 context->releaseWindowsContext(hdc, view_rect);
401 context->restore();
402 }
403
404 // TODO(ojan): http://b/1143983 make this work for inline elements as they can
405 // wrap (use highlightRange instead?)
406 void ScrollView::ScrollViewPrivate::highlightInspectedNode(
407 GraphicsContext* context, Frame* frame) const
408 {
409 WebViewImpl* c = static_cast<WebViewImpl*>(m_view->client());
410 const WebCore::Node* inspected_node = c->getInspectedNode(frame);
411
412 if (!inspected_node)
413 return;
414
415 SkPaint paint;
416 paint.setARGB(122, 255, 225, 0); // Yellow
417
418 // TODO(ojan): http://b/1143991 Once we sync a Skia version that supports
419 // it, use SkPorterDuff::kScreenMode and remove the transparency.
420 // Then port highlightMatches/highlightRanges to use this as well.
421 // Although, perhaps the web inspector really should be using
422 // an alpha overlay? It's less pretty, but more clear what node
423 // is being overlayed. In this case, the TODO is to make
424 // highlightMatches/Ranges use Skia and to leave this as is.
425 //
426 // paint.setPorterDuffXfermode(SkPorterDuff::kScreenMode);
427
428 // TODO(ojan): http://b/1143975 Draw the padding/border/margin boxes in
429 // different colors.
430 context->platformContext()->paintSkPaint(inspected_node->getRect(), paint);
431 }
432
433 void ScrollView::ScrollViewPrivate::highlightRange(HDC hdc, HDC mem_dc,
434 RefPtr<Range> range) const {
435 // We need to figure out whether the match that we want to
436 // highlight is on a single line or on multiple lines.
437 IntRect start = VisiblePosition(range->startPosition()).caretRect();
438 IntRect end = VisiblePosition(range->endPosition()).caretRect();
439 IntRect bounds = range->boundingBox();
440
441 // Multi-line bounds have different y pos for start and end.
442 if (start.y() == end.y()) {
443 int x = bounds.topLeft().x() - m_scrollOffset.width();
444 int y = bounds.topLeft().y() - m_scrollOffset.height();
445 int w = bounds.bottomRight().x() - bounds.topLeft().x() + 1;
446 int h = bounds.bottomRight().y() - bounds.topLeft().y() + 1;
447
448 // MERGECOPY the relevant bits back, creating a highlight.
449 BitBlt(hdc, x, y, w, h, mem_dc, x, y, MERGECOPY);
450 } else {
451 // Multi line bounds, for example, when we need to highlight
452 // all the numbers (and only the numbers) in this block of
453 // text:
454 //
455 // xxxxxxxxxxxxxxxx11111111
456 // 222222222222222222222222
457 // 222222222222222222222222
458 // 333333333333333xxxxxxxxx
459 //
460 // In this case, the bounding box will contain all the text,
461 // (including the exes (x)). We highlight in three steps.
462 // First we highlight the segment containing the ones (1)
463 // above. Then the whole middle section is highlighted, or the
464 // twos (2), and finally the remaining segment consisting of
465 // the threes (3) is highlighted.
466
467 const int row_height = start.height();
468 int x = 0, y = 0, w = 0, h = 0;
469
470 // The start and end caret can be outside the bounding box, for leading
471 // and trailing whitespace and we should not highlight those.
472 if (start.intersects(bounds)) {
473 // Highlight the first segment.
474 x = start.x() - m_scrollOffset.width();
475 y = start.y() - m_scrollOffset.height();
476 w = bounds.topRight().x() - start.x() + 1;
477 h = row_height;
478
479 BitBlt(hdc, x, y, w, h, mem_dc, x, y, MERGECOPY);
480 }
481
482 // Figure out how large the middle section is.
483 int rows_between = (end.y() - start.y()) / row_height - 1;
484
485 if (rows_between > 0) {
486 // Highlight the middle segment.
487 x = bounds.x() - m_scrollOffset.width();
488 y = bounds.y() - m_scrollOffset.height() + row_height;
489 w = bounds.width();
490 h = rows_between * row_height;
491
492 BitBlt(hdc, x, y, w, h, mem_dc, x, y, MERGECOPY);
493 }
494
495 // The end caret might not intersect the bounding box, for example
496 // when highlighting the last letter of a line that wraps. In that
497 // case the end caret is set to the beginning of the next line, and
498 // since it doesn't intersect with the bounding box we don't need to
499 // highlight.
500 if (end.intersects(bounds)) {
501 // Highlight the remaining segment.
502 x = bounds.bottomLeft().x() - m_scrollOffset.width();
503 y = bounds.bottomLeft().y() - m_scrollOffset.height() -
504 row_height + 1;
505 w = end.x() - bounds.bottomLeft().x();
506 h = row_height;
507
508 BitBlt(hdc, x, y, w, h, mem_dc, x, y, MERGECOPY);
509 }
510 }
511 }
512
513 ScrollView::ScrollView()
514 {
515 m_data = new ScrollViewPrivate(this);
516 }
517
518 ScrollView::~ScrollView()
519 {
520 delete m_data;
521 }
522
523 void ScrollView::updateContents(const IntRect& rect, bool now)
524 {
525 if (rect.isEmpty())
526 return;
527
528 IntRect containingWindowRect = contentsToWindow(rect);
529
530 if (containingWindowRect.x() < 0)
531 containingWindowRect.setX(0);
532 if (containingWindowRect.y() < 0)
533 containingWindowRect.setY(0);
534
535 updateWindowRect(containingWindowRect, now);
536 }
537
538 void ScrollView::updateWindowRect(const IntRect& rect, bool now)
539 {
540 // TODO(dglazkov): make sure this is actually the right way to do this
541
542 // Cache the dirty spot.
543 addToDirtyRegion(rect);
544
545 // since painting always happens asynchronously, we don't have a way to
546 // honor the "now" parameter. it is unclear if it matters.
547 if (now) {
548 // TODO(iyengar): Should we force a layout to occur here?
549 geometryChanged();
550 }
551 }
552
553 void ScrollView::update()
554 {
555 // TODO(iyengar): Should we force a layout to occur here?
556 geometryChanged();
557 }
558
559 int ScrollView::visibleWidth() const
560 {
561 return width() - (m_data->m_vBar ? m_data->m_vBar->width() : 0);
562 }
563
564 int ScrollView::visibleHeight() const
565 {
566 return height() - (m_data->m_hBar ? m_data->m_hBar->height() : 0);
567 }
568
569 FloatRect ScrollView::visibleContentRect() const
570 {
571 return FloatRect(contentsX(), contentsY(), visibleWidth(), visibleHeight());
572 }
573
574 FloatRect ScrollView::visibleContentRectConsideringExternalScrollers() const
575 {
576 // external scrollers not supported for now
577 return visibleContentRect();
578 }
579
580 void ScrollView::setContentsPos(int newX, int newY)
581 {
582 int dx = newX - contentsX();
583 int dy = newY - contentsY();
584 scrollBy(dx, dy);
585 }
586
587 void ScrollView::resizeContents(int w, int h)
588 {
589 IntSize newContentsSize(w, h);
590 if (m_data->m_contentsSize != newContentsSize) {
591 m_data->m_contentsSize = newContentsSize;
592 updateScrollbars(m_data->m_scrollOffset);
593 }
594 }
595
596 void ScrollView::setFrameGeometry(const IntRect& newGeometry)
597 {
598 IntRect normalizedNewGeometry = newGeometry;
599
600 // Webkit sometimes attempts to set negative sizes due to
601 // sloppy calculations of width with margins and such.
602 // (RenderPart:updateWidgetPosition is one example.)
603 // Safeguard against this and prevent negative heights/widths.
604 if (normalizedNewGeometry.width() < 0)
605 normalizedNewGeometry.setWidth(0);
606 if (normalizedNewGeometry.height() < 0)
607 normalizedNewGeometry.setHeight(0);
608
609 IntRect oldGeometry = frameGeometry();
610 Widget::setFrameGeometry(normalizedNewGeometry);
611
612 if (normalizedNewGeometry == oldGeometry)
613 return;
614
615 if (normalizedNewGeometry.width() != oldGeometry.width() ||
616 normalizedNewGeometry.height() != oldGeometry.height()) {
617 updateScrollbars(m_data->m_scrollOffset);
618
619 // when used to display a popup menu, we do not have a frame
620 FrameView* frameView = static_cast<FrameView*>(this);
621 if (frameView->frame())
622 frameView->setNeedsLayout();
623 }
624
625 geometryChanged();
626 }
627
628 int ScrollView::contentsX() const
629 {
630 return scrollOffset().width();
631 }
632
633 int ScrollView::contentsY() const
634 {
635 return scrollOffset().height();
636 }
637
638 int ScrollView::contentsWidth() const
639 {
640 return m_data->m_contentsSize.width();
641 }
642
643 int ScrollView::contentsHeight() const
644 {
645 return m_data->m_contentsSize.height();
646 }
647
648 IntPoint ScrollView::windowToContents(const IntPoint& windowPoint) const
649 {
650 IntPoint viewPoint = convertFromContainingWindow(windowPoint);
651 return viewPoint + scrollOffset();
652 }
653
654 IntPoint ScrollView::contentsToWindow(const IntPoint& contentsPoint) const
655 {
656 IntPoint viewPoint = contentsPoint - scrollOffset();
657 return convertToContainingWindow(viewPoint);
658 }
659
660 IntPoint ScrollView::convertChildToSelf(const Widget* child, const IntPoint& poi nt) const
661 {
662 IntPoint newPoint = point;
663 if (child != m_data->m_hBar && child != m_data->m_vBar)
664 newPoint = point - scrollOffset();
665 return Widget::convertChildToSelf(child, newPoint);
666 }
667
668 IntPoint ScrollView::convertSelfToChild(const Widget* child, const IntPoint& poi nt) const
669 {
670 IntPoint newPoint = point;
671 if (child != m_data->m_hBar && child != m_data->m_vBar)
672 newPoint = point + scrollOffset();
673 return Widget::convertSelfToChild(child, newPoint);
674 }
675
676 IntSize ScrollView::scrollOffset() const
677 {
678 return m_data->m_scrollOffset;
679 }
680
681 IntSize ScrollView::maximumScroll() const
682 {
683 // We should not check whether scrolling is allowed for this view before cal culating
684 // the maximumScroll. Please refer to http://b/issue?id=1164704, where in sc rolling
685 // would not work on a scrollview created with scrollbars disabled. The curr ent
686 // behavior mirrors Safari's webkit implementation. Firefox also behaves sim ilarly.
687 IntSize delta = (m_data->m_contentsSize - IntSize(visibleWidth(), visibleHei ght())) - scrollOffset();
688 delta.clampNegativeToZero();
689 return delta;
690 }
691
692 void ScrollView::scrollBy(int dx, int dy)
693 {
694 IntSize scrollOffset = m_data->m_scrollOffset;
695 IntSize newScrollOffset = scrollOffset + IntSize(dx, dy).shrunkTo(maximumScr oll());
696 newScrollOffset.clampNegativeToZero();
697
698 if (newScrollOffset == scrollOffset)
699 return;
700
701 updateScrollbars(newScrollOffset);
702 }
703
704 void ScrollView::scrollRectIntoViewRecursively(const IntRect& r)
705 {
706 IntPoint p(max(0, r.x()), max(0, r.y()));
707 ScrollView* view = this;
708 while (view) {
709 view->setContentsPos(p.x(), p.y());
710 p.move(view->x() - view->scrollOffset().width(), view->y() - view->scrol lOffset().height());
711 view = static_cast<ScrollView*>(view->parent());
712 }
713 }
714
715 WebCore::ScrollbarMode ScrollView::hScrollbarMode() const
716 {
717 return m_data->m_hScrollbarMode;
718 }
719
720 WebCore::ScrollbarMode ScrollView::vScrollbarMode() const
721 {
722 return m_data->m_vScrollbarMode;
723 }
724
725 void ScrollView::suppressScrollbars(bool suppressed, bool repaintOnSuppress)
726 {
727 m_data->m_scrollbarsSuppressed = suppressed;
728 if (repaintOnSuppress && !suppressed) {
729 if (m_data->m_hBar)
730 m_data->m_hBar->invalidate();
731 if (m_data->m_vBar)
732 m_data->m_vBar->invalidate();
733
734 // Invalidate the scroll corner too on unsuppress.
735 IntRect hCorner;
736 if (m_data->m_hBar && width() - m_data->m_hBar->width() > 0) {
737 hCorner = IntRect(m_data->m_hBar->width(),
738 height() - m_data->m_hBar->height(),
739 width() - m_data->m_hBar->width(),
740 m_data->m_hBar->height());
741 invalidateRect(hCorner);
742 }
743
744 if (m_data->m_vBar && height() - m_data->m_vBar->height() > 0) {
745 IntRect vCorner(width() - m_data->m_vBar->width(),
746 m_data->m_vBar->height(),
747 m_data->m_vBar->width(),
748 height() - m_data->m_vBar->height());
749 if (vCorner != hCorner)
750 invalidateRect(vCorner);
751 }
752 }
753 }
754
755 void ScrollView::setHScrollbarMode(ScrollbarMode newMode)
756 {
757 if (m_data->m_hScrollbarMode != newMode) {
758 m_data->m_hScrollbarMode = newMode;
759 updateScrollbars(m_data->m_scrollOffset);
760 }
761 }
762
763 void ScrollView::setVScrollbarMode(ScrollbarMode newMode)
764 {
765 if (m_data->m_vScrollbarMode != newMode) {
766 m_data->m_vScrollbarMode = newMode;
767 updateScrollbars(m_data->m_scrollOffset);
768 }
769 }
770
771 void ScrollView::setScrollbarsMode(ScrollbarMode newMode)
772 {
773 if (m_data->m_hScrollbarMode != newMode ||
774 m_data->m_vScrollbarMode != newMode) {
775 m_data->m_hScrollbarMode = m_data->m_vScrollbarMode = newMode;
776 updateScrollbars(m_data->m_scrollOffset);
777 }
778 }
779
780 void ScrollView::setStaticBackground(bool flag)
781 {
782 m_data->m_hasStaticBackground = flag;
783 }
784
785 void ScrollView::updateScrollbars(const IntSize& desiredOffset)
786 {
787 // Don't allow re-entrancy into this function.
788 if (m_data->m_inUpdateScrollbars)
789 return;
790
791 m_data->m_inUpdateScrollbars = true;
792
793 bool hasVerticalScrollbar = m_data->m_vBar;
794 bool hasHorizontalScrollbar = m_data->m_hBar;
795 bool oldHasVertical = hasVerticalScrollbar;
796 bool oldHasHorizontal = hasHorizontalScrollbar;
797 ScrollbarMode hScroll = m_data->m_hScrollbarMode;
798 ScrollbarMode vScroll = m_data->m_vScrollbarMode;
799
800 const int cVerticalWidth = PlatformScrollbar::verticalScrollbarWidth();
801 const int cHorizontalHeight = PlatformScrollbar::horizontalScrollbarHeight() ;
802
803 // we may not be able to support scrollbars due to our frame geometry
804 if (width() < cVerticalWidth)
805 vScroll = ScrollbarAlwaysOff;
806 if (height() < cHorizontalHeight)
807 hScroll = ScrollbarAlwaysOff;
808
809 for (int pass = 0; pass < 2; pass++) {
810 bool scrollsVertically;
811 bool scrollsHorizontally;
812
813 if (!m_data->m_scrollbarsSuppressed && (hScroll == ScrollbarAuto || vScr oll == ScrollbarAuto)) {
814 // Do a layout if pending before checking if scrollbars are needed.
815 if (hasVerticalScrollbar != oldHasVertical || hasHorizontalScrollbar != oldHasHorizontal)
816 static_cast<FrameView*>(this)->layout();
817
818 scrollsVertically = (vScroll == ScrollbarAlwaysOn) || (vScroll == Sc rollbarAuto && contentsHeight() > height());
819 if (scrollsVertically)
820 scrollsHorizontally = (hScroll == ScrollbarAlwaysOn) || (hScroll == ScrollbarAuto && contentsWidth() + cVerticalWidth > width());
821 else {
822 scrollsHorizontally = (hScroll == ScrollbarAlwaysOn) || (hScroll == ScrollbarAuto && contentsWidth() > width());
823 if (scrollsHorizontally)
824 scrollsVertically = (vScroll == ScrollbarAlwaysOn) || (vScro ll == ScrollbarAuto && contentsHeight() + cHorizontalHeight > height());
825 }
826 }
827 else {
828 scrollsHorizontally = (hScroll == ScrollbarAuto) ? hasHorizontalScro llbar : (hScroll == ScrollbarAlwaysOn);
829 scrollsVertically = (vScroll == ScrollbarAuto) ? hasVerticalScrollba r : (vScroll == ScrollbarAlwaysOn);
830 }
831
832 if (hasVerticalScrollbar != scrollsVertically) {
833 m_data->setHasVerticalScrollbar(scrollsVertically);
834 hasVerticalScrollbar = scrollsVertically;
835 }
836
837 if (hasHorizontalScrollbar != scrollsHorizontally) {
838 m_data->setHasHorizontalScrollbar(scrollsHorizontally);
839 hasHorizontalScrollbar = scrollsHorizontally;
840 }
841 }
842
843 // Set up the range (and page step/line step).
844 IntSize maxScrollPosition(contentsWidth() - visibleWidth(), contentsHeight() - visibleHeight());
845 IntSize scroll = desiredOffset.shrunkTo(maxScrollPosition);
846 scroll.clampNegativeToZero();
847
848 if (m_data->m_hBar) {
849 int clientWidth = visibleWidth();
850 m_data->m_hBar->setEnabled(contentsWidth() > clientWidth);
851 int pageStep = (clientWidth - PAGE_KEEP);
852 if (pageStep < 0) pageStep = clientWidth;
853 IntRect oldRect(m_data->m_hBar->frameGeometry());
854 IntRect hBarRect = IntRect(0,
855 height() - m_data->m_hBar->height(),
856 width() - (m_data->m_vBar ? m_data->m_vBar->w idth() : 0),
857 m_data->m_hBar->height());
858 m_data->m_hBar->setRect(hBarRect);
859 if (!m_data->m_scrollbarsSuppressed && oldRect != m_data->m_hBar->frameG eometry())
860 m_data->m_hBar->invalidate();
861
862 if (m_data->m_scrollbarsSuppressed)
863 m_data->m_hBar->setSuppressInvalidation(true);
864 m_data->m_hBar->setSteps(LINE_STEP, pageStep);
865 m_data->m_hBar->setProportion(clientWidth, contentsWidth());
866 m_data->m_hBar->setValue(scroll.width());
867 if (m_data->m_scrollbarsSuppressed)
868 m_data->m_hBar->setSuppressInvalidation(false);
869 }
870
871 if (m_data->m_vBar) {
872 int clientHeight = visibleHeight();
873 m_data->m_vBar->setEnabled(contentsHeight() > clientHeight);
874 int pageStep = (clientHeight - PAGE_KEEP);
875 if (pageStep < 0) pageStep = clientHeight;
876 IntRect oldRect(m_data->m_vBar->frameGeometry());
877 IntRect vBarRect = IntRect(width() - m_data->m_vBar->width(),
878 0,
879 m_data->m_vBar->width(),
880 height() - (m_data->m_hBar ? m_data->m_hBar-> height() : 0));
881 m_data->m_vBar->setRect(vBarRect);
882 if (!m_data->m_scrollbarsSuppressed && oldRect != m_data->m_vBar->frameG eometry())
883 m_data->m_vBar->invalidate();
884
885 if (m_data->m_scrollbarsSuppressed)
886 m_data->m_vBar->setSuppressInvalidation(true);
887 m_data->m_vBar->setSteps(LINE_STEP, pageStep);
888 m_data->m_vBar->setProportion(clientHeight, contentsHeight());
889 m_data->m_vBar->setValue(scroll.height());
890 if (m_data->m_scrollbarsSuppressed)
891 m_data->m_vBar->setSuppressInvalidation(false);
892 }
893
894 if (oldHasVertical != (m_data->m_vBar != 0) || oldHasHorizontal != (m_data-> m_hBar != 0))
895 geometryChanged();
896
897 // See if our offset has changed in a situation where we might not have scro llbars.
898 // This can happen when editing a body with overflow:hidden and scrolling to reveal selection.
899 // It can also happen when maximizing a window that has scrollbars (but the new maximized result
900 // does not).
901 IntSize scrollDelta = scroll - m_data->m_scrollOffset;
902 if (scrollDelta != IntSize()) {
903 m_data->m_scrollOffset = scroll;
904 m_data->scrollBackingStore(scrollDelta);
905
906 // Inform the delegate that the scroll position has changed.
907 WidgetClientWin* c = static_cast<WidgetClientWin*>(client());
908 if (c)
909 c->onScrollPositionChanged(this);
910 }
911
912 m_data->m_inUpdateScrollbars = false;
913
914 ASSERT(visibleWidth() >= 0);
915 ASSERT(visibleHeight() >= 0);
916 }
917
918 PlatformScrollbar* ScrollView::scrollbarUnderMouse(const PlatformMouseEvent& mou seEvent)
919 {
920 IntPoint viewPoint = convertFromContainingWindow(mouseEvent.pos());
921 if (m_data->m_hBar && m_data->m_hBar->frameGeometry().contains(viewPoint))
922 return m_data->m_hBar.get();
923 if (m_data->m_vBar && m_data->m_vBar->frameGeometry().contains(viewPoint))
924 return m_data->m_vBar.get();
925 return 0;
926 }
927
928 void ScrollView::addChild(Widget* child)
929 {
930 child->setParent(this);
931
932 // There is only one global widget client (which should be the WebViewImpl).
933 // It is responsible for things like capturing the mouse.
934 child->setClient(client());
935
936 m_data->m_children.add(child);
937 }
938
939 void ScrollView::removeChild(Widget* child)
940 {
941 child->setParent(0);
942 m_data->m_children.remove(child);
943 }
944
945 void ScrollView::paint(GraphicsContext* context, const IntRect& rect)
946 {
947 // FIXME: This code is here so we don't have to fork FrameView.h/.cpp.
948 // In the end, FrameView should just merge with ScrollView.
949 ASSERT(isFrameView());
950
951 if (context->paintingDisabled())
952 return;
953
954 if (Frame* frame = static_cast<FrameView*>(this)->frame()) {
955 IntRect documentDirtyRect = rect;
956 documentDirtyRect.intersect(frameGeometry());
957
958 context->save();
959
960 context->translate(x(), y());
961 documentDirtyRect.move(-x(), -y());
962
963 context->translate(-contentsX(), -contentsY());
964 documentDirtyRect.move(contentsX(), contentsY());
965
966 // do not allow painting outside of the dirty rect
967 context->clip(documentDirtyRect);
968
969 frame->paint(context, documentDirtyRect);
970
971 // Highlights the node selected in the DOM inspector.
972 m_data->highlightInspectedNode(context, frame);
973
974 context->restore();
975 }
976
977 // Highlight the matches found on the page, during a FindInPage operation.
978 m_data->highlightMatches(context);
979
980 // Now paint the scrollbars.
981 if (!m_data->m_scrollbarsSuppressed && (m_data->m_hBar || m_data->m_vBar)) {
982 context->save();
983 IntRect scrollViewDirtyRect = rect;
984 scrollViewDirtyRect.intersect(frameGeometry());
985 context->translate(x(), y());
986 scrollViewDirtyRect.move(-x(), -y());
987 if (m_data->m_hBar)
988 m_data->m_hBar->paint(context, scrollViewDirtyRect);
989 if (m_data->m_vBar)
990 m_data->m_vBar->paint(context, scrollViewDirtyRect);
991
992 // Fill the scroll corner with white.
993 IntRect hCorner;
994 if (m_data->m_hBar && width() - m_data->m_hBar->width() > 0) {
995 hCorner = IntRect(m_data->m_hBar->width(),
996 height() - m_data->m_hBar->height(),
997 width() - m_data->m_hBar->width(),
998 m_data->m_hBar->height());
999 if (hCorner.intersects(scrollViewDirtyRect))
1000 context->fillRect(hCorner, Color::white);
1001 }
1002
1003 if (m_data->m_vBar && height() - m_data->m_vBar->height() > 0) {
1004 IntRect vCorner(width() - m_data->m_vBar->width(),
1005 m_data->m_vBar->height(),
1006 m_data->m_vBar->width(),
1007 height() - m_data->m_vBar->height());
1008 if (vCorner != hCorner && vCorner.intersects(scrollViewDirtyRect))
1009 context->fillRect(vCorner, Color::white);
1010 }
1011
1012 context->restore();
1013 }
1014 }
1015
1016 void ScrollView::themeChanged()
1017 {
1018 PlatformScrollbar::themeChanged();
1019 theme()->themeChanged();
1020 invalidate();
1021 }
1022
1023 void ScrollView::wheelEvent(PlatformWheelEvent& e)
1024 {
1025 if (!m_data->allowsScrolling())
1026 return;
1027
1028 // Determine how much we want to scroll. If we can move at all, we will acc ept the event.
1029 IntSize maxScrollDelta = maximumScroll();
1030 if ((e.deltaX() < 0 && maxScrollDelta.width() > 0) ||
1031 (e.deltaX() > 0 && scrollOffset().width() > 0) ||
1032 (e.deltaY() < 0 && maxScrollDelta.height() > 0) ||
1033 (e.deltaY() > 0 && scrollOffset().height() > 0)) {
1034 e.accept();
1035 scrollBy(-e.deltaX() * LINE_STEP, -e.deltaY() * LINE_STEP);
1036 }
1037 }
1038
1039 HashSet<Widget*>* ScrollView::children()
1040 {
1041 return &(m_data->m_children);
1042 }
1043
1044 void ScrollView::geometryChanged() const
1045 {
1046 HashSet<Widget*>::const_iterator end = m_data->m_children.end();
1047 for (HashSet<Widget*>::const_iterator current = m_data->m_children.begin(); current != end; ++current)
1048 (*current)->geometryChanged();
1049 }
1050
1051 bool ScrollView::scroll(ScrollDirection direction, ScrollGranularity granularity )
1052 {
1053 if (direction == ScrollUp || direction == ScrollDown) {
1054 if (m_data->m_vBar)
1055 return m_data->m_vBar->scroll(direction, granularity);
1056 } else {
1057 if (m_data->m_hBar)
1058 return m_data->m_hBar->scroll(direction, granularity);
1059 }
1060 return false;
1061 }
1062
1063 IntRect ScrollView::windowResizerRect()
1064 {
1065 return IntRect();
1066 }
1067
1068 bool ScrollView::resizerOverlapsContent() const
1069 {
1070 return !m_data->m_scrollbarsAvoidingResizer;
1071 }
1072
1073 void ScrollView::adjustOverlappingScrollbarCount(int overlapDelta)
1074 {
1075 int oldCount = m_data->m_scrollbarsAvoidingResizer;
1076 m_data->m_scrollbarsAvoidingResizer += overlapDelta;
1077 if (parent() && parent()->isFrameView())
1078 static_cast<FrameView*>(parent())->adjustOverlappingScrollbarCount(overl apDelta);
1079 else if (!m_data->m_scrollbarsSuppressed) {
1080 // If we went from n to 0 or from 0 to n and we're the outermost view,
1081 // we need to invalidate the windowResizerRect(), since it will now need to paint
1082 // differently.
1083 if (oldCount > 0 && m_data->m_scrollbarsAvoidingResizer == 0 ||
1084 oldCount == 0 && m_data->m_scrollbarsAvoidingResizer > 0)
1085 invalidateRect(windowResizerRect());
1086 }
1087 }
1088
1089 void ScrollView::setParent(ScrollView* parentView)
1090 {
1091 if (!parentView && m_data->m_scrollbarsAvoidingResizer && parent() && parent ()->isFrameView())
1092 static_cast<FrameView*>(parent())->adjustOverlappingScrollbarCount(false );
1093 Widget::setParent(parentView);
1094 }
1095
1096 void ScrollView::addToDirtyRegion(const IntRect& containingWindowRect)
1097 {
1098 WidgetClientWin* c = static_cast<WidgetClientWin*>(client());
1099 if (c)
1100 c->invalidateRect(containingWindowRect);
1101 }
1102
1103 void ScrollView::scrollBackingStore(int dx, int dy, const IntRect& scrollViewRec t, const IntRect& clipRect)
1104 {
1105 // We don't know how to scroll in two directions at once.
1106 if (dx && dy) {
1107 IntRect updateRect = clipRect;
1108 updateRect.intersect(scrollViewRect);
1109 addToDirtyRegion(updateRect);
1110 return;
1111 }
1112
1113 WidgetClientWin* c = static_cast<WidgetClientWin*>(client());
1114 if (c) {
1115 // TODO(ericroman): would be better to pass both the scroll rect
1116 // and clip rect up to the client and let them decide how best to
1117 // scroll the backing store.
1118 IntRect clippedScrollRect = scrollViewRect;
1119 clippedScrollRect.intersect(clipRect);
1120 c->scrollRect(dx, dy, clippedScrollRect);
1121 }
1122 }
1123
1124 void ScrollView::updateBackingStore()
1125 {
1126 // nothing to do. painting happens asynchronously.
1127 }
1128
1129 bool ScrollView::inWindow() const
1130 {
1131 WidgetClientWin* c = static_cast<WidgetClientWin*>(client());
1132 if (!c)
1133 return false;
1134
1135 return !c->isHidden();
1136 }
1137
1138 void ScrollView::attachToWindow()
1139 {
1140 if (m_data->m_attachedToWindow)
1141 return;
1142
1143 m_data->m_attachedToWindow = true;
1144
1145 if (m_data->m_visible) {
1146 HashSet<Widget*>::iterator end = m_data->m_children.end();
1147 for (HashSet<Widget*>::iterator it = m_data->m_children.begin(); it != e nd; ++it)
1148 (*it)->attachToWindow();
1149 }
1150 }
1151
1152 void ScrollView::detachFromWindow()
1153 {
1154 if (!m_data->m_attachedToWindow)
1155 return;
1156
1157 if (m_data->m_visible) {
1158 HashSet<Widget*>::iterator end = m_data->m_children.end();
1159 for (HashSet<Widget*>::iterator it = m_data->m_children.begin(); it != e nd; ++it)
1160 (*it)->detachFromWindow();
1161 }
1162
1163 m_data->m_attachedToWindow = false;
1164 }
1165
1166 void ScrollView::show()
1167 {
1168 if (!m_data->m_visible) {
1169 m_data->m_visible = true;
1170 if (isAttachedToWindow()) {
1171 HashSet<Widget*>::iterator end = m_data->m_children.end();
1172 for (HashSet<Widget*>::iterator it = m_data->m_children.begin(); it != end; ++it)
1173 (*it)->attachToWindow();
1174 }
1175 }
1176
1177 Widget::show();
1178 }
1179
1180 void ScrollView::hide()
1181 {
1182 if (m_data->m_visible) {
1183 if (isAttachedToWindow()) {
1184 HashSet<Widget*>::iterator end = m_data->m_children.end();
1185 for (HashSet<Widget*>::iterator it = m_data->m_children.begin(); it != end; ++it)
1186 (*it)->detachFromWindow();
1187 }
1188 m_data->m_visible = false;
1189 }
1190
1191 Widget::hide();
1192 }
1193
1194 bool ScrollView::isAttachedToWindow() const
1195 {
1196 return m_data->m_attachedToWindow;
1197 }
1198
1199 void ScrollView::setAllowsScrolling(bool flag)
1200 {
1201 m_data->setAllowsScrolling(flag);
1202 }
1203
1204 bool ScrollView::allowsScrolling() const
1205 {
1206 return m_data->allowsScrolling();
1207 }
1208
1209 void ScrollView::printPanScrollIcon(const IntPoint& iconPosition)
1210 {
1211 m_data->m_drawPanScrollIcon = true;
1212 m_data->m_panScrollIconPoint = IntPoint(iconPosition.x() - panIconSizeLength / 2 , iconPosition.y() - panIconSizeLength / 2) ;
1213
1214 updateWindowRect(IntRect(m_data->m_panScrollIconPoint, IntSize(panIconSizeLe ngth,panIconSizeLength)), true);
1215 }
1216
1217 void ScrollView::removePanScrollIcon()
1218 {
1219 m_data->m_drawPanScrollIcon = false;
1220
1221 updateWindowRect(IntRect(m_data->m_panScrollIconPoint, IntSize(panIconSizeLe ngth, panIconSizeLength)), true);
1222 }
1223
1224 bool ScrollView::isScrollable()
1225 {
1226 return m_data->m_vBar != 0 || m_data->m_hBar != 0;
1227 }
1228
1229 } // namespace WebCore
OLDNEW
« no previous file with comments | « webkit/port/platform/ScreenWin.cpp ('k') | webkit/port/platform/SearchPopupMenuWin.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698