Changeset 53637 in webkit


Ignore:
Timestamp:
Jan 21, 2010 12:19:10 PM (14 years ago)
Author:
Simon Fraser
Message:

2010-01-20 Simon Fraser <Simon Fraser>

Reviewed by Dave Hyatt.

Hit testing on composited plugins is broken
https://bugs.webkit.org/show_bug.cgi?id=33927
<rdar://problem/7559069>

RenderWidget::paint()'s strategy of moving widgets at paint time, using tx and ty, was flawed
because tx,ty are not always root-relative, especially when painting into compositing layers.
This would move widgets to the wrong location, which caused hit testing issues.

Widgets are usually positioned by layout. The one time this was not true was scrolling fixed-position
elements, so we now reposition widgets after scrolling too.

There was a related problem, which was that widgets expect the graphics context to be set up for
root-relative painting. To fix this, adjust the CTM and the paintRect when the widget's frameRect
is in a different coordinate system to the painting offset.

Test: plugins/mouse-events-fixedpos.html

  • page/FrameView.cpp: (WebCore::FrameView::scrollPositionChanged): Update widget positions, to handle widgets in fixed position elements, but only if we're not already inside of layout.
  • platform/graphics/GraphicsContext.h: (WebCore::GraphicsContext::translate): Add a translate() convenience method that takes a FloatSize.
  • platform/graphics/IntSize.h: (WebCore::IntSize::isZero): Add a convenience method for testing for a zero size.
  • platform/mac/WidgetMac.mm: (WebCore::Widget::paint): Adjust a comment.
  • rendering/RenderWidget.cpp: (WebCore::RenderWidget::paint): Detect when the widget's frame is in a different coordinate system to painting, and adjust the CTM and paintRect in that case.
Location:
trunk
Files:
2 added
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r53635 r53637  
     12010-01-20  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Reviewed by Dave Hyatt.
     4
     5        Hit testing on composited plugins is broken
     6        https://bugs.webkit.org/show_bug.cgi?id=33927
     7        <rdar://problem/7559069>
     8
     9        Testcase for hit testing on a fixed-position plugin after scrolling.
     10       
     11        * plugins/mouse-events-fixedpos-expected.txt: Added.
     12        * plugins/mouse-events-fixedpos.html: Added.
     13
    1142010-01-21  Diego Gonzalez  <diego.gonzalez@openbossa.org>
    215
  • trunk/WebCore/ChangeLog

    r53634 r53637  
     12010-01-20  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Reviewed by Dave Hyatt.
     4
     5        Hit testing on composited plugins is broken
     6        https://bugs.webkit.org/show_bug.cgi?id=33927
     7        <rdar://problem/7559069>
     8
     9        RenderWidget::paint()'s strategy of moving widgets at paint time, using tx and ty, was flawed
     10        because tx,ty are not always root-relative, especially when painting into compositing layers.
     11        This would move widgets to the wrong location, which caused hit testing issues.
     12       
     13        Widgets are usually positioned by layout. The one time this was not true was scrolling fixed-position
     14        elements, so we now reposition widgets after scrolling too.
     15       
     16        There was a related problem, which was that widgets expect the graphics context to be set up for
     17        root-relative painting. To fix this, adjust the CTM and the paintRect when the widget's frameRect
     18        is in a different coordinate system to the painting offset.
     19       
     20        Test: plugins/mouse-events-fixedpos.html
     21
     22        * page/FrameView.cpp:
     23        (WebCore::FrameView::scrollPositionChanged): Update widget positions, to handle widgets in fixed position
     24        elements, but only if we're not already inside of layout.
     25
     26        * platform/graphics/GraphicsContext.h:
     27        (WebCore::GraphicsContext::translate): Add a translate() convenience method that takes a FloatSize.
     28
     29        * platform/graphics/IntSize.h:
     30        (WebCore::IntSize::isZero): Add a convenience method for testing for a zero size.
     31
     32        * platform/mac/WidgetMac.mm:
     33        (WebCore::Widget::paint): Adjust a comment.
     34
     35        * rendering/RenderWidget.cpp:
     36        (WebCore::RenderWidget::paint): Detect when the widget's frame is in a different coordinate system
     37        to painting, and adjust the CTM and paintRect in that case.
     38
    1392010-01-21  Andrei Popescu  <andreip@google.com>
    240
  • trunk/WebCore/page/FrameView.cpp

    r53218 r53637  
    951951        layer->updateLayerPositions(RenderLayer::UpdateCompositingLayers);
    952952#endif
     953
     954    // Update widget positions to take care of widgets inside fixed position elements,
     955    // but only if we're not inside of layout.
     956    if (!m_nestedLayoutCount) {
     957        if (RenderView* root = m_frame->contentRenderer())
     958            root->updateWidgetPositions();
     959    }
    953960}
    954961
  • trunk/WebCore/platform/graphics/GraphicsContext.h

    r52791 r53637  
    292292        void scale(const FloatSize&);
    293293        void rotate(float angleInRadians);
     294        void translate(const FloatSize& size) { translate(size.width(), size.height()); }
    294295        void translate(float x, float y);
    295296        IntPoint origin();
  • trunk/WebCore/platform/graphics/IntSize.h

    r48232 r53637  
    7070
    7171    bool isEmpty() const { return m_width <= 0 || m_height <= 0; }
    72 
     72    bool isZero() const { return !m_width && !m_height; }
     73   
    7374    void expand(int width, int height)
    7475    {
  • trunk/WebCore/platform/mac/WidgetMac.mm

    r53523 r53637  
    198198    } else {
    199199        // This is the case of drawing into a bitmap context other than a window backing store. It gets hit beneath
    200         // -cacheDisplayInRect:toBitmapImageRep:.
     200        // -cacheDisplayInRect:toBitmapImageRep:, and when painting into compositing layers.
    201201
    202202        // Transparent subframes are in fact implemented with scroll views that return YES from -drawsBackground (whenever the WebView
  • trunk/WebCore/rendering/RenderWidget.cpp

    r51212 r53637  
    253253
    254254    if (m_widget) {
    255         // Move the widget if necessary.  We normally move and resize widgets during layout, but sometimes
    256         // widgets can move without layout occurring (most notably when you scroll a document that
    257         // contains fixed positioned elements).
    258         m_widget->move(tx + borderLeft() + paddingLeft(), ty + borderTop() + paddingTop());
    259 
    260255        // Tell the widget to paint now.  This is the only time the widget is allowed
    261256        // to paint itself.  That way it will composite properly with z-indexed layers.
    262257        if (m_substituteImage)
    263258            paintInfo.context->drawImage(m_substituteImage.get(), style()->colorSpace(), m_widget->frameRect());
    264         else
    265             m_widget->paint(paintInfo.context, paintInfo.rect);
    266 
     259        else {
     260            IntPoint widgetLocation = m_widget->frameRect().location();
     261            IntPoint paintLocation(tx + borderLeft() + paddingLeft(), ty + borderTop() + paddingTop());
     262            IntRect paintRect = paintInfo.rect;
     263
     264            IntSize paintOffset = paintLocation - widgetLocation;
     265            // When painting widgets into compositing layers, tx and ty are relative to the enclosing compositing layer,
     266            // not the root. In this case, shift the CTM and adjust the paintRect to be root-relative to fix plug-in drawing.
     267            if (!paintOffset.isZero()) {
     268                paintInfo.context->translate(paintOffset);
     269                paintRect.move(-paintOffset);
     270            }
     271            m_widget->paint(paintInfo.context, paintRect);
     272
     273            if (!paintOffset.isZero())
     274                paintInfo.context->translate(-paintOffset);
     275        }
    267276        if (m_widget->isFrameView() && paintInfo.overlapTestRequests && !static_cast<FrameView*>(m_widget.get())->useSlowRepaintsIfNotOverlapped()) {
    268277            ASSERT(!paintInfo.overlapTestRequests->contains(this));
Note: See TracChangeset for help on using the changeset viewer.