WebCore:
2009-07-02 David Hyatt <hyatt@apple.com>
Reviewed by Simon Fraser.
Fix for bug 22119, clicks in the scrollbars of transformed content don't work. Add new
conversion methods for going across parent/child widget boundaries that can be implemented
by the FrameView and ScrollbarClient to be transform-aware.
Test cases added in platform/mac/fast/forms and platform/mac/fast/overflow.
* WebCore.base.exp:
* page/EventHandler.cpp:
(WebCore::EventHandler::handleMouseMoveEvent):
* page/FrameView.cpp:
(WebCore::FrameView::convertFromScrollbarToContainingView):
(WebCore::FrameView::convertFromContainingViewToScrollbar):
(WebCore::FrameView::convertFromRenderer):
(WebCore::FrameView::convertToRenderer):
(WebCore::FrameView::convertToContainingView):
(WebCore::FrameView::convertFromContainingView):
* page/FrameView.h:
* platform/ScrollView.h:
* platform/Scrollbar.cpp:
(WebCore::Scrollbar::convertToContainingView):
(WebCore::Scrollbar::convertFromContainingView):
* platform/Scrollbar.h:
* platform/ScrollbarClient.h:
(WebCore::ScrollbarClient::convertFromScrollbarToContainingView):
(WebCore::ScrollbarClient::convertFromContainingViewToScrollbar):
* platform/Widget.cpp:
(WebCore::Widget::convertFromContainingWindow):
(WebCore::Widget::convertToContainingWindow):
(WebCore::Widget::convertFromRootToContainingWindow):
(WebCore::Widget::convertFromContainingWindowToRoot):
(WebCore::Widget::convertToContainingView):
(WebCore::Widget::convertFromContainingView):
* platform/Widget.h:
* platform/graphics/IntPoint.h:
(WebCore::IntPoint::move):
* platform/mac/WidgetMac.mm:
(WebCore::Widget::convertFromRootToContainingWindow):
(WebCore::Widget::convertFromContainingWindowToRoot):
* rendering/RenderBlock.cpp:
(WebCore::RenderBlock::isPointInOverflowControl):
* rendering/RenderDataGrid.cpp:
(WebCore::RenderDataGrid::convertFromScrollbarToContainingView):
(WebCore::RenderDataGrid::convertFromContainingViewToScrollbar):
* rendering/RenderDataGrid.h:
* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::convertFromScrollbarToContainingView):
(WebCore::RenderLayer::convertFromContainingViewToScrollbar):
(WebCore::RenderLayer::scrollbarOffset):
(WebCore::RenderLayer::hitTestOverflowControls):
* rendering/RenderLayer.h:
* rendering/RenderListBox.cpp:
(WebCore::RenderListBox::isPointInOverflowControl):
(WebCore::RenderListBox::convertFromScrollbarToContainingView):
(WebCore::RenderListBox::convertFromContainingViewToScrollbar):
* rendering/RenderListBox.h:
LayoutTests:
2009-07-02 David Hyatt <hyatt@apple.com>
Reviewed by Simon Fraser.
Test cases for bug 22119, clicks in scrollbar of transformed element don't work.
* platform/mac/fast/forms/listbox-scrollbar-hit-test-expected.txt: Added.
* platform/mac/fast/forms/listbox-scrollbar-hit-test.html: Added.
* platform/mac/fast/overflow/overflow-scrollbar-hit-test-expected.txt: Added.
* platform/mac/fast/overflow/overflow-scrollbar-hit-test.html: Added.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@45478 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 5ef22c6..3621bc3 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,14 @@
+2009-07-02 David Hyatt <hyatt@apple.com>
+
+ Reviewed by Simon Fraser.
+
+ Test cases for bug 22119, clicks in scrollbar of transformed element don't work.
+
+ * platform/mac/fast/forms/listbox-scrollbar-hit-test-expected.txt: Added.
+ * platform/mac/fast/forms/listbox-scrollbar-hit-test.html: Added.
+ * platform/mac/fast/overflow/overflow-scrollbar-hit-test-expected.txt: Added.
+ * platform/mac/fast/overflow/overflow-scrollbar-hit-test.html: Added.
+
2009-07-02 Dan Bernstein <mitz@apple.com>
Reviewed by Dave Hyatt and Simon Fraser.
diff --git a/LayoutTests/platform/mac/fast/forms/listbox-scrollbar-hit-test-expected.txt b/LayoutTests/platform/mac/fast/forms/listbox-scrollbar-hit-test-expected.txt
new file mode 100644
index 0000000..e3a2785
--- /dev/null
+++ b/LayoutTests/platform/mac/fast/forms/listbox-scrollbar-hit-test-expected.txt
@@ -0,0 +1,10 @@
+
+Testing clicks on select1
+Scrolled down by itemHeight on down arrow click: PASS
+Scrolled up by itemHeight on up arrow click: PASS
+
+Testing clicks on select2
+Scrolled down by itemHeight on down arrow click: PASS
+Scrolled up by itemHeight on up arrow click: PASS
+
+
diff --git a/LayoutTests/platform/mac/fast/forms/listbox-scrollbar-hit-test.html b/LayoutTests/platform/mac/fast/forms/listbox-scrollbar-hit-test.html
new file mode 100644
index 0000000..8eb04cd
--- /dev/null
+++ b/LayoutTests/platform/mac/fast/forms/listbox-scrollbar-hit-test.html
@@ -0,0 +1,112 @@
+<html>
+<head>
+ <title>Listbox scrollbar hit testing</title>
+ <style type="text/css" media="screen">
+ select {
+ border: 20px inset gray;
+ padding: 10px;
+ }
+
+ #results {
+ margin-top: 50px;
+ }
+ </style>
+ <script type="text/javascript" charset="utf-8">
+ function sendClick(element, clientX, clientY)
+ {
+ if (window.eventSender) {
+ eventSender.mouseMoveTo(clientX, clientY);
+ eventSender.mouseDown();
+ eventSender.mouseUp();
+ }
+ }
+
+ function mouseDownOnSelect(selId, translateX, translateY)
+ {
+ log('Testing clicks on ' + selId);
+
+ var selectElement = document.getElementById(selId);
+ var itemHeight = 14;
+ var border = 20;
+ var scrollbarWidth = 10;
+ var scrollbarButtonHeight = 12;
+
+ var scrollbarMidX = translateX + selectElement.offsetLeft + selectElement.offsetWidth - border - scrollbarWidth / 2;
+ // Recall that DRT runs with both scroll arrows at the end of the scrollbar
+ var scrollbarTopArrowY = translateY + selectElement.offsetTop + selectElement.offsetHeight - border - scrollbarButtonHeight - 3;
+ var scrollbarBottomArrowY = translateY + selectElement.offsetTop + selectElement.offsetHeight - border - 3;
+
+ sendClick(selectElement, scrollbarMidX, scrollbarBottomArrowY);
+ sendClick(selectElement, scrollbarMidX, scrollbarBottomArrowY);
+ if (selectElement.scrollTop == 2 * itemHeight)
+ log('Scrolled down by itemHeight on down arrow click: PASS');
+ else
+ log('Failed to scroll down - scrollTop is ' + selectElement.scrollTop + ': FAIL');
+
+ sendClick(selectElement, scrollbarMidX, scrollbarTopArrowY);
+ if (selectElement.scrollTop == itemHeight)
+ log('Scrolled up by itemHeight on up arrow click: PASS');
+ else
+ log('Failed to scroll up - scrollTop is ' + selectElement.scrollTop + ': FAIL');
+
+ log('');
+ }
+
+ function log(msg)
+ {
+ var results = document.getElementById('results');
+ results.innerHTML += msg + '<br>';
+ }
+
+ function test()
+ {
+ if (window.layoutTestController) {
+ layoutTestController.dumpAsText();
+ layoutTestController.waitUntilDone();
+ }
+
+ if (!window.eventSender) {
+ log('This test only runs in DRT');
+ }
+
+ // Have to wait for the select to be painted before the
+ // scrollbar is sized correctly.
+ setTimeout(function() {
+ mouseDownOnSelect('select1', 0, 0);
+ mouseDownOnSelect('select2', 50, 50);
+ if (window.layoutTestController)
+ layoutTestController.notifyDone();
+ }, 0);
+ }
+ </script>
+</head>
+<body onload="test()">
+
+ <select id="select1" size="5">
+ <option selected value="0">item 0</option>
+ <option value="1">item 1</option>
+ <option value="2">item 2</option>
+ <option value="3">item 3</option>
+ <option value="4">item 4</option>
+ <option value="5">item 5</option>
+ <option value="6">item 6</option>
+ <option value="7">item 7</option>
+ <option value="8">item 8</option>
+ </select>
+
+ <select id="select2" size="5" style="-webkit-transform: translate(50px, 50px);">
+ <option selected value="0">item 0</option>
+ <option value="1">item 1</option>
+ <option value="2">item 2</option>
+ <option value="3">item 3</option>
+ <option value="4">item 4</option>
+ <option value="5">item 5</option>
+ <option value="6">item 6</option>
+ <option value="7">item 7</option>
+ <option value="8">item 8</option>
+ </select>
+
+ <div id="results">
+ </div>
+</body>
+</html>
diff --git a/LayoutTests/platform/mac/fast/overflow/overflow-scrollbar-hit-test-expected.txt b/LayoutTests/platform/mac/fast/overflow/overflow-scrollbar-hit-test-expected.txt
new file mode 100644
index 0000000..549c793
--- /dev/null
+++ b/LayoutTests/platform/mac/fast/overflow/overflow-scrollbar-hit-test-expected.txt
@@ -0,0 +1,12 @@
+Inner
+
+Inner
+Testing clicks on box1
+Scrolled down by 80 on down arrow click: PASS
+Scrolled up by 40 on up arrow click: PASS
+
+Testing clicks on box2
+Scrolled down by 80 on down arrow click: PASS
+Scrolled up by 40 on up arrow click: PASS
+
+
diff --git a/LayoutTests/platform/mac/fast/overflow/overflow-scrollbar-hit-test.html b/LayoutTests/platform/mac/fast/overflow/overflow-scrollbar-hit-test.html
new file mode 100644
index 0000000..8d8c674
--- /dev/null
+++ b/LayoutTests/platform/mac/fast/overflow/overflow-scrollbar-hit-test.html
@@ -0,0 +1,108 @@
+<html>
+<head>
+ <title>Overflow scrollbar hit testing</title>
+ <style type="text/css" media="screen">
+ .box {
+ display: inline-block;
+ width: 150px;
+ height: 150px;
+ border: 20px inset gray;
+ padding: 10px;
+ margin: 15px;
+ overflow: scroll;
+ }
+
+ .inner {
+ width: 300px;
+ height: 300px;
+ border: 1px solid gray;
+ }
+
+ #results {
+ margin-top: 50px;
+ }
+ </style>
+ <script type="text/javascript" charset="utf-8">
+ function sendClick(element, clientX, clientY)
+ {
+ if (window.eventSender) {
+ eventSender.mouseMoveTo(clientX, clientY);
+ eventSender.mouseDown();
+ eventSender.mouseUp();
+ }
+ }
+
+ function mouseDownOnOverflowDiv(elementId, translateX, translateY)
+ {
+ log('Testing clicks on ' + elementId);
+
+ var element = document.getElementById(elementId);
+ var scrollIncrement = 40;
+ var border = 20;
+ var scrollbarWidth = 16;
+ var scrollbarHeight = 16;
+
+ var scrollbarMidX = translateX + element.offsetLeft + element.offsetWidth - border - scrollbarWidth / 2;
+ // Recall that DRT sets scroll arrows to be together at end end of the scrollbar
+ var scrollbarTopArrowY = translateY + element.offsetTop + element.offsetHeight - border - scrollbarHeight - scrollbarHeight - 3;
+ var scrollbarBottomArrowY = translateY + element.offsetTop + element.offsetHeight - border - scrollbarHeight - 3;
+
+ sendClick(element, scrollbarMidX, scrollbarBottomArrowY);
+ sendClick(element, scrollbarMidX, scrollbarBottomArrowY);
+ if (element.scrollTop == 2 * scrollIncrement)
+ log('Scrolled down by ' + (2 * scrollIncrement) + ' on down arrow click: PASS');
+ else
+ log('Failed to scroll down - scrollTop is ' + element.scrollTop + ': FAIL');
+
+ sendClick(element, scrollbarMidX, scrollbarTopArrowY);
+ if (element.scrollTop == scrollIncrement)
+ log('Scrolled up by ' + scrollIncrement + ' on up arrow click: PASS');
+ else
+ log('Failed to scroll up - scrollTop is ' + element.scrollTop + ': FAIL');
+
+ log('');
+ }
+
+ function log(msg)
+ {
+ var results = document.getElementById('results');
+ results.innerHTML += msg + '<br>';
+ }
+
+ function test()
+ {
+ if (window.layoutTestController) {
+ layoutTestController.dumpAsText();
+ layoutTestController.waitUntilDone();
+ }
+
+ if (!window.eventSender) {
+ log('This test only runs in DRT');
+ }
+
+ // Have to wait for the select to be painted before the
+ // scrollbar is sized correctly.
+ setTimeout(function() {
+ mouseDownOnOverflowDiv('box1', 0, 0);
+ mouseDownOnOverflowDiv('box2', 50, 50);
+ if (window.layoutTestController)
+ layoutTestController.notifyDone();
+ }, 0);
+ }
+ </script>
+</head>
+<body onload="test()">
+
+
+ <div class="box" id="box1">
+ <div class="inner">Inner</div>
+ </div>
+
+ <div class="box" id="box2" style="-webkit-transform: translate(50px, 50px);">
+ <div class="inner">Inner</div>
+ </div>
+
+ <div id="results">
+ </div>
+</body>
+</html>
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 2b8197f..dddc854 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,63 @@
+2009-07-02 David Hyatt <hyatt@apple.com>
+
+ Reviewed by Simon Fraser.
+
+ Fix for bug 22119, clicks in the scrollbars of transformed content don't work. Add new
+ conversion methods for going across parent/child widget boundaries that can be implemented
+ by the FrameView and ScrollbarClient to be transform-aware.
+
+ Test cases added in platform/mac/fast/forms and platform/mac/fast/overflow.
+
+ * WebCore.base.exp:
+ * page/EventHandler.cpp:
+ (WebCore::EventHandler::handleMouseMoveEvent):
+ * page/FrameView.cpp:
+ (WebCore::FrameView::convertFromScrollbarToContainingView):
+ (WebCore::FrameView::convertFromContainingViewToScrollbar):
+ (WebCore::FrameView::convertFromRenderer):
+ (WebCore::FrameView::convertToRenderer):
+ (WebCore::FrameView::convertToContainingView):
+ (WebCore::FrameView::convertFromContainingView):
+ * page/FrameView.h:
+ * platform/ScrollView.h:
+ * platform/Scrollbar.cpp:
+ (WebCore::Scrollbar::convertToContainingView):
+ (WebCore::Scrollbar::convertFromContainingView):
+ * platform/Scrollbar.h:
+ * platform/ScrollbarClient.h:
+ (WebCore::ScrollbarClient::convertFromScrollbarToContainingView):
+ (WebCore::ScrollbarClient::convertFromContainingViewToScrollbar):
+ * platform/Widget.cpp:
+ (WebCore::Widget::convertFromContainingWindow):
+ (WebCore::Widget::convertToContainingWindow):
+ (WebCore::Widget::convertFromRootToContainingWindow):
+ (WebCore::Widget::convertFromContainingWindowToRoot):
+ (WebCore::Widget::convertToContainingView):
+ (WebCore::Widget::convertFromContainingView):
+ * platform/Widget.h:
+ * platform/graphics/IntPoint.h:
+ (WebCore::IntPoint::move):
+ * platform/mac/WidgetMac.mm:
+ (WebCore::Widget::convertFromRootToContainingWindow):
+ (WebCore::Widget::convertFromContainingWindowToRoot):
+ * rendering/RenderBlock.cpp:
+ (WebCore::RenderBlock::isPointInOverflowControl):
+ * rendering/RenderDataGrid.cpp:
+ (WebCore::RenderDataGrid::convertFromScrollbarToContainingView):
+ (WebCore::RenderDataGrid::convertFromContainingViewToScrollbar):
+ * rendering/RenderDataGrid.h:
+ * rendering/RenderLayer.cpp:
+ (WebCore::RenderLayer::convertFromScrollbarToContainingView):
+ (WebCore::RenderLayer::convertFromContainingViewToScrollbar):
+ (WebCore::RenderLayer::scrollbarOffset):
+ (WebCore::RenderLayer::hitTestOverflowControls):
+ * rendering/RenderLayer.h:
+ * rendering/RenderListBox.cpp:
+ (WebCore::RenderListBox::isPointInOverflowControl):
+ (WebCore::RenderListBox::convertFromScrollbarToContainingView):
+ (WebCore::RenderListBox::convertFromContainingViewToScrollbar):
+ * rendering/RenderListBox.h:
+
2009-07-02 Dan Bernstein <mitz@apple.com>
Reviewed by Dave Hyatt and Simon Fraser.
diff --git a/WebCore/WebCore.base.exp b/WebCore/WebCore.base.exp
index d5fac6a..11def5f 100644
--- a/WebCore/WebCore.base.exp
+++ b/WebCore/WebCore.base.exp
@@ -932,6 +932,10 @@
__ZNK7WebCore6String9substringEjj
__ZNK7WebCore6StringcvN3JSC7UStringEEv
__ZNK7WebCore6Widget9frameRectEv
+__ZNK7WebCore6Widget23convertToContainingViewERKNS_8IntPointE
+__ZNK7WebCore6Widget23convertToContainingViewERKNS_7IntRectE
+__ZNK7WebCore6Widget25convertFromContainingViewERKNS_7IntRectE
+__ZNK7WebCore6Widget25convertFromContainingViewERKNS_8IntPointE
__ZNK7WebCore7CString4dataEv
__ZNK7WebCore7CString6lengthEv
__ZNK7WebCore7Element12getAttributeERKNS_13QualifiedNameE
diff --git a/WebCore/page/EventHandler.cpp b/WebCore/page/EventHandler.cpp
index 87e9ecc02..42edc69 100644
--- a/WebCore/page/EventHandler.cpp
+++ b/WebCore/page/EventHandler.cpp
@@ -1297,7 +1297,7 @@
// Send events right to a scrollbar if the mouse is pressed.
if (m_lastScrollbarUnderMouse && m_mousePressed)
- return m_lastScrollbarUnderMouse->mouseMoved(m_lastScrollbarUnderMouse->transformEvent(mouseEvent));
+ return m_lastScrollbarUnderMouse->mouseMoved(mouseEvent);
// Treat mouse move events while the mouse is pressed as "read-only" in prepareMouseEvent
// if we are allowed to select.
@@ -1349,7 +1349,7 @@
swallowEvent |= passMouseMoveEventToSubframe(mev, newSubframe.get(), hoveredNode);
} else {
if (scrollbar && !m_mousePressed)
- scrollbar->mouseMoved(scrollbar->transformEvent(mouseEvent)); // Handle hover effects on platforms that support visual feedback on scrollbar hovering.
+ scrollbar->mouseMoved(mouseEvent); // Handle hover effects on platforms that support visual feedback on scrollbar hovering.
if (Page* page = m_frame->page()) {
if ((!m_resizeLayer || !m_resizeLayer->inResizeMode()) && !page->mainFrame()->eventHandler()->panScrollInProgress()) {
if (FrameView* view = m_frame->view())
diff --git a/WebCore/page/FrameView.cpp b/WebCore/page/FrameView.cpp
index 45fc0ad..65c825a 100644
--- a/WebCore/page/FrameView.cpp
+++ b/WebCore/page/FrameView.cpp
@@ -1294,6 +1294,39 @@
tickmarks = frame()->document()->renderedRectsForMarkers(DocumentMarker::TextMatch);
}
+IntRect FrameView::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntRect& localRect) const
+{
+ // Scrollbars won't be transformed within us
+ IntRect newRect = localRect;
+ newRect.move(scrollbar->x(), scrollbar->y());
+ return newRect;
+}
+
+IntRect FrameView::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntRect& parentRect) const
+{
+ IntRect newRect = parentRect;
+ // Scrollbars won't be transformed within us
+ newRect.move(-scrollbar->x(), -scrollbar->y());
+ return newRect;
+}
+
+// FIXME: test these on windows
+IntPoint FrameView::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntPoint& localPoint) const
+{
+ // Scrollbars won't be transformed within us
+ IntPoint newPoint = localPoint;
+ newPoint.move(scrollbar->x(), scrollbar->y());
+ return newPoint;
+}
+
+IntPoint FrameView::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntPoint& parentPoint) const
+{
+ IntPoint newPoint = parentPoint;
+ // Scrollbars won't be transformed within us
+ newPoint.move(-scrollbar->x(), -scrollbar->y());
+ return newPoint;
+}
+
IntRect FrameView::windowResizerRect() const
{
Page* page = frame() ? frame()->page() : 0;
@@ -1519,4 +1552,142 @@
*newBottom = oldBottom;
}
+IntRect FrameView::convertFromRenderer(const RenderObject* renderer, const IntRect& rendererRect) const
+{
+ IntRect rect = renderer->localToAbsoluteQuad(FloatRect(rendererRect)).enclosingBoundingBox();
+
+ // Convert from page ("absolute") to FrameView coordinates.
+ rect.move(-scrollX(), -scrollY());
+
+ return rect;
+}
+
+IntRect FrameView::convertToRenderer(const RenderObject* renderer, const IntRect& viewRect) const
+{
+ IntRect rect = viewRect;
+
+ // Convert from FrameView coords into page ("absolute") coordinates.
+ rect.move(scrollX(), scrollY());
+
+ // FIXME: we don't have a way to map an absolute rect down to a local quad, so just
+ // move the rect for now.
+ rect.setLocation(roundedIntPoint(renderer->absoluteToLocal(rect.location(), false, true /* use transforms */)));
+ return rect;
+}
+
+IntPoint FrameView::convertFromRenderer(const RenderObject* renderer, const IntPoint& rendererPoint) const
+{
+ IntPoint point = roundedIntPoint(renderer->localToAbsolute(rendererPoint, false, true /* use transforms */));
+
+ // Convert from page ("absolute") to FrameView coordinates.
+ point.move(-scrollX(), -scrollY());
+ return point;
+}
+
+IntPoint FrameView::convertToRenderer(const RenderObject* renderer, const IntPoint& viewPoint) const
+{
+ IntPoint point = viewPoint;
+
+ // Convert from FrameView coords into page ("absolute") coordinates.
+ point += IntSize(scrollX(), scrollY());
+
+ return roundedIntPoint(renderer->absoluteToLocal(point, false, true /* use transforms */));
+}
+
+IntRect FrameView::convertToContainingView(const IntRect& localRect) const
+{
+ if (const ScrollView* parentScrollView = parent()) {
+ if (parentScrollView->isFrameView()) {
+ const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
+ // Get our renderer in the parent view
+ RenderPart* renderer = m_frame->ownerRenderer();
+ if (!renderer)
+ return localRect;
+
+ IntRect rect(localRect);
+ // Add borders and padding??
+ rect.move(renderer->borderLeft() + renderer->paddingLeft(),
+ renderer->borderTop() + renderer->paddingTop());
+ return parentView->convertFromRenderer(renderer, rect);
+ }
+
+ return Widget::convertToContainingView(localRect);
+ }
+
+ return localRect;
+}
+
+IntRect FrameView::convertFromContainingView(const IntRect& parentRect) const
+{
+ if (const ScrollView* parentScrollView = parent()) {
+ if (parentScrollView->isFrameView()) {
+ const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
+
+ // Get our renderer in the parent view
+ RenderPart* renderer = m_frame->ownerRenderer();
+ if (!renderer)
+ return parentRect;
+
+ IntRect rect = parentView->convertToRenderer(renderer, parentRect);
+ // Subtract borders and padding
+ rect.move(-renderer->borderLeft() - renderer->paddingLeft(),
+ -renderer->borderTop() - renderer->paddingTop());
+ return rect;
+ }
+
+ return Widget::convertFromContainingView(parentRect);
+ }
+
+ return parentRect;
+}
+
+IntPoint FrameView::convertToContainingView(const IntPoint& localPoint) const
+{
+ if (const ScrollView* parentScrollView = parent()) {
+ if (parentScrollView->isFrameView()) {
+ const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
+
+ // Get our renderer in the parent view
+ RenderPart* renderer = m_frame->ownerRenderer();
+ if (!renderer)
+ return localPoint;
+
+ IntPoint point(localPoint);
+
+ // Add borders and padding
+ point.move(renderer->borderLeft() + renderer->paddingLeft(),
+ renderer->borderTop() + renderer->paddingTop());
+ return parentView->convertFromRenderer(renderer, point);
+ }
+
+ return Widget::convertToContainingView(localPoint);
+ }
+
+ return localPoint;
+}
+
+IntPoint FrameView::convertFromContainingView(const IntPoint& parentPoint) const
+{
+ if (const ScrollView* parentScrollView = parent()) {
+ if (parentScrollView->isFrameView()) {
+ const FrameView* parentView = static_cast<const FrameView*>(parentScrollView);
+
+ // Get our renderer in the parent view
+ RenderPart* renderer = m_frame->ownerRenderer();
+ if (!renderer)
+ return parentPoint;
+
+ IntPoint point = parentView->convertToRenderer(renderer, parentPoint);
+ // Subtract borders and padding
+ point.move(-renderer->borderLeft() - renderer->paddingLeft(),
+ -renderer->borderTop() - renderer->paddingTop());
+ return point;
+ }
+
+ return Widget::convertFromContainingView(parentPoint);
+ }
+
+ return parentPoint;
+}
+
} // namespace WebCore
diff --git a/WebCore/page/FrameView.h b/WebCore/page/FrameView.h
index 9dabe56..9ab281e 100644
--- a/WebCore/page/FrameView.h
+++ b/WebCore/page/FrameView.h
@@ -126,11 +126,6 @@
virtual IntRect windowClipRect(bool clipToContents = true) const;
IntRect windowClipRectForLayer(const RenderLayer*, bool clipToLayerContents) const;
- virtual bool isActive() const;
- virtual void invalidateScrollbarRect(Scrollbar*, const IntRect&);
- virtual void valueChanged(Scrollbar*);
- virtual void getTickmarks(Vector<IntRect>&) const;
-
virtual IntRect windowResizerRect() const;
virtual void scrollRectIntoViewRecursively(const IntRect&);
@@ -188,6 +183,11 @@
bool lockedToAnchor() { return m_lockedToAnchor; }
void setLockedToAnchor(bool lockedToAnchor) { m_lockedToAnchor = lockedToAnchor; }
+ // Methods to convert points and rects between the coordinate space of the renderer, and this view.
+ virtual IntRect convertFromRenderer(const RenderObject*, const IntRect&) const;
+ virtual IntRect convertToRenderer(const RenderObject*, const IntRect&) const;
+ virtual IntPoint convertFromRenderer(const RenderObject*, const IntPoint&) const;
+ virtual IntPoint convertToRenderer(const RenderObject*, const IntPoint&) const;
private:
FrameView(Frame*);
@@ -215,6 +215,23 @@
layout();
}
+ // Override ScrollView methods to do point conversion via renderers, in order to
+ // take transforms into account.
+ virtual IntRect convertToContainingView(const IntRect&) const;
+ virtual IntRect convertFromContainingView(const IntRect&) const;
+ virtual IntPoint convertToContainingView(const IntPoint&) const;
+ virtual IntPoint convertFromContainingView(const IntPoint&) const;
+
+ // ScrollBarClient interface
+ virtual void valueChanged(Scrollbar*);
+ virtual void invalidateScrollbarRect(Scrollbar*, const IntRect&);
+ virtual bool isActive() const;
+ virtual void getTickmarks(Vector<IntRect>&) const;
+ virtual IntRect convertFromScrollbarToContainingView(const Scrollbar*, const IntRect&) const;
+ virtual IntRect convertFromContainingViewToScrollbar(const Scrollbar*, const IntRect&) const;
+ virtual IntPoint convertFromScrollbarToContainingView(const Scrollbar*, const IntPoint&) const;
+ virtual IntPoint convertFromContainingViewToScrollbar(const Scrollbar*, const IntPoint&) const;
+
void deferredRepaintTimerFired(Timer<FrameView>*);
void doDeferredRepaints();
void updateDeferredRepaintDelay();
diff --git a/WebCore/platform/ScrollView.h b/WebCore/platform/ScrollView.h
index 814b704..5bb49e6 100644
--- a/WebCore/platform/ScrollView.h
+++ b/WebCore/platform/ScrollView.h
@@ -221,6 +221,11 @@
virtual bool scrollbarCornerPresent() const;
+ virtual IntRect convertFromScrollbarToContainingView(const Scrollbar*, const IntRect&) const = 0;
+ virtual IntRect convertFromContainingViewToScrollbar(const Scrollbar*, const IntRect&) const = 0;
+ virtual IntPoint convertFromScrollbarToContainingView(const Scrollbar*, const IntPoint&) const = 0;
+ virtual IntPoint convertFromContainingViewToScrollbar(const Scrollbar*, const IntPoint&) const = 0;
+
protected:
virtual void repaintContentRectangle(const IntRect&, bool now = false);
virtual void paintContents(GraphicsContext*, const IntRect& damageRect) = 0;
diff --git a/WebCore/platform/Scrollbar.cpp b/WebCore/platform/Scrollbar.cpp
index babf3d4..4574f63 100644
--- a/WebCore/platform/Scrollbar.cpp
+++ b/WebCore/platform/Scrollbar.cpp
@@ -449,9 +449,36 @@
m_client->invalidateScrollbarRect(this, rect);
}
-PlatformMouseEvent Scrollbar::transformEvent(const PlatformMouseEvent& event)
+IntRect Scrollbar::convertToContainingView(const IntRect& localRect) const
{
- return event;
+ if (m_client)
+ return m_client->convertFromScrollbarToContainingView(this, localRect);
+
+ return Widget::convertToContainingView(localRect);
+}
+
+IntRect Scrollbar::convertFromContainingView(const IntRect& parentRect) const
+{
+ if (m_client)
+ return m_client->convertFromContainingViewToScrollbar(this, parentRect);
+
+ return Widget::convertFromContainingView(parentRect);
+}
+
+IntPoint Scrollbar::convertToContainingView(const IntPoint& localPoint) const
+{
+ if (m_client)
+ return m_client->convertFromScrollbarToContainingView(this, localPoint);
+
+ return Widget::convertToContainingView(localPoint);
+}
+
+IntPoint Scrollbar::convertFromContainingView(const IntPoint& parentPoint) const
+{
+ if (m_client)
+ return m_client->convertFromContainingViewToScrollbar(this, parentPoint);
+
+ return Widget::convertFromContainingView(parentPoint);
}
}
diff --git a/WebCore/platform/Scrollbar.h b/WebCore/platform/Scrollbar.h
index 711ae36..78430b1 100644
--- a/WebCore/platform/Scrollbar.h
+++ b/WebCore/platform/Scrollbar.h
@@ -110,10 +110,6 @@
bool contextMenu(const PlatformMouseEvent& event);
#endif
- // Takes an event and accounts for any transforms that might occur on the scrollbar. Returns
- // a new event that has had all of the transforms applied.
- PlatformMouseEvent transformEvent(const PlatformMouseEvent&);
-
ScrollbarTheme* theme() const { return m_theme; }
virtual void setParent(ScrollView*);
@@ -126,13 +122,19 @@
virtual void styleChanged() { }
+ virtual IntRect convertToContainingView(const IntRect&) const;
+ virtual IntRect convertFromContainingView(const IntRect&) const;
+
+ virtual IntPoint convertToContainingView(const IntPoint&) const;
+ virtual IntPoint convertFromContainingView(const IntPoint&) const;
+
private:
virtual bool isScrollbar() const { return true; }
protected:
virtual void updateThumbPosition();
virtual void updateThumbProportion();
-
+
void autoscrollTimerFired(Timer<Scrollbar>*);
void startTimerIfNeeded(double delay);
void stopTimerIfNeeded();
diff --git a/WebCore/platform/ScrollbarClient.h b/WebCore/platform/ScrollbarClient.h
index f720e95..3b44216 100644
--- a/WebCore/platform/ScrollbarClient.h
+++ b/WebCore/platform/ScrollbarClient.h
@@ -27,12 +27,11 @@
#define ScrollbarClient_h
#include "IntRect.h"
+#include "ScrollBar.h"
#include <wtf/Vector.h>
namespace WebCore {
-class Scrollbar;
-
class ScrollbarClient {
public:
virtual ~ScrollbarClient() {}
@@ -45,6 +44,29 @@
virtual bool scrollbarCornerPresent() const = 0;
virtual void getTickmarks(Vector<IntRect>&) const { }
+
+ // Convert points and rects between the scrollbar and its containing view.
+ // The client needs to implement these in order to be aware of layout effects
+ // like CSS transforms.
+ virtual IntRect convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntRect& scrollbarRect) const
+ {
+ return scrollbar->Widget::convertToContainingView(scrollbarRect);
+ }
+
+ virtual IntRect convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntRect& parentRect) const
+ {
+ return scrollbar->Widget::convertFromContainingView(parentRect);
+ }
+
+ virtual IntPoint convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntPoint& scrollbarPoint) const
+ {
+ return scrollbar->Widget::convertToContainingView(scrollbarPoint);
+ }
+
+ virtual IntPoint convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntPoint& parentPoint) const
+ {
+ return scrollbar->Widget::convertFromContainingView(parentPoint);
+ }
};
}
diff --git a/WebCore/platform/Widget.cpp b/WebCore/platform/Widget.cpp
index a456431..5bb903b 100644
--- a/WebCore/platform/Widget.cpp
+++ b/WebCore/platform/Widget.cpp
@@ -69,42 +69,61 @@
parent()->removeChild(this);
}
+IntRect Widget::convertFromContainingWindow(const IntRect& windowRect) const
+{
+ if (const ScrollView* parentScrollView = parent()) {
+ IntRect parentRect = parentScrollView->convertFromContainingWindow(windowRect);
+ return convertFromContainingView(parentRect);
+ }
+ return convertFromContainingWindowToRoot(this, windowRect);
+}
+
+IntRect Widget::convertToContainingWindow(const IntRect& localRect) const
+{
+ if (const ScrollView* parentScrollView = parent()) {
+ IntRect parentRect = convertToContainingView(localRect);
+ return parentScrollView->convertToContainingWindow(parentRect);
+ }
+ return convertFromRootToContainingWindow(this, localRect);
+}
+
+IntPoint Widget::convertFromContainingWindow(const IntPoint& windowPoint) const
+{
+ if (const ScrollView* parentScrollView = parent()) {
+ IntPoint parentPoint = parentScrollView->convertFromContainingWindow(windowPoint);
+ return convertFromContainingView(parentPoint);
+ }
+ return convertFromContainingWindowToRoot(this, windowPoint);
+}
+
+IntPoint Widget::convertToContainingWindow(const IntPoint& localPoint) const
+{
+ if (const ScrollView* parentScrollView = parent()) {
+ IntPoint parentPoint = convertToContainingView(localPoint);
+ return parentScrollView->convertToContainingWindow(parentPoint);
+ }
+ return convertFromRootToContainingWindow(this, localPoint);
+}
+
#if !PLATFORM(MAC)
-
-IntRect Widget::convertToContainingWindow(const IntRect& rect) const
+IntRect Widget::convertFromRootToContainingWindow(const Widget*, const IntRect& rect)
{
- IntRect convertedRect = rect;
- convertedRect.setLocation(convertToContainingWindow(convertedRect.location()));
- return convertedRect;
+ return rect;
}
-IntPoint Widget::convertToContainingWindow(const IntPoint& point) const
+IntRect Widget::convertFromContainingWindowToRoot(const Widget*, const IntRect& rect)
{
- IntPoint windowPoint = point;
- const Widget* childWidget = this;
- for (const ScrollView* parentScrollView = parent();
- parentScrollView;
- childWidget = parentScrollView, parentScrollView = parentScrollView->parent())
- windowPoint = parentScrollView->convertChildToSelf(childWidget, windowPoint);
- return windowPoint;
+ return rect;
}
-IntPoint Widget::convertFromContainingWindow(const IntPoint& point) const
+IntPoint Widget::convertFromRootToContainingWindow(const Widget*, const IntPoint& point)
{
- IntPoint widgetPoint = point;
- const Widget* childWidget = this;
- for (const ScrollView* parentScrollView = parent();
- parentScrollView;
- childWidget = parentScrollView, parentScrollView = parentScrollView->parent())
- widgetPoint = parentScrollView->convertSelfToChild(childWidget, widgetPoint);
- return widgetPoint;
+ return point;
}
-IntRect Widget::convertFromContainingWindow(const IntRect& rect) const
+IntPoint Widget::convertFromContainingWindowToRoot(const Widget*, const IntPoint& point)
{
- IntRect result = rect;
- result.setLocation(convertFromContainingWindow(rect.location()));
- return result;
+ return point;
}
#endif
@@ -118,4 +137,41 @@
}
#endif
+IntRect Widget::convertToContainingView(const IntRect& localRect) const
+{
+ if (const ScrollView* parentScrollView = parent()) {
+ IntRect parentRect(localRect);
+ parentRect.setLocation(parentScrollView->convertChildToSelf(this, localRect.location()));
+ return parentRect;
+ }
+ return localRect;
}
+
+IntRect Widget::convertFromContainingView(const IntRect& parentRect) const
+{
+ if (const ScrollView* parentScrollView = parent()) {
+ IntRect localRect = parentRect;
+ localRect.setLocation(parentScrollView->convertSelfToChild(this, localRect.location()));
+ return localRect;
+ }
+
+ return parentRect;
+}
+
+IntPoint Widget::convertToContainingView(const IntPoint& localPoint) const
+{
+ if (const ScrollView* parentScrollView = parent())
+ return parentScrollView->convertChildToSelf(this, localPoint);
+
+ return localPoint;
+}
+
+IntPoint Widget::convertFromContainingView(const IntPoint& parentPoint) const
+{
+ if (const ScrollView* parentScrollView = parent())
+ return parentScrollView->convertSelfToChild(this, parentPoint);
+
+ return parentPoint;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/Widget.h b/WebCore/platform/Widget.h
index b6c0054..80e16da 100644
--- a/WebCore/platform/Widget.h
+++ b/WebCore/platform/Widget.h
@@ -81,7 +81,6 @@
class GraphicsContext;
class PlatformMouseEvent;
class ScrollView;
-class WidgetClient;
class WidgetPrivate;
// The Widget class serves as a base class for three kinds of objects:
@@ -164,9 +163,10 @@
// up with an inaccurate rect. Always make sure to use the rect-based convertFromContainingWindow method
// when converting window rects.
IntRect convertToContainingWindow(const IntRect&) const;
- IntPoint convertToContainingWindow(const IntPoint&) const;
- IntPoint convertFromContainingWindow(const IntPoint&) const; // See comment above about when not to use this method.
IntRect convertFromContainingWindow(const IntRect&) const;
+
+ IntPoint convertToContainingWindow(const IntPoint&) const;
+ IntPoint convertFromContainingWindow(const IntPoint&) const;
virtual void frameRectsChanged() {}
@@ -179,12 +179,26 @@
void removeFromSuperview();
#endif
+ // Virtual methods to convert points to/from the containing ScrollView
+ virtual IntRect convertToContainingView(const IntRect&) const;
+ virtual IntRect convertFromContainingView(const IntRect&) const;
+ virtual IntPoint convertToContainingView(const IntPoint&) const;
+ virtual IntPoint convertFromContainingView(const IntPoint&) const;
+
private:
void init(PlatformWidget); // Must be called by all Widget constructors to initialize cross-platform data.
void releasePlatformWidget();
void retainPlatformWidget();
+ // These methods are used to convert from the root widget to the containing window,
+ // which has behavior that may differ between platforms (e.g. Mac uses flipped window coordinates).
+ static IntRect convertFromRootToContainingWindow(const Widget* rootWidget, const IntRect&);
+ static IntRect convertFromContainingWindowToRoot(const Widget* rootWidget, const IntRect&);
+
+ static IntPoint convertFromRootToContainingWindow(const Widget* rootWidget, const IntPoint&);
+ static IntPoint convertFromContainingWindowToRoot(const Widget* rootWidget, const IntPoint&);
+
private:
ScrollView* m_parent;
PlatformWidget m_widget;
diff --git a/WebCore/platform/graphics/IntPoint.h b/WebCore/platform/graphics/IntPoint.h
index 1cae191..21af67b 100644
--- a/WebCore/platform/graphics/IntPoint.h
+++ b/WebCore/platform/graphics/IntPoint.h
@@ -80,6 +80,7 @@
void setX(int x) { m_x = x; }
void setY(int y) { m_y = y; }
+ void move(const IntSize& s) { move(s.width(), s.height()); }
void move(int dx, int dy) { m_x += dx; m_y += dy; }
IntPoint expandedTo(const IntPoint& other) const
diff --git a/WebCore/platform/mac/WidgetMac.mm b/WebCore/platform/mac/WidgetMac.mm
index 1aaf4b2..8653a03 100644
--- a/WebCore/platform/mac/WidgetMac.mm
+++ b/WebCore/platform/mac/WidgetMac.mm
@@ -283,72 +283,52 @@
}
}
-IntPoint Widget::convertFromContainingWindow(const IntPoint& point) const
+// These are here to deal with flipped coords on Mac.
+IntRect Widget::convertFromRootToContainingWindow(const Widget* rootWidget, const IntRect& rect)
{
- if (!platformWidget()) {
- if (!parent())
- return point;
- IntPoint result = parent()->convertFromContainingWindow(point);
- result.move(parent()->scrollX() - x(), parent()->scrollY() - y());
- return result;
- }
-
- BEGIN_BLOCK_OBJC_EXCEPTIONS;
- return IntPoint([platformWidget() convertPoint:point fromView:nil]);
- END_BLOCK_OBJC_EXCEPTIONS;
-
- return point;
-}
+ if (!rootWidget->platformWidget())
+ return rect;
-IntRect Widget::convertFromContainingWindow(const IntRect& rect) const
-{
- if (!platformWidget()) {
- if (!parent())
- return rect;
- IntRect result = parent()->convertFromContainingWindow(rect);
- result.move(parent()->scrollX() - x(), parent()->scrollY() - y());
- return result;
- }
-
BEGIN_BLOCK_OBJC_EXCEPTIONS;
- return enclosingIntRect([platformWidget() convertRect:rect fromView:nil]);
+ return enclosingIntRect([rootWidget->platformWidget() convertRect:rect toView:nil]);
END_BLOCK_OBJC_EXCEPTIONS;
-
+
return rect;
}
-IntRect Widget::convertToContainingWindow(const IntRect& r) const
+IntRect Widget::convertFromContainingWindowToRoot(const Widget* rootWidget, const IntRect& rect)
{
- if (!platformWidget()) {
- if (!parent())
- return r;
- IntRect result = r;
- result.move(parent()->scrollX() - x(), parent()->scrollY() - y());
- return parent()->convertToContainingWindow(result);
- }
-
+ if (!rootWidget->platformWidget())
+ return rect;
+
BEGIN_BLOCK_OBJC_EXCEPTIONS;
- return IntRect([platformWidget() convertRect:r toView:nil]);
+ return enclosingIntRect([rootWidget->platformWidget() convertRect:rect fromView:nil]);
END_BLOCK_OBJC_EXCEPTIONS;
- return r;
+ return rect;
}
-
-IntPoint Widget::convertToContainingWindow(const IntPoint& p) const
+
+IntPoint Widget::convertFromRootToContainingWindow(const Widget* rootWidget, const IntPoint& point)
{
- if (!platformWidget()) {
- if (!parent())
- return p;
- IntPoint result = p;
- result.move(parent()->scrollX() - x(), parent()->scrollY() - y());
- return parent()->convertToContainingWindow(result);
- }
-
+ if (!rootWidget->platformWidget())
+ return point;
+
BEGIN_BLOCK_OBJC_EXCEPTIONS;
- return IntPoint([platformWidget() convertPoint:p toView:nil]);
+ return IntPoint([rootWidget->platformWidget() convertPoint:point toView:nil]);
+ END_BLOCK_OBJC_EXCEPTIONS;
+ return point;
+}
+
+IntPoint Widget::convertFromContainingWindowToRoot(const Widget* rootWidget, const IntPoint& point)
+{
+ if (!rootWidget->platformWidget())
+ return point;
+
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+ return IntPoint([rootWidget->platformWidget() convertPoint:point fromView:nil]);
END_BLOCK_OBJC_EXCEPTIONS;
- return p;
+ return point;
}
void Widget::releasePlatformWidget()
diff --git a/WebCore/rendering/RenderBlock.cpp b/WebCore/rendering/RenderBlock.cpp
index 98426ed..39123ef 100644
--- a/WebCore/rendering/RenderBlock.cpp
+++ b/WebCore/rendering/RenderBlock.cpp
@@ -3246,12 +3246,12 @@
m_overflowHeight = max(m_overflowHeight, r.bottom());
}
-bool RenderBlock::isPointInOverflowControl(HitTestResult& result, int, int, int, int)
+bool RenderBlock::isPointInOverflowControl(HitTestResult& result, int _x, int _y, int _tx, int _ty)
{
if (!scrollsOverflow())
return false;
- return layer()->hitTestOverflowControls(result);
+ return layer()->hitTestOverflowControls(result, IntPoint(_x - _tx, _y - _ty));
}
bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction)
diff --git a/WebCore/rendering/RenderDataGrid.cpp b/WebCore/rendering/RenderDataGrid.cpp
index 7e5cb53..bdf723f 100644
--- a/WebCore/rendering/RenderDataGrid.cpp
+++ b/WebCore/rendering/RenderDataGrid.cpp
@@ -34,6 +34,7 @@
#include "Frame.h"
#include "GraphicsContext.h"
#include "Page.h"
+#include "RenderView.h"
#include "Scrollbar.h"
using std::min;
@@ -185,6 +186,65 @@
return page && page->focusController()->isActive();
}
+
+IntRect RenderDataGrid::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntRect& scrollbarRect) const
+{
+ RenderView* view = this->view();
+ if (!view)
+ return scrollbarRect;
+
+ IntRect rect = scrollbarRect;
+
+ int scrollbarLeft = width() - borderRight() - scrollbar->width();
+ int scrollbarTop = borderTop();
+ rect.move(scrollbarLeft, scrollbarTop);
+
+ return view->frameView()->convertFromRenderer(this, rect);
+}
+
+IntRect RenderDataGrid::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntRect& parentRect) const
+{
+ RenderView* view = this->view();
+ if (!view)
+ return parentRect;
+
+ IntRect rect = view->frameView()->convertToRenderer(this, parentRect);
+
+ int scrollbarLeft = width() - borderRight() - scrollbar->width();
+ int scrollbarTop = borderTop();
+ rect.move(-scrollbarLeft, -scrollbarTop);
+ return rect;
+}
+
+IntPoint RenderDataGrid::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntPoint& scrollbarPoint) const
+{
+ RenderView* view = this->view();
+ if (!view)
+ return scrollbarPoint;
+
+ IntPoint point = scrollbarPoint;
+
+ int scrollbarLeft = width() - borderRight() - scrollbar->width();
+ int scrollbarTop = borderTop();
+ point.move(scrollbarLeft, scrollbarTop);
+
+ return view->frameView()->convertFromRenderer(this, point);
+}
+
+IntPoint RenderDataGrid::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntPoint& parentPoint) const
+{
+ RenderView* view = this->view();
+ if (!view)
+ return parentPoint;
+
+ IntPoint point = view->frameView()->convertToRenderer(this, parentPoint);
+
+ int scrollbarLeft = width() - borderRight() - scrollbar->width();
+ int scrollbarTop = borderTop();
+ point.move(-scrollbarLeft, -scrollbarTop);
+ return point;
+}
+
}
#endif
diff --git a/WebCore/rendering/RenderDataGrid.h b/WebCore/rendering/RenderDataGrid.h
index 4f9f728..467edcc 100644
--- a/WebCore/rendering/RenderDataGrid.h
+++ b/WebCore/rendering/RenderDataGrid.h
@@ -69,6 +69,10 @@
virtual void invalidateScrollbarRect(Scrollbar*, const IntRect&);
virtual bool isActive() const;
virtual bool scrollbarCornerPresent() const { return false; } // We don't support resize on data grids yet. If we did this would have to change.
+ virtual IntRect convertFromScrollbarToContainingView(const Scrollbar*, const IntRect&) const;
+ virtual IntRect convertFromContainingViewToScrollbar(const Scrollbar*, const IntRect&) const;
+ virtual IntPoint convertFromScrollbarToContainingView(const Scrollbar*, const IntPoint&) const;
+ virtual IntPoint convertFromContainingViewToScrollbar(const Scrollbar*, const IntPoint&) const;
RefPtr<Scrollbar> m_vBar;
};
diff --git a/WebCore/rendering/RenderLayer.cpp b/WebCore/rendering/RenderLayer.cpp
index c51706b..3cde6b8 100644
--- a/WebCore/rendering/RenderLayer.cpp
+++ b/WebCore/rendering/RenderLayer.cpp
@@ -1424,6 +1424,66 @@
return !scrollCornerRect(this, renderBox()->borderBoxRect()).isEmpty();
}
+IntRect RenderLayer::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntRect& scrollbarRect) const
+{
+ RenderView* view = renderer()->view();
+ if (!view)
+ return scrollbarRect;
+
+ IntRect rect = scrollbarRect;
+ rect.move(scrollbarOffset(scrollbar));
+
+ return view->frameView()->convertFromRenderer(renderer(), rect);
+}
+
+IntRect RenderLayer::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntRect& parentRect) const
+{
+ RenderView* view = renderer()->view();
+ if (!view)
+ return parentRect;
+
+ IntRect rect = view->frameView()->convertToRenderer(renderer(), parentRect);
+ rect.move(-scrollbarOffset(scrollbar));
+ return rect;
+}
+
+IntPoint RenderLayer::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntPoint& scrollbarPoint) const
+{
+ RenderView* view = renderer()->view();
+ if (!view)
+ return scrollbarPoint;
+
+ IntPoint point = scrollbarPoint;
+ point.move(scrollbarOffset(scrollbar));
+ return view->frameView()->convertFromRenderer(renderer(), point);
+}
+
+IntPoint RenderLayer::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntPoint& parentPoint) const
+{
+ RenderView* view = renderer()->view();
+ if (!view)
+ return parentPoint;
+
+ IntPoint point = view->frameView()->convertToRenderer(renderer(), parentPoint);
+
+ point.move(-scrollbarOffset(scrollbar));
+ return point;
+}
+
+IntSize RenderLayer::scrollbarOffset(const Scrollbar* scrollbar) const
+{
+ RenderBox* box = renderBox();
+
+ if (scrollbar == m_vBar.get())
+ return IntSize(box->width() - box->borderRight() - scrollbar->width(), box->borderTop());
+
+ if (scrollbar == m_hBar.get())
+ return IntSize(box->borderLeft(), box->height() - box->borderBottom() - scrollbar->height());
+
+ ASSERT_NOT_REACHED();
+ return IntSize();
+}
+
void RenderLayer::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect)
{
IntRect scrollRect = rect;
@@ -1835,34 +1895,29 @@
return resizerCornerRect(this, localBounds).contains(localPoint);
}
-bool RenderLayer::hitTestOverflowControls(HitTestResult& result)
+bool RenderLayer::hitTestOverflowControls(HitTestResult& result, const IntPoint& localPoint)
{
if (!m_hBar && !m_vBar && (!renderer()->hasOverflowClip() || renderer()->style()->resize() == RESIZE_NONE))
return false;
RenderBox* box = renderBox();
ASSERT(box);
-
- int x = 0;
- int y = 0;
- convertToLayerCoords(root(), x, y);
- IntRect absBounds(x, y, box->width(), box->height());
IntRect resizeControlRect;
if (renderer()->style()->resize() != RESIZE_NONE) {
- resizeControlRect = resizerCornerRect(this, absBounds);
- if (resizeControlRect.contains(result.point()))
+ resizeControlRect = resizerCornerRect(this, box->borderBoxRect());
+ if (resizeControlRect.contains(localPoint))
return true;
}
int resizeControlSize = max(resizeControlRect.height(), 0);
if (m_vBar) {
- IntRect vBarRect(absBounds.right() - box->borderRight() - m_vBar->width(),
- absBounds.y() + box->borderTop(),
+ IntRect vBarRect(box->width() - box->borderRight() - m_vBar->width(),
+ box->borderTop(),
m_vBar->width(),
- absBounds.height() - (box->borderTop() + box->borderBottom()) - (m_hBar ? m_hBar->height() : resizeControlSize));
- if (vBarRect.contains(result.point())) {
+ box->height() - (box->borderTop() + box->borderBottom()) - (m_hBar ? m_hBar->height() : resizeControlSize));
+ if (vBarRect.contains(localPoint)) {
result.setScrollbar(m_vBar.get());
return true;
}
@@ -1870,11 +1925,11 @@
resizeControlSize = max(resizeControlRect.width(), 0);
if (m_hBar) {
- IntRect hBarRect(absBounds.x() + box->borderLeft(),
- absBounds.bottom() - box->borderBottom() - m_hBar->height(),
- absBounds.width() - (box->borderLeft() + box->borderRight()) - (m_vBar ? m_vBar->width() : resizeControlSize),
+ IntRect hBarRect(box->borderLeft(),
+ box->height() - box->borderBottom() - m_hBar->height(),
+ box->width() - (box->borderLeft() + box->borderRight()) - (m_vBar ? m_vBar->width() : resizeControlSize),
m_hBar->height());
- if (hBarRect.contains(result.point())) {
+ if (hBarRect.contains(localPoint)) {
result.setScrollbar(m_hBar.get());
return true;
}
diff --git a/WebCore/rendering/RenderLayer.h b/WebCore/rendering/RenderLayer.h
index 971c4d1..1138658 100644
--- a/WebCore/rendering/RenderLayer.h
+++ b/WebCore/rendering/RenderLayer.h
@@ -264,7 +264,7 @@
void positionOverflowControls(int tx, int ty);
bool isPointInResizeControl(const IntPoint& absolutePoint) const;
- bool hitTestOverflowControls(HitTestResult&);
+ bool hitTestOverflowControls(HitTestResult&, const IntPoint& localPoint);
IntSize offsetFromResizeCorner(const IntPoint& absolutePoint) const;
void paintOverflowControls(GraphicsContext*, int tx, int ty, const IntRect& damageRect);
@@ -476,11 +476,18 @@
bool shouldBeNormalFlowOnly() const;
+ // ScrollBarClient interface
virtual void valueChanged(Scrollbar*);
virtual void invalidateScrollbarRect(Scrollbar*, const IntRect&);
virtual bool isActive() const;
virtual bool scrollbarCornerPresent() const;
-
+ virtual IntRect convertFromScrollbarToContainingView(const Scrollbar*, const IntRect&) const;
+ virtual IntRect convertFromContainingViewToScrollbar(const Scrollbar*, const IntRect&) const;
+ virtual IntPoint convertFromScrollbarToContainingView(const Scrollbar*, const IntPoint&) const;
+ virtual IntPoint convertFromContainingViewToScrollbar(const Scrollbar*, const IntPoint&) const;
+
+ IntSize scrollbarOffset(const Scrollbar*) const;
+
void updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow);
void childVisibilityChanged(bool newVisibility);
diff --git a/WebCore/rendering/RenderListBox.cpp b/WebCore/rendering/RenderListBox.cpp
index 83c569e..b4a7e9b 100644
--- a/WebCore/rendering/RenderListBox.cpp
+++ b/WebCore/rendering/RenderListBox.cpp
@@ -370,7 +370,7 @@
return false;
IntRect vertRect(_tx + width() - borderRight() - m_vBar->width(),
- _ty,
+ _ty + borderTop(),
m_vBar->width(),
height() - borderTop() - borderBottom());
@@ -623,6 +623,64 @@
repaintRectangle(scrollRect);
}
+IntRect RenderListBox::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntRect& scrollbarRect) const
+{
+ RenderView* view = this->view();
+ if (!view)
+ return scrollbarRect;
+
+ IntRect rect = scrollbarRect;
+
+ int scrollbarLeft = width() - borderRight() - scrollbar->width();
+ int scrollbarTop = borderTop();
+ rect.move(scrollbarLeft, scrollbarTop);
+
+ return view->frameView()->convertFromRenderer(this, rect);
+}
+
+IntRect RenderListBox::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntRect& parentRect) const
+{
+ RenderView* view = this->view();
+ if (!view)
+ return parentRect;
+
+ IntRect rect = view->frameView()->convertToRenderer(this, parentRect);
+
+ int scrollbarLeft = width() - borderRight() - scrollbar->width();
+ int scrollbarTop = borderTop();
+ rect.move(-scrollbarLeft, -scrollbarTop);
+ return rect;
+}
+
+IntPoint RenderListBox::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntPoint& scrollbarPoint) const
+{
+ RenderView* view = this->view();
+ if (!view)
+ return scrollbarPoint;
+
+ IntPoint point = scrollbarPoint;
+
+ int scrollbarLeft = width() - borderRight() - scrollbar->width();
+ int scrollbarTop = borderTop();
+ point.move(scrollbarLeft, scrollbarTop);
+
+ return view->frameView()->convertFromRenderer(this, point);
+}
+
+IntPoint RenderListBox::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntPoint& parentPoint) const
+{
+ RenderView* view = this->view();
+ if (!view)
+ return parentPoint;
+
+ IntPoint point = view->frameView()->convertToRenderer(this, parentPoint);
+
+ int scrollbarLeft = width() - borderRight() - scrollbar->width();
+ int scrollbarTop = borderTop();
+ point.move(-scrollbarLeft, -scrollbarTop);
+ return point;
+}
+
PassRefPtr<Scrollbar> RenderListBox::createScrollbar()
{
RefPtr<Scrollbar> widget;
diff --git a/WebCore/rendering/RenderListBox.h b/WebCore/rendering/RenderListBox.h
index b8c0540..dd257a8 100644
--- a/WebCore/rendering/RenderListBox.h
+++ b/WebCore/rendering/RenderListBox.h
@@ -101,6 +101,10 @@
virtual void invalidateScrollbarRect(Scrollbar*, const IntRect&);
virtual bool isActive() const;
virtual bool scrollbarCornerPresent() const { return false; } // We don't support resize on list boxes yet. If we did this would have to change.
+ virtual IntRect convertFromScrollbarToContainingView(const Scrollbar*, const IntRect&) const;
+ virtual IntRect convertFromContainingViewToScrollbar(const Scrollbar*, const IntRect&) const;
+ virtual IntPoint convertFromScrollbarToContainingView(const Scrollbar*, const IntPoint&) const;
+ virtual IntPoint convertFromContainingViewToScrollbar(const Scrollbar*, const IntPoint&) const;
void setHasVerticalScrollbar(bool hasScrollbar);
PassRefPtr<Scrollbar> createScrollbar();