Browse Source

WebView scroll wheel support, more efficient texture updates

Josh Engebretson 10 years ago
parent
commit
504fb5cdfc

+ 1 - 1
Source/Atomic/UI/UIInput.cpp

@@ -154,7 +154,7 @@ void UI::HandleMouseWheel(StringHash eventType, VariantMap& eventData)
 
 
     Input* input = GetSubsystem<Input>();
     Input* input = GetSubsystem<Input>();
 
 
-    rootWidget_->InvokeWheel(input->GetMousePosition().x_, input->GetMousePosition().y_, 0, delta > 0 ? -1 : 1, tb::TB_MODIFIER_NONE);
+    rootWidget_->InvokeWheel(input->GetMousePosition().x_, input->GetMousePosition().y_, 0, -delta, tb::TB_MODIFIER_NONE);
 
 
 }
 }
 
 

+ 5 - 0
Source/AtomicWebView/UIWebView.cpp

@@ -171,6 +171,11 @@ bool UIWebView::OnEvent(const TBWidgetEvent &ev)
         webClient_->SendMouseMoveEvent(ev.target_x, ev.target_y, 0);
         webClient_->SendMouseMoveEvent(ev.target_x, ev.target_y, 0);
         return true;
         return true;
     }
     }
+    else if (ev.type == EVENT_TYPE_WHEEL)
+    {
+        webClient_->SendMouseWheelEvent(ev.target_x, ev.target_y, 0, ev.delta_x, ev.delta_y);
+        return true;
+    }
 
 
 
 
     return UIWidget::OnEvent(ev);
     return UIWidget::OnEvent(ev);

+ 24 - 0
Source/AtomicWebView/WebClient.cpp

@@ -72,6 +72,8 @@ public:
         CefWindowInfo windowInfo;
         CefWindowInfo windowInfo;
         CefBrowserSettings browserSettings;
         CefBrowserSettings browserSettings;
 
 
+        //browserSettings.webgl = STATE_ENABLED;
+
         windowInfo.width = width;
         windowInfo.width = width;
         windowInfo.height = height;
         windowInfo.height = height;
 
 
@@ -201,6 +203,28 @@ void WebClient::SendMouseMoveEvent(int x, int y, unsigned modifier, bool mouseLe
 
 
 }
 }
 
 
+void WebClient::SendMouseWheelEvent(int x, int y, unsigned modifier,int deltaX, int deltaY) const
+{
+    if (!d_->browser_.get())
+        return;
+
+    CefRefPtr<CefBrowserHost> host = d_->browser_->GetHost();
+
+    CefMouseEvent mevent;
+    mevent.x = x;
+    mevent.y = y;
+    mevent.modifiers = 0;
+
+#ifdef ATOMIC_PLATFORM_OSX
+    deltaY = -deltaY;
+#endif
+
+    host->SendMouseWheelEvent(mevent, deltaX, deltaY * 5);
+
+}
+
+
+
 void WebClient::WasResized()
 void WebClient::WasResized()
 {
 {
     if (!d_->browser_.get())
     if (!d_->browser_.get())

+ 1 - 0
Source/AtomicWebView/WebClient.h

@@ -36,6 +36,7 @@ public:
 
 
     void SendMouseClickEvent(int x, int y, unsigned button, bool mouseUp, unsigned modifier) const;
     void SendMouseClickEvent(int x, int y, unsigned button, bool mouseUp, unsigned modifier) const;
     void SendMouseMoveEvent(int x, int y, unsigned modifier, bool mouseLeave = false) const;
     void SendMouseMoveEvent(int x, int y, unsigned modifier, bool mouseLeave = false) const;
+    void SendMouseWheelEvent(int x, int y, unsigned modifier, int deltaX, int deltaY) const;
 
 
 private:
 private:
 
 

+ 139 - 1
Source/AtomicWebView/WebTexture2D.cpp

@@ -1,3 +1,8 @@
+
+#ifdef ATOMIC_PLATFORM_OSX
+#include <ThirdParty/GLEW/glew.h>
+#endif
+
 #include <ThirdParty/CEF/include/cef_render_handler.h>
 #include <ThirdParty/CEF/include/cef_render_handler.h>
 
 
 #include <Atomic/IO/Log.h>
 #include <Atomic/IO/Log.h>
@@ -26,6 +31,58 @@ public:
         webTexture2D_ = webTexture2D;
         webTexture2D_ = webTexture2D;
     }
     }
 
 
+    void OnPopupShow(CefRefPtr<CefBrowser> browser, bool show) OVERRIDE
+    {
+        if (!show)
+        {
+            // Clear the popup rectangle.
+            ClearPopupRects();
+        }
+    }
+
+    void OnPopupSize(CefRefPtr<CefBrowser> browser, const CefRect& rect) OVERRIDE
+    {
+        if (rect.width <= 0 || rect.height <= 0)
+        {
+            ClearPopupRects();
+            return;
+        }
+
+        popupRectOriginal_ = rect;
+        popupRect_ = GetPopupRectInWebView(popupRectOriginal_);
+    }
+
+    CefRect GetPopupRectInWebView(const CefRect& original_rect) {
+
+        CefRect rc(original_rect);
+
+        // if x or y are negative, move them to 0.
+        if (rc.x < 0)
+            rc.x = 0;
+        if (rc.y < 0)
+            rc.y = 0;
+
+        // if popup goes outside the view, try to reposition origin
+        if (rc.x + rc.width > webTexture2D_->GetWidth())
+            rc.x = webTexture2D_->GetWidth() - rc.width;
+        if (rc.y + rc.height > webTexture2D_->GetHeight())
+            rc.y = webTexture2D_->GetHeight() - rc.height;
+
+        // if x or y became negative, move them to 0 again.
+        if (rc.x < 0)
+            rc.x = 0;
+        if (rc.y < 0)
+            rc.y = 0;
+
+        return rc;
+    }
+
+    void ClearPopupRects()
+    {
+        popupRect_.Set(0, 0, 0, 0);
+        popupRectOriginal_.Set(0, 0, 0, 0);
+    }
+
     bool GetViewRect(CefRefPtr<CefBrowser> browser, CefRect &rect) OVERRIDE
     bool GetViewRect(CefRefPtr<CefBrowser> browser, CefRect &rect) OVERRIDE
     {
     {
         rect = CefRect(0, 0, webTexture2D_->GetWidth(), webTexture2D_->GetHeight());
         rect = CefRect(0, 0, webTexture2D_->GetWidth(), webTexture2D_->GetHeight());
@@ -35,20 +92,101 @@ public:
     void OnPaint(CefRefPtr<CefBrowser> browser, PaintElementType type, const RectList &dirtyRects,
     void OnPaint(CefRefPtr<CefBrowser> browser, PaintElementType type, const RectList &dirtyRects,
                  const void *buffer, int width, int height) OVERRIDE
                  const void *buffer, int width, int height) OVERRIDE
     {
     {
+        glEnable(GL_TEXTURE_2D);
 
 
         if (type == PET_VIEW)
         if (type == PET_VIEW)
         {
         {
-            if (width == webTexture2D_->GetWidth() && height == webTexture2D_->GetHeight())
+            glBindTexture(GL_TEXTURE_2D, webTexture2D_->GetTexture2D()->GetGPUObject());
+
+            glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
+
+            if (dirtyRects.size() == 1 &&
+                    dirtyRects[0] == CefRect(0, 0, webTexture2D_->GetWidth(), webTexture2D_->GetHeight()))
             {
             {
                 Texture2D* tex = webTexture2D_->texture_;
                 Texture2D* tex = webTexture2D_->texture_;
+                glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
+                glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
                 tex->SetData(0, 0, 0, width, height, buffer);
                 tex->SetData(0, 0, 0, width, height, buffer);
             }
             }
+            else
+            {
+                // Update just the dirty rectangles.
+                CefRenderHandler::RectList::const_iterator i = dirtyRects.begin();
+
+                for (; i != dirtyRects.end(); ++i)
+                {
+                    const CefRect& rect = *i;
+
+                    glPixelStorei(GL_UNPACK_SKIP_PIXELS, rect.x);
+                    glPixelStorei(GL_UNPACK_SKIP_ROWS, rect.y);
+                    glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x, rect.y, rect.width,
+                                    rect.height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
+                                    buffer);
+
+                }
+
+            }
+
+            glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
+            glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
+            glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+
+            glBindTexture(GL_TEXTURE_2D, 0);
         }
         }
+        else if (type == PET_POPUP && popupRect_.width > 0 && popupRect_.height > 0)
+        {
+            int skip_pixels = 0, x = popupRect_.x;
+            int skip_rows = 0, y = popupRect_.y;
+            int w = width;
+            int h = height;
+            int viewwidth = webTexture2D_->GetWidth();
+            int viewheight = webTexture2D_->GetHeight();
+
+            // Adjust the popup to fit inside the view.
+            if (x < 0)
+            {
+                skip_pixels = -x;
+                x = 0;
+            }
+            if (y < 0)
+            {
+                skip_rows = -y;
+                y = 0;
+            }
+            if (x + w > viewwidth)
+            {
+                w -= x + w - viewwidth;
+            }
+            if (y + h > viewheight)
+            {
+                h -= y + h - viewheight;
+            }
+
+            glBindTexture(GL_TEXTURE_2D, webTexture2D_->GetTexture2D()->GetGPUObject());
+
+            // Update the popup rectangle.
+            glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
+            glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels);
+            glPixelStorei(GL_UNPACK_SKIP_ROWS, skip_rows);
+
+            glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_BGRA,
+                            GL_UNSIGNED_INT_8_8_8_8_REV, buffer);
+
+            glBindTexture(GL_TEXTURE_2D, 0);
+
+            glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
+            glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
+        }
+
+        glDisable(GL_TEXTURE_2D);
 
 
     }
     }
 
 
 private:
 private:
 
 
+    CefRect popupRect_;
+    CefRect popupRectOriginal_;
+
     WeakPtr<WebTexture2D> webTexture2D_;
     WeakPtr<WebTexture2D> webTexture2D_;
 
 
 };
 };