[haiku-webkit-commits] r272 - in webkit/trunk/WebKit/haiku: API WebCoreSupport

  • From: webkit@xxxxxxxxxxxxxxx
  • To: haiku-webkit-commits@xxxxxxxxxxxxx
  • Date: Tue, 02 Mar 2010 21:26:45 +0000

Author: stippi
Date: Tue Mar  2 21:26:45 2010
New Revision: 272
URL: http://mmlr.dyndns.org/changeset/272

Log:
Implemented completely smooth scrolling by moving the bitmap contents. In
ChromeClientHaiku::paint(), the contentChanged flag actually tells us whether
the paint is used for scrolling. Since we now implement scroll(), we can ignore
these events (confirmed with Gtk port). I did see some glitches, so something
with the calculation of the dirty region in BWebPage::scroll() could be wrong
still. Otherwise it works mighty fine.

Modified:
   webkit/trunk/WebKit/haiku/API/WebPage.cpp
   webkit/trunk/WebKit/haiku/API/WebPage.h
   webkit/trunk/WebKit/haiku/API/WebView.cpp
   webkit/trunk/WebKit/haiku/API/WebView.h
   webkit/trunk/WebKit/haiku/WebCoreSupport/ChromeClientHaiku.cpp

Modified: webkit/trunk/WebKit/haiku/API/WebPage.cpp
==============================================================================
--- webkit/trunk/WebKit/haiku/API/WebPage.cpp   Tue Mar  2 21:24:06 2010        
(r271)
+++ webkit/trunk/WebKit/haiku/API/WebPage.cpp   Tue Mar  2 21:26:45 2010        
(r272)
@@ -519,6 +519,8 @@
 void BWebPage::paint(BRect rect, bool contentChanged, bool immediate,
     bool repaintContentOnly)
 {
+       if (!rect.IsValid())
+               return;
     // Block any drawing as long as the BWebView is hidden
     // (should be extended to when the containing BWebWindow is not
     // currently on screen either...)
@@ -558,15 +560,11 @@
     }
     m_webView->UnlockLooper();
 
-    WebCore::GraphicsContext context(offscreenView);
-
-    offscreenView->PushState();
     if (!rect.IsValid())
         rect = offscreenView->Bounds();
     BRegion region(rect);
-    offscreenView->ConstrainClippingRegion(&region);
-    view->paint(&context, IntRect(rect));
-    offscreenView->PopState();
+    internalPaint(offscreenView, &region);
+
     offscreenView->UnlockLooper();
 
     m_pageDirty = false;
@@ -575,6 +573,113 @@
     m_webView->SetOffscreenViewClean(rect, immediate);
 }
 
+void BWebPage::scroll(int xOffset, int yOffset, const BRect& rectToScroll,
+       const BRect& clipRect)
+{
+    if (!m_webView->LockLooper())
+        return;
+    BBitmap* bitmap = m_webView->OffscreenBitmap();
+    BView* offscreenView = m_webView->OffscreenView();
+
+    // Lock the offscreen bitmap while we still have the
+    // window locked. This cannot deadlock and makes sure
+    // the window is not deleting the offscreen view right
+    // after we unlock it and before locking the bitmap.
+    if (!bitmap->Lock()) {
+       m_webView->UnlockLooper();
+       return;
+    }
+    m_webView->UnlockLooper();
+
+       BRect clip = offscreenView->Bounds();
+       BRect rectAtSrc = rectToScroll;
+       BRect rectAtDst = rectAtSrc.OffsetByCopy(xOffset, yOffset);
+       BRegion repaintRegion(rectAtSrc);
+       if (clip.Intersects(rectAtSrc) && clip.Intersects(rectAtDst)) {
+               uint8* src = reinterpret_cast<uint8*>(bitmap->Bits());
+               uint32 bytesPerRow = bitmap->BytesPerRow();
+               // clip source rect
+               rectAtSrc = rectAtSrc & clip;
+               // clip dest rect
+               rectAtDst = rectAtDst & clip;
+               // move dest back over source and clip source to dest
+               rectAtDst.OffsetBy(-xOffset, -yOffset);
+               rectAtSrc = rectAtSrc & rectAtDst;
+               // remember the part that will be clean
+               rectAtDst.OffsetBy(xOffset, yOffset);
+               repaintRegion.Exclude(rectAtDst);
+
+               // calc offset in buffer
+               src += (int32)rectAtSrc.left * 4
+                       + (int32)rectAtSrc.top * bytesPerRow;
+
+               uint32 width = rectAtSrc.IntegerWidth() + 1;
+               uint32 height = rectAtSrc.IntegerHeight() + 1;
+
+               int32 xIncrement;
+               int32 yIncrement;
+       
+               if (yOffset == 0 && xOffset > 0) {
+                       // copy from right to left
+                       xIncrement = -1;
+                       src += (width - 1) * 4;
+               } else {
+                       // copy from left to right
+                       xIncrement = 1;
+               }
+       
+               if (yOffset > 0) {
+                       // copy from bottom to top
+                       yIncrement = -bytesPerRow;
+                       src += (height - 1) * bytesPerRow;
+               } else {
+                       // copy from top to bottom
+                       yIncrement = bytesPerRow;
+               }
+       
+               uint8* dst = src + yOffset * bytesPerRow + xOffset * 4;
+       
+               if (xIncrement == 1) {
+                       for (uint32 y = 0; y < height; y++) {
+                               memcpy(dst, src, width * 4);
+                               src += yIncrement;
+                               dst += yIncrement;
+                       }
+               } else {
+                       for (uint32 y = 0; y < height; y++) {
+                               uint32* srcHandle = (uint32*)src;
+                               uint32* dstHandle = (uint32*)dst;
+                               for (uint32 x = 0; x < width; x++) {
+                                       *dstHandle = *srcHandle;
+                                       srcHandle += xIncrement;
+                                       dstHandle += xIncrement;
+                               }
+                               src += yIncrement;
+                               dst += yIncrement;
+                       }
+               }
+       }
+
+       if (repaintRegion.Frame().IsValid())
+               internalPaint(offscreenView, &repaintRegion);
+
+    bitmap->Unlock();
+
+    // Notify the view that it can now pull the bitmap in its own thread
+    m_webView->SetOffscreenViewClean(rectToScroll, false);
+}
+
+void BWebPage::internalPaint(BView* offscreenView, BRegion* dirty)
+{
+    WebCore::Frame* frame = m_mainFrame->Frame();
+    WebCore::FrameView* view = frame->view();
+    offscreenView->PushState();
+    offscreenView->ConstrainClippingRegion(dirty);
+    WebCore::GraphicsContext context(offscreenView);
+    view->paint(&context, IntRect(dirty->Frame()));
+    offscreenView->PopState();
+}
+
 // #pragma mark - private
 
 void BWebPage::MessageReceived(BMessage* message)

Modified: webkit/trunk/WebKit/haiku/API/WebPage.h
==============================================================================
--- webkit/trunk/WebKit/haiku/API/WebPage.h     Tue Mar  2 21:24:06 2010        
(r271)
+++ webkit/trunk/WebKit/haiku/API/WebPage.h     Tue Mar  2 21:26:45 2010        
(r272)
@@ -34,6 +34,8 @@
 #include <Rect.h>
 #include <String.h>
 
+class BRegion;
+class BView;
 class BWebDownload;
 class BWebFrame;
 class BWebSettings;
@@ -164,6 +166,9 @@
 
        void paint(BRect rect, bool contentChanged, bool immediate,
                bool repaintContentOnly);
+       void scroll(int scrollDeltaX, int scrollDeltaY, const BRect& 
rectToScroll,
+               const BRect& clipRect);
+       void internalPaint(BView* view, BRegion* dirty);
 
 private:
        virtual                                         ~BWebPage();

Modified: webkit/trunk/WebKit/haiku/API/WebView.cpp
==============================================================================
--- webkit/trunk/WebKit/haiku/API/WebView.cpp   Tue Mar  2 21:24:06 2010        
(r271)
+++ webkit/trunk/WebKit/haiku/API/WebView.cpp   Tue Mar  2 21:26:45 2010        
(r272)
@@ -66,6 +66,10 @@
 
 BWebView::~BWebView()
 {
+       if (fOffscreenBitmap) {
+               fOffscreenBitmap->Lock();
+               delete fOffscreenBitmap;
+       }
 }
 
 // #pragma mark - BView hooks
@@ -146,15 +150,15 @@
         GetMouse(&where, &buttons);
         BPoint screenWhere = ConvertToScreen(where);
         fWebPage->mouseWheelChanged(message, where, screenWhere);
-        // NOTE: This solves a bug in WebKit itself, it should issue a mouse
-        // event when scrolling by wheel event. The effects of the this bug
-        // can be witnessed in Safari as well.
-        BMessage mouseMessage(B_MOUSE_MOVED);
-        mouseMessage.AddPoint("be:view_where", where);
-        mouseMessage.AddPoint("screen_where", screenWhere);
-        mouseMessage.AddInt32("buttons", buttons);
-        mouseMessage.AddInt32("modifiers", modifiers());
-        fWebPage->mouseEvent(&mouseMessage, where, screenWhere);
+//        // NOTE: This solves a bug in WebKit itself, it should issue a mouse
+//        // event when scrolling by wheel event. The effects of the this bug
+//        // can be witnessed in Safari as well.
+//        BMessage mouseMessage(B_MOUSE_MOVED);
+//        mouseMessage.AddPoint("be:view_where", where);
+//        mouseMessage.AddPoint("screen_where", screenWhere);
+//        mouseMessage.AddInt32("buttons", buttons);
+//        mouseMessage.AddInt32("modifiers", modifiers());
+//        fWebPage->mouseEvent(&mouseMessage, where, screenWhere);
         break;
     }
 
@@ -279,6 +283,19 @@
            wrapSelection, startInSelection);
 }
 
+void BWebView::SendFakeMouseMovedEvent()
+{
+       if (!LockLooper())
+           return;
+
+    BPoint where;
+    uint32 buttons;
+    GetMouse(&where, &buttons);
+    BPoint screenWhere = ConvertToScreen(where);
+    _DispatchFakeMouseMovedEvent(where, screenWhere, buttons);
+    UnlockLooper();
+}
+
 // #pragma mark - API for WebPage only
 
 void BWebView::SetOffscreenViewClean(BRect cleanRect, bool immediate)
@@ -367,6 +384,20 @@
     fWebPage->mouseEvent(message, where, ConvertToScreen(where));
 }
 
+void BWebView::_DispatchFakeMouseMovedEvent(const BPoint& where,
+       const BPoint& screenWhere, uint32 buttons)
+{
+    // NOTE: This solves a bug in WebKit itself, it should issue a mouse
+    // event when scrolling by wheel event. The effects of the this bug
+    // can be witnessed in Safari as well.
+    BMessage mouseMessage(B_MOUSE_MOVED);
+    mouseMessage.AddPoint("be:view_where", where);
+    mouseMessage.AddPoint("screen_where", screenWhere);
+    mouseMessage.AddInt32("buttons", buttons);
+    mouseMessage.AddInt32("modifiers", modifiers());
+    fWebPage->mouseEvent(&mouseMessage, where, screenWhere);
+}
+
 void BWebView::_DispatchKeyEvent(uint32 sanityWhat)
 {
     BMessage* message = Looper()->CurrentMessage();

Modified: webkit/trunk/WebKit/haiku/API/WebView.h
==============================================================================
--- webkit/trunk/WebKit/haiku/API/WebView.h     Tue Mar  2 21:24:06 2010        
(r271)
+++ webkit/trunk/WebKit/haiku/API/WebView.h     Tue Mar  2 21:26:45 2010        
(r272)
@@ -86,8 +86,12 @@
                                                                        bool 
wrapSelection = true,
                                                                        bool 
startInSelection = false);
 
+                       void                            
SendFakeMouseMovedEvent();
+
 private:
        friend class BWebPage;
+       inline  BBitmap*                        OffscreenBitmap() const
+                                                                       { 
return fOffscreenBitmap; }
        inline  BView*                          OffscreenView() const
                                                                        { 
return fOffscreenView; }
                        void                            
SetOffscreenViewClean(BRect cleanRect,
@@ -98,8 +102,9 @@
                        void                            
_ResizeOffscreenView(int width, int height);
                        void                            
_DispatchMouseEvent(const BPoint& where,
                                                                        uint32 
sanityWhat);
+                       void                            
_DispatchFakeMouseMovedEvent(const BPoint& where,
+                                                                       const 
BPoint& screenWhere, uint32 buttons);
                        void                            
_DispatchKeyEvent(uint32 sanityWhat);
-
 private:
                        uint32                          fLastMouseButtons;
 

Modified: webkit/trunk/WebKit/haiku/WebCoreSupport/ChromeClientHaiku.cpp
==============================================================================
--- webkit/trunk/WebKit/haiku/WebCoreSupport/ChromeClientHaiku.cpp      Tue Mar 
 2 21:24:06 2010        (r271)
+++ webkit/trunk/WebKit/haiku/WebCoreSupport/ChromeClientHaiku.cpp      Tue Mar 
 2 21:26:45 2010        (r272)
@@ -283,16 +283,27 @@
 
 void ChromeClientHaiku::repaint(const IntRect& rect, bool contentChanged, bool 
immediate, bool repaintContentOnly)
 {
+//printf("ChromeClientHaiku::repaint(rect(%d, %d, %d, %d), contentChanged: %d, 
"
+//"immediate: %d, repaintContentOnly: %d)\n",
+//rect.x(), rect.y(), rect.right(), rect.bottom(), contentChanged, immediate, 
repaintContentOnly);
     // TODO: This deadlocks when called from the app thread during init 
(fortunately immediate is false then)
-    if (immediate)
-        m_webPage->paint(BRect(rect), contentChanged, immediate, 
repaintContentOnly);
-    else
-        m_webPage->draw(BRect(rect));
+    // contentChanged == false is used for scrolling.
+    if (contentChanged) {
+           if (immediate)
+               m_webPage->paint(BRect(rect), contentChanged, immediate, 
repaintContentOnly);
+           else
+               m_webPage->draw(BRect(rect));
+    }
 }
 
 void ChromeClientHaiku::scroll(const IntSize& scrollDelta, const IntRect& 
rectToScroll, const IntRect& clipRect)
 {
-    // TODO: Find out how to tell WebCore not to repaint the area that we were 
able to scroll.
+//printf("ChromeClientHaiku::scroll(%d x %d, rectToScroll(%d, %d, %d, %d), "
+//"clipRect(%d, %d, %d, %d))\n", scrollDelta.width(), scrollDelta.height(),
+//rectToScroll.x(), rectToScroll.y(), rectToScroll.right(), 
rectToScroll.bottom(),
+//clipRect.x(), clipRect.y(), clipRect.right(), clipRect.bottom());
+    m_webPage->scroll(scrollDelta.width(), scrollDelta.height(), rectToScroll, 
clipRect);
+    m_webView->SendFakeMouseMovedEvent();
 }
 
 IntPoint ChromeClientHaiku::screenToWindow(const IntPoint& point) const

Other related posts:

  • » [haiku-webkit-commits] r272 - in webkit/trunk/WebKit/haiku: API WebCoreSupport - webkit