Changeset 98827 in webkit


Ignore:
Timestamp:
Oct 30, 2011 9:29:33 AM (13 years ago)
Author:
Martin Robinson
Message:

[GTK] Switch to a backing store approach for painting WebKitWebView
https://bugs.webkit.org/show_bug.cgi?id=70213

Reviewed by Gustavo Noronha Silva.

Source/WebCore:

No new tests. The changes to WebCore should not change
behavior. The changes in WebKit are covered by existing
tests.

  • platform/cairo/WidgetBackingStore.h:

(WebCore::WidgetBackingStore::size): Added this getter for the size.

  • platform/cairo/WidgetBackingStoreCairo.cpp:

(WebCore::WidgetBackingStore::WidgetBackingStore): Initialize size.

  • platform/graphics/cairo/CairoUtilities.cpp:

(WebCore::copyRectFromCairoSurfaceToContext): Added this new helper.
(WebCore::copyRectFromOneSurfaceToAnother): Use the new helper.

  • platform/graphics/cairo/CairoUtilities.h:
  • platform/gtk/GtkWidgetBackingStoreX11.cpp:

(WebCore::WidgetBackingStore::WidgetBackingStore): Initialize the size.

Source/WebKit/gtk:

Paint the WebView into a backing store. This prevents expose events from
triggering a layout, making scrolling and resizing much smoother.

  • WebCoreSupport/ChromeClientGtk.cpp:

(WebKit::ChromeClient::ChromeClient): Initialize new members.
(WebKit::repaintEverythingSoonTimeout): Added this helper which repaints
the WebView more quickly during resize events.
(WebKit::clipOutOldWidgetArea): Clips out the old widget area, so that we
can clear out invalid pixels when growing the widget into a pre-existing
backing store.
(WebKit::clearEverywhereInBackingStore): Clear out the entire backing store.
(WebKit::ChromeClient::widgetSizeChanged): Handle widget size changes by
intelligently resizing or reusing the existing backing store.
(WebKit::coalesceRectsIfPossible): Moved this method from webkitwebview.cpp.
(WebKit::paintWebView): Moved this method from webkitwebview.cpp.
(WebKit::ChromeClient::performAllPendingScrolls): If there are any pending
scrolling operations, perform them by scrolling the backing store.
(WebKit::ChromeClient::paint): Added this timer callback, which paints the
WebView after a short timeout.
(WebKit::ChromeClient::invalidateWindow): No need to do anything here any longer.
(WebKit::ChromeClient::invalidateContentsAndWindow): Now unite the rect with
the existing dirty region and queue the paint timeout.
(WebKit::ChromeClient::scroll): Now just queue a scroll event in the repaint timeout.
Intelligently calculate the area to move and the dirty area using code derived
from WebKit2.

  • WebCoreSupport/ChromeClientGtk.h: Added new method definitions and also use

the WebCore namespace to avoid lots of uses of "WebCore::".

  • webkit/webkitwebview.cpp:

(webkit_web_view_draw): Now just blit the backing store into the widget.
(webkit_web_view_expose): Ditto.
(webkit_web_view_size_allocate): Let the ChromeClient know the widget size changed.
(webkit_web_view_init): Turn off GDK double buffering as we have our own double
buffer.

  • webkit/webkitwebviewprivate.h: Add the backing store member.
Location:
trunk/Source
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r98826 r98827  
     12011-10-29  Martin Robinson  <mrobinson@igalia.com>
     2
     3        [GTK] Switch to a backing store approach for painting WebKitWebView
     4        https://bugs.webkit.org/show_bug.cgi?id=70213
     5
     6        Reviewed by Gustavo Noronha Silva.
     7
     8        No new tests. The changes to WebCore should not change
     9        behavior. The changes in WebKit are covered by existing
     10        tests.
     11
     12        * platform/cairo/WidgetBackingStore.h:
     13        (WebCore::WidgetBackingStore::size): Added this getter for the size.
     14        * platform/cairo/WidgetBackingStoreCairo.cpp:
     15        (WebCore::WidgetBackingStore::WidgetBackingStore): Initialize size.
     16        * platform/graphics/cairo/CairoUtilities.cpp:
     17        (WebCore::copyRectFromCairoSurfaceToContext): Added this new helper.
     18        (WebCore::copyRectFromOneSurfaceToAnother): Use the new helper.
     19        * platform/graphics/cairo/CairoUtilities.h:
     20        * platform/gtk/GtkWidgetBackingStoreX11.cpp:
     21        (WebCore::WidgetBackingStore::WidgetBackingStore): Initialize the size.
     22
    1232011-10-30  Sheriff Bot  <webkit.review.bot@gmail.com>
    224
  • trunk/Source/WebCore/platform/cairo/WidgetBackingStore.h

    r95935 r98827  
    5252    cairo_surface_t* cairoSurface();
    5353    void scroll(const IntRect& scrollRect, const IntSize& scrollOffset);
     54    const IntSize& size() { return m_size; }
    5455
    5556private:
     
    5758
    5859    OwnPtr<WidgetBackingStorePrivate> m_private;
     60    IntSize m_size;
    5961};
    6062
  • trunk/Source/WebCore/platform/cairo/WidgetBackingStoreCairo.cpp

    r95935 r98827  
    7373WidgetBackingStore::WidgetBackingStore(PlatformWidget widget, const IntSize& size)
    7474    : m_private(WidgetBackingStorePrivate::create(widget, size))
     75    , m_size(size)
    7576{
    7677}
  • trunk/Source/WebCore/platform/graphics/cairo/CairoUtilities.cpp

    r95901 r98827  
    187187}
    188188
     189void copyRectFromCairoSurfaceToContext(cairo_surface_t* from, cairo_t* to, const IntSize& offset, const IntRect& rect)
     190{
     191    cairo_set_source_surface(to, from, offset.width(), offset.height());
     192    cairo_rectangle(to, rect.x(), rect.y(), rect.width(), rect.height());
     193    cairo_fill(to);
     194}
     195
    189196void copyRectFromOneSurfaceToAnother(cairo_surface_t* from, cairo_surface_t* to, const IntSize& offset, const IntRect& rect)
    190197{
    191198    RefPtr<cairo_t> context = adoptRef(cairo_create(to));
    192     cairo_set_source_surface(context.get(), from, offset.width(), offset.height());
    193     cairo_rectangle(context.get(), rect.x(), rect.y(), rect.width(), rect.height());
    194     cairo_fill(context.get());
     199    copyRectFromCairoSurfaceToContext(from, context.get(), offset, rect);
    195200}
    196201
  • trunk/Source/WebCore/platform/graphics/cairo/CairoUtilities.h

    r95901 r98827  
    5050                               const AffineTransform& patternTransform, const FloatPoint& phase, cairo_operator_t op, const FloatRect& destRect);
    5151PassRefPtr<cairo_surface_t> copyCairoImageSurface(cairo_surface_t*);
    52 void copyRectFromOneSurfaceToAnother(cairo_surface_t* from, cairo_surface_t* to, const IntSize&, const IntRect&);
     52
     53void copyRectFromCairoSurfaceToContext(cairo_surface_t* from, cairo_t* to, const IntSize& offset, const IntRect&);
     54void copyRectFromOneSurfaceToAnother(cairo_surface_t* from, cairo_surface_t* to, const IntSize& offset, const IntRect&);
    5355
    5456} // namespace WebCore
  • trunk/Source/WebCore/platform/gtk/GtkWidgetBackingStoreX11.cpp

    r95935 r98827  
    7878WidgetBackingStore::WidgetBackingStore(GtkWidget* widget, const IntSize& size)
    7979    : m_private(WidgetBackingStorePrivate::create(widget, size))
     80    , m_size(size)
    8081{
    8182}
  • trunk/Source/WebKit/gtk/ChangeLog

    r98730 r98827  
     12011-10-29  Martin Robinson  <mrobinson@igalia.com>
     2
     3        [GTK] Switch to a backing store approach for painting WebKitWebView
     4        https://bugs.webkit.org/show_bug.cgi?id=70213
     5
     6        Reviewed by Gustavo Noronha Silva.
     7
     8        Paint the WebView into a backing store. This prevents expose events from
     9        triggering a layout, making scrolling and resizing much smoother.
     10
     11        * WebCoreSupport/ChromeClientGtk.cpp:
     12        (WebKit::ChromeClient::ChromeClient): Initialize new members.
     13        (WebKit::repaintEverythingSoonTimeout): Added this helper which repaints
     14        the WebView more quickly during resize events.
     15        (WebKit::clipOutOldWidgetArea): Clips out the old widget area, so that we
     16        can clear out invalid pixels when growing the widget into a pre-existing
     17        backing store.
     18        (WebKit::clearEverywhereInBackingStore): Clear out the entire backing store.
     19        (WebKit::ChromeClient::widgetSizeChanged): Handle widget size changes by
     20        intelligently resizing or reusing the existing backing store.
     21        (WebKit::coalesceRectsIfPossible): Moved this method from webkitwebview.cpp.
     22        (WebKit::paintWebView): Moved this method from webkitwebview.cpp.
     23        (WebKit::ChromeClient::performAllPendingScrolls): If there are any pending
     24        scrolling operations, perform them by scrolling the backing store.
     25        (WebKit::ChromeClient::paint): Added this timer callback, which paints the
     26        WebView after a short timeout.
     27        (WebKit::ChromeClient::invalidateWindow): No need to do anything here any longer.
     28        (WebKit::ChromeClient::invalidateContentsAndWindow): Now unite the rect with
     29        the existing dirty region and queue the paint timeout.
     30        (WebKit::ChromeClient::scroll): Now just queue a scroll event in the repaint timeout.
     31        Intelligently calculate the area to move and the dirty area using code derived
     32        from WebKit2.
     33        * WebCoreSupport/ChromeClientGtk.h: Added new method definitions and also use
     34        the WebCore namespace to avoid lots of uses of "WebCore::".
     35        * webkit/webkitwebview.cpp:
     36        (webkit_web_view_draw): Now just blit the backing store into the widget.
     37        (webkit_web_view_expose): Ditto.
     38        (webkit_web_view_size_allocate): Let the ChromeClient know the widget size changed.
     39        (webkit_web_view_init): Turn off GDK double buffering as we have our own double
     40        buffer.
     41        * webkit/webkitwebviewprivate.h: Add the backing store member.
     42
    1432011-10-28  Jochen Eisinger  <jochen@chromium.org>
    244
  • trunk/Source/WebKit/gtk/WebCoreSupport/ChromeClientGtk.cpp

    r98472 r98827  
    4040#include "HitTestResult.h"
    4141#include "Icon.h"
     42#include "InspectorController.h"
    4243#include "IntRect.h"
    4344#include "KURL.h"
     
    4748#include "PopupMenuClient.h"
    4849#include "PopupMenuGtk.h"
     50#include "RefPtrCairo.h"
    4951#include "SearchPopupMenuGtk.h"
    5052#include "SecurityOrigin.h"
     
    6264#include <glib/gi18n-lib.h>
    6365#include <gtk/gtk.h>
     66#include <wtf/MathExtras.h>
    6467#include <wtf/text/CString.h>
    6568
     
    7679    , m_adjustmentWatcher(webView)
    7780    , m_closeSoonTimer(0)
    78     , m_pendingScrollInvalidations(false)
     81    , m_displayTimer(this, &ChromeClient::paint)
     82    , m_lastDisplayTime(0)
     83    , m_repaintSoonSourceId(0)
    7984{
    8085    ASSERT(m_webView);
     
    378383#endif
    379384
     385static gboolean repaintEverythingSoonTimeout(ChromeClient* client)
     386{
     387    client->paint(0);
     388    return FALSE;
     389}
     390
     391static void clipOutOldWidgetArea(cairo_t* cr, const IntSize& oldSize, const IntSize& newSize)
     392{
     393    cairo_move_to(cr, oldSize.width(), 0);
     394    cairo_line_to(cr, newSize.width(), 0);
     395    cairo_line_to(cr, newSize.width(), newSize.height());
     396    cairo_line_to(cr, 0, newSize.height());
     397    cairo_line_to(cr, 0, oldSize.height());
     398    cairo_line_to(cr, oldSize.width(), oldSize.height());
     399    cairo_close_path(cr);
     400    cairo_clip(cr);
     401}
     402
     403static void clearEverywhereInBackingStore(WebKitWebView* webView, cairo_t* cr)
     404{
     405    // The strategy here is to quickly draw white into this new canvas, so that
     406    // when a user quickly resizes the WebView in an environment that has opaque
     407    // resizing (like Gnome Shell), there are no drawing artifacts.
     408    if (!webView->priv->transparent) {
     409        cairo_set_source_rgb(cr, 1, 1, 1);
     410        cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
     411    } else
     412        cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
     413    cairo_paint(cr);
     414}
     415
     416void ChromeClient::widgetSizeChanged(const IntSize& oldWidgetSize, IntSize newSize)
     417{
     418    WidgetBackingStore* backingStore = m_webView->priv->backingStore.get();
     419
     420    // Grow the backing store by at least 1.5 times the current size. This prevents
     421    // lots of unnecessary allocations during an opaque resize.
     422    if (backingStore) {
     423        const IntSize& oldSize = backingStore->size();
     424        if (newSize.width() > oldSize.width())
     425            newSize.setWidth(std::max(newSize.width(), static_cast<int>(oldSize.width() * 1.5)));
     426        if (newSize.height() > oldSize.height())
     427            newSize.setHeight(std::max(newSize.height(), static_cast<int>(oldSize.height() * 1.5)));
     428    }
     429
     430    // If we did not have a backing store before or if the backing store is growing, we need
     431    // to reallocate a new one and set it up so that we don't see artifacts while resizing.
     432    if (!backingStore
     433        || newSize.width() > backingStore->size().width()
     434        || newSize.height() > backingStore->size().height()) {
     435
     436        OwnPtr<WidgetBackingStore> newBackingStore =
     437            WebCore::WidgetBackingStore::create(GTK_WIDGET(m_webView), newSize);
     438        RefPtr<cairo_t> cr = adoptRef(cairo_create(newBackingStore->cairoSurface()));
     439
     440        clearEverywhereInBackingStore(m_webView, cr.get());
     441
     442        // Now we copy the old backing store image over the new cleared surface to prevent
     443        // annoying flashing as the widget grows. We do the "real" paint in a timeout
     444        // since we don't want to block resizing too long.
     445        if (backingStore) {
     446            cairo_set_source_surface(cr.get(), backingStore->cairoSurface(), 0, 0);
     447            cairo_rectangle(cr.get(), 0, 0, backingStore->size().width(), backingStore->size().height());
     448            cairo_fill(cr.get());
     449        }
     450
     451        m_webView->priv->backingStore = newBackingStore.release();
     452        backingStore = m_webView->priv->backingStore.get();
     453
     454    } else if (oldWidgetSize.width() < newSize.width() || oldWidgetSize.height() < newSize.height()) {
     455        // The widget is growing, but we did not need to create a new backing store.
     456        // We should clear any old data outside of the old widget region.
     457        RefPtr<cairo_t> cr = adoptRef(cairo_create(backingStore->cairoSurface()));
     458        clipOutOldWidgetArea(cr.get(), oldWidgetSize, newSize);
     459        clearEverywhereInBackingStore(m_webView, cr.get());
     460    }
     461
     462    // We need to force a redraw and ignore the framerate cap.
     463    m_lastDisplayTime = 0;
     464    m_dirtyRegion.unite(IntRect(IntPoint(), backingStore->size()));
     465
     466    // WebCore timers by default have a lower priority which leads to more artifacts when opaque
     467    // resize is on, thus we use g_timeout_add here to force a higher timeout priority.
     468    if (!m_repaintSoonSourceId)
     469        m_repaintSoonSourceId = g_timeout_add(0, reinterpret_cast<GSourceFunc>(repaintEverythingSoonTimeout), this);
     470}
     471
     472static void coalesceRectsIfPossible(const IntRect& clipRect, Vector<IntRect>& rects)
     473{
     474    const unsigned int cRectThreshold = 10;
     475    const float cWastedSpaceThreshold = 0.75f;
     476    bool useUnionedRect = (rects.size() <= 1) || (rects.size() > cRectThreshold);
     477    if (!useUnionedRect) {
     478        // Attempt to guess whether or not we should use the unioned rect or the individual rects.
     479        // We do this by computing the percentage of "wasted space" in the union. If that wasted space
     480        // is too large, then we will do individual rect painting instead.
     481        float unionPixels = (clipRect.width() * clipRect.height());
     482        float singlePixels = 0;
     483        for (size_t i = 0; i < rects.size(); ++i)
     484            singlePixels += rects[i].width() * rects[i].height();
     485        float wastedSpace = 1 - (singlePixels / unionPixels);
     486        if (wastedSpace <= cWastedSpaceThreshold)
     487            useUnionedRect = true;
     488    }
     489
     490    if (!useUnionedRect)
     491        return;
     492
     493    rects.clear();
     494    rects.append(clipRect);
     495}
     496
     497static void paintWebView(WebKitWebView* webView, Frame* frame, Region dirtyRegion)
     498{
     499    if (!webView->priv->backingStore)
     500        return;
     501
     502    Vector<IntRect> rects = dirtyRegion.rects();
     503    coalesceRectsIfPossible(dirtyRegion.bounds(), rects);
     504    frame->view()->updateLayoutAndStyleIfNeededRecursive();
     505
     506    RefPtr<cairo_t> backingStoreContext = adoptRef(cairo_create(webView->priv->backingStore->cairoSurface()));
     507    GraphicsContext gc(backingStoreContext.get());
     508    for (size_t i = 0; i < rects.size(); i++) {
     509        const IntRect& rect = rects[i];
     510
     511        gc.save();
     512        gc.clip(rect);
     513        if (webView->priv->transparent)
     514            gc.clearRect(rect);
     515        frame->view()->paint(&gc, rect);
     516        gc.restore();
     517    }
     518
     519    gc.save();
     520    gc.clip(dirtyRegion.bounds());
     521    frame->page()->inspectorController()->drawHighlight(gc);
     522    gc.restore();
     523}
     524
     525void ChromeClient::performAllPendingScrolls()
     526{
     527    if (!m_webView->priv->backingStore)
     528        return;
     529
     530    // Scroll all pending scroll rects and invalidate those parts of the widget.
     531    for (size_t i = 0; i < m_rectsToScroll.size(); i++) {
     532        IntRect& scrollRect = m_rectsToScroll[i];
     533        m_webView->priv->backingStore->scroll(scrollRect, m_scrollOffsets[i]);
     534        gtk_widget_queue_draw_area(GTK_WIDGET(m_webView),
     535                                   scrollRect.x(), scrollRect.y(),
     536                                   scrollRect.width(), scrollRect.height());
     537    }
     538
     539    m_rectsToScroll.clear();
     540    m_scrollOffsets.clear();
     541}
     542
     543
     544void ChromeClient::paint(WebCore::Timer<ChromeClient>*)
     545{
     546    static const double minimumFrameInterval = 1.0 / 60.0; // No more than 60 frames a second.
     547    double timeSinceLastDisplay = currentTime() - m_lastDisplayTime;
     548    double timeUntilNextDisplay = minimumFrameInterval - timeSinceLastDisplay;
     549
     550    if (timeUntilNextDisplay > 0) {
     551        m_displayTimer.startOneShot(timeUntilNextDisplay);
     552        return;
     553    }
     554
     555    Frame* frame = core(m_webView)->mainFrame();
     556    if (!frame || !frame->contentRenderer() || !frame->view())
     557        return;
     558
     559    performAllPendingScrolls();
     560    paintWebView(m_webView, frame, m_dirtyRegion);
     561
     562    const IntRect& rect = m_dirtyRegion.bounds();
     563    gtk_widget_queue_draw_area(GTK_WIDGET(m_webView), rect.x(), rect.y(), rect.width(), rect.height());
     564
     565    m_dirtyRegion = Region();
     566    m_lastDisplayTime = currentTime();
     567    m_repaintSoonSourceId = 0;
     568}
     569
    380570void ChromeClient::invalidateWindow(const IntRect&, bool immediate)
    381571{
    382     // If we've invalidated regions for scrolling, force GDK to process those invalidations
    383     // now. This will also cause child windows to move right away. This prevents redraw
    384     // artifacts with child windows (e.g. Flash plugin instances).
    385     if (immediate && m_pendingScrollInvalidations) {
    386         m_pendingScrollInvalidations = false;
    387         if (GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(m_webView)))
    388             gdk_window_process_updates(window, TRUE);
    389     }
    390572}
    391573
    392574void ChromeClient::invalidateContentsAndWindow(const IntRect& updateRect, bool immediate)
    393575{
    394     GdkRectangle rect = updateRect;
    395     GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(m_webView));
    396 
    397     if (window && !updateRect.isEmpty()) {
    398         gdk_window_invalidate_rect(window, &rect, FALSE);
    399         // We don't currently do immediate updates since they delay other UI elements.
    400         //if (immediate)
    401         //    gdk_window_process_updates(window, FALSE);
    402     }
     576    if (updateRect.isEmpty())
     577        return;
     578    m_dirtyRegion.unite(updateRect);
     579    m_displayTimer.startOneShot(0);
    403580}
    404581
     
    411588void ChromeClient::scroll(const IntSize& delta, const IntRect& rectToScroll, const IntRect& clipRect)
    412589{
    413     GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(m_webView));
    414     if (!window)
    415         return;
    416 
    417     m_pendingScrollInvalidations = true;
    418 
    419     // We cannot use gdk_window_scroll here because it is only able to
    420     // scroll the whole window at once, and we often need to scroll
    421     // portions of the window only (think frames).
    422     GdkRectangle area = clipRect;
    423     GdkRectangle moveRect;
    424 
    425     GdkRectangle sourceRect = area;
    426     sourceRect.x -= delta.width();
    427     sourceRect.y -= delta.height();
    428 
    429 #ifdef GTK_API_VERSION_2
    430     GdkRegion* invalidRegion = gdk_region_rectangle(&area);
    431 
    432     if (gdk_rectangle_intersect(&area, &sourceRect, &moveRect)) {
    433         GdkRegion* moveRegion = gdk_region_rectangle(&moveRect);
    434         gdk_window_move_region(window, moveRegion, delta.width(), delta.height());
    435         gdk_region_offset(moveRegion, delta.width(), delta.height());
    436         gdk_region_subtract(invalidRegion, moveRegion);
    437         gdk_region_destroy(moveRegion);
    438     }
    439 
    440     gdk_window_invalidate_region(window, invalidRegion, FALSE);
    441     gdk_region_destroy(invalidRegion);
    442 #else
    443     cairo_region_t* invalidRegion = cairo_region_create_rectangle(&area);
    444 
    445     if (gdk_rectangle_intersect(&area, &sourceRect, &moveRect)) {
    446         cairo_region_t* moveRegion = cairo_region_create_rectangle(&moveRect);
    447         gdk_window_move_region(window, moveRegion, delta.width(), delta.height());
    448         cairo_region_translate(moveRegion, delta.width(), delta.height());
    449         cairo_region_subtract(invalidRegion, moveRegion);
    450         cairo_region_destroy(moveRegion);
    451     }
    452 
    453     gdk_window_invalidate_region(window, invalidRegion, FALSE);
    454     cairo_region_destroy(invalidRegion);
    455 #endif
     590    m_rectsToScroll.append(rectToScroll);
     591    m_scrollOffsets.append(delta);
     592
     593    // The code to calculate the scroll repaint region is originally from WebKit2.
     594    // Get the part of the dirty region that is in the scroll rect.
     595    Region dirtyRegionInScrollRect = intersect(rectToScroll, m_dirtyRegion);
     596    if (!dirtyRegionInScrollRect.isEmpty()) {
     597        // There are parts of the dirty region that are inside the scroll rect.
     598        // We need to subtract them from the region, move them and re-add them.
     599        m_dirtyRegion.subtract(rectToScroll);
     600
     601        // Move the dirty parts.
     602        Region movedDirtyRegionInScrollRect = intersect(translate(dirtyRegionInScrollRect, delta), rectToScroll);
     603
     604        // And add them back.
     605        m_dirtyRegion.unite(movedDirtyRegionInScrollRect);
     606    }
     607
     608    // Compute the scroll repaint region.
     609    Region scrollRepaintRegion = subtract(rectToScroll, translate(rectToScroll, delta));
     610    m_dirtyRegion.unite(scrollRepaintRegion);
     611    m_displayTimer.startOneShot(0);
    456612
    457613    m_adjustmentWatcher.updateAdjustmentsFromScrollbarsLater();
  • trunk/Source/WebKit/gtk/WebCoreSupport/ChromeClientGtk.h

    r98472 r98827  
    2424#include "ChromeClient.h"
    2525#include "GtkAdjustmentWatcher.h"
     26#include "IntRect.h"
     27#include "IntSize.h"
    2628#include "KURL.h"
    2729#include "PopupMenu.h"
     30#include "Region.h"
    2831#include "SearchPopupMenu.h"
     32#include "Timer.h"
    2933
     34using namespace WebCore;
    3035typedef struct _WebKitWebView WebKitWebView;
    3136
     
    4449        virtual void chromeDestroyed();
    4550
    46         virtual void setWindowRect(const WebCore::FloatRect&);
    47         virtual WebCore::FloatRect windowRect();
     51        virtual void setWindowRect(const FloatRect&);
     52        virtual FloatRect windowRect();
    4853
    49         virtual WebCore::FloatRect pageRect();
     54        virtual FloatRect pageRect();
    5055
    5156        virtual void focus();
    5257        virtual void unfocus();
    5358
    54         virtual bool canTakeFocus(WebCore::FocusDirection);
    55         virtual void takeFocus(WebCore::FocusDirection);
     59        virtual bool canTakeFocus(FocusDirection);
     60        virtual void takeFocus(FocusDirection);
    5661
    57         virtual void focusedNodeChanged(WebCore::Node*);
    58         virtual void focusedFrameChanged(WebCore::Frame*);
     62        virtual void focusedNodeChanged(Node*);
     63        virtual void focusedFrameChanged(Frame*);
    5964
    60         virtual WebCore::Page* createWindow(WebCore::Frame*, const WebCore::FrameLoadRequest&, const WebCore::WindowFeatures&, const WebCore::NavigationAction&);
     65        virtual Page* createWindow(Frame*, const FrameLoadRequest&, const WindowFeatures&, const NavigationAction&);
    6166        virtual void show();
    6267
     
    7883        virtual void setResizable(bool);
    7984
    80         virtual void addMessageToConsole(WebCore::MessageSource source, WebCore::MessageType type,
    81                                          WebCore::MessageLevel level, const WTF::String& message,
     85        virtual void addMessageToConsole(MessageSource source, MessageType type,
     86                                         MessageLevel level, const WTF::String& message,
    8287                                         unsigned int lineNumber, const WTF::String& sourceID);
    8388
    8489        virtual bool canRunBeforeUnloadConfirmPanel();
    85         virtual bool runBeforeUnloadConfirmPanel(const WTF::String& message, WebCore::Frame* frame);
     90        virtual bool runBeforeUnloadConfirmPanel(const WTF::String& message, Frame* frame);
    8691
    8792        virtual void closeWindowSoon();
    8893
    89         virtual void runJavaScriptAlert(WebCore::Frame*, const WTF::String&);
    90         virtual bool runJavaScriptConfirm(WebCore::Frame*, const WTF::String&);
    91         virtual bool runJavaScriptPrompt(WebCore::Frame*, const WTF::String& message, const WTF::String& defaultValue, WTF::String& result);
     94        virtual void runJavaScriptAlert(Frame*, const WTF::String&);
     95        virtual bool runJavaScriptConfirm(Frame*, const WTF::String&);
     96        virtual bool runJavaScriptPrompt(Frame*, const WTF::String& message, const WTF::String& defaultValue, WTF::String& result);
    9297        virtual void setStatusbarText(const WTF::String&);
    9398        virtual bool shouldInterruptJavaScript();
    94         virtual WebCore::KeyboardUIMode keyboardUIMode();
     99        virtual KeyboardUIMode keyboardUIMode();
    95100
    96         virtual WebCore::IntRect windowResizerRect() const;
     101        virtual IntRect windowResizerRect() const;
    97102#if ENABLE(REGISTER_PROTOCOL_HANDLER)
    98103        virtual void registerProtocolHandler(const WTF::String&, const WTF::String&, const WTF::String&, const WTF::String&);
    99104#endif
    100         virtual void invalidateWindow(const WebCore::IntRect&, bool);
    101         virtual void invalidateContentsAndWindow(const WebCore::IntRect&, bool);
    102         virtual void invalidateContentsForSlowScroll(const WebCore::IntRect&, bool);
    103         virtual void scroll(const WebCore::IntSize& scrollDelta, const WebCore::IntRect& rectToScroll, const WebCore::IntRect& clipRect);
     105        virtual void invalidateWindow(const IntRect&, bool);
     106        virtual void invalidateContentsAndWindow(const IntRect&, bool);
     107        virtual void invalidateContentsForSlowScroll(const IntRect&, bool);
     108        virtual void scroll(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect);
    104109
    105         virtual WebCore::IntPoint screenToWindow(const WebCore::IntPoint&) const;
    106         virtual WebCore::IntRect windowToScreen(const WebCore::IntRect&) const;
     110        virtual IntPoint screenToWindow(const IntPoint&) const;
     111        virtual IntRect windowToScreen(const IntRect&) const;
    107112        virtual PlatformPageClient platformPageClient() const;
    108         virtual void contentsSizeChanged(WebCore::Frame*, const WebCore::IntSize&) const;
     113        virtual void contentsSizeChanged(Frame*, const IntSize&) const;
    109114
    110115        virtual void scrollbarsModeDidChange() const;
    111         virtual void mouseDidMoveOverElement(const WebCore::HitTestResult&, unsigned modifierFlags);
     116        virtual void mouseDidMoveOverElement(const HitTestResult&, unsigned modifierFlags);
    112117
    113         virtual void setToolTip(const WTF::String&, WebCore::TextDirection);
     118        virtual void setToolTip(const WTF::String&, TextDirection);
    114119
    115         virtual void dispatchViewportPropertiesDidChange(const WebCore::ViewportArguments&) const;
     120        virtual void dispatchViewportPropertiesDidChange(const ViewportArguments&) const;
    116121
    117         virtual void print(WebCore::Frame*);
     122        virtual void print(Frame*);
    118123#if ENABLE(SQL_DATABASE)
    119         virtual void exceededDatabaseQuota(WebCore::Frame*, const WTF::String&);
     124        virtual void exceededDatabaseQuota(Frame*, const WTF::String&);
    120125#endif
    121126        virtual void reachedMaxAppCacheSize(int64_t spaceNeeded);
    122         virtual void reachedApplicationCacheOriginQuota(WebCore::SecurityOrigin*, int64_t totalSpaceNeeded);
     127        virtual void reachedApplicationCacheOriginQuota(SecurityOrigin*, int64_t totalSpaceNeeded);
    123128#if ENABLE(CONTEXT_MENUS)
    124129        virtual void showContextMenu() { }
    125130#endif
    126         virtual void runOpenPanel(WebCore::Frame*, PassRefPtr<WebCore::FileChooser>);
    127         virtual void loadIconForFiles(const Vector<WTF::String>&, WebCore::FileIconLoader*);
     131        virtual void runOpenPanel(Frame*, PassRefPtr<FileChooser>);
     132        virtual void loadIconForFiles(const Vector<WTF::String>&, FileIconLoader*);
    128133
    129         virtual void formStateDidChange(const WebCore::Node*) { }
     134        virtual void formStateDidChange(const Node*) { }
    130135
    131         virtual void setCursor(const WebCore::Cursor&);
     136        virtual void setCursor(const Cursor&);
    132137        virtual void setCursorHiddenUntilMouseMoves(bool);
    133138
    134         virtual void scrollRectIntoView(const WebCore::IntRect&) const { }
    135         virtual void requestGeolocationPermissionForFrame(WebCore::Frame*, WebCore::Geolocation*);
    136         virtual void cancelGeolocationPermissionRequestForFrame(WebCore::Frame*, WebCore::Geolocation*);
     139        virtual void scrollRectIntoView(const IntRect&) const { }
     140        virtual void requestGeolocationPermissionForFrame(Frame*, Geolocation*);
     141        virtual void cancelGeolocationPermissionRequestForFrame(Frame*, Geolocation*);
    137142
    138143        virtual bool selectItemWritingDirectionIsNatural();
    139144        virtual bool selectItemAlignmentFollowsMenuWritingDirection();
    140         virtual PassRefPtr<WebCore::PopupMenu> createPopupMenu(WebCore::PopupMenuClient*) const;
    141         virtual PassRefPtr<WebCore::SearchPopupMenu> createSearchPopupMenu(WebCore::PopupMenuClient*) const;
     145        virtual PassRefPtr<PopupMenu> createPopupMenu(PopupMenuClient*) const;
     146        virtual PassRefPtr<SearchPopupMenu> createSearchPopupMenu(PopupMenuClient*) const;
    142147#if ENABLE(VIDEO)
    143         virtual bool supportsFullscreenForNode(const WebCore::Node*);
    144         virtual void enterFullscreenForNode(WebCore::Node*);
    145         virtual void exitFullscreenForNode(WebCore::Node*);
     148        virtual bool supportsFullscreenForNode(const Node*);
     149        virtual void enterFullscreenForNode(Node*);
     150        virtual void exitFullscreenForNode(Node*);
    146151#endif
    147152
    148153#if ENABLE(FULLSCREEN_API)
    149         virtual bool supportsFullScreenForElement(const WebCore::Element*, bool withKeyboard);
    150         virtual void enterFullScreenForElement(WebCore::Element*);
    151         virtual void exitFullScreenForElement(WebCore::Element*);
     154        virtual bool supportsFullScreenForElement(const Element*, bool withKeyboard);
     155        virtual void enterFullScreenForElement(Element*);
     156        virtual void exitFullScreenForElement(Element*);
    152157#endif
    153158
    154         virtual bool shouldRubberBandInDirection(WebCore::ScrollDirection) const { return true; }
     159        virtual bool shouldRubberBandInDirection(ScrollDirection) const { return true; }
    155160        virtual void numWheelEventHandlersChanged(unsigned) { }
    156161
    157162#if USE(ACCELERATED_COMPOSITING)
    158         virtual void attachRootGraphicsLayer(WebCore::Frame*, WebCore::GraphicsLayer*);
     163        virtual void attachRootGraphicsLayer(Frame*, GraphicsLayer*);
    159164        virtual void setNeedsOneShotDrawingSynchronization();
    160165        virtual void scheduleCompositingLayerSync();
     
    162167#endif
    163168
     169        void performAllPendingScrolls();
     170        void paint(Timer<ChromeClient>*);
     171        void widgetSizeChanged(const IntSize& oldWidgetSize, IntSize newSize);
     172
    164173    private:
    165174        WebKitWebView* m_webView;
    166175        GtkAdjustmentWatcher m_adjustmentWatcher;
    167         WebCore::KURL m_hoveredLinkURL;
     176        KURL m_hoveredLinkURL;
    168177        unsigned int m_closeSoonTimer;
    169         bool m_pendingScrollInvalidations;
     178
     179        Timer <ChromeClient> m_displayTimer;
     180        Region m_dirtyRegion;
     181        Vector<IntRect> m_rectsToScroll;
     182        Vector<IntSize> m_scrollOffsets;
     183        double m_lastDisplayTime;
     184        uint m_repaintSoonSourceId;
    170185    };
    171186}
  • trunk/Source/WebKit/gtk/webkit/webkitwebview.cpp

    r98730 r98827  
    3434#include "AbstractDatabase.h"
    3535#include "BackForwardListImpl.h"
     36#include "CairoUtilities.h"
    3637#include "Chrome.h"
    3738#include "ChromeClientGtk.h"
     
    6869#include "IconDatabase.h"
    6970#include "InspectorClientGtk.h"
    70 #include "InspectorController.h"
    7171#include "MemoryCache.h"
    7272#include "MouseEventWithHitTestResults.h"
     
    623623}
    624624
    625 static bool shouldCoalesce(const IntRect& rect, const Vector<IntRect>& rects)
    626 {
    627     const unsigned int cRectThreshold = 10;
    628     const float cWastedSpaceThreshold = 0.75f;
    629     bool useUnionedRect = (rects.size() <= 1) || (rects.size() > cRectThreshold);
    630     if (useUnionedRect)
    631         return true;
    632     // Attempt to guess whether or not we should use the unioned rect or the individual rects.
    633     // We do this by computing the percentage of "wasted space" in the union.  If that wasted space
    634     // is too large, then we will do individual rect painting instead.
    635     float unionPixels = (rect.width() * rect.height());
    636     float singlePixels = 0;
    637     for (size_t i = 0; i < rects.size(); ++i)
    638         singlePixels += rects[i].width() * rects[i].height();
    639     float wastedSpace = 1 - (singlePixels / unionPixels);
    640     if (wastedSpace <= cWastedSpaceThreshold)
    641         useUnionedRect = true;
    642     return useUnionedRect;
    643 }
    644 
    645 static void paintWebView(Frame* frame, gboolean transparent, GraphicsContext& context, const IntRect& clipRect, const Vector<IntRect>& rects)
    646 {
    647     bool coalesce = true;
    648 
    649     if (rects.size() > 0)
    650         coalesce = shouldCoalesce(clipRect, rects);
    651 
    652     if (coalesce) {
    653         context.clip(clipRect);
    654         if (transparent)
    655             context.clearRect(clipRect);
    656         frame->view()->paint(&context, clipRect);
    657     } else {
    658         for (size_t i = 0; i < rects.size(); i++) {
    659             IntRect rect = rects[i];
    660             context.save();
    661             context.clip(rect);
    662             if (transparent)
    663                 context.clearRect(rect);
    664             frame->view()->paint(&context, rect);
    665             context.restore();
    666         }
    667     }
    668 
    669     context.save();
    670     context.clip(clipRect);
    671     frame->page()->inspectorController()->drawHighlight(context);
    672     context.restore();
    673 }
    674625#ifdef GTK_API_VERSION_2
    675626static gboolean webkit_web_view_expose_event(GtkWidget* widget, GdkEventExpose* event)
    676627{
    677     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
    678     WebKitWebViewPrivate* priv = webView->priv;
    679 
    680     Frame* frame = core(webView)->mainFrame();
    681     if (frame->contentRenderer() && frame->view()) {
    682         frame->view()->updateLayoutAndStyleIfNeededRecursive();
    683 
    684         RefPtr<cairo_t> cr = adoptRef(gdk_cairo_create(event->window));
    685         GraphicsContext gc(cr.get());
    686         gc.setGdkExposeEvent(event);
    687 
    688         int rectCount;
    689         GOwnPtr<GdkRectangle> rects;
    690         gdk_region_get_rectangles(event->region, &rects.outPtr(), &rectCount);
    691         Vector<IntRect> paintRects;
    692         for (int i = 0; i < rectCount; i++)
    693             paintRects.append(IntRect(rects.get()[i]));
    694 
    695         paintWebView(frame, priv->transparent, gc, static_cast<IntRect>(event->area), paintRects);
     628    int rectCount;
     629    GOwnPtr<GdkRectangle> rects;
     630    gdk_region_get_rectangles(event->region, &rects.outPtr(), &rectCount);
     631
     632    RefPtr<cairo_t> cr = adoptRef(gdk_cairo_create(event->window));
     633    for (int i = 0; i < rectCount; i++) {
     634        copyRectFromCairoSurfaceToContext(WEBKIT_WEB_VIEW(widget)->priv->backingStore->cairoSurface(),
     635                                          cr.get(), IntSize(), IntRect(rects.get()[i]));
    696636    }
    697 
    698637    return FALSE;
    699638}
     
    701640static gboolean webkit_web_view_draw(GtkWidget* widget, cairo_t* cr)
    702641{
    703     WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
    704     WebKitWebViewPrivate* priv = webView->priv;
    705642    GdkRectangle clipRect;
    706 
    707643    if (!gdk_cairo_get_clip_rectangle(cr, &clipRect))
    708644        return FALSE;
    709645
    710     Frame* frame = core(webView)->mainFrame();
    711     if (frame->contentRenderer() && frame->view()) {
    712         GraphicsContext gc(cr);
    713         IntRect rect = clipRect;
    714         cairo_rectangle_list_t* rectList = cairo_copy_clip_rectangle_list(cr);
    715 
    716         frame->view()->updateLayoutAndStyleIfNeededRecursive();
    717 
    718         Vector<IntRect> rects;
    719         if (!rectList->status && rectList->num_rectangles > 0) {
    720             for (int i = 0; i < rectList->num_rectangles; i++)
    721                 rects.append(enclosingIntRect(FloatRect(rectList->rectangles[i])));
    722         }
    723         paintWebView(frame, priv->transparent, gc, rect, rects);
    724 
     646    cairo_rectangle_list_t* rectList = cairo_copy_clip_rectangle_list(cr);
     647    if (rectList->status || !rectList->num_rectangles) {
    725648        cairo_rectangle_list_destroy(rectList);
     649        return FALSE;
    726650    }
     651
     652    Vector<IntRect> rects;
     653    for (int i = 0; i < rectList->num_rectangles; i++) {
     654        copyRectFromCairoSurfaceToContext(WEBKIT_WEB_VIEW(widget)->priv->backingStore->cairoSurface(),
     655                                          cr, IntSize(), enclosingIntRect(FloatRect(rectList->rectangles[i])));
     656    }
     657    cairo_rectangle_list_destroy(rectList);
    727658
    728659    return FALSE;
     
    915846
    916847    WebKitWebView* webView = WEBKIT_WEB_VIEW(widget);
    917 
    918848    Page* page = core(webView);
    919     Frame* frame = page->mainFrame();
    920     if (!frame->view())
    921         return;
    922 
    923     frame->view()->resize(allocation->width, allocation->height);
    924     static_cast<WebKit::ChromeClient*>(page->chrome()->client())->adjustmentWatcher()->updateAdjustmentsFromScrollbars();
     849    IntSize oldSize;
     850    if (FrameView* frameView = page->mainFrame()->view()) {
     851        oldSize = frameView->size();
     852        frameView->resize(allocation->width, allocation->height);
     853    }
     854
     855    WebKit::ChromeClient* chromeClient = static_cast<WebKit::ChromeClient*>(page->chrome()->client());
     856    chromeClient->widgetSizeChanged(oldSize, IntSize(allocation->width, allocation->height));
     857    chromeClient->adjustmentWatcher()->updateAdjustmentsFromScrollbars();
    925858}
    926859
     
    33483281
    33493282    gtk_widget_set_can_focus(GTK_WIDGET(webView), TRUE);
     3283    gtk_widget_set_double_buffered(GTK_WIDGET(webView), FALSE);
     3284
    33503285    priv->mainFrame = WEBKIT_WEB_FRAME(webkit_web_frame_new(webView));
    33513286    priv->lastPopupXPosition = priv->lastPopupYPosition = -1;
  • trunk/Source/WebKit/gtk/webkit/webkitwebviewprivate.h

    r96299 r98827  
    3030#include "Page.h"
    3131#include "ResourceHandle.h"
     32#include "WidgetBackingStore.h"
    3233#include <webkit/webkitwebview.h>
    3334
     
    4344struct _WebKitWebViewPrivate {
    4445    WebCore::Page* corePage;
     46    OwnPtr<WebCore::WidgetBackingStore> backingStore;
    4547    GRefPtr<WebKitWebSettings> webSettings;
    4648    GRefPtr<WebKitWebInspector> webInspector;
Note: See TracChangeset for help on using the changeset viewer.